@@ -364,7 +364,13 @@ impl<'a> InferenceContext<'a> {
364364 }
365365 ( params, ret_ty)
366366 }
367- None => ( Vec :: new ( ) , self . err_ty ( ) ) , // FIXME diagnostic
367+ None => {
368+ self . result . diagnostics . push ( InferenceDiagnostic :: ExpectedFunction {
369+ call_expr : tgt_expr,
370+ found : callee_ty. clone ( ) ,
371+ } ) ;
372+ ( Vec :: new ( ) , self . err_ty ( ) )
373+ }
368374 } ;
369375 let indices_to_skip = self . check_legacy_const_generics ( derefed_callee, args) ;
370376 self . register_obligations_for_call ( & callee_ty) ;
@@ -546,71 +552,7 @@ impl<'a> InferenceContext<'a> {
546552 }
547553 ty
548554 }
549- Expr :: Field { expr, name } => {
550- let receiver_ty = self . infer_expr_inner ( * expr, & Expectation :: none ( ) ) ;
551-
552- let mut autoderef = Autoderef :: new ( & mut self . table , receiver_ty) ;
553- let mut private_field = None ;
554- let ty = autoderef. by_ref ( ) . find_map ( |( derefed_ty, _) | {
555- let ( field_id, parameters) = match derefed_ty. kind ( Interner ) {
556- TyKind :: Tuple ( _, substs) => {
557- return name. as_tuple_index ( ) . and_then ( |idx| {
558- substs
559- . as_slice ( Interner )
560- . get ( idx)
561- . map ( |a| a. assert_ty_ref ( Interner ) )
562- . cloned ( )
563- } ) ;
564- }
565- TyKind :: Adt ( AdtId ( hir_def:: AdtId :: StructId ( s) ) , parameters) => {
566- let local_id = self . db . struct_data ( * s) . variant_data . field ( name) ?;
567- let field = FieldId { parent : ( * s) . into ( ) , local_id } ;
568- ( field, parameters. clone ( ) )
569- }
570- TyKind :: Adt ( AdtId ( hir_def:: AdtId :: UnionId ( u) ) , parameters) => {
571- let local_id = self . db . union_data ( * u) . variant_data . field ( name) ?;
572- let field = FieldId { parent : ( * u) . into ( ) , local_id } ;
573- ( field, parameters. clone ( ) )
574- }
575- _ => return None ,
576- } ;
577- let is_visible = self . db . field_visibilities ( field_id. parent ) [ field_id. local_id ]
578- . is_visible_from ( self . db . upcast ( ) , self . resolver . module ( ) ) ;
579- if !is_visible {
580- if private_field. is_none ( ) {
581- private_field = Some ( field_id) ;
582- }
583- return None ;
584- }
585- // can't have `write_field_resolution` here because `self.table` is borrowed :(
586- self . result . field_resolutions . insert ( tgt_expr, field_id) ;
587- let ty = self . db . field_types ( field_id. parent ) [ field_id. local_id ]
588- . clone ( )
589- . substitute ( Interner , & parameters) ;
590- Some ( ty)
591- } ) ;
592- let ty = match ty {
593- Some ( ty) => {
594- let adjustments = auto_deref_adjust_steps ( & autoderef) ;
595- self . write_expr_adj ( * expr, adjustments) ;
596- let ty = self . insert_type_vars ( ty) ;
597- let ty = self . normalize_associated_types_in ( ty) ;
598- ty
599- }
600- _ => {
601- // Write down the first private field resolution if we found no field
602- // This aids IDE features for private fields like goto def
603- if let Some ( field) = private_field {
604- self . result . field_resolutions . insert ( tgt_expr, field) ;
605- self . result
606- . diagnostics
607- . push ( InferenceDiagnostic :: PrivateField { expr : tgt_expr, field } ) ;
608- }
609- self . err_ty ( )
610- }
611- } ;
612- ty
613- }
555+ Expr :: Field { expr, name } => self . infer_field_access ( tgt_expr, * expr, name) ,
614556 Expr :: Await { expr } => {
615557 let inner_ty = self . infer_expr_inner ( * expr, & Expectation :: none ( ) ) ;
616558 self . resolve_associated_type ( inner_ty, self . resolve_future_future_output ( ) )
@@ -1270,6 +1212,118 @@ impl<'a> InferenceContext<'a> {
12701212 }
12711213 }
12721214
1215+ fn lookup_field (
1216+ & mut self ,
1217+ receiver_ty : & Ty ,
1218+ name : & Name ,
1219+ ) -> Option < ( Ty , Option < FieldId > , Vec < Adjustment > , bool ) > {
1220+ let mut autoderef = Autoderef :: new ( & mut self . table , receiver_ty. clone ( ) ) ;
1221+ let mut private_field = None ;
1222+ let res = autoderef. by_ref ( ) . find_map ( |( derefed_ty, _) | {
1223+ let ( field_id, parameters) = match derefed_ty. kind ( Interner ) {
1224+ TyKind :: Tuple ( _, substs) => {
1225+ return name. as_tuple_index ( ) . and_then ( |idx| {
1226+ substs
1227+ . as_slice ( Interner )
1228+ . get ( idx)
1229+ . map ( |a| a. assert_ty_ref ( Interner ) )
1230+ . cloned ( )
1231+ . map ( |ty| ( None , ty) )
1232+ } ) ;
1233+ }
1234+ TyKind :: Adt ( AdtId ( hir_def:: AdtId :: StructId ( s) ) , parameters) => {
1235+ let local_id = self . db . struct_data ( * s) . variant_data . field ( name) ?;
1236+ let field = FieldId { parent : ( * s) . into ( ) , local_id } ;
1237+ ( field, parameters. clone ( ) )
1238+ }
1239+ TyKind :: Adt ( AdtId ( hir_def:: AdtId :: UnionId ( u) ) , parameters) => {
1240+ let local_id = self . db . union_data ( * u) . variant_data . field ( name) ?;
1241+ let field = FieldId { parent : ( * u) . into ( ) , local_id } ;
1242+ ( field, parameters. clone ( ) )
1243+ }
1244+ _ => return None ,
1245+ } ;
1246+ let is_visible = self . db . field_visibilities ( field_id. parent ) [ field_id. local_id ]
1247+ . is_visible_from ( self . db . upcast ( ) , self . resolver . module ( ) ) ;
1248+ if !is_visible {
1249+ if private_field. is_none ( ) {
1250+ private_field = Some ( ( field_id, parameters) ) ;
1251+ }
1252+ return None ;
1253+ }
1254+ let ty = self . db . field_types ( field_id. parent ) [ field_id. local_id ]
1255+ . clone ( )
1256+ . substitute ( Interner , & parameters) ;
1257+ Some ( ( Some ( field_id) , ty) )
1258+ } ) ;
1259+
1260+ Some ( match res {
1261+ Some ( ( field_id, ty) ) => {
1262+ let adjustments = auto_deref_adjust_steps ( & autoderef) ;
1263+ let ty = self . insert_type_vars ( ty) ;
1264+ let ty = self . normalize_associated_types_in ( ty) ;
1265+
1266+ ( ty, field_id, adjustments, true )
1267+ }
1268+ None => {
1269+ let ( field_id, subst) = private_field?;
1270+ let adjustments = auto_deref_adjust_steps ( & autoderef) ;
1271+ let ty = self . db . field_types ( field_id. parent ) [ field_id. local_id ]
1272+ . clone ( )
1273+ . substitute ( Interner , & subst) ;
1274+ let ty = self . insert_type_vars ( ty) ;
1275+ let ty = self . normalize_associated_types_in ( ty) ;
1276+
1277+ ( ty, Some ( field_id) , adjustments, false )
1278+ }
1279+ } )
1280+ }
1281+
1282+ fn infer_field_access ( & mut self , tgt_expr : ExprId , receiver : ExprId , name : & Name ) -> Ty {
1283+ let receiver_ty = self . infer_expr_inner ( receiver, & Expectation :: none ( ) ) ;
1284+ match self . lookup_field ( & receiver_ty, name) {
1285+ Some ( ( ty, field_id, adjustments, is_public) ) => {
1286+ self . write_expr_adj ( receiver, adjustments) ;
1287+ if let Some ( field_id) = field_id {
1288+ self . result . field_resolutions . insert ( tgt_expr, field_id) ;
1289+ }
1290+ if !is_public {
1291+ if let Some ( field) = field_id {
1292+ // FIXME: Merge this diagnostic into UnresolvedField?
1293+ self . result
1294+ . diagnostics
1295+ . push ( InferenceDiagnostic :: PrivateField { expr : tgt_expr, field } ) ;
1296+ }
1297+ }
1298+ ty
1299+ }
1300+ None => {
1301+ // no field found,
1302+ let method_with_same_name_exists = {
1303+ let canonicalized_receiver = self . canonicalize ( receiver_ty. clone ( ) ) ;
1304+ let traits_in_scope = self . resolver . traits_in_scope ( self . db . upcast ( ) ) ;
1305+
1306+ method_resolution:: lookup_method (
1307+ self . db ,
1308+ & canonicalized_receiver. value ,
1309+ self . trait_env . clone ( ) ,
1310+ & traits_in_scope,
1311+ VisibleFromModule :: Filter ( self . resolver . module ( ) ) ,
1312+ name,
1313+ )
1314+ . is_some ( )
1315+ } ;
1316+ self . result . diagnostics . push ( InferenceDiagnostic :: UnresolvedField {
1317+ expr : tgt_expr,
1318+ receiver : receiver_ty,
1319+ name : name. clone ( ) ,
1320+ method_with_same_name_exists,
1321+ } ) ;
1322+ self . err_ty ( )
1323+ }
1324+ }
1325+ }
1326+
12731327 fn infer_method_call (
12741328 & mut self ,
12751329 tgt_expr : ExprId ,
@@ -1307,11 +1361,30 @@ impl<'a> InferenceContext<'a> {
13071361 }
13081362 ( ty, self . db . value_ty ( func. into ( ) ) , substs)
13091363 }
1310- None => (
1311- receiver_ty,
1312- Binders :: empty ( Interner , self . err_ty ( ) ) ,
1313- Substitution :: empty ( Interner ) ,
1314- ) ,
1364+ None => {
1365+ let field_with_same_name_exists = match self . lookup_field ( & receiver_ty, method_name)
1366+ {
1367+ Some ( ( ty, field_id, adjustments, _public) ) => {
1368+ self . write_expr_adj ( receiver, adjustments) ;
1369+ if let Some ( field_id) = field_id {
1370+ self . result . field_resolutions . insert ( tgt_expr, field_id) ;
1371+ }
1372+ Some ( ty)
1373+ }
1374+ None => None ,
1375+ } ;
1376+ self . result . diagnostics . push ( InferenceDiagnostic :: UnresolvedMethodCall {
1377+ expr : tgt_expr,
1378+ receiver : receiver_ty. clone ( ) ,
1379+ name : method_name. clone ( ) ,
1380+ field_with_same_name : field_with_same_name_exists,
1381+ } ) ;
1382+ (
1383+ receiver_ty,
1384+ Binders :: empty ( Interner , self . err_ty ( ) ) ,
1385+ Substitution :: empty ( Interner ) ,
1386+ )
1387+ }
13151388 } ;
13161389 let method_ty = method_ty. substitute ( Interner , & substs) ;
13171390 self . register_obligations_for_call ( & method_ty) ;
0 commit comments