@@ -254,6 +254,11 @@ impl TraitImpls {
254
254
. flat_map ( |v| v. iter ( ) . copied ( ) )
255
255
}
256
256
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
+
257
262
pub fn all_impls ( & self ) -> impl Iterator < Item = ImplId > + ' _ {
258
263
self . map . values ( ) . flat_map ( |map| map. values ( ) . flat_map ( |v| v. iter ( ) . copied ( ) ) )
259
264
}
@@ -1170,7 +1175,7 @@ fn iterate_trait_method_candidates(
1170
1175
for & ( _, item) in data. items . iter ( ) {
1171
1176
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
1172
1177
// 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) {
1174
1179
IsValidCandidate :: Yes => true ,
1175
1180
IsValidCandidate :: NotVisible => false ,
1176
1181
IsValidCandidate :: No => continue ,
@@ -1414,6 +1419,74 @@ fn is_valid_candidate(
1414
1419
}
1415
1420
}
1416
1421
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
+
1417
1490
enum IsValidCandidate {
1418
1491
Yes ,
1419
1492
No ,
@@ -1441,6 +1514,8 @@ fn is_valid_fn_candidate(
1441
1514
}
1442
1515
table. run_in_snapshot ( |table| {
1443
1516
let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1517
+
1518
+ let _p = tracing:: span!( tracing:: Level :: INFO , "subst_for_def" ) . entered ( ) ;
1444
1519
let ( impl_subst, expect_self_ty) = match container {
1445
1520
ItemContainerId :: ImplId ( it) => {
1446
1521
let subst =
@@ -1460,6 +1535,7 @@ fn is_valid_fn_candidate(
1460
1535
check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
1461
1536
1462
1537
if let Some ( receiver_ty) = receiver_ty {
1538
+ let _p = tracing:: span!( tracing:: Level :: INFO , "check_receiver_ty" ) . entered ( ) ;
1463
1539
check_that ! ( data. has_self_param( ) ) ;
1464
1540
1465
1541
let fn_subst = TyBuilder :: subst_for_def ( db, fn_id, Some ( impl_subst. clone ( ) ) )
@@ -1474,6 +1550,7 @@ fn is_valid_fn_candidate(
1474
1550
}
1475
1551
1476
1552
if let ItemContainerId :: ImplId ( impl_id) = container {
1553
+ let _p = tracing:: span!( tracing:: Level :: INFO , "check_item_container" ) . entered ( ) ;
1477
1554
// We need to consider the bounds on the impl to distinguish functions of the same name
1478
1555
// for a type.
1479
1556
let predicates = db. generic_predicates ( impl_id. into ( ) ) ;
0 commit comments