@@ -10,6 +10,7 @@ use hir_def::{
10
10
data:: { adt:: StructFlags , ImplData } ,
11
11
item_scope:: ItemScope ,
12
12
nameres:: DefMap ,
13
+ resolver:: HasResolver ,
13
14
AssocItemId , BlockId , ConstId , FunctionId , HasModule , ImplId , ItemContainerId , Lookup ,
14
15
ModuleDefId , ModuleId , TraitId ,
15
16
} ;
@@ -1002,6 +1003,20 @@ pub fn iterate_method_candidates_dyn(
1002
1003
}
1003
1004
}
1004
1005
1006
+ pub fn iterate_trait_item_candidates (
1007
+ ty : & Canonical < Ty > ,
1008
+ db : & dyn HirDatabase ,
1009
+ env : Arc < TraitEnvironment > ,
1010
+ traits_in_scope : & FxHashSet < TraitId > ,
1011
+ name : Option < & Name > ,
1012
+ callback : & mut dyn FnMut ( AssocItemId , bool ) -> ControlFlow < ( ) > ,
1013
+ ) {
1014
+ let mut table = InferenceTable :: new ( db, env) ;
1015
+ let self_ty = table. instantiate_canonical ( ty. clone ( ) ) ;
1016
+
1017
+ iterate_trait_item_candidates_ ( & self_ty, & mut table, traits_in_scope, name, None , callback) ;
1018
+ }
1019
+
1005
1020
fn iterate_method_candidates_with_autoref (
1006
1021
receiver_ty : & Canonical < Ty > ,
1007
1022
first_adjustment : ReceiverAdjustments ,
@@ -1145,6 +1160,26 @@ fn iterate_trait_method_candidates(
1145
1160
receiver_ty : Option < & Ty > ,
1146
1161
receiver_adjustments : Option < ReceiverAdjustments > ,
1147
1162
callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
1163
+ ) -> ControlFlow < ( ) > {
1164
+ iterate_trait_item_candidates_ (
1165
+ self_ty,
1166
+ table,
1167
+ traits_in_scope,
1168
+ name,
1169
+ receiver_ty,
1170
+ & mut move |assoc_item_id, visible| {
1171
+ callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , assoc_item_id, visible)
1172
+ } ,
1173
+ )
1174
+ }
1175
+
1176
+ fn iterate_trait_item_candidates_ (
1177
+ self_ty : & Ty ,
1178
+ table : & mut InferenceTable < ' _ > ,
1179
+ traits_in_scope : & FxHashSet < TraitId > ,
1180
+ name : Option < & Name > ,
1181
+ receiver_ty : Option < & Ty > ,
1182
+ callback : & mut dyn FnMut ( AssocItemId , bool ) -> ControlFlow < ( ) > ,
1148
1183
) -> ControlFlow < ( ) > {
1149
1184
let db = table. db ;
1150
1185
let env = table. trait_env . clone ( ) ;
@@ -1187,7 +1222,7 @@ fn iterate_trait_method_candidates(
1187
1222
}
1188
1223
}
1189
1224
known_implemented = true ;
1190
- callback ( receiver_adjustments . clone ( ) . unwrap_or_default ( ) , item, visible) ?;
1225
+ callback ( item, visible) ?;
1191
1226
}
1192
1227
}
1193
1228
ControlFlow :: Continue ( ( ) )
@@ -1382,6 +1417,8 @@ fn is_valid_candidate(
1382
1417
visible_from_module : Option < ModuleId > ,
1383
1418
) -> IsValidCandidate {
1384
1419
let db = table. db ;
1420
+ let def_db = db. upcast ( ) ;
1421
+
1385
1422
match item {
1386
1423
AssocItemId :: FunctionId ( f) => {
1387
1424
is_valid_fn_candidate ( table, f, name, receiver_ty, self_ty, visible_from_module)
@@ -1397,23 +1434,61 @@ fn is_valid_candidate(
1397
1434
}
1398
1435
}
1399
1436
if let ItemContainerId :: ImplId ( impl_id) = c. lookup ( db. upcast ( ) ) . container {
1400
- let self_ty_matches = table. run_in_snapshot ( |table| {
1401
- let expected_self_ty = TyBuilder :: impl_self_ty ( db, impl_id)
1402
- . fill_with_inference_vars ( table)
1403
- . build ( ) ;
1404
- table. unify ( & expected_self_ty, self_ty)
1405
- } ) ;
1406
- if !self_ty_matches {
1437
+ if !self_ty_matches ( table, db, impl_id, self_ty) {
1407
1438
cov_mark:: hit!( const_candidate_self_type_mismatch) ;
1408
1439
return IsValidCandidate :: No ;
1409
1440
}
1410
1441
}
1411
1442
IsValidCandidate :: Yes
1412
1443
}
1413
- _ => IsValidCandidate :: No ,
1444
+ AssocItemId :: TypeAliasId ( t) => {
1445
+ // Q: should this branch be restricted to `iterate_trait_item_candidates()`?
1446
+ //
1447
+ // the code below does not seem to be called when adding tests to
1448
+ // `method_resolution.rs`, so resolution of type aliases is likely performed at some
1449
+ // other point. due to the marks below, however, the test which ensures that marks have
1450
+ // corresponding checks will fail
1451
+ let data = db. type_alias_data ( t) ;
1452
+
1453
+ check_that ! ( receiver_ty. is_none( ) ) ;
1454
+ check_that ! ( name. map_or( true , |n| data. name == * n) ) ;
1455
+
1456
+ if let Some ( from_module) = visible_from_module {
1457
+ // Q: should the resolved visibility be added to the database?
1458
+ let visibility = data. visibility . resolve ( def_db, & t. resolver ( def_db) ) ;
1459
+
1460
+ if !visibility. is_visible_from ( def_db, from_module) {
1461
+ // cov_mark::hit!(type_alias_candidate_not_visible);
1462
+ return IsValidCandidate :: NotVisible ;
1463
+ }
1464
+ }
1465
+
1466
+ // Q: is it correct to use the same check as `ConstId`?
1467
+ if let ItemContainerId :: ImplId ( impl_id) = t. lookup ( def_db) . container {
1468
+ if !self_ty_matches ( table, db, impl_id, self_ty) {
1469
+ // cov_mark::hit!(type_alias_candidate_self_type_mismatch);
1470
+ return IsValidCandidate :: No ;
1471
+ }
1472
+ }
1473
+
1474
+ IsValidCandidate :: Yes
1475
+ }
1414
1476
}
1415
1477
}
1416
1478
1479
+ fn self_ty_matches (
1480
+ table : & mut InferenceTable < ' _ > ,
1481
+ db : & dyn HirDatabase ,
1482
+ impl_id : ImplId ,
1483
+ self_ty : & Ty ,
1484
+ ) -> bool {
1485
+ table. run_in_snapshot ( |table| {
1486
+ let expected_self_ty =
1487
+ TyBuilder :: impl_self_ty ( db, impl_id) . fill_with_inference_vars ( table) . build ( ) ;
1488
+ table. unify ( & expected_self_ty, self_ty)
1489
+ } )
1490
+ }
1491
+
1417
1492
enum IsValidCandidate {
1418
1493
Yes ,
1419
1494
No ,
0 commit comments