-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Point at const
definition when used instead of a binding in a let
statement
#132708
Changes from all commits
ff2f7a7
c25b44b
6dc79f6
a5b4d45
f563efe
f1772d5
bb37e5d
6480b76
912ee65
29acf8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -332,7 +332,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | |
PatKind::Wild | | ||
// these just wrap other patterns, which we recurse on below. | ||
PatKind::Or { .. } | | ||
PatKind::InlineConstant { .. } | | ||
PatKind::ExpandedConstant { .. } | | ||
PatKind::AscribeUserType { .. } | | ||
PatKind::Error(_) => {} | ||
} | ||
|
@@ -386,8 +386,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | |
visit::walk_pat(self, pat); | ||
self.inside_adt = old_inside_adt; | ||
} | ||
PatKind::InlineConstant { def, .. } => { | ||
self.visit_inner_body(*def); | ||
PatKind::ExpandedConstant { def_id, is_inline, .. } => { | ||
if let Some(def) = def_id.as_local() | ||
&& *is_inline | ||
{ | ||
self.visit_inner_body(def); | ||
} | ||
Comment on lines
+389
to
+394
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...and here are the two places where |
||
visit::walk_pat(self, pat); | ||
} | ||
_ => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -668,8 +668,25 @@ 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::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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, you read my mind with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Specifically, this pat name will not possibly be tied to arbitrary source code, in |
||
// 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 { | ||
subpattern: box Pat { kind: PatKind::Constant { .. }, .. }, | ||
.. | ||
Nadrieril marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
@@ -682,9 +699,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { | |
misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral { | ||
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 }); | ||
} | ||
} | ||
|
||
|
@@ -733,6 +747,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, | ||
|
@@ -1102,13 +1117,13 @@ fn report_non_exhaustive_match<'p, 'tcx>( | |
if ty.is_ptr_sized_integral() { | ||
if ty.inner() == cx.tcx.types.usize { | ||
err.note(format!( | ||
"`{ty}` does not have a fixed maximum value, so half-open ranges are necessary to match \ | ||
exhaustively", | ||
"`{ty}` does not have a fixed maximum value, so half-open ranges are \ | ||
necessary to match exhaustively", | ||
)); | ||
} else if ty.inner() == cx.tcx.types.isize { | ||
err.note(format!( | ||
"`{ty}` does not have fixed minimum and maximum values, so half-open ranges are necessary to match \ | ||
exhaustively", | ||
"`{ty}` does not have fixed minimum and maximum values, so half-open \ | ||
ranges are necessary to match exhaustively", | ||
)); | ||
} | ||
} else if ty.inner() == cx.tcx.types.str_ { | ||
|
@@ -1129,6 +1144,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 `_`. | ||
let suggest_the_witnesses = witnesses.len() < 4; | ||
let suggested_arm = if suggest_the_witnesses { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here...