@@ -3070,7 +3070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3070
3070
"ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}" ,
3071
3071
ident, base, expr, base_ty
3072
3072
) ;
3073
- let mut err = self . no_such_field_err ( ident, base_ty, base . hir_id ) ;
3073
+ let mut err = self . no_such_field_err ( ident, base_ty, expr ) ;
3074
3074
3075
3075
match * base_ty. peel_refs ( ) . kind ( ) {
3076
3076
ty:: Array ( _, len) => {
@@ -3283,32 +3283,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3283
3283
) ;
3284
3284
}
3285
3285
3286
- fn no_such_field_err ( & self , field : Ident , expr_t : Ty < ' tcx > , id : HirId ) -> Diag < ' _ > {
3286
+ fn no_such_field_err (
3287
+ & self ,
3288
+ field : Ident ,
3289
+ base_ty : Ty < ' tcx > ,
3290
+ expr : & hir:: Expr < ' tcx > ,
3291
+ ) -> Diag < ' _ > {
3287
3292
let span = field. span ;
3288
- debug ! ( "no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})" , span, field, expr_t ) ;
3293
+ debug ! ( "no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})" , span, field, base_ty ) ;
3289
3294
3290
3295
let mut err = type_error_struct ! (
3291
3296
self . dcx( ) ,
3292
3297
span,
3293
- expr_t ,
3298
+ base_ty ,
3294
3299
E0609 ,
3295
- "no field `{field}` on type `{expr_t }`" ,
3300
+ "no field `{field}` on type `{base_ty }`" ,
3296
3301
) ;
3302
+ if let Some ( within_macro_span) = span. within_macro ( expr. span , self . tcx . sess . source_map ( ) ) {
3303
+ err. span_label ( within_macro_span, "due to this macro variable" ) ;
3304
+ }
3297
3305
3298
3306
// try to add a suggestion in case the field is a nested field of a field of the Adt
3299
- let mod_id = self . tcx . parent_module ( id ) . to_def_id ( ) ;
3300
- let ( ty, unwrap) = if let ty:: Adt ( def, args) = expr_t . kind ( )
3307
+ let mod_id = self . tcx . parent_module ( expr . hir_id ) . to_def_id ( ) ;
3308
+ let ( ty, unwrap) = if let ty:: Adt ( def, args) = base_ty . kind ( )
3301
3309
&& ( self . tcx . is_diagnostic_item ( sym:: Result , def. did ( ) )
3302
3310
|| self . tcx . is_diagnostic_item ( sym:: Option , def. did ( ) ) )
3303
3311
&& let Some ( arg) = args. get ( 0 )
3304
3312
&& let Some ( ty) = arg. as_type ( )
3305
3313
{
3306
3314
( ty, "unwrap()." )
3307
3315
} else {
3308
- ( expr_t , "" )
3316
+ ( base_ty , "" )
3309
3317
} ;
3310
3318
for ( found_fields, args) in
3311
- self . get_field_candidates_considering_privacy_for_diag ( span, ty, mod_id, id )
3319
+ self . get_field_candidates_considering_privacy_for_diag ( span, ty, mod_id, expr . hir_id )
3312
3320
{
3313
3321
let field_names = found_fields. iter ( ) . map ( |field| field. name ) . collect :: < Vec < _ > > ( ) ;
3314
3322
let mut candidate_fields: Vec < _ > = found_fields
@@ -3321,7 +3329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3321
3329
args,
3322
3330
vec ! [ ] ,
3323
3331
mod_id,
3324
- id ,
3332
+ expr . hir_id ,
3325
3333
)
3326
3334
} )
3327
3335
. map ( |mut field_path| {
@@ -3332,7 +3340,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3332
3340
candidate_fields. sort ( ) ;
3333
3341
3334
3342
let len = candidate_fields. len ( ) ;
3335
- if len > 0 {
3343
+ // Don't suggest `.field` if the base expr is from a different
3344
+ // syntax context than the field.
3345
+ if len > 0 && expr. span . eq_ctxt ( field. span ) {
3336
3346
err. span_suggestions (
3337
3347
field. span . shrink_to_lo ( ) ,
3338
3348
format ! (
@@ -3968,7 +3978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3968
3978
_ => ( ) ,
3969
3979
} ;
3970
3980
3971
- self . no_such_field_err ( field, container, expr. hir_id ) . emit ( ) ;
3981
+ self . no_such_field_err ( field, container, expr) . emit ( ) ;
3972
3982
3973
3983
break ;
3974
3984
}
0 commit comments