@@ -10,6 +10,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
1010use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
1111use rustc_hir:: { HirId , Pat , PatKind } ;
1212use rustc_infer:: infer;
13+ use rustc_infer:: infer:: error_reporting:: same_type_modulo_infer;
1314use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
1415use rustc_middle:: middle:: stability:: EvalResult ;
1516use rustc_middle:: ty:: { self , Adt , BindingMode , Ty , TypeFoldable } ;
@@ -1258,7 +1259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12581259 self . field_ty ( span, f, substs)
12591260 } )
12601261 . unwrap_or_else ( || {
1261- inexistent_fields. push ( field. ident ) ;
1262+ inexistent_fields. push ( field) ;
12621263 no_field_errors = false ;
12631264 tcx. ty_error ( )
12641265 } )
@@ -1276,13 +1277,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12761277 . collect :: < Vec < _ > > ( ) ;
12771278
12781279 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 )
12801281 {
12811282 Some ( self . error_inexistent_fields (
12821283 adt. variant_descr ( ) ,
12831284 & inexistent_fields,
12841285 & mut unmentioned_fields,
12851286 variant,
1287+ substs,
12861288 ) )
12871289 } else {
12881290 None
@@ -1448,28 +1450,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14481450 fn error_inexistent_fields (
14491451 & self ,
14501452 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 ) > ,
14531455 variant : & ty:: VariantDef ,
1456+ substs : & ' tcx ty:: List < ty:: subst:: GenericArg < ' tcx > > ,
14541457 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
14551458 let tcx = self . tcx ;
14561459 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" , "" )
14581461 } else {
14591462 (
14601463 format ! (
14611464 "fields named {}" ,
14621465 inexistent_fields
14631466 . iter( )
1464- . map( |ident | format!( "`{}`" , ident) )
1467+ . map( |field | format!( "`{}`" , field . ident) )
14651468 . collect:: <Vec <String >>( )
14661469 . join( ", " )
14671470 ) ,
14681471 "these" ,
14691472 "s" ,
14701473 )
14711474 } ;
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 < _ > > ( ) ;
14731476 let mut err = struct_span_err ! (
14741477 tcx. sess,
14751478 spans,
@@ -1479,9 +1482,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14791482 tcx. def_path_str( variant. def_id) ,
14801483 field_names
14811484 ) ;
1482- if let Some ( ident ) = inexistent_fields. last ( ) {
1485+ if let Some ( pat_field ) = inexistent_fields. last ( ) {
14831486 err. span_label (
1484- ident. span ,
1487+ pat_field . ident . span ,
14851488 format ! (
14861489 "{} `{}` does not have {} field{}" ,
14871490 kind_name,
@@ -1494,10 +1497,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14941497 if unmentioned_fields. len ( ) == 1 {
14951498 let input =
14961499 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 ) ;
14981501 if let Some ( suggested_name) = suggested_name {
14991502 err. span_suggestion (
1500- ident. span ,
1503+ pat_field . ident . span ,
15011504 "a field with a similar name exists" ,
15021505 suggested_name. to_string ( ) ,
15031506 Applicability :: MaybeIncorrect ,
@@ -1513,17 +1516,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15131516 unmentioned_fields. retain ( |& ( _, x) | x. name != suggested_name) ;
15141517 }
15151518 } 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+ }
15271543 }
15281544 }
15291545 }
0 commit comments