@@ -10,6 +10,7 @@ use hir_def::{
1010 data:: { adt:: StructFlags , ImplData } ,
1111 item_scope:: ItemScope ,
1212 nameres:: DefMap ,
13+ resolver:: HasResolver ,
1314 AssocItemId , BlockId , ConstId , FunctionId , HasModule , ImplId , ItemContainerId , Lookup ,
1415 ModuleDefId , ModuleId , TraitId ,
1516} ;
@@ -1002,6 +1003,20 @@ pub fn iterate_method_candidates_dyn(
10021003 }
10031004}
10041005
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+
10051020fn iterate_method_candidates_with_autoref (
10061021 receiver_ty : & Canonical < Ty > ,
10071022 first_adjustment : ReceiverAdjustments ,
@@ -1145,6 +1160,26 @@ fn iterate_trait_method_candidates(
11451160 receiver_ty : Option < & Ty > ,
11461161 receiver_adjustments : Option < ReceiverAdjustments > ,
11471162 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 < ( ) > ,
11481183) -> ControlFlow < ( ) > {
11491184 let db = table. db ;
11501185 let env = table. trait_env . clone ( ) ;
@@ -1187,7 +1222,7 @@ fn iterate_trait_method_candidates(
11871222 }
11881223 }
11891224 known_implemented = true ;
1190- callback ( receiver_adjustments . clone ( ) . unwrap_or_default ( ) , item, visible) ?;
1225+ callback ( item, visible) ?;
11911226 }
11921227 }
11931228 ControlFlow :: Continue ( ( ) )
@@ -1382,6 +1417,8 @@ fn is_valid_candidate(
13821417 visible_from_module : Option < ModuleId > ,
13831418) -> IsValidCandidate {
13841419 let db = table. db ;
1420+ let def_db = db. upcast ( ) ;
1421+
13851422 match item {
13861423 AssocItemId :: FunctionId ( f) => {
13871424 is_valid_fn_candidate ( table, f, name, receiver_ty, self_ty, visible_from_module)
@@ -1397,23 +1434,61 @@ fn is_valid_candidate(
13971434 }
13981435 }
13991436 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) {
14071438 cov_mark:: hit!( const_candidate_self_type_mismatch) ;
14081439 return IsValidCandidate :: No ;
14091440 }
14101441 }
14111442 IsValidCandidate :: Yes
14121443 }
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+ }
14141476 }
14151477}
14161478
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+
14171492enum IsValidCandidate {
14181493 Yes ,
14191494 No ,
0 commit comments