Point at const
definition when used instead of a binding in a let
statement
After: ``` error[E0005]: refutable pattern in local binding --> $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; | ^^^ | | | pattern `1_u32..=u32::MAX` not covered | 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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u32` ``` Before: ``` error[E0005]: refutable pattern in local binding --> $DIR/bad-pattern.rs:19:13 | LL | let PAT = v1; | ^^^ | | | 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: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u32` ```
This commit is contained in:
parent
917a50a039
commit
ff2f7a7a83
18 changed files with 78 additions and 28 deletions
|
@ -144,7 +144,9 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
|
|||
let mut targets = Vec::new();
|
||||
for arm in rest {
|
||||
let arm = &self.thir[*arm];
|
||||
let PatKind::Constant { value } = arm.pattern.kind else {
|
||||
let (PatKind::Constant { value } | PatKind::NamedConstant { value, span: _ }) =
|
||||
arm.pattern.kind
|
||||
else {
|
||||
return Err(ParseError {
|
||||
span: arm.pattern.span,
|
||||
item_description: format!("{:?}", arm.pattern.kind),
|
||||
|
|
|
@ -129,7 +129,9 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
PatKind::Constant { value } => TestCase::Constant { value },
|
||||
PatKind::Constant { value } | PatKind::NamedConstant { value, span: _ } => {
|
||||
TestCase::Constant { value }
|
||||
}
|
||||
|
||||
PatKind::AscribeUserType {
|
||||
ascription: thir::Ascription { ref annotation, variance },
|
||||
|
|
|
@ -882,6 +882,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
PatKind::Constant { .. }
|
||||
| PatKind::NamedConstant { .. }
|
||||
| PatKind::Range { .. }
|
||||
| PatKind::Wild
|
||||
| PatKind::Never
|
||||
|
|
|
@ -316,6 +316,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
PatKind::Binding { .. }
|
||||
// match is conditional on having this value
|
||||
| PatKind::Constant { .. }
|
||||
| PatKind::NamedConstant { .. }
|
||||
| PatKind::Variant { .. }
|
||||
| PatKind::Leaf { .. }
|
||||
| PatKind::Deref { .. }
|
||||
|
|
|
@ -860,8 +860,10 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
|
|||
pub(crate) uncovered: Uncovered,
|
||||
#[subdiagnostic]
|
||||
pub(crate) inform: Option<Inform>,
|
||||
#[label(mir_build_confused)]
|
||||
pub(crate) interpreted_as_const: Option<Span>,
|
||||
#[subdiagnostic]
|
||||
pub(crate) interpreted_as_const: Option<InterpretedAsConst>,
|
||||
pub(crate) interpreted_as_const_sugg: Option<InterpretedAsConst>,
|
||||
#[subdiagnostic]
|
||||
pub(crate) adt_defined_here: Option<AdtDefinedHere<'tcx>>,
|
||||
#[note(mir_build_privately_uninhabited)]
|
||||
|
@ -913,7 +915,6 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
|
|||
code = "{variable}_var",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
#[label(mir_build_confused)]
|
||||
pub(crate) struct InterpretedAsConst {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
|
|
|
@ -668,8 +668,20 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
let mut let_suggestion = None;
|
||||
let mut misc_suggestion = None;
|
||||
let mut interpreted_as_const = None;
|
||||
let mut interpreted_as_const_sugg = None;
|
||||
|
||||
if let PatKind::Constant { .. }
|
||||
if let PatKind::NamedConstant { span, .. }
|
||||
| PatKind::AscribeUserType {
|
||||
subpattern: box Pat { kind: PatKind::NamedConstant { span, .. }, .. },
|
||||
..
|
||||
} = pat.kind
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
|
||||
{
|
||||
// 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: snippet });
|
||||
} else if let PatKind::Constant { .. }
|
||||
| PatKind::AscribeUserType {
|
||||
subpattern: box Pat { kind: PatKind::Constant { .. }, .. },
|
||||
..
|
||||
|
@ -683,7 +695,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
start_span: pat.span.shrink_to_lo(),
|
||||
});
|
||||
} else if snippet.chars().all(|c| c.is_alphanumeric() || c == '_') {
|
||||
interpreted_as_const =
|
||||
interpreted_as_const = Some(pat.span);
|
||||
interpreted_as_const_sugg =
|
||||
Some(InterpretedAsConst { span: pat.span, variable: snippet });
|
||||
}
|
||||
}
|
||||
|
@ -733,6 +746,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
uncovered: Uncovered::new(pat.span, &cx, witnesses),
|
||||
inform,
|
||||
interpreted_as_const,
|
||||
interpreted_as_const_sugg,
|
||||
witness_1_is_privately_uninhabited,
|
||||
_p: (),
|
||||
pattern_ty,
|
||||
|
|
|
@ -157,7 +157,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
}
|
||||
kind => (kind, None, None),
|
||||
};
|
||||
let value = if let PatKind::Constant { value } = kind {
|
||||
let value = if let PatKind::Constant { value }
|
||||
| PatKind::NamedConstant { value, span: _ } = kind
|
||||
{
|
||||
value
|
||||
} else {
|
||||
let msg = format!(
|
||||
|
@ -560,9 +562,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
_ => return pat_from_kind(self.lower_variant_or_leaf(res, id, span, ty, vec![])),
|
||||
};
|
||||
|
||||
// HERE
|
||||
let args = self.typeck_results.node_args(id);
|
||||
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 def_span = self.tcx.def_span(def_id);
|
||||
let mut pattern = self.const_to_pat(c, ty, id, span);
|
||||
if let PatKind::Constant { value } = pattern.kind {
|
||||
pattern.kind = PatKind::NamedConstant { value, span: def_span };
|
||||
}
|
||||
tracing::info!("pattern {pattern:#?} {c:?} {ty:?} {id:?}");
|
||||
|
||||
if !is_associated_const {
|
||||
return pattern;
|
||||
|
|
|
@ -702,7 +702,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
self.print_pat(subpattern, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::Constant { value } => {
|
||||
PatKind::Constant { value } | PatKind::NamedConstant { value, span: _ } => {
|
||||
print_indented!(self, "Constant {", depth_lvl + 1);
|
||||
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue