@@ -552,71 +552,7 @@ impl<'a> InferenceContext<'a> {
552552 }
553553 ty
554554 }
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) ,
620556 Expr :: Await { expr } => {
621557 let inner_ty = self . infer_expr_inner ( * expr, & Expectation :: none ( ) ) ;
622558 self . resolve_associated_type ( inner_ty, self . resolve_future_future_output ( ) )
@@ -1276,6 +1212,92 @@ impl<'a> InferenceContext<'a> {
12761212 }
12771213 }
12781214
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+
12791301 fn infer_method_call (
12801302 & mut self ,
12811303 tgt_expr : ExprId ,
0 commit comments