@@ -364,7 +364,13 @@ impl<'a> InferenceContext<'a> {
364
364
}
365
365
( params, ret_ty)
366
366
}
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
+ }
368
374
} ;
369
375
let indices_to_skip = self . check_legacy_const_generics ( derefed_callee, args) ;
370
376
self . register_obligations_for_call ( & callee_ty) ;
@@ -546,71 +552,7 @@ impl<'a> InferenceContext<'a> {
546
552
}
547
553
ty
548
554
}
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) ,
614
556
Expr :: Await { expr } => {
615
557
let inner_ty = self . infer_expr_inner ( * expr, & Expectation :: none ( ) ) ;
616
558
self . resolve_associated_type ( inner_ty, self . resolve_future_future_output ( ) )
@@ -1270,6 +1212,118 @@ impl<'a> InferenceContext<'a> {
1270
1212
}
1271
1213
}
1272
1214
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
+
1273
1327
fn infer_method_call (
1274
1328
& mut self ,
1275
1329
tgt_expr : ExprId ,
@@ -1307,11 +1361,30 @@ impl<'a> InferenceContext<'a> {
1307
1361
}
1308
1362
( ty, self . db . value_ty ( func. into ( ) ) , substs)
1309
1363
}
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
+ }
1315
1388
} ;
1316
1389
let method_ty = method_ty. substitute ( Interner , & substs) ;
1317
1390
self . register_obligations_for_call ( & method_ty) ;
0 commit comments