mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 13:49:34 +01:00
Auto merge of #133261 - matthiaskrgr:rollup-ekui4we, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #129838 (uefi: process: Add args support) - #130800 (Mark `get_mut` and `set_position` in `std::io::Cursor` as const.) - #132708 (Point at `const` definition when used instead of a binding in a `let` statement) - #133226 (Make `PointerLike` opt-in instead of built-in) - #133244 (Account for `wasm32v1-none` when exporting TLS symbols) - #133257 (Add `UnordMap::clear` method) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
2d0ea7956c
@ -1279,7 +1279,7 @@ impl<'a> WasmLd<'a> {
|
|||||||
let mut wasm_ld = WasmLd { cmd, sess };
|
let mut wasm_ld = WasmLd { cmd, sess };
|
||||||
if sess.target_features.contains(&sym::atomics) {
|
if sess.target_features.contains(&sym::atomics) {
|
||||||
wasm_ld.link_args(&["--shared-memory", "--max-memory=1073741824", "--import-memory"]);
|
wasm_ld.link_args(&["--shared-memory", "--max-memory=1073741824", "--import-memory"]);
|
||||||
if sess.target.os == "unknown" {
|
if sess.target.os == "unknown" || sess.target.os == "none" {
|
||||||
wasm_ld.link_args(&[
|
wasm_ld.link_args(&[
|
||||||
"--export=__wasm_init_tls",
|
"--export=__wasm_init_tls",
|
||||||
"--export=__tls_size",
|
"--export=__tls_size",
|
||||||
@ -1403,7 +1403,7 @@ impl<'a> Linker for WasmLd<'a> {
|
|||||||
// symbols explicitly passed via the `--export` flags above and hides all
|
// symbols explicitly passed via the `--export` flags above and hides all
|
||||||
// others. Various bits and pieces of wasm32-unknown-unknown tooling use
|
// others. Various bits and pieces of wasm32-unknown-unknown tooling use
|
||||||
// this, so be sure these symbols make their way out of the linker as well.
|
// this, so be sure these symbols make their way out of the linker as well.
|
||||||
if self.sess.target.os == "unknown" {
|
if self.sess.target.os == "unknown" || self.sess.target.os == "none" {
|
||||||
self.link_args(&["--export=__heap_base", "--export=__data_end"]);
|
self.link_args(&["--export=__heap_base", "--export=__data_end"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,6 +602,11 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, v)| v)
|
.map(|(_, v)| v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.inner.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, Q: ?Sized, V> Index<&Q> for UnordMap<K, V>
|
impl<K, Q: ?Sized, V> Index<&Q> for UnordMap<K, V>
|
||||||
|
@ -37,22 +37,19 @@ pub(super) fn check_trait<'tcx>(
|
|||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let lang_items = tcx.lang_items();
|
let lang_items = tcx.lang_items();
|
||||||
let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
|
let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
|
||||||
let mut res = checker.check(lang_items.drop_trait(), visit_implementation_of_drop);
|
checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
|
||||||
res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy));
|
checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
|
||||||
res = res.and(checker.check(lang_items.const_param_ty_trait(), |checker| {
|
checker.check(lang_items.const_param_ty_trait(), |checker| {
|
||||||
visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
|
visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
|
||||||
}));
|
})?;
|
||||||
res = res.and(checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
|
checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
|
||||||
visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
|
visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
|
||||||
}));
|
})?;
|
||||||
|
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
|
||||||
res = res.and(
|
checker
|
||||||
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized),
|
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
|
||||||
);
|
checker.check(lang_items.pointer_like(), visit_implementation_of_pointer_like)?;
|
||||||
res.and(
|
Ok(())
|
||||||
checker
|
|
||||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Checker<'tcx> {
|
struct Checker<'tcx> {
|
||||||
@ -663,3 +660,63 @@ fn infringing_fields_error<'tcx>(
|
|||||||
|
|
||||||
err.emit()
|
err.emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||||
|
let tcx = checker.tcx;
|
||||||
|
let typing_env = ty::TypingEnv::non_body_analysis(tcx, checker.impl_def_id);
|
||||||
|
let impl_span = tcx.def_span(checker.impl_def_id);
|
||||||
|
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
|
||||||
|
|
||||||
|
// If an ADT is repr(transparent)...
|
||||||
|
if let ty::Adt(def, args) = *self_ty.kind()
|
||||||
|
&& def.repr().transparent()
|
||||||
|
{
|
||||||
|
// FIXME(compiler-errors): This should and could be deduplicated into a query.
|
||||||
|
// Find the nontrivial field.
|
||||||
|
let adt_typing_env = ty::TypingEnv::non_body_analysis(tcx, def.did());
|
||||||
|
let nontrivial_field = def.all_fields().find(|field_def| {
|
||||||
|
let field_ty = tcx.type_of(field_def.did).instantiate_identity();
|
||||||
|
!tcx.layout_of(adt_typing_env.as_query_input(field_ty))
|
||||||
|
.is_ok_and(|layout| layout.layout.is_1zst())
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(nontrivial_field) = nontrivial_field {
|
||||||
|
// Check that the nontrivial field implements `PointerLike`.
|
||||||
|
let nontrivial_field = nontrivial_field.ty(tcx, args);
|
||||||
|
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
|
||||||
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
ocx.register_bound(
|
||||||
|
ObligationCause::misc(impl_span, checker.impl_def_id),
|
||||||
|
param_env,
|
||||||
|
nontrivial_field,
|
||||||
|
tcx.lang_items().pointer_like().unwrap(),
|
||||||
|
);
|
||||||
|
// FIXME(dyn-star): We should regionck this implementation.
|
||||||
|
if ocx.select_all_or_error().is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_permitted_primitive = match *self_ty.kind() {
|
||||||
|
ty::Adt(def, _) => def.is_box(),
|
||||||
|
ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_permitted_primitive
|
||||||
|
&& let Ok(layout) = tcx.layout_of(typing_env.as_query_input(self_ty))
|
||||||
|
&& layout.layout.is_pointer_like(&tcx.data_layout)
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(tcx
|
||||||
|
.dcx()
|
||||||
|
.struct_span_err(
|
||||||
|
impl_span,
|
||||||
|
"implementation must be applied to type that has the same ABI as a pointer, \
|
||||||
|
or is `repr(transparent)` and whose field is `PointerLike`",
|
||||||
|
)
|
||||||
|
.emit())
|
||||||
|
}
|
||||||
|
@ -656,7 +656,7 @@ impl<'tcx> Pat<'tcx> {
|
|||||||
| Binding { subpattern: Some(subpattern), .. }
|
| Binding { subpattern: Some(subpattern), .. }
|
||||||
| Deref { subpattern }
|
| Deref { subpattern }
|
||||||
| DerefPattern { subpattern, .. }
|
| DerefPattern { subpattern, .. }
|
||||||
| InlineConstant { subpattern, .. } => subpattern.walk_(it),
|
| ExpandedConstant { subpattern, .. } => subpattern.walk_(it),
|
||||||
Leaf { subpatterns } | Variant { subpatterns, .. } => {
|
Leaf { subpatterns } | Variant { subpatterns, .. } => {
|
||||||
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
|
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
|
||||||
}
|
}
|
||||||
@ -799,12 +799,17 @@ pub enum PatKind<'tcx> {
|
|||||||
value: mir::Const<'tcx>,
|
value: mir::Const<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Inline constant found while lowering a pattern.
|
/// Pattern obtained by converting a constant (inline or named) to its pattern
|
||||||
InlineConstant {
|
/// representation using `const_to_pat`.
|
||||||
/// [LocalDefId] of the constant, we need this so that we have a
|
ExpandedConstant {
|
||||||
|
/// [DefId] of the constant, we need this so that we have a
|
||||||
/// reference that can be used by unsafety checking to visit nested
|
/// reference that can be used by unsafety checking to visit nested
|
||||||
/// unevaluated constants.
|
/// unevaluated constants and for diagnostics. If the `DefId` doesn't
|
||||||
def: LocalDefId,
|
/// correspond to a local crate, it points at the `const` item.
|
||||||
|
def_id: DefId,
|
||||||
|
/// If `false`, then `def_id` points at a `const` item, otherwise it
|
||||||
|
/// corresponds to a local inline const.
|
||||||
|
is_inline: bool,
|
||||||
/// If the inline constant is used in a range pattern, this subpattern
|
/// If the inline constant is used in a range pattern, this subpattern
|
||||||
/// represents the range (if both ends are inline constants, there will
|
/// represents the range (if both ends are inline constants, there will
|
||||||
/// be multiple InlineConstant wrappers).
|
/// be multiple InlineConstant wrappers).
|
||||||
|
@ -247,7 +247,7 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Constant { value: _ } => {}
|
Constant { value: _ } => {}
|
||||||
InlineConstant { def: _, subpattern } => visitor.visit_pat(subpattern),
|
ExpandedConstant { def_id: _, is_inline: _, subpattern } => visitor.visit_pat(subpattern),
|
||||||
Range(_) => {}
|
Range(_) => {}
|
||||||
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
|
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
|
||||||
for subpattern in prefix.iter() {
|
for subpattern in prefix.iter() {
|
||||||
|
@ -602,19 +602,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||||||
self.coroutine_is_async_gen(coroutine_def_id)
|
self.coroutine_is_async_gen(coroutine_def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't use `TypingEnv` here as it's only defined in `rustc_middle` and
|
|
||||||
// `rustc_next_trait_solver` shouldn't have to know about it.
|
|
||||||
fn layout_is_pointer_like(
|
|
||||||
self,
|
|
||||||
typing_mode: ty::TypingMode<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> bool {
|
|
||||||
let typing_env = ty::TypingEnv { typing_mode, param_env };
|
|
||||||
self.layout_of(self.erase_regions(typing_env).as_query_input(self.erase_regions(ty)))
|
|
||||||
.is_ok_and(|layout| layout.layout.is_pointer_like(&self.data_layout))
|
|
||||||
}
|
|
||||||
|
|
||||||
type UnsizingParams = &'tcx rustc_index::bit_set::BitSet<u32>;
|
type UnsizingParams = &'tcx rustc_index::bit_set::BitSet<u32>;
|
||||||
fn unsizing_params_for_adt(self, adt_def_id: DefId) -> Self::UnsizingParams {
|
fn unsizing_params_for_adt(self, adt_def_id: DefId) -> Self::UnsizingParams {
|
||||||
self.unsizing_params_for_adt(adt_def_id)
|
self.unsizing_params_for_adt(adt_def_id)
|
||||||
@ -688,7 +675,6 @@ bidirectional_lang_item_map! {
|
|||||||
Metadata,
|
Metadata,
|
||||||
Option,
|
Option,
|
||||||
PointeeTrait,
|
PointeeTrait,
|
||||||
PointerLike,
|
|
||||||
Poll,
|
Poll,
|
||||||
Sized,
|
Sized,
|
||||||
TransmuteTrait,
|
TransmuteTrait,
|
||||||
|
@ -144,12 +144,20 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
|
|||||||
let mut targets = Vec::new();
|
let mut targets = Vec::new();
|
||||||
for arm in rest {
|
for arm in rest {
|
||||||
let arm = &self.thir[*arm];
|
let arm = &self.thir[*arm];
|
||||||
let PatKind::Constant { value } = arm.pattern.kind else {
|
let value = match arm.pattern.kind {
|
||||||
return Err(ParseError {
|
PatKind::Constant { value } => value,
|
||||||
span: arm.pattern.span,
|
PatKind::ExpandedConstant { ref subpattern, def_id: _, is_inline: false }
|
||||||
item_description: format!("{:?}", arm.pattern.kind),
|
if let PatKind::Constant { value } = subpattern.kind =>
|
||||||
expected: "constant pattern".to_string(),
|
{
|
||||||
});
|
value
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(ParseError {
|
||||||
|
span: arm.pattern.span,
|
||||||
|
item_description: format!("{:?}", arm.pattern.kind),
|
||||||
|
expected: "constant pattern".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
values.push(value.eval_bits(self.tcx, self.typing_env));
|
values.push(value.eval_bits(self.tcx, self.typing_env));
|
||||||
targets.push(self.parse_block(arm.body)?);
|
targets.push(self.parse_block(arm.body)?);
|
||||||
|
@ -162,7 +162,11 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
|||||||
TestCase::Irrefutable { ascription: None, binding }
|
TestCase::Irrefutable { ascription: None, binding }
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::InlineConstant { subpattern: ref pattern, def, .. } => {
|
PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => {
|
||||||
|
subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx));
|
||||||
|
default_irrefutable()
|
||||||
|
}
|
||||||
|
PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => {
|
||||||
// Apply a type ascription for the inline constant to the value at `match_pair.place`
|
// Apply a type ascription for the inline constant to the value at `match_pair.place`
|
||||||
let ascription = place.map(|source| {
|
let ascription = place.map(|source| {
|
||||||
let span = pattern.span;
|
let span = pattern.span;
|
||||||
@ -173,7 +177,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
|||||||
})
|
})
|
||||||
.args;
|
.args;
|
||||||
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
|
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
|
||||||
def.to_def_id(),
|
def_id,
|
||||||
ty::UserArgs { args, user_self_ty: None },
|
ty::UserArgs { args, user_self_ty: None },
|
||||||
));
|
));
|
||||||
let annotation = ty::CanonicalUserTypeAnnotation {
|
let annotation = ty::CanonicalUserTypeAnnotation {
|
||||||
|
@ -926,7 +926,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
|
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::InlineConstant { ref subpattern, .. } => {
|
PatKind::ExpandedConstant { ref subpattern, .. } => {
|
||||||
self.visit_primary_bindings(subpattern, pattern_user_ty, f)
|
self.visit_primary_bindings(subpattern, pattern_user_ty, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||||||
PatKind::Wild |
|
PatKind::Wild |
|
||||||
// these just wrap other patterns, which we recurse on below.
|
// these just wrap other patterns, which we recurse on below.
|
||||||
PatKind::Or { .. } |
|
PatKind::Or { .. } |
|
||||||
PatKind::InlineConstant { .. } |
|
PatKind::ExpandedConstant { .. } |
|
||||||
PatKind::AscribeUserType { .. } |
|
PatKind::AscribeUserType { .. } |
|
||||||
PatKind::Error(_) => {}
|
PatKind::Error(_) => {}
|
||||||
}
|
}
|
||||||
@ -386,8 +386,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||||||
visit::walk_pat(self, pat);
|
visit::walk_pat(self, pat);
|
||||||
self.inside_adt = old_inside_adt;
|
self.inside_adt = old_inside_adt;
|
||||||
}
|
}
|
||||||
PatKind::InlineConstant { def, .. } => {
|
PatKind::ExpandedConstant { def_id, is_inline, .. } => {
|
||||||
self.visit_inner_body(*def);
|
if let Some(def) = def_id.as_local()
|
||||||
|
&& *is_inline
|
||||||
|
{
|
||||||
|
self.visit_inner_body(def);
|
||||||
|
}
|
||||||
visit::walk_pat(self, pat);
|
visit::walk_pat(self, pat);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -860,8 +860,10 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
|
|||||||
pub(crate) uncovered: Uncovered,
|
pub(crate) uncovered: Uncovered,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub(crate) inform: Option<Inform>,
|
pub(crate) inform: Option<Inform>,
|
||||||
|
#[label(mir_build_confused)]
|
||||||
|
pub(crate) interpreted_as_const: Option<Span>,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub(crate) interpreted_as_const: Option<InterpretedAsConst>,
|
pub(crate) interpreted_as_const_sugg: Option<InterpretedAsConst>,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub(crate) adt_defined_here: Option<AdtDefinedHere<'tcx>>,
|
pub(crate) adt_defined_here: Option<AdtDefinedHere<'tcx>>,
|
||||||
#[note(mir_build_privately_uninhabited)]
|
#[note(mir_build_privately_uninhabited)]
|
||||||
@ -911,9 +913,9 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
|
|||||||
#[suggestion(
|
#[suggestion(
|
||||||
mir_build_interpreted_as_const,
|
mir_build_interpreted_as_const,
|
||||||
code = "{variable}_var",
|
code = "{variable}_var",
|
||||||
applicability = "maybe-incorrect"
|
applicability = "maybe-incorrect",
|
||||||
|
style = "verbose"
|
||||||
)]
|
)]
|
||||||
#[label(mir_build_confused)]
|
|
||||||
pub(crate) struct InterpretedAsConst {
|
pub(crate) struct InterpretedAsConst {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub(crate) span: Span,
|
pub(crate) span: Span,
|
||||||
|
@ -678,8 +678,25 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
let mut let_suggestion = None;
|
let mut let_suggestion = None;
|
||||||
let mut misc_suggestion = None;
|
let mut misc_suggestion = None;
|
||||||
let mut interpreted_as_const = None;
|
let mut interpreted_as_const = None;
|
||||||
|
let mut interpreted_as_const_sugg = None;
|
||||||
|
|
||||||
if let PatKind::Constant { .. }
|
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. }
|
||||||
|
| PatKind::AscribeUserType {
|
||||||
|
subpattern:
|
||||||
|
box Pat { kind: PatKind::ExpandedConstant { def_id, is_inline: false, .. }, .. },
|
||||||
|
..
|
||||||
|
} = pat.kind
|
||||||
|
&& let DefKind::Const = self.tcx.def_kind(def_id)
|
||||||
|
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
|
||||||
|
// We filter out paths with multiple path::segments.
|
||||||
|
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
|
||||||
|
{
|
||||||
|
let span = self.tcx.def_span(def_id);
|
||||||
|
let variable = self.tcx.item_name(def_id).to_string();
|
||||||
|
// When we encounter a constant as the binding name, point at the `const` definition.
|
||||||
|
interpreted_as_const = Some(span);
|
||||||
|
interpreted_as_const_sugg = Some(InterpretedAsConst { span: pat.span, variable });
|
||||||
|
} else if let PatKind::Constant { .. }
|
||||||
| PatKind::AscribeUserType {
|
| PatKind::AscribeUserType {
|
||||||
subpattern: box Pat { kind: PatKind::Constant { .. }, .. },
|
subpattern: box Pat { kind: PatKind::Constant { .. }, .. },
|
||||||
..
|
..
|
||||||
@ -692,9 +709,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral {
|
misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral {
|
||||||
start_span: pat.span.shrink_to_lo(),
|
start_span: pat.span.shrink_to_lo(),
|
||||||
});
|
});
|
||||||
} else if snippet.chars().all(|c| c.is_alphanumeric() || c == '_') {
|
|
||||||
interpreted_as_const =
|
|
||||||
Some(InterpretedAsConst { span: pat.span, variable: snippet });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,6 +757,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
uncovered: Uncovered::new(pat.span, &cx, witnesses),
|
uncovered: Uncovered::new(pat.span, &cx, witnesses),
|
||||||
inform,
|
inform,
|
||||||
interpreted_as_const,
|
interpreted_as_const,
|
||||||
|
interpreted_as_const_sugg,
|
||||||
witness_1_is_privately_uninhabited,
|
witness_1_is_privately_uninhabited,
|
||||||
_p: (),
|
_p: (),
|
||||||
pattern_ty,
|
pattern_ty,
|
||||||
@ -1112,13 +1127,13 @@ fn report_non_exhaustive_match<'p, 'tcx>(
|
|||||||
if ty.is_ptr_sized_integral() {
|
if ty.is_ptr_sized_integral() {
|
||||||
if ty.inner() == cx.tcx.types.usize {
|
if ty.inner() == cx.tcx.types.usize {
|
||||||
err.note(format!(
|
err.note(format!(
|
||||||
"`{ty}` does not have a fixed maximum value, so half-open ranges are necessary to match \
|
"`{ty}` does not have a fixed maximum value, so half-open ranges are \
|
||||||
exhaustively",
|
necessary to match exhaustively",
|
||||||
));
|
));
|
||||||
} else if ty.inner() == cx.tcx.types.isize {
|
} else if ty.inner() == cx.tcx.types.isize {
|
||||||
err.note(format!(
|
err.note(format!(
|
||||||
"`{ty}` does not have fixed minimum and maximum values, so half-open ranges are necessary to match \
|
"`{ty}` does not have fixed minimum and maximum values, so half-open \
|
||||||
exhaustively",
|
ranges are necessary to match exhaustively",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else if ty.inner() == cx.tcx.types.str_ {
|
} else if ty.inner() == cx.tcx.types.str_ {
|
||||||
@ -1139,6 +1154,31 @@ fn report_non_exhaustive_match<'p, 'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for &arm in arms {
|
||||||
|
let arm = &thir.arms[arm];
|
||||||
|
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = arm.pattern.kind
|
||||||
|
&& let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span)
|
||||||
|
// We filter out paths with multiple path::segments.
|
||||||
|
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
|
||||||
|
{
|
||||||
|
let const_name = cx.tcx.item_name(def_id);
|
||||||
|
err.span_label(
|
||||||
|
arm.pattern.span,
|
||||||
|
format!(
|
||||||
|
"this pattern doesn't introduce a new catch-all binding, but rather pattern \
|
||||||
|
matches against the value of constant `{const_name}`",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
err.span_note(cx.tcx.def_span(def_id), format!("constant `{const_name}` defined here"));
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
arm.pattern.span.shrink_to_hi(),
|
||||||
|
"if you meant to introduce a binding, use a different name",
|
||||||
|
"_var".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Whether we suggest the actual missing patterns or `_`.
|
// Whether we suggest the actual missing patterns or `_`.
|
||||||
let suggest_the_witnesses = witnesses.len() < 4;
|
let suggest_the_witnesses = witnesses.len() < 4;
|
||||||
let suggested_arm = if suggest_the_witnesses {
|
let suggested_arm = if suggest_the_witnesses {
|
||||||
|
@ -149,21 +149,30 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
None => Ok((None, None, None)),
|
None => Ok((None, None, None)),
|
||||||
Some(expr) => {
|
Some(expr) => {
|
||||||
let (kind, ascr, inline_const) = match self.lower_lit(expr) {
|
let (kind, ascr, inline_const) = match self.lower_lit(expr) {
|
||||||
PatKind::InlineConstant { subpattern, def } => {
|
PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => {
|
||||||
(subpattern.kind, None, Some(def))
|
(subpattern.kind, None, def_id.as_local())
|
||||||
|
}
|
||||||
|
PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => {
|
||||||
|
(subpattern.kind, None, None)
|
||||||
}
|
}
|
||||||
PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
|
PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
|
||||||
(kind, Some(ascription), None)
|
(kind, Some(ascription), None)
|
||||||
}
|
}
|
||||||
kind => (kind, None, None),
|
kind => (kind, None, None),
|
||||||
};
|
};
|
||||||
let value = if let PatKind::Constant { value } = kind {
|
let value = match kind {
|
||||||
value
|
PatKind::Constant { value } => value,
|
||||||
} else {
|
PatKind::ExpandedConstant { subpattern, .. }
|
||||||
let msg = format!(
|
if let PatKind::Constant { value } = subpattern.kind =>
|
||||||
"found bad range pattern endpoint `{expr:?}` outside of error recovery"
|
{
|
||||||
);
|
value
|
||||||
return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
|
}
|
||||||
|
_ => {
|
||||||
|
let msg = format!(
|
||||||
|
"found bad range pattern endpoint `{expr:?}` outside of error recovery"
|
||||||
|
);
|
||||||
|
return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const))
|
Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const))
|
||||||
}
|
}
|
||||||
@ -288,7 +297,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
for def in [lo_inline, hi_inline].into_iter().flatten() {
|
for def in [lo_inline, hi_inline].into_iter().flatten() {
|
||||||
kind = PatKind::InlineConstant { def, subpattern: Box::new(Pat { span, ty, kind }) };
|
kind = PatKind::ExpandedConstant {
|
||||||
|
def_id: def.to_def_id(),
|
||||||
|
is_inline: true,
|
||||||
|
subpattern: Box::new(Pat { span, ty, kind }),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Ok(kind)
|
Ok(kind)
|
||||||
}
|
}
|
||||||
@ -562,7 +575,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let args = self.typeck_results.node_args(id);
|
let args = self.typeck_results.node_args(id);
|
||||||
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
|
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
|
||||||
let pattern = self.const_to_pat(c, ty, id, span);
|
let subpattern = self.const_to_pat(c, ty, id, span);
|
||||||
|
let pattern = Box::new(Pat {
|
||||||
|
span,
|
||||||
|
ty,
|
||||||
|
kind: PatKind::ExpandedConstant { subpattern, def_id, is_inline: false },
|
||||||
|
});
|
||||||
|
|
||||||
if !is_associated_const {
|
if !is_associated_const {
|
||||||
return pattern;
|
return pattern;
|
||||||
@ -637,7 +655,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
|
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
|
||||||
let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
|
let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
|
||||||
PatKind::InlineConstant { subpattern, def: def_id }
|
PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts literals, paths and negation of literals to patterns.
|
/// Converts literals, paths and negation of literals to patterns.
|
||||||
|
@ -707,9 +707,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||||||
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
|
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
|
||||||
print_indented!(self, "}", depth_lvl + 1);
|
print_indented!(self, "}", depth_lvl + 1);
|
||||||
}
|
}
|
||||||
PatKind::InlineConstant { def, subpattern } => {
|
PatKind::ExpandedConstant { def_id, is_inline, subpattern } => {
|
||||||
print_indented!(self, "InlineConstant {", depth_lvl + 1);
|
print_indented!(self, "ExpandedConstant {", depth_lvl + 1);
|
||||||
print_indented!(self, format!("def: {:?}", def), depth_lvl + 2);
|
print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2);
|
||||||
|
print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2);
|
||||||
print_indented!(self, "subpattern:", depth_lvl + 2);
|
print_indented!(self, "subpattern:", depth_lvl + 2);
|
||||||
self.print_pat(subpattern, depth_lvl + 2);
|
self.print_pat(subpattern, depth_lvl + 2);
|
||||||
print_indented!(self, "}", depth_lvl + 1);
|
print_indented!(self, "}", depth_lvl + 1);
|
||||||
|
@ -159,13 +159,6 @@ where
|
|||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
) -> Result<Candidate<I>, NoSolution>;
|
) -> Result<Candidate<I>, NoSolution>;
|
||||||
|
|
||||||
/// A type is `PointerLike` if we can compute its layout, and that layout
|
|
||||||
/// matches the layout of `usize`.
|
|
||||||
fn consider_builtin_pointer_like_candidate(
|
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
|
||||||
goal: Goal<I, Self>,
|
|
||||||
) -> Result<Candidate<I>, NoSolution>;
|
|
||||||
|
|
||||||
/// A type is a `FnPtr` if it is of `FnPtr` type.
|
/// A type is a `FnPtr` if it is of `FnPtr` type.
|
||||||
fn consider_builtin_fn_ptr_trait_candidate(
|
fn consider_builtin_fn_ptr_trait_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
@ -449,9 +442,6 @@ where
|
|||||||
ty::ClosureKind::FnOnce,
|
ty::ClosureKind::FnOnce,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Some(TraitSolverLangItem::PointerLike) => {
|
|
||||||
G::consider_builtin_pointer_like_candidate(self, goal)
|
|
||||||
}
|
|
||||||
Some(TraitSolverLangItem::FnPtrTrait) => {
|
Some(TraitSolverLangItem::FnPtrTrait) => {
|
||||||
G::consider_builtin_fn_ptr_trait_candidate(self, goal)
|
G::consider_builtin_fn_ptr_trait_candidate(self, goal)
|
||||||
}
|
}
|
||||||
|
@ -210,13 +210,6 @@ where
|
|||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_builtin_pointer_like_candidate(
|
|
||||||
_ecx: &mut EvalCtxt<'_, D>,
|
|
||||||
_goal: Goal<I, Self>,
|
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
|
||||||
unreachable!("PointerLike is not const")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consider_builtin_fn_ptr_trait_candidate(
|
fn consider_builtin_fn_ptr_trait_candidate(
|
||||||
_ecx: &mut EvalCtxt<'_, D>,
|
_ecx: &mut EvalCtxt<'_, D>,
|
||||||
_goal: Goal<I, Self>,
|
_goal: Goal<I, Self>,
|
||||||
|
@ -363,13 +363,6 @@ where
|
|||||||
panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
|
panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_builtin_pointer_like_candidate(
|
|
||||||
_ecx: &mut EvalCtxt<'_, D>,
|
|
||||||
goal: Goal<I, Self>,
|
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
|
||||||
panic!("`PointerLike` does not have an associated type: {:?}", goal);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consider_builtin_fn_ptr_trait_candidate(
|
fn consider_builtin_fn_ptr_trait_candidate(
|
||||||
_ecx: &mut EvalCtxt<'_, D>,
|
_ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
|
@ -248,32 +248,6 @@ where
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_builtin_pointer_like_candidate(
|
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
|
||||||
goal: Goal<I, Self>,
|
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
|
||||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
|
||||||
return Err(NoSolution);
|
|
||||||
}
|
|
||||||
|
|
||||||
let cx = ecx.cx();
|
|
||||||
// But if there are inference variables, we have to wait until it's resolved.
|
|
||||||
if (goal.param_env, goal.predicate.self_ty()).has_non_region_infer() {
|
|
||||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if cx.layout_is_pointer_like(
|
|
||||||
ecx.typing_mode(goal.param_env),
|
|
||||||
goal.param_env,
|
|
||||||
goal.predicate.self_ty(),
|
|
||||||
) {
|
|
||||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
|
|
||||||
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
|
|
||||||
} else {
|
|
||||||
Err(NoSolution)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consider_builtin_fn_ptr_trait_candidate(
|
fn consider_builtin_fn_ptr_trait_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
|
@ -465,7 +465,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||||||
let fields: Vec<_>;
|
let fields: Vec<_>;
|
||||||
match &pat.kind {
|
match &pat.kind {
|
||||||
PatKind::AscribeUserType { subpattern, .. }
|
PatKind::AscribeUserType { subpattern, .. }
|
||||||
| PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern),
|
| PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern),
|
||||||
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
|
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
|
||||||
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
|
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
|
||||||
ctor = Wildcard;
|
ctor = Wildcard;
|
||||||
|
@ -111,8 +111,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
|
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
|
||||||
} else if tcx.is_lang_item(def_id, LangItem::Tuple) {
|
} else if tcx.is_lang_item(def_id, LangItem::Tuple) {
|
||||||
self.assemble_candidate_for_tuple(obligation, &mut candidates);
|
self.assemble_candidate_for_tuple(obligation, &mut candidates);
|
||||||
} else if tcx.is_lang_item(def_id, LangItem::PointerLike) {
|
|
||||||
self.assemble_candidate_for_pointer_like(obligation, &mut candidates);
|
|
||||||
} else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
|
} else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
|
||||||
self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
|
self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
|
||||||
} else {
|
} else {
|
||||||
@ -1216,35 +1214,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assemble_candidate_for_pointer_like(
|
|
||||||
&mut self,
|
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
|
||||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
|
||||||
) {
|
|
||||||
// The regions of a type don't affect the size of the type
|
|
||||||
let tcx = self.tcx();
|
|
||||||
let self_ty = tcx.instantiate_bound_regions_with_erased(obligation.predicate.self_ty());
|
|
||||||
|
|
||||||
// But if there are inference variables, we have to wait until it's resolved.
|
|
||||||
if (obligation.param_env, self_ty).has_non_region_infer() {
|
|
||||||
candidates.ambiguous = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should erase regions from both the param-env and type, since both
|
|
||||||
// may have infer regions. Specifically, after canonicalizing and instantiating,
|
|
||||||
// early bound regions turn into region vars in both the new and old solver.
|
|
||||||
let key = self.infcx.pseudo_canonicalize_query(
|
|
||||||
tcx.erase_regions(obligation.param_env),
|
|
||||||
tcx.erase_regions(self_ty),
|
|
||||||
);
|
|
||||||
if let Ok(layout) = tcx.layout_of(key)
|
|
||||||
&& layout.layout.is_pointer_like(&tcx.data_layout)
|
|
||||||
{
|
|
||||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assemble_candidates_for_fn_ptr_trait(
|
fn assemble_candidates_for_fn_ptr_trait(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
obligation: &PolyTraitObligation<'tcx>,
|
||||||
|
@ -13,7 +13,7 @@ use crate::lang_items::TraitSolverLangItem;
|
|||||||
use crate::relate::Relate;
|
use crate::relate::Relate;
|
||||||
use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
|
use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
|
||||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||||
use crate::{self as ty, TypingMode, search_graph};
|
use crate::{self as ty, search_graph};
|
||||||
|
|
||||||
pub trait Interner:
|
pub trait Interner:
|
||||||
Sized
|
Sized
|
||||||
@ -278,13 +278,6 @@ pub trait Interner:
|
|||||||
fn coroutine_is_gen(self, coroutine_def_id: Self::DefId) -> bool;
|
fn coroutine_is_gen(self, coroutine_def_id: Self::DefId) -> bool;
|
||||||
fn coroutine_is_async_gen(self, coroutine_def_id: Self::DefId) -> bool;
|
fn coroutine_is_async_gen(self, coroutine_def_id: Self::DefId) -> bool;
|
||||||
|
|
||||||
fn layout_is_pointer_like(
|
|
||||||
self,
|
|
||||||
typing_mode: TypingMode<Self>,
|
|
||||||
param_env: Self::ParamEnv,
|
|
||||||
ty: Self::Ty,
|
|
||||||
) -> bool;
|
|
||||||
|
|
||||||
type UnsizingParams: Deref<Target = BitSet<u32>>;
|
type UnsizingParams: Deref<Target = BitSet<u32>>;
|
||||||
fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams;
|
fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams;
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ pub enum TraitSolverLangItem {
|
|||||||
Metadata,
|
Metadata,
|
||||||
Option,
|
Option,
|
||||||
PointeeTrait,
|
PointeeTrait,
|
||||||
PointerLike,
|
|
||||||
Poll,
|
Poll,
|
||||||
Sized,
|
Sized,
|
||||||
TransmuteTrait,
|
TransmuteTrait,
|
||||||
|
@ -191,6 +191,8 @@ use core::error::{self, Error};
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
use core::marker::PointerLike;
|
||||||
use core::marker::{Tuple, Unsize};
|
use core::marker::{Tuple, Unsize};
|
||||||
use core::mem::{self, SizedTypeProperties};
|
use core::mem::{self, SizedTypeProperties};
|
||||||
use core::ops::{
|
use core::ops::{
|
||||||
@ -2131,3 +2133,7 @@ impl<E: Error> Error for Box<E> {
|
|||||||
Error::provide(&**self, request);
|
Error::provide(&**self, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||||
|
impl<T> PointerLike for Box<T> {}
|
||||||
|
@ -136,6 +136,7 @@
|
|||||||
#![feature(panic_internals)]
|
#![feature(panic_internals)]
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
#![feature(pin_coerce_unsized_trait)]
|
#![feature(pin_coerce_unsized_trait)]
|
||||||
|
#![feature(pointer_like_trait)]
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(ptr_sub_ptr)]
|
#![feature(ptr_sub_ptr)]
|
||||||
|
@ -981,6 +981,18 @@ pub trait Tuple {}
|
|||||||
)]
|
)]
|
||||||
pub trait PointerLike {}
|
pub trait PointerLike {}
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
marker_impls! {
|
||||||
|
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||||
|
PointerLike for
|
||||||
|
usize,
|
||||||
|
{T} &T,
|
||||||
|
{T} &mut T,
|
||||||
|
{T} *const T,
|
||||||
|
{T} *mut T,
|
||||||
|
{T: PointerLike} crate::pin::Pin<T>,
|
||||||
|
}
|
||||||
|
|
||||||
/// A marker for types which can be used as types of `const` generic parameters.
|
/// A marker for types which can be used as types of `const` generic parameters.
|
||||||
///
|
///
|
||||||
/// These types must have a proper equivalence relation (`Eq`) and it must be automatically
|
/// These types must have a proper equivalence relation (`Eq`) and it must be automatically
|
||||||
|
@ -153,7 +153,8 @@ impl<T> Cursor<T> {
|
|||||||
/// let reference = buff.get_mut();
|
/// let reference = buff.get_mut();
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get_mut(&mut self) -> &mut T {
|
#[rustc_const_unstable(feature = "const_mut_cursor", issue = "130801")]
|
||||||
|
pub const fn get_mut(&mut self) -> &mut T {
|
||||||
&mut self.inner
|
&mut self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +201,8 @@ impl<T> Cursor<T> {
|
|||||||
/// assert_eq!(buff.position(), 4);
|
/// assert_eq!(buff.position(), 4);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn set_position(&mut self, pos: u64) {
|
#[rustc_const_unstable(feature = "const_mut_cursor", issue = "130801")]
|
||||||
|
pub const fn set_position(&mut self, pos: u64) {
|
||||||
self.pos = pos;
|
self.pos = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ use crate::{fmt, io};
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Command {
|
pub struct Command {
|
||||||
prog: OsString,
|
prog: OsString,
|
||||||
|
args: Vec<OsString>,
|
||||||
stdout: Option<Stdio>,
|
stdout: Option<Stdio>,
|
||||||
stderr: Option<Stdio>,
|
stderr: Option<Stdio>,
|
||||||
}
|
}
|
||||||
@ -39,12 +40,11 @@ pub enum Stdio {
|
|||||||
|
|
||||||
impl Command {
|
impl Command {
|
||||||
pub fn new(program: &OsStr) -> Command {
|
pub fn new(program: &OsStr) -> Command {
|
||||||
Command { prog: program.to_os_string(), stdout: None, stderr: None }
|
Command { prog: program.to_os_string(), args: Vec::new(), stdout: None, stderr: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Implement arguments as reverse of parsing algorithm
|
pub fn arg(&mut self, arg: &OsStr) {
|
||||||
pub fn arg(&mut self, _arg: &OsStr) {
|
self.args.push(arg.to_os_string());
|
||||||
panic!("unsupported")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||||
@ -72,7 +72,7 @@ impl Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_args(&self) -> CommandArgs<'_> {
|
pub fn get_args(&self) -> CommandArgs<'_> {
|
||||||
panic!("unsupported")
|
CommandArgs { iter: self.args.iter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_envs(&self) -> CommandEnvs<'_> {
|
pub fn get_envs(&self) -> CommandEnvs<'_> {
|
||||||
@ -116,6 +116,12 @@ impl Command {
|
|||||||
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||||
let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?;
|
let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?;
|
||||||
|
|
||||||
|
// UEFI adds the bin name by default
|
||||||
|
if !self.args.is_empty() {
|
||||||
|
let args = uefi_command_internal::create_args(&self.prog, &self.args);
|
||||||
|
cmd.set_args(args);
|
||||||
|
}
|
||||||
|
|
||||||
// Setup Stdout
|
// Setup Stdout
|
||||||
let stdout = self.stdout.unwrap_or(Stdio::MakePipe);
|
let stdout = self.stdout.unwrap_or(Stdio::MakePipe);
|
||||||
let stdout = Self::create_pipe(stdout)?;
|
let stdout = Self::create_pipe(stdout)?;
|
||||||
@ -315,7 +321,7 @@ mod uefi_command_internal {
|
|||||||
stdout: Option<helpers::OwnedProtocol<PipeProtocol>>,
|
stdout: Option<helpers::OwnedProtocol<PipeProtocol>>,
|
||||||
stderr: Option<helpers::OwnedProtocol<PipeProtocol>>,
|
stderr: Option<helpers::OwnedProtocol<PipeProtocol>>,
|
||||||
st: OwnedTable<r_efi::efi::SystemTable>,
|
st: OwnedTable<r_efi::efi::SystemTable>,
|
||||||
args: Option<Vec<u16>>,
|
args: Option<(*mut u16, usize)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
@ -449,20 +455,20 @@ mod uefi_command_internal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_args(&mut self, args: &OsStr) {
|
pub fn set_args(&mut self, args: Box<[u16]>) {
|
||||||
let loaded_image: NonNull<loaded_image::Protocol> =
|
let loaded_image: NonNull<loaded_image::Protocol> =
|
||||||
helpers::open_protocol(self.handle, loaded_image::PROTOCOL_GUID).unwrap();
|
helpers::open_protocol(self.handle, loaded_image::PROTOCOL_GUID).unwrap();
|
||||||
|
|
||||||
let mut args = args.encode_wide().collect::<Vec<u16>>();
|
let len = args.len();
|
||||||
let args_size = (crate::mem::size_of::<u16>() * args.len()) as u32;
|
let args_size: u32 = crate::mem::size_of_val(&args).try_into().unwrap();
|
||||||
|
let ptr = Box::into_raw(args).as_mut_ptr();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
(*loaded_image.as_ptr()).load_options =
|
(*loaded_image.as_ptr()).load_options = ptr as *mut crate::ffi::c_void;
|
||||||
args.as_mut_ptr() as *mut crate::ffi::c_void;
|
|
||||||
(*loaded_image.as_ptr()).load_options_size = args_size;
|
(*loaded_image.as_ptr()).load_options_size = args_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.args = Some(args);
|
self.args = Some((ptr, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_st_crc32(&mut self) -> io::Result<()> {
|
fn update_st_crc32(&mut self) -> io::Result<()> {
|
||||||
@ -502,6 +508,10 @@ mod uefi_command_internal {
|
|||||||
((*bt.as_ptr()).unload_image)(self.handle.as_ptr());
|
((*bt.as_ptr()).unload_image)(self.handle.as_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some((ptr, len)) = self.args {
|
||||||
|
let _ = unsafe { Box::from_raw(crate::ptr::slice_from_raw_parts_mut(ptr, len)) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,4 +691,38 @@ mod uefi_command_internal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_args(prog: &OsStr, args: &[OsString]) -> Box<[u16]> {
|
||||||
|
const QUOTE: u16 = 0x0022;
|
||||||
|
const SPACE: u16 = 0x0020;
|
||||||
|
const CARET: u16 = 0x005e;
|
||||||
|
const NULL: u16 = 0;
|
||||||
|
|
||||||
|
// This is the lower bound on the final length under the assumption that
|
||||||
|
// the arguments only contain ASCII characters.
|
||||||
|
let mut res = Vec::with_capacity(args.iter().map(|arg| arg.len() + 3).sum());
|
||||||
|
|
||||||
|
// Wrap program name in quotes to avoid any problems
|
||||||
|
res.push(QUOTE);
|
||||||
|
res.extend(prog.encode_wide());
|
||||||
|
res.push(QUOTE);
|
||||||
|
res.push(SPACE);
|
||||||
|
|
||||||
|
for arg in args {
|
||||||
|
// Wrap the argument in quotes to be treat as single arg
|
||||||
|
res.push(QUOTE);
|
||||||
|
for c in arg.encode_wide() {
|
||||||
|
// CARET in quotes is used to escape CARET or QUOTE
|
||||||
|
if c == QUOTE || c == CARET {
|
||||||
|
res.push(CARET);
|
||||||
|
}
|
||||||
|
res.push(c);
|
||||||
|
}
|
||||||
|
res.push(QUOTE);
|
||||||
|
|
||||||
|
res.push(SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.into_boxed_slice()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
//@ known-bug: #113280
|
|
||||||
//@ only-x86_64
|
|
||||||
|
|
||||||
#![feature(dyn_star, pointer_like_trait)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::marker::PointerLike;
|
|
||||||
|
|
||||||
fn make_dyn_star<'a>(t: impl PointerLike + Debug + 'a) -> dyn* Debug + 'a {
|
|
||||||
f32::from_bits(0x1) as f64
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("{:?}", make_dyn_star(Box::new(1i32)));
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
//@ known-bug: #127676
|
|
||||||
//@ edition:2018
|
|
||||||
|
|
||||||
#![feature(dyn_star,const_async_blocks)]
|
|
||||||
|
|
||||||
static S: dyn* Send + Sync = async { 42 };
|
|
||||||
|
|
||||||
pub fn main() {}
|
|
@ -97,16 +97,19 @@ LL | if let Refutable::A = v3 { todo!() };
|
|||||||
error[E0005]: refutable pattern in local binding
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/bad-pattern.rs:19:13
|
--> $DIR/bad-pattern.rs:19:13
|
||||||
|
|
|
|
||||||
|
LL | const PAT: u32 = 0;
|
||||||
|
| -------------- missing patterns are not covered because `PAT` is interpreted as a constant pattern, not a new variable
|
||||||
|
...
|
||||||
LL | let PAT = v1;
|
LL | let PAT = v1;
|
||||||
| ^^^
|
| ^^^ pattern `1_u32..=u32::MAX` not covered
|
||||||
| |
|
|
||||||
| pattern `1_u32..=u32::MAX` not covered
|
|
||||||
| missing patterns are not covered because `PAT` is interpreted as a constant pattern, not a new variable
|
|
||||||
| help: introduce a variable instead: `PAT_var`
|
|
||||||
|
|
|
|
||||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
= note: the matched value is of type `u32`
|
= note: the matched value is of type `u32`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let PAT_var = v1;
|
||||||
|
| ~~~~~~~
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
@ -1,28 +1,43 @@
|
|||||||
mod foo {
|
mod foo {
|
||||||
pub const b: u8 = 2;
|
pub const b: u8 = 2;
|
||||||
pub const d: u8 = 2;
|
//~^ missing patterns are not covered because `b` is interpreted as a constant pattern, not a new variable
|
||||||
|
pub const d: (u8, u8) = (2, 1);
|
||||||
|
//~^ missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
|
||||||
}
|
}
|
||||||
|
|
||||||
use foo::b as c;
|
use foo::b as c;
|
||||||
use foo::d;
|
use foo::d;
|
||||||
|
|
||||||
const a: u8 = 2;
|
const a: u8 = 2;
|
||||||
|
//~^ missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
struct S {
|
||||||
|
foo: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
const e: S = S {
|
||||||
|
foo: 0,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = 4;
|
let a = 4;
|
||||||
//~^ ERROR refutable pattern in local binding
|
//~^ ERROR refutable pattern in local binding
|
||||||
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||||
//~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
|
||||||
//~| HELP introduce a variable instead
|
//~| HELP introduce a variable instead
|
||||||
let c = 4;
|
let c = 4;
|
||||||
//~^ ERROR refutable pattern in local binding
|
//~^ ERROR refutable pattern in local binding
|
||||||
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||||
//~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
|
|
||||||
//~| HELP introduce a variable instead
|
//~| HELP introduce a variable instead
|
||||||
let d = 4;
|
let d = (4, 4);
|
||||||
//~^ ERROR refutable pattern in local binding
|
//~^ ERROR refutable pattern in local binding
|
||||||
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
//~| patterns `(0_u8..=1_u8, _)` and `(3_u8..=u8::MAX, _)` not covered
|
||||||
//~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
|
|
||||||
//~| HELP introduce a variable instead
|
//~| HELP introduce a variable instead
|
||||||
|
let e = S {
|
||||||
|
//~^ ERROR refutable pattern in local binding
|
||||||
|
//~| pattern `S { foo: 1_u8..=u8::MAX }` not covered
|
||||||
|
//~| HELP introduce a variable instead
|
||||||
|
foo: 1,
|
||||||
|
};
|
||||||
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
|
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
|
||||||
}
|
}
|
||||||
|
@ -1,45 +1,76 @@
|
|||||||
error[E0005]: refutable pattern in local binding
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/const-pattern-irrefutable.rs:12:9
|
--> $DIR/const-pattern-irrefutable.rs:24:9
|
||||||
|
|
|
|
||||||
|
LL | const a: u8 = 2;
|
||||||
|
| ----------- missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
||||||
|
...
|
||||||
LL | let a = 4;
|
LL | let a = 4;
|
||||||
| ^
|
| ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||||
| |
|
|
||||||
| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
|
||||||
| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
|
||||||
| help: introduce a variable instead: `a_var`
|
|
||||||
|
|
|
|
||||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
= note: the matched value is of type `u8`
|
= note: the matched value is of type `u8`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let a_var = 4;
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/const-pattern-irrefutable.rs:17:9
|
--> $DIR/const-pattern-irrefutable.rs:28:9
|
||||||
|
|
|
|
||||||
|
LL | pub const b: u8 = 2;
|
||||||
|
| --------------- missing patterns are not covered because `b` is interpreted as a constant pattern, not a new variable
|
||||||
|
...
|
||||||
LL | let c = 4;
|
LL | let c = 4;
|
||||||
| ^
|
| ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||||
| |
|
|
||||||
| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
|
||||||
| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
|
|
||||||
| help: introduce a variable instead: `c_var`
|
|
||||||
|
|
|
|
||||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
= note: the matched value is of type `u8`
|
= note: the matched value is of type `u8`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let b_var = 4;
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/const-pattern-irrefutable.rs:22:9
|
--> $DIR/const-pattern-irrefutable.rs:32:9
|
||||||
|
|
|
|
||||||
LL | let d = 4;
|
LL | pub const d: (u8, u8) = (2, 1);
|
||||||
| ^
|
| --------------------- missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
|
||||||
| |
|
...
|
||||||
| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
LL | let d = (4, 4);
|
||||||
| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
|
| ^ patterns `(0_u8..=1_u8, _)` and `(3_u8..=u8::MAX, _)` not covered
|
||||||
| help: introduce a variable instead: `d_var`
|
|
||||||
|
|
|
|
||||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
= note: the matched value is of type `u8`
|
= note: the matched value is of type `(u8, u8)`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let d_var = (4, 4);
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error[E0005]: refutable pattern in local binding
|
||||||
|
--> $DIR/const-pattern-irrefutable.rs:36:9
|
||||||
|
|
|
||||||
|
LL | const e: S = S {
|
||||||
|
| ---------- missing patterns are not covered because `e` is interpreted as a constant pattern, not a new variable
|
||||||
|
...
|
||||||
|
LL | let e = S {
|
||||||
|
| ^ pattern `S { foo: 1_u8..=u8::MAX }` not covered
|
||||||
|
|
|
||||||
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
|
note: `S` defined here
|
||||||
|
--> $DIR/const-pattern-irrefutable.rs:15:8
|
||||||
|
|
|
||||||
|
LL | struct S {
|
||||||
|
| ^
|
||||||
|
= note: the matched value is of type `S`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let e_var = S {
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0005`.
|
For more information about this error, try `rustc --explain E0005`.
|
||||||
|
@ -3,8 +3,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
|||||||
|
|
|
|
||||||
LL | match &[][..] {
|
LL | match &[][..] {
|
||||||
| ^^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
LL |
|
||||||
|
LL | E_SL => {}
|
||||||
|
| ---- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `E_SL`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `&[E]`
|
= note: the matched value is of type `&[E]`
|
||||||
|
note: constant `E_SL` defined here
|
||||||
|
--> $DIR/incomplete-slice.rs:6:1
|
||||||
|
|
|
||||||
|
LL | const E_SL: &[E] = &[E::A];
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | E_SL_var => {}
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
|
||||||
LL ~ E_SL => {},
|
LL ~ E_SL => {},
|
||||||
|
9
tests/ui/dyn-star/async-block-dyn-star.rs
Normal file
9
tests/ui/dyn-star/async-block-dyn-star.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//@ edition:2018
|
||||||
|
|
||||||
|
#![feature(dyn_star, const_async_blocks)]
|
||||||
|
//~^ WARN the feature `dyn_star` is incomplete
|
||||||
|
|
||||||
|
static S: dyn* Send + Sync = async { 42 };
|
||||||
|
//~^ needs to have the same ABI as a pointer
|
||||||
|
|
||||||
|
pub fn main() {}
|
20
tests/ui/dyn-star/async-block-dyn-star.stderr
Normal file
20
tests/ui/dyn-star/async-block-dyn-star.stderr
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/async-block-dyn-star.rs:3:12
|
||||||
|
|
|
||||||
|
LL | #![feature(dyn_star, const_async_blocks)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}` needs to have the same ABI as a pointer
|
||||||
|
--> $DIR/async-block-dyn-star.rs:6:30
|
||||||
|
|
|
||||||
|
LL | static S: dyn* Send + Sync = async { 42 };
|
||||||
|
| ^^^^^^^^^^^^ `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}` needs to be a pointer-like type
|
||||||
|
|
|
||||||
|
= help: the trait `PointerLike` is not implemented for `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
@ -1,14 +1,17 @@
|
|||||||
error[E0277]: `&T` needs to have the same ABI as a pointer
|
error[E0277]: `&T` needs to have the same ABI as a pointer
|
||||||
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
||||||
|
|
|
|
||||||
|
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||||
|
| - this type parameter needs to be `Sized`
|
||||||
LL | dyn_debug(t);
|
LL | dyn_debug(t);
|
||||||
| ^ `&T` needs to be a pointer-like type
|
| ^ `&T` needs to be a pointer-like type
|
||||||
|
|
|
|
||||||
= help: the trait `PointerLike` is not implemented for `&T`
|
= note: required for `&T` to implement `PointerLike`
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||||
|
|
|
||||||
|
LL - fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||||
|
LL + fn polymorphic<T: Debug>(t: &T) {
|
||||||
|
|
|
|
||||||
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerLike {
|
|
||||||
| +++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
error[E0277]: `&T` needs to have the same ABI as a pointer
|
error[E0277]: `&T` needs to have the same ABI as a pointer
|
||||||
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
||||||
|
|
|
|
||||||
|
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||||
|
| - this type parameter needs to be `Sized`
|
||||||
LL | dyn_debug(t);
|
LL | dyn_debug(t);
|
||||||
| ^ `&T` needs to be a pointer-like type
|
| ^ `&T` needs to be a pointer-like type
|
||||||
|
|
|
|
||||||
= help: the trait `PointerLike` is not implemented for `&T`
|
= note: required for `&T` to implement `PointerLike`
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||||
|
|
|
||||||
|
LL - fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||||
|
LL + fn polymorphic<T: Debug>(t: &T) {
|
||||||
|
|
|
|
||||||
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerLike {
|
|
||||||
| +++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
//@ run-pass
|
//@ run-pass
|
||||||
//@ check-run-results
|
//@ check-run-results
|
||||||
#![feature(dyn_star)]
|
#![feature(dyn_star, pointer_like_trait)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::marker::PointerLike;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
struct Foo(#[allow(dead_code)] usize);
|
struct Foo(#[allow(dead_code)] usize);
|
||||||
|
|
||||||
|
// FIXME(dyn_star): Make this into a derive.
|
||||||
|
impl PointerLike for Foo {}
|
||||||
|
|
||||||
impl Drop for Foo {
|
impl Drop for Foo {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
println!("destructor called");
|
println!("destructor called");
|
||||||
|
@ -3,13 +3,18 @@
|
|||||||
// This used to ICE, because the compiler confused a pointer-like to dyn* coercion
|
// This used to ICE, because the compiler confused a pointer-like to dyn* coercion
|
||||||
// with a c-like enum to integer cast.
|
// with a c-like enum to integer cast.
|
||||||
|
|
||||||
#![feature(dyn_star)]
|
#![feature(dyn_star, pointer_like_trait)]
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
|
use std::marker::PointerLike;
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
enum E {
|
enum E {
|
||||||
Num(usize),
|
Num(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PointerLike for E {}
|
||||||
|
|
||||||
trait Trait {}
|
trait Trait {}
|
||||||
impl Trait for E {}
|
impl Trait for E {}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ trait Foo {}
|
|||||||
|
|
||||||
fn make_dyn_star() {
|
fn make_dyn_star() {
|
||||||
let i = 42;
|
let i = 42;
|
||||||
let dyn_i: dyn* Foo = i; //~ ERROR trait bound `{integer}: Foo` is not satisfied
|
let dyn_i: dyn* Foo = i; //~ ERROR trait bound `usize: Foo` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0277]: the trait bound `{integer}: Foo` is not satisfied
|
error[E0277]: the trait bound `usize: Foo` is not satisfied
|
||||||
--> $DIR/error.rs:10:27
|
--> $DIR/error.rs:10:27
|
||||||
|
|
|
|
||||||
LL | let dyn_i: dyn* Foo = i;
|
LL | let dyn_i: dyn* Foo = i;
|
||||||
| ^ the trait `Foo` is not implemented for `{integer}`
|
| ^ the trait `Foo` is not implemented for `usize`
|
||||||
|
|
|
|
||||||
help: this trait has no implementations, consider adding one
|
help: this trait has no implementations, consider adding one
|
||||||
--> $DIR/error.rs:6:1
|
--> $DIR/error.rs:6:1
|
||||||
|
16
tests/ui/dyn-star/float-as-dyn-star.rs
Normal file
16
tests/ui/dyn-star/float-as-dyn-star.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//@ only-x86_64
|
||||||
|
|
||||||
|
#![feature(dyn_star, pointer_like_trait)]
|
||||||
|
//~^ WARN the feature `dyn_star` is incomplete
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::marker::PointerLike;
|
||||||
|
|
||||||
|
fn make_dyn_star() -> dyn* Debug + 'static {
|
||||||
|
f32::from_bits(0x1) as f64
|
||||||
|
//~^ ERROR `f64` needs to have the same ABI as a pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("{:?}", make_dyn_star());
|
||||||
|
}
|
21
tests/ui/dyn-star/float-as-dyn-star.stderr
Normal file
21
tests/ui/dyn-star/float-as-dyn-star.stderr
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/float-as-dyn-star.rs:3:12
|
||||||
|
|
|
||||||
|
LL | #![feature(dyn_star, pointer_like_trait)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: `f64` needs to have the same ABI as a pointer
|
||||||
|
--> $DIR/float-as-dyn-star.rs:10:5
|
||||||
|
|
|
||||||
|
LL | f32::from_bits(0x1) as f64
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `f64` needs to be a pointer-like type
|
||||||
|
|
|
||||||
|
= help: the trait `PointerLike` is not implemented for `f64`
|
||||||
|
= help: the trait `PointerLike` is implemented for `usize`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
@ -7,6 +7,14 @@ LL | #![feature(dyn_star, trait_upcasting)]
|
|||||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: `W` needs to have the same ABI as a pointer
|
||||||
|
--> $DIR/upcast.rs:28:23
|
||||||
|
|
|
||||||
|
LL | let w: dyn* Foo = W(0);
|
||||||
|
| ^^^^ `W` needs to be a pointer-like type
|
||||||
|
|
|
||||||
|
= help: the trait `PointerLike` is not implemented for `W`
|
||||||
|
|
||||||
error[E0277]: `dyn* Foo` needs to have the same ABI as a pointer
|
error[E0277]: `dyn* Foo` needs to have the same ABI as a pointer
|
||||||
--> $DIR/upcast.rs:30:23
|
--> $DIR/upcast.rs:30:23
|
||||||
|
|
|
|
||||||
@ -15,6 +23,6 @@ LL | let w: dyn* Bar = w;
|
|||||||
|
|
|
|
||||||
= help: the trait `PointerLike` is not implemented for `dyn* Foo`
|
= help: the trait `PointerLike` is not implemented for `dyn* Foo`
|
||||||
|
|
||||||
error: aborting due to 1 previous error; 1 warning emitted
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
10
tests/ui/match/intended-binding-pattern-is-const.rs
Normal file
10
tests/ui/match/intended-binding-pattern-is-const.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
fn main() {
|
||||||
|
match 1 { //~ ERROR non-exhaustive patterns
|
||||||
|
//~^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
|
||||||
|
//~| the matched value is of type `i32`
|
||||||
|
x => {} //~ this pattern doesn't introduce a new catch-all binding
|
||||||
|
//~^ HELP ensure that all possible cases are being handled
|
||||||
|
//~| HELP if you meant to introduce a binding, use a different name
|
||||||
|
}
|
||||||
|
const x: i32 = 4; //~ NOTE constant `x` defined here
|
||||||
|
}
|
27
tests/ui/match/intended-binding-pattern-is-const.stderr
Normal file
27
tests/ui/match/intended-binding-pattern-is-const.stderr
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
error[E0004]: non-exhaustive patterns: `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
|
||||||
|
--> $DIR/intended-binding-pattern-is-const.rs:2:11
|
||||||
|
|
|
||||||
|
LL | match 1 {
|
||||||
|
| ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
|
||||||
|
...
|
||||||
|
LL | x => {}
|
||||||
|
| - this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `x`
|
||||||
|
|
|
||||||
|
= note: the matched value is of type `i32`
|
||||||
|
note: constant `x` defined here
|
||||||
|
--> $DIR/intended-binding-pattern-is-const.rs:9:5
|
||||||
|
|
|
||||||
|
LL | const x: i32 = 4;
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | x_var => {}
|
||||||
|
| ++++
|
||||||
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
||||||
|
LL | x => {}, i32::MIN..=3_i32 | 5_i32..=i32::MAX => todo!()
|
||||||
|
| ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0004`.
|
@ -1,30 +1,34 @@
|
|||||||
error[E0005]: refutable pattern in local binding
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/issue-112269.rs:3:9
|
--> $DIR/issue-112269.rs:3:9
|
||||||
|
|
|
|
||||||
|
LL | const x: i32 = 4;
|
||||||
|
| ------------ missing patterns are not covered because `x` is interpreted as a constant pattern, not a new variable
|
||||||
LL | let x: i32 = 3;
|
LL | let x: i32 = 3;
|
||||||
| ^
|
| ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
|
||||||
| |
|
|
||||||
| patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
|
|
||||||
| missing patterns are not covered because `x` is interpreted as a constant pattern, not a new variable
|
|
||||||
| help: introduce a variable instead: `x_var`
|
|
||||||
|
|
|
|
||||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
= note: the matched value is of type `i32`
|
= note: the matched value is of type `i32`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let x_var: i32 = 3;
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/issue-112269.rs:7:9
|
--> $DIR/issue-112269.rs:7:9
|
||||||
|
|
|
|
||||||
|
LL | const y: i32 = 3;
|
||||||
|
| ------------ missing patterns are not covered because `y` is interpreted as a constant pattern, not a new variable
|
||||||
LL | let y = 4;
|
LL | let y = 4;
|
||||||
| ^
|
| ^ patterns `i32::MIN..=2_i32` and `4_i32..=i32::MAX` not covered
|
||||||
| |
|
|
||||||
| patterns `i32::MIN..=2_i32` and `4_i32..=i32::MAX` not covered
|
|
||||||
| missing patterns are not covered because `y` is interpreted as a constant pattern, not a new variable
|
|
||||||
| help: introduce a variable instead: `y_var`
|
|
||||||
|
|
|
|
||||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
= note: the matched value is of type `i32`
|
= note: the matched value is of type `i32`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let y_var = 4;
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -3,8 +3,20 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered
|
|||||||
|
|
|
|
||||||
LL | match (true, false) {
|
LL | match (true, false) {
|
||||||
| ^^^^^^^^^^^^^ pattern `(true, false)` not covered
|
| ^^^^^^^^^^^^^ pattern `(true, false)` not covered
|
||||||
|
LL |
|
||||||
|
LL | TRUE_TRUE => (),
|
||||||
|
| --------- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `TRUE_TRUE`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `(bool, bool)`
|
= note: the matched value is of type `(bool, bool)`
|
||||||
|
note: constant `TRUE_TRUE` defined here
|
||||||
|
--> $DIR/match-arm-statics-2.rs:14:1
|
||||||
|
|
|
||||||
|
LL | const TRUE_TRUE: (bool, bool) = (true, true);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | TRUE_TRUE_var => (),
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||||
|
|
|
|
||||||
LL ~ (false, true) => (),
|
LL ~ (false, true) => (),
|
||||||
|
@ -199,8 +199,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
|||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
LL |
|
||||||
|
LL | CONST => {}
|
||||||
|
| ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
note: constant `CONST` defined here
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:88:5
|
||||||
|
|
|
||||||
|
LL | const CONST: &[bool] = &[true];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | CONST_var => {}
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
|
||||||
LL ~ CONST => {},
|
LL ~ CONST => {},
|
||||||
@ -212,8 +224,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
|||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
LL |
|
||||||
|
LL | CONST => {}
|
||||||
|
| ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
note: constant `CONST` defined here
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:88:5
|
||||||
|
|
|
||||||
|
LL | const CONST: &[bool] = &[true];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | CONST_var => {}
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
|
||||||
LL ~ &[false] => {},
|
LL ~ &[false] => {},
|
||||||
@ -225,8 +249,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
|||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
...
|
||||||
|
LL | CONST => {}
|
||||||
|
| ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
note: constant `CONST` defined here
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:88:5
|
||||||
|
|
|
||||||
|
LL | const CONST: &[bool] = &[true];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | CONST_var => {}
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
||||||
|
|
|
|
||||||
LL ~ CONST => {},
|
LL ~ CONST => {},
|
||||||
@ -238,8 +274,20 @@ error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
|
|||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[_, _, ..]` not covered
|
| ^ pattern `&[_, _, ..]` not covered
|
||||||
|
...
|
||||||
|
LL | CONST => {}
|
||||||
|
| ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
note: constant `CONST` defined here
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:88:5
|
||||||
|
|
|
||||||
|
LL | const CONST: &[bool] = &[true];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | CONST_var => {}
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||||
|
|
|
|
||||||
LL ~ CONST => {},
|
LL ~ CONST => {},
|
||||||
@ -251,8 +299,20 @@ error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
|||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[false]` not covered
|
| ^ pattern `&[false]` not covered
|
||||||
|
...
|
||||||
|
LL | CONST => {}
|
||||||
|
| ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
note: constant `CONST` defined here
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:88:5
|
||||||
|
|
|
||||||
|
LL | const CONST: &[bool] = &[true];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | CONST_var => {}
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||||
|
|
|
|
||||||
LL ~ &[_, _, ..] => {},
|
LL ~ &[_, _, ..] => {},
|
||||||
@ -264,8 +324,20 @@ error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
|||||||
|
|
|
|
||||||
LL | match s1 {
|
LL | match s1 {
|
||||||
| ^^ pattern `&[false]` not covered
|
| ^^ pattern `&[false]` not covered
|
||||||
|
LL |
|
||||||
|
LL | CONST1 => {}
|
||||||
|
| ------ this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST1`
|
||||||
|
|
|
|
||||||
= note: the matched value is of type `&[bool; 1]`
|
= note: the matched value is of type `&[bool; 1]`
|
||||||
|
note: constant `CONST1` defined here
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:124:5
|
||||||
|
|
|
||||||
|
LL | const CONST1: &[bool; 1] = &[true];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: if you meant to introduce a binding, use a different name
|
||||||
|
|
|
||||||
|
LL | CONST1_var => {}
|
||||||
|
| ++++
|
||||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||||
|
|
|
|
||||||
LL ~ CONST1 => {},
|
LL ~ CONST1 => {},
|
||||||
|
@ -2,9 +2,9 @@ fn main() {
|
|||||||
let A = 3;
|
let A = 3;
|
||||||
//~^ ERROR refutable pattern in local binding
|
//~^ ERROR refutable pattern in local binding
|
||||||
//~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
|
//~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
|
||||||
//~| missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable
|
|
||||||
//~| HELP introduce a variable instead
|
//~| HELP introduce a variable instead
|
||||||
//~| SUGGESTION A_var
|
//~| SUGGESTION A_var
|
||||||
|
|
||||||
const A: i32 = 2;
|
const A: i32 = 2;
|
||||||
|
//~^ missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,18 @@ error[E0005]: refutable pattern in local binding
|
|||||||
--> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9
|
--> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9
|
||||||
|
|
|
|
||||||
LL | let A = 3;
|
LL | let A = 3;
|
||||||
| ^
|
| ^ patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
|
||||||
| |
|
...
|
||||||
| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
|
LL | const A: i32 = 2;
|
||||||
| missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable
|
| ------------ missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable
|
||||||
| help: introduce a variable instead: `A_var`
|
|
||||||
|
|
|
|
||||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
= note: the matched value is of type `i32`
|
= note: the matched value is of type `i32`
|
||||||
|
help: introduce a variable instead
|
||||||
|
|
|
||||||
|
LL | let A_var = 3;
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user