@@ -254,6 +254,11 @@ impl TraitImpls {
254254 . flat_map ( |v| v. iter ( ) . copied ( ) )
255255 }
256256
257+ /// Queries whether `self_ty` has potentially applicable implementations of `trait_`.
258+ pub fn has_impls_for_trait_and_self_ty ( & self , trait_ : TraitId , self_ty : TyFingerprint ) -> bool {
259+ self . for_trait_and_self_ty ( trait_, self_ty) . next ( ) . is_some ( )
260+ }
261+
257262 pub fn all_impls ( & self ) -> impl Iterator < Item = ImplId > + ' _ {
258263 self . map . values ( ) . flat_map ( |map| map. values ( ) . flat_map ( |v| v. iter ( ) . copied ( ) ) )
259264 }
@@ -1170,7 +1175,7 @@ fn iterate_trait_method_candidates(
11701175 for & ( _, item) in data. items . iter ( ) {
11711176 // Don't pass a `visible_from_module` down to `is_valid_candidate`,
11721177 // since only inherent methods should be included into visibility checking.
1173- let visible = match is_valid_candidate ( table, name, receiver_ty, item, self_ty, None ) {
1178+ let visible = match is_valid_method_candidate ( table, name, receiver_ty, item, self_ty) {
11741179 IsValidCandidate :: Yes => true ,
11751180 IsValidCandidate :: NotVisible => false ,
11761181 IsValidCandidate :: No => continue ,
@@ -1414,6 +1419,74 @@ fn is_valid_candidate(
14141419 }
14151420}
14161421
1422+ /// Checks whether a given `AssocItemId` is applicable for `receiver_ty`.
1423+ ///
1424+ /// This method should *only* be called by [`iterate_trait_method_candidates`],
1425+ /// as it is responsible for determining applicability in completions.
1426+ #[ tracing:: instrument( skip_all, fields( name) ) ]
1427+ fn is_valid_method_candidate (
1428+ table : & mut InferenceTable < ' _ > ,
1429+ name : Option < & Name > ,
1430+ receiver_ty : Option < & Ty > ,
1431+ item : AssocItemId ,
1432+ self_ty : & Ty ,
1433+ ) -> IsValidCandidate {
1434+ let db = table. db ;
1435+ match item {
1436+ AssocItemId :: FunctionId ( fn_id) => {
1437+ let data = db. function_data ( fn_id) ;
1438+
1439+ check_that ! ( name. map_or( true , |n| n == & data. name) ) ;
1440+
1441+ table. run_in_snapshot ( |table| {
1442+ let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1443+ let ( impl_subst, expect_self_ty) = match container {
1444+ ItemContainerId :: ImplId ( it) => {
1445+ let subst = TyBuilder :: subst_for_def ( db, it, None )
1446+ . fill_with_inference_vars ( table)
1447+ . build ( ) ;
1448+ let self_ty = db. impl_self_ty ( it) . substitute ( Interner , & subst) ;
1449+ ( subst, self_ty)
1450+ }
1451+ ItemContainerId :: TraitId ( it) => {
1452+ let subst = TyBuilder :: subst_for_def ( db, it, None )
1453+ . fill_with_inference_vars ( table)
1454+ . build ( ) ;
1455+ let self_ty = subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( ) ;
1456+ ( subst, self_ty)
1457+ }
1458+ _ => unreachable ! ( ) ,
1459+ } ;
1460+
1461+ check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
1462+
1463+ if let Some ( receiver_ty) = receiver_ty {
1464+ check_that ! ( data. has_self_param( ) ) ;
1465+
1466+ let fn_subst = TyBuilder :: subst_for_def ( db, fn_id, Some ( impl_subst. clone ( ) ) )
1467+ . fill_with_inference_vars ( table)
1468+ . build ( ) ;
1469+
1470+ let sig = db. callable_item_signature ( fn_id. into ( ) ) ;
1471+ let expected_receiver =
1472+ sig. map ( |s| s. params ( ) [ 0 ] . clone ( ) ) . substitute ( Interner , & fn_subst) ;
1473+
1474+ check_that ! ( table. unify( receiver_ty, & expected_receiver) ) ;
1475+ }
1476+
1477+ IsValidCandidate :: Yes
1478+ } )
1479+ }
1480+ AssocItemId :: ConstId ( c) => {
1481+ check_that ! ( receiver_ty. is_none( ) ) ;
1482+ check_that ! ( name. map_or( true , |n| db. const_data( c) . name. as_ref( ) == Some ( n) ) ) ;
1483+
1484+ IsValidCandidate :: Yes
1485+ }
1486+ _ => IsValidCandidate :: No ,
1487+ }
1488+ }
1489+
14171490enum IsValidCandidate {
14181491 Yes ,
14191492 No ,
@@ -1441,6 +1514,8 @@ fn is_valid_fn_candidate(
14411514 }
14421515 table. run_in_snapshot ( |table| {
14431516 let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1517+
1518+ let _p = tracing:: span!( tracing:: Level :: INFO , "subst_for_def" ) . entered ( ) ;
14441519 let ( impl_subst, expect_self_ty) = match container {
14451520 ItemContainerId :: ImplId ( it) => {
14461521 let subst =
@@ -1460,6 +1535,7 @@ fn is_valid_fn_candidate(
14601535 check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
14611536
14621537 if let Some ( receiver_ty) = receiver_ty {
1538+ let _p = tracing:: span!( tracing:: Level :: INFO , "check_receiver_ty" ) . entered ( ) ;
14631539 check_that ! ( data. has_self_param( ) ) ;
14641540
14651541 let fn_subst = TyBuilder :: subst_for_def ( db, fn_id, Some ( impl_subst. clone ( ) ) )
@@ -1474,6 +1550,7 @@ fn is_valid_fn_candidate(
14741550 }
14751551
14761552 if let ItemContainerId :: ImplId ( impl_id) = container {
1553+ let _p = tracing:: span!( tracing:: Level :: INFO , "check_item_container" ) . entered ( ) ;
14771554 // We need to consider the bounds on the impl to distinguish functions of the same name
14781555 // for a type.
14791556 let predicates = db. generic_predicates ( impl_id. into ( ) ) ;
0 commit comments