@@ -10,6 +10,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
10
10
use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
11
11
use rustc_hir:: { HirId , Pat , PatKind } ;
12
12
use rustc_infer:: infer;
13
+ use rustc_infer:: infer:: error_reporting:: same_type_modulo_infer;
13
14
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
14
15
use rustc_middle:: middle:: stability:: EvalResult ;
15
16
use rustc_middle:: ty:: { self , Adt , BindingMode , Ty , TypeFoldable } ;
@@ -1258,7 +1259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1258
1259
self . field_ty ( span, f, substs)
1259
1260
} )
1260
1261
. unwrap_or_else ( || {
1261
- inexistent_fields. push ( field. ident ) ;
1262
+ inexistent_fields. push ( field) ;
1262
1263
no_field_errors = false ;
1263
1264
tcx. ty_error ( )
1264
1265
} )
@@ -1276,13 +1277,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1276
1277
. collect :: < Vec < _ > > ( ) ;
1277
1278
1278
1279
let inexistent_fields_err = if !( inexistent_fields. is_empty ( ) || variant. is_recovered ( ) )
1279
- && !inexistent_fields. iter ( ) . any ( |field| field. name == kw:: Underscore )
1280
+ && !inexistent_fields. iter ( ) . any ( |field| field. ident . name == kw:: Underscore )
1280
1281
{
1281
1282
Some ( self . error_inexistent_fields (
1282
1283
adt. variant_descr ( ) ,
1283
1284
& inexistent_fields,
1284
1285
& mut unmentioned_fields,
1285
1286
variant,
1287
+ substs,
1286
1288
) )
1287
1289
} else {
1288
1290
None
@@ -1448,28 +1450,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1448
1450
fn error_inexistent_fields (
1449
1451
& self ,
1450
1452
kind_name : & str ,
1451
- inexistent_fields : & [ Ident ] ,
1452
- unmentioned_fields : & mut Vec < ( & ty:: FieldDef , Ident ) > ,
1453
+ inexistent_fields : & [ & hir :: PatField < ' tcx > ] ,
1454
+ unmentioned_fields : & mut Vec < ( & ' tcx ty:: FieldDef , Ident ) > ,
1453
1455
variant : & ty:: VariantDef ,
1456
+ substs : & ' tcx ty:: List < ty:: subst:: GenericArg < ' tcx > > ,
1454
1457
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
1455
1458
let tcx = self . tcx ;
1456
1459
let ( field_names, t, plural) = if inexistent_fields. len ( ) == 1 {
1457
- ( format ! ( "a field named `{}`" , inexistent_fields[ 0 ] ) , "this" , "" )
1460
+ ( format ! ( "a field named `{}`" , inexistent_fields[ 0 ] . ident ) , "this" , "" )
1458
1461
} else {
1459
1462
(
1460
1463
format ! (
1461
1464
"fields named {}" ,
1462
1465
inexistent_fields
1463
1466
. iter( )
1464
- . map( |ident | format!( "`{}`" , ident) )
1467
+ . map( |field | format!( "`{}`" , field . ident) )
1465
1468
. collect:: <Vec <String >>( )
1466
1469
. join( ", " )
1467
1470
) ,
1468
1471
"these" ,
1469
1472
"s" ,
1470
1473
)
1471
1474
} ;
1472
- let spans = inexistent_fields. iter ( ) . map ( |ident| ident. span ) . collect :: < Vec < _ > > ( ) ;
1475
+ let spans = inexistent_fields. iter ( ) . map ( |field| field . ident . span ) . collect :: < Vec < _ > > ( ) ;
1473
1476
let mut err = struct_span_err ! (
1474
1477
tcx. sess,
1475
1478
spans,
@@ -1479,9 +1482,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1479
1482
tcx. def_path_str( variant. def_id) ,
1480
1483
field_names
1481
1484
) ;
1482
- if let Some ( ident ) = inexistent_fields. last ( ) {
1485
+ if let Some ( pat_field ) = inexistent_fields. last ( ) {
1483
1486
err. span_label (
1484
- ident. span ,
1487
+ pat_field . ident . span ,
1485
1488
format ! (
1486
1489
"{} `{}` does not have {} field{}" ,
1487
1490
kind_name,
@@ -1494,10 +1497,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1494
1497
if unmentioned_fields. len ( ) == 1 {
1495
1498
let input =
1496
1499
unmentioned_fields. iter ( ) . map ( |( _, field) | field. name ) . collect :: < Vec < _ > > ( ) ;
1497
- let suggested_name = find_best_match_for_name ( & input, ident. name , None ) ;
1500
+ let suggested_name = find_best_match_for_name ( & input, pat_field . ident . name , None ) ;
1498
1501
if let Some ( suggested_name) = suggested_name {
1499
1502
err. span_suggestion (
1500
- ident. span ,
1503
+ pat_field . ident . span ,
1501
1504
"a field with a similar name exists" ,
1502
1505
suggested_name. to_string ( ) ,
1503
1506
Applicability :: MaybeIncorrect ,
@@ -1513,17 +1516,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1513
1516
unmentioned_fields. retain ( |& ( _, x) | x. name != suggested_name) ;
1514
1517
}
1515
1518
} else if inexistent_fields. len ( ) == 1 {
1516
- let unmentioned_field = unmentioned_fields[ 0 ] . 1 . name ;
1517
- err. span_suggestion_short (
1518
- ident. span ,
1519
- & format ! (
1520
- "`{}` has a field named `{}`" ,
1521
- tcx. def_path_str( variant. def_id) ,
1522
- unmentioned_field
1523
- ) ,
1524
- unmentioned_field. to_string ( ) ,
1525
- Applicability :: MaybeIncorrect ,
1526
- ) ;
1519
+ match pat_field. pat . kind {
1520
+ PatKind :: Lit ( expr)
1521
+ if !same_type_modulo_infer (
1522
+ self . typeck_results . borrow ( ) . expr_ty ( expr) ,
1523
+ self . field_ty (
1524
+ unmentioned_fields[ 0 ] . 1 . span ,
1525
+ unmentioned_fields[ 0 ] . 0 ,
1526
+ substs,
1527
+ ) ,
1528
+ ) => { }
1529
+ _ => {
1530
+ let unmentioned_field = unmentioned_fields[ 0 ] . 1 . name ;
1531
+ err. span_suggestion_short (
1532
+ pat_field. ident . span ,
1533
+ & format ! (
1534
+ "`{}` has a field named `{}`" ,
1535
+ tcx. def_path_str( variant. def_id) ,
1536
+ unmentioned_field
1537
+ ) ,
1538
+ unmentioned_field. to_string ( ) ,
1539
+ Applicability :: MaybeIncorrect ,
1540
+ ) ;
1541
+ }
1542
+ }
1527
1543
}
1528
1544
}
1529
1545
}
0 commit comments