@@ -270,20 +270,51 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
270270 "refutable pattern in {}: {} not covered" ,
271271 origin, joined_patterns
272272 ) ;
273- err . span_label ( pat . span , match & pat. kind {
273+ match & pat. kind {
274274 hir:: PatKind :: Path ( hir:: QPath :: Resolved ( None , path) )
275- if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) => {
276- format ! ( "interpreted as {} {} pattern, not new variable" ,
277- path . res . article ( ) , path. res . descr ( ) )
275+ if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) =>
276+ {
277+ const_not_var ( & mut err , cx . tcx , pat , path) ;
278278 }
279- _ => pattern_not_convered_label ( & witnesses, & joined_patterns) ,
280- } ) ;
279+ _ => {
280+ err. span_label (
281+ pat. span ,
282+ pattern_not_covered_label ( & witnesses, & joined_patterns) ,
283+ ) ;
284+ }
285+ }
286+
281287 adt_defined_here ( cx, & mut err, pattern_ty, & witnesses) ;
282288 err. emit ( ) ;
283289 } ) ;
284290 }
285291}
286292
293+ /// A path pattern was interpreted as a constant, not a new variable.
294+ /// This caused an irrefutable match failure in e.g. `let`.
295+ fn const_not_var ( err : & mut DiagnosticBuilder < ' _ > , tcx : TyCtxt < ' _ > , pat : & Pat , path : & hir:: Path ) {
296+ let descr = path. res . descr ( ) ;
297+ err. span_label ( pat. span , format ! (
298+ "interpreted as {} {} pattern, not a new variable" ,
299+ path. res. article( ) ,
300+ descr,
301+ ) ) ;
302+
303+ err. span_suggestion (
304+ pat. span ,
305+ "introduce a variable instead" ,
306+ format ! ( "{}_var" , path. segments[ 0 ] . ident) . to_lowercase ( ) ,
307+ // Cannot use `MachineApplicable` as it's not really *always* correct
308+ // because there may be such an identifier in scope or the user maybe
309+ // really wanted to match against the constant. This is quite unlikely however.
310+ Applicability :: MaybeIncorrect ,
311+ ) ;
312+
313+ if let Some ( span) = tcx. hir ( ) . res_span ( path. res ) {
314+ err. span_label ( span, format ! ( "{} defined here" , descr) ) ;
315+ }
316+ }
317+
287318fn check_for_bindings_named_same_as_variants ( cx : & MatchVisitor < ' _ , ' _ > , pat : & Pat ) {
288319 pat. walk ( |p| {
289320 if let hir:: PatKind :: Binding ( _, _, ident, None ) = p. kind {
@@ -449,7 +480,7 @@ fn check_exhaustive<'tcx>(
449480 cx. tcx . sess , sp,
450481 format ! ( "non-exhaustive patterns: {} not covered" , joined_patterns) ,
451482 ) ;
452- err. span_label ( sp, pattern_not_convered_label ( & witnesses, & joined_patterns) ) ;
483+ err. span_label ( sp, pattern_not_covered_label ( & witnesses, & joined_patterns) ) ;
453484 adt_defined_here ( cx, & mut err, scrut_ty, & witnesses) ;
454485 err. help (
455486 "ensure that all possible cases are being handled, \
@@ -475,7 +506,7 @@ fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
475506 }
476507}
477508
478- fn pattern_not_convered_label ( witnesses : & [ super :: Pat < ' _ > ] , joined_patterns : & str ) -> String {
509+ fn pattern_not_covered_label ( witnesses : & [ super :: Pat < ' _ > ] , joined_patterns : & str ) -> String {
479510 format ! ( "pattern{} {} not covered" , rustc_errors:: pluralise!( witnesses. len( ) ) , joined_patterns)
480511}
481512
0 commit comments