@@ -270,20 +270,51 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
270
270
"refutable pattern in {}: {} not covered" ,
271
271
origin, joined_patterns
272
272
) ;
273
- err . span_label ( pat . span , match & pat. kind {
273
+ match & pat. kind {
274
274
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) ;
278
278
}
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
+
281
287
adt_defined_here ( cx, & mut err, pattern_ty, & witnesses) ;
282
288
err. emit ( ) ;
283
289
} ) ;
284
290
}
285
291
}
286
292
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
+
287
318
fn check_for_bindings_named_same_as_variants ( cx : & MatchVisitor < ' _ , ' _ > , pat : & Pat ) {
288
319
pat. walk ( |p| {
289
320
if let hir:: PatKind :: Binding ( _, _, ident, None ) = p. kind {
@@ -449,7 +480,7 @@ fn check_exhaustive<'tcx>(
449
480
cx. tcx . sess , sp,
450
481
format ! ( "non-exhaustive patterns: {} not covered" , joined_patterns) ,
451
482
) ;
452
- err. span_label ( sp, pattern_not_convered_label ( & witnesses, & joined_patterns) ) ;
483
+ err. span_label ( sp, pattern_not_covered_label ( & witnesses, & joined_patterns) ) ;
453
484
adt_defined_here ( cx, & mut err, scrut_ty, & witnesses) ;
454
485
err. help (
455
486
"ensure that all possible cases are being handled, \
@@ -475,7 +506,7 @@ fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
475
506
}
476
507
}
477
508
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 {
479
510
format ! ( "pattern{} {} not covered" , rustc_errors:: pluralise!( witnesses. len( ) ) , joined_patterns)
480
511
}
481
512
0 commit comments