@@ -552,71 +552,7 @@ impl<'a> InferenceContext<'a> {
552
552
}
553
553
ty
554
554
}
555
- Expr :: Field { expr, name } => {
556
- let receiver_ty = self . infer_expr_inner ( * expr, & Expectation :: none ( ) ) ;
557
-
558
- let mut autoderef = Autoderef :: new ( & mut self . table , receiver_ty) ;
559
- let mut private_field = None ;
560
- let ty = autoderef. by_ref ( ) . find_map ( |( derefed_ty, _) | {
561
- let ( field_id, parameters) = match derefed_ty. kind ( Interner ) {
562
- TyKind :: Tuple ( _, substs) => {
563
- return name. as_tuple_index ( ) . and_then ( |idx| {
564
- substs
565
- . as_slice ( Interner )
566
- . get ( idx)
567
- . map ( |a| a. assert_ty_ref ( Interner ) )
568
- . cloned ( )
569
- } ) ;
570
- }
571
- TyKind :: Adt ( AdtId ( hir_def:: AdtId :: StructId ( s) ) , parameters) => {
572
- let local_id = self . db . struct_data ( * s) . variant_data . field ( name) ?;
573
- let field = FieldId { parent : ( * s) . into ( ) , local_id } ;
574
- ( field, parameters. clone ( ) )
575
- }
576
- TyKind :: Adt ( AdtId ( hir_def:: AdtId :: UnionId ( u) ) , parameters) => {
577
- let local_id = self . db . union_data ( * u) . variant_data . field ( name) ?;
578
- let field = FieldId { parent : ( * u) . into ( ) , local_id } ;
579
- ( field, parameters. clone ( ) )
580
- }
581
- _ => return None ,
582
- } ;
583
- let is_visible = self . db . field_visibilities ( field_id. parent ) [ field_id. local_id ]
584
- . is_visible_from ( self . db . upcast ( ) , self . resolver . module ( ) ) ;
585
- if !is_visible {
586
- if private_field. is_none ( ) {
587
- private_field = Some ( field_id) ;
588
- }
589
- return None ;
590
- }
591
- // can't have `write_field_resolution` here because `self.table` is borrowed :(
592
- self . result . field_resolutions . insert ( tgt_expr, field_id) ;
593
- let ty = self . db . field_types ( field_id. parent ) [ field_id. local_id ]
594
- . clone ( )
595
- . substitute ( Interner , & parameters) ;
596
- Some ( ty)
597
- } ) ;
598
- let ty = match ty {
599
- Some ( ty) => {
600
- let adjustments = auto_deref_adjust_steps ( & autoderef) ;
601
- self . write_expr_adj ( * expr, adjustments) ;
602
- let ty = self . insert_type_vars ( ty) ;
603
- let ty = self . normalize_associated_types_in ( ty) ;
604
- ty
605
- }
606
- _ => {
607
- // Write down the first private field resolution if we found no field
608
- // This aids IDE features for private fields like goto def
609
- if let Some ( field) = private_field {
610
- self . result . field_resolutions . insert ( tgt_expr, field) ;
611
- self . result
612
- . diagnostics
613
- . push ( InferenceDiagnostic :: PrivateField { expr : tgt_expr, field } ) ;
614
- }
615
- self . err_ty ( )
616
- }
617
- } ;
618
- ty
619
- }
555
+ Expr :: Field { expr, name } => self . infer_field_access ( tgt_expr, * expr, name) ,
620
556
Expr :: Await { expr } => {
621
557
let inner_ty = self . infer_expr_inner ( * expr, & Expectation :: none ( ) ) ;
622
558
self . resolve_associated_type ( inner_ty, self . resolve_future_future_output ( ) )
@@ -1276,6 +1212,92 @@ impl<'a> InferenceContext<'a> {
1276
1212
}
1277
1213
}
1278
1214
1215
+ fn infer_field_access ( & mut self , tgt_expr : ExprId , expr : ExprId , name : & Name ) -> Ty {
1216
+ let receiver_ty = self . infer_expr_inner ( expr, & Expectation :: none ( ) ) ;
1217
+
1218
+ let mut autoderef = Autoderef :: new ( & mut self . table , receiver_ty. clone ( ) ) ;
1219
+ let mut private_field = None ;
1220
+ let ty = autoderef. by_ref ( ) . find_map ( |( derefed_ty, _) | {
1221
+ let ( field_id, parameters) = match derefed_ty. kind ( Interner ) {
1222
+ TyKind :: Tuple ( _, substs) => {
1223
+ return name. as_tuple_index ( ) . and_then ( |idx| {
1224
+ substs
1225
+ . as_slice ( Interner )
1226
+ . get ( idx)
1227
+ . map ( |a| a. assert_ty_ref ( Interner ) )
1228
+ . cloned ( )
1229
+ } ) ;
1230
+ }
1231
+ TyKind :: Adt ( AdtId ( hir_def:: AdtId :: StructId ( s) ) , parameters) => {
1232
+ let local_id = self . db . struct_data ( * s) . variant_data . field ( name) ?;
1233
+ let field = FieldId { parent : ( * s) . into ( ) , local_id } ;
1234
+ ( field, parameters. clone ( ) )
1235
+ }
1236
+ TyKind :: Adt ( AdtId ( hir_def:: AdtId :: UnionId ( u) ) , parameters) => {
1237
+ let local_id = self . db . union_data ( * u) . variant_data . field ( name) ?;
1238
+ let field = FieldId { parent : ( * u) . into ( ) , local_id } ;
1239
+ ( field, parameters. clone ( ) )
1240
+ }
1241
+ _ => return None ,
1242
+ } ;
1243
+ let is_visible = self . db . field_visibilities ( field_id. parent ) [ field_id. local_id ]
1244
+ . is_visible_from ( self . db . upcast ( ) , self . resolver . module ( ) ) ;
1245
+ if !is_visible {
1246
+ if private_field. is_none ( ) {
1247
+ private_field = Some ( field_id) ;
1248
+ }
1249
+ return None ;
1250
+ }
1251
+ // can't have `write_field_resolution` here because `self.table` is borrowed :(
1252
+ self . result . field_resolutions . insert ( tgt_expr, field_id) ;
1253
+ let ty = self . db . field_types ( field_id. parent ) [ field_id. local_id ]
1254
+ . clone ( )
1255
+ . substitute ( Interner , & parameters) ;
1256
+ Some ( ty)
1257
+ } ) ;
1258
+ let ty = match ty {
1259
+ Some ( ty) => {
1260
+ let adjustments = auto_deref_adjust_steps ( & autoderef) ;
1261
+ self . write_expr_adj ( expr, adjustments) ;
1262
+ let ty = self . insert_type_vars ( ty) ;
1263
+ let ty = self . normalize_associated_types_in ( ty) ;
1264
+ ty
1265
+ }
1266
+ _ => {
1267
+ // Write down the first private field resolution if we found no field
1268
+ // This aids IDE features for private fields like goto def
1269
+ if let Some ( field) = private_field {
1270
+ self . result . field_resolutions . insert ( tgt_expr, field) ;
1271
+ // FIXME: Merge this diagnostic into UnresolvedField
1272
+ self . result
1273
+ . diagnostics
1274
+ . push ( InferenceDiagnostic :: PrivateField { expr : tgt_expr, field } ) ;
1275
+ } else {
1276
+ // no field found, try looking for a method of the same name
1277
+ let canonicalized_receiver = self . canonicalize ( receiver_ty. clone ( ) ) ;
1278
+ let traits_in_scope = self . resolver . traits_in_scope ( self . db . upcast ( ) ) ;
1279
+
1280
+ let resolved = method_resolution:: lookup_method (
1281
+ self . db ,
1282
+ & canonicalized_receiver. value ,
1283
+ self . trait_env . clone ( ) ,
1284
+ & traits_in_scope,
1285
+ VisibleFromModule :: Filter ( self . resolver . module ( ) ) ,
1286
+ name,
1287
+ ) ;
1288
+ self . result . diagnostics . push ( InferenceDiagnostic :: UnresolvedField {
1289
+ expr : tgt_expr,
1290
+ receiver : receiver_ty,
1291
+ name : name. clone ( ) ,
1292
+ method_with_same_name_exists : resolved. is_some ( ) ,
1293
+ } ) ;
1294
+ }
1295
+ self . err_ty ( )
1296
+ }
1297
+ } ;
1298
+ ty
1299
+ }
1300
+
1279
1301
fn infer_method_call (
1280
1302
& mut self ,
1281
1303
tgt_expr : ExprId ,
0 commit comments