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