@@ -1176,11 +1176,12 @@ fn iterate_trait_method_candidates(
1176
1176
for & ( _, item) in data. items . iter ( ) {
1177
1177
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
1178
1178
// since only inherent methods should be included into visibility checking.
1179
- let visible = match is_valid_method_candidate ( table, name, receiver_ty, item, self_ty) {
1180
- IsValidCandidate :: Yes => true ,
1181
- IsValidCandidate :: NotVisible => false ,
1182
- IsValidCandidate :: No => continue ,
1183
- } ;
1179
+ let visible =
1180
+ match is_valid_trait_method_candidate ( table, t, name, receiver_ty, item, self_ty) {
1181
+ IsValidCandidate :: Yes => true ,
1182
+ IsValidCandidate :: NotVisible => false ,
1183
+ IsValidCandidate :: No => continue ,
1184
+ } ;
1184
1185
if !known_implemented {
1185
1186
let goal = generic_implements_goal ( db, env. clone ( ) , t, & canonical_self_ty) ;
1186
1187
if db. trait_solve ( env. krate , env. block , goal. cast ( Interner ) ) . is_none ( ) {
@@ -1302,12 +1303,18 @@ fn iterate_inherent_methods(
1302
1303
let data = db. trait_data ( t) ;
1303
1304
for & ( _, item) in data. items . iter ( ) {
1304
1305
// We don't pass `visible_from_module` as all trait items should be visible.
1305
- let visible =
1306
- match is_valid_candidate ( table, name, receiver_ty, item, self_ty, None ) {
1307
- IsValidCandidate :: Yes => true ,
1308
- IsValidCandidate :: NotVisible => false ,
1309
- IsValidCandidate :: No => continue ,
1310
- } ;
1306
+ let visible = match is_valid_trait_method_candidate (
1307
+ table,
1308
+ t,
1309
+ name,
1310
+ receiver_ty,
1311
+ item,
1312
+ self_ty,
1313
+ ) {
1314
+ IsValidCandidate :: Yes => true ,
1315
+ IsValidCandidate :: NotVisible => false ,
1316
+ IsValidCandidate :: No => continue ,
1317
+ } ;
1311
1318
callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item, visible) ?;
1312
1319
}
1313
1320
}
@@ -1325,17 +1332,16 @@ fn iterate_inherent_methods(
1325
1332
visible_from_module : Option < ModuleId > ,
1326
1333
callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
1327
1334
) -> ControlFlow < ( ) > {
1328
- let db = table. db ;
1329
- let impls_for_self_ty = impls. for_self_ty ( self_ty) ;
1330
- for & impl_def in impls_for_self_ty {
1331
- for & item in & db. impl_data ( impl_def) . items {
1332
- let visible = match is_valid_candidate (
1335
+ for & impl_id in impls. for_self_ty ( self_ty) {
1336
+ for & item in & table. db . impl_data ( impl_id) . items {
1337
+ let visible = match is_valid_impl_method_candidate (
1333
1338
table,
1334
- name,
1335
- receiver_ty,
1336
- item,
1337
1339
self_ty,
1340
+ receiver_ty,
1338
1341
visible_from_module,
1342
+ name,
1343
+ impl_id,
1344
+ item,
1339
1345
) {
1340
1346
IsValidCandidate :: Yes => true ,
1341
1347
IsValidCandidate :: NotVisible => false ,
@@ -1378,21 +1384,34 @@ macro_rules! check_that {
1378
1384
} ;
1379
1385
}
1380
1386
1387
+ enum IsValidCandidate {
1388
+ Yes ,
1389
+ No ,
1390
+ NotVisible ,
1391
+ }
1392
+
1381
1393
#[ tracing:: instrument( skip_all, fields( name) ) ]
1382
- fn is_valid_candidate (
1394
+ fn is_valid_impl_method_candidate (
1383
1395
table : & mut InferenceTable < ' _ > ,
1384
- name : Option < & Name > ,
1385
- receiver_ty : Option < & Ty > ,
1386
- item : AssocItemId ,
1387
1396
self_ty : & Ty ,
1397
+ receiver_ty : Option < & Ty > ,
1388
1398
visible_from_module : Option < ModuleId > ,
1399
+ name : Option < & Name > ,
1400
+ impl_id : ImplId ,
1401
+ item : AssocItemId ,
1389
1402
) -> IsValidCandidate {
1390
- let db = table. db ;
1391
1403
match item {
1392
- AssocItemId :: FunctionId ( f) => {
1393
- is_valid_fn_candidate ( table, f, name, receiver_ty, self_ty, visible_from_module)
1394
- }
1404
+ AssocItemId :: FunctionId ( f) => is_valid_impl_fn_candidate (
1405
+ table,
1406
+ impl_id,
1407
+ f,
1408
+ name,
1409
+ receiver_ty,
1410
+ self_ty,
1411
+ visible_from_module,
1412
+ ) ,
1395
1413
AssocItemId :: ConstId ( c) => {
1414
+ let db = table. db ;
1396
1415
check_that ! ( receiver_ty. is_none( ) ) ;
1397
1416
check_that ! ( name. map_or( true , |n| db. const_data( c) . name. as_ref( ) == Some ( n) ) ) ;
1398
1417
@@ -1402,17 +1421,14 @@ fn is_valid_candidate(
1402
1421
return IsValidCandidate :: NotVisible ;
1403
1422
}
1404
1423
}
1405
- if let ItemContainerId :: ImplId ( impl_id) = c. lookup ( db. upcast ( ) ) . container {
1406
- let self_ty_matches = table. run_in_snapshot ( |table| {
1407
- let expected_self_ty = TyBuilder :: impl_self_ty ( db, impl_id)
1408
- . fill_with_inference_vars ( table)
1409
- . build ( ) ;
1410
- table. unify ( & expected_self_ty, self_ty)
1411
- } ) ;
1412
- if !self_ty_matches {
1413
- cov_mark:: hit!( const_candidate_self_type_mismatch) ;
1414
- return IsValidCandidate :: No ;
1415
- }
1424
+ let self_ty_matches = table. run_in_snapshot ( |table| {
1425
+ let expected_self_ty =
1426
+ TyBuilder :: impl_self_ty ( db, impl_id) . fill_with_inference_vars ( table) . build ( ) ;
1427
+ table. unify ( & expected_self_ty, self_ty)
1428
+ } ) ;
1429
+ if !self_ty_matches {
1430
+ cov_mark:: hit!( const_candidate_self_type_mismatch) ;
1431
+ return IsValidCandidate :: No ;
1416
1432
}
1417
1433
IsValidCandidate :: Yes
1418
1434
}
@@ -1421,12 +1437,10 @@ fn is_valid_candidate(
1421
1437
}
1422
1438
1423
1439
/// Checks whether a given `AssocItemId` is applicable for `receiver_ty`.
1424
- ///
1425
- /// This method should *only* be called by [`iterate_trait_method_candidates`],
1426
- /// as it is responsible for determining applicability in completions.
1427
1440
#[ tracing:: instrument( skip_all, fields( name) ) ]
1428
- fn is_valid_method_candidate (
1441
+ fn is_valid_trait_method_candidate (
1429
1442
table : & mut InferenceTable < ' _ > ,
1443
+ trait_id : TraitId ,
1430
1444
name : Option < & Name > ,
1431
1445
receiver_ty : Option < & Ty > ,
1432
1446
item : AssocItemId ,
@@ -1440,24 +1454,10 @@ fn is_valid_method_candidate(
1440
1454
check_that ! ( name. map_or( true , |n| n == & data. name) ) ;
1441
1455
1442
1456
table. run_in_snapshot ( |table| {
1443
- let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1444
- let ( impl_subst, expect_self_ty) = match container {
1445
- ItemContainerId :: ImplId ( it) => {
1446
- let subst = TyBuilder :: subst_for_def ( db, it, None )
1447
- . fill_with_inference_vars ( table)
1448
- . build ( ) ;
1449
- let self_ty = db. impl_self_ty ( it) . substitute ( Interner , & subst) ;
1450
- ( subst, self_ty)
1451
- }
1452
- ItemContainerId :: TraitId ( it) => {
1453
- let subst = TyBuilder :: subst_for_def ( db, it, None )
1454
- . fill_with_inference_vars ( table)
1455
- . build ( ) ;
1456
- let self_ty = subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( ) ;
1457
- ( subst, self_ty)
1458
- }
1459
- _ => unreachable ! ( ) ,
1460
- } ;
1457
+ let impl_subst = TyBuilder :: subst_for_def ( db, trait_id, None )
1458
+ . fill_with_inference_vars ( table)
1459
+ . build ( ) ;
1460
+ let expect_self_ty = impl_subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( ) ;
1461
1461
1462
1462
check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
1463
1463
@@ -1488,15 +1488,10 @@ fn is_valid_method_candidate(
1488
1488
}
1489
1489
}
1490
1490
1491
- enum IsValidCandidate {
1492
- Yes ,
1493
- No ,
1494
- NotVisible ,
1495
- }
1496
-
1497
1491
#[ tracing:: instrument( skip_all, fields( name) ) ]
1498
- fn is_valid_fn_candidate (
1492
+ fn is_valid_impl_fn_candidate (
1499
1493
table : & mut InferenceTable < ' _ > ,
1494
+ impl_id : ImplId ,
1500
1495
fn_id : FunctionId ,
1501
1496
name : Option < & Name > ,
1502
1497
receiver_ty : Option < & Ty > ,
@@ -1514,24 +1509,10 @@ fn is_valid_fn_candidate(
1514
1509
}
1515
1510
}
1516
1511
table. run_in_snapshot ( |table| {
1517
- let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1518
-
1519
1512
let _p = tracing:: span!( tracing:: Level :: INFO , "subst_for_def" ) . entered ( ) ;
1520
- let ( impl_subst, expect_self_ty) = match container {
1521
- ItemContainerId :: ImplId ( it) => {
1522
- let subst =
1523
- TyBuilder :: subst_for_def ( db, it, None ) . fill_with_inference_vars ( table) . build ( ) ;
1524
- let self_ty = db. impl_self_ty ( it) . substitute ( Interner , & subst) ;
1525
- ( subst, self_ty)
1526
- }
1527
- ItemContainerId :: TraitId ( it) => {
1528
- let subst =
1529
- TyBuilder :: subst_for_def ( db, it, None ) . fill_with_inference_vars ( table) . build ( ) ;
1530
- let self_ty = subst. at ( Interner , 0 ) . assert_ty_ref ( Interner ) . clone ( ) ;
1531
- ( subst, self_ty)
1532
- }
1533
- _ => unreachable ! ( ) ,
1534
- } ;
1513
+ let impl_subst =
1514
+ TyBuilder :: subst_for_def ( db, impl_id, None ) . fill_with_inference_vars ( table) . build ( ) ;
1515
+ let expect_self_ty = db. impl_self_ty ( impl_id) . substitute ( Interner , & impl_subst) ;
1535
1516
1536
1517
check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
1537
1518
@@ -1550,63 +1531,55 @@ fn is_valid_fn_candidate(
1550
1531
check_that ! ( table. unify( receiver_ty, & expected_receiver) ) ;
1551
1532
}
1552
1533
1553
- if let ItemContainerId :: ImplId ( impl_id) = container {
1554
- let _p = tracing:: span!( tracing:: Level :: INFO , "check_item_container" ) . entered ( ) ;
1555
- // We need to consider the bounds on the impl to distinguish functions of the same name
1556
- // for a type.
1557
- let predicates = db. generic_predicates ( impl_id. into ( ) ) ;
1558
- let goals = predicates. iter ( ) . map ( |p| {
1559
- let ( p, b) = p
1560
- . clone ( )
1561
- . substitute ( Interner , & impl_subst)
1562
- // Skipping the inner binders is ok, as we don't handle quantified where
1563
- // clauses yet.
1564
- . into_value_and_skipped_binders ( ) ;
1565
- stdx:: always!( b. len( Interner ) == 0 ) ;
1566
-
1567
- p. cast :: < Goal > ( Interner )
1568
- } ) ;
1569
-
1570
- for goal in goals. clone ( ) {
1571
- let in_env = InEnvironment :: new ( & table. trait_env . env , goal) ;
1572
- let canonicalized = table. canonicalize ( in_env) ;
1573
- let solution = table. db . trait_solve (
1574
- table. trait_env . krate ,
1575
- table. trait_env . block ,
1576
- canonicalized. value . clone ( ) ,
1577
- ) ;
1578
-
1579
- match solution {
1580
- Some ( Solution :: Unique ( canonical_subst) ) => {
1581
- canonicalized. apply_solution (
1582
- table,
1583
- Canonical {
1584
- binders : canonical_subst. binders ,
1585
- value : canonical_subst. value . subst ,
1586
- } ,
1587
- ) ;
1588
- }
1589
- Some ( Solution :: Ambig ( Guidance :: Definite ( substs) ) ) => {
1590
- canonicalized. apply_solution ( table, substs) ;
1591
- }
1592
- Some ( _) => ( ) ,
1593
- None => return IsValidCandidate :: No ,
1534
+ // We need to consider the bounds on the impl to distinguish functions of the same name
1535
+ // for a type.
1536
+ let predicates = db. generic_predicates ( impl_id. into ( ) ) ;
1537
+ let goals = predicates. iter ( ) . map ( |p| {
1538
+ let ( p, b) = p
1539
+ . clone ( )
1540
+ . substitute ( Interner , & impl_subst)
1541
+ // Skipping the inner binders is ok, as we don't handle quantified where
1542
+ // clauses yet.
1543
+ . into_value_and_skipped_binders ( ) ;
1544
+ stdx:: always!( b. len( Interner ) == 0 ) ;
1545
+
1546
+ p. cast :: < Goal > ( Interner )
1547
+ } ) ;
1548
+
1549
+ for goal in goals. clone ( ) {
1550
+ let in_env = InEnvironment :: new ( & table. trait_env . env , goal) ;
1551
+ let canonicalized = table. canonicalize ( in_env) ;
1552
+ let solution = table. db . trait_solve (
1553
+ table. trait_env . krate ,
1554
+ table. trait_env . block ,
1555
+ canonicalized. value . clone ( ) ,
1556
+ ) ;
1557
+
1558
+ match solution {
1559
+ Some ( Solution :: Unique ( canonical_subst) ) => {
1560
+ canonicalized. apply_solution (
1561
+ table,
1562
+ Canonical {
1563
+ binders : canonical_subst. binders ,
1564
+ value : canonical_subst. value . subst ,
1565
+ } ,
1566
+ ) ;
1594
1567
}
1595
- }
1596
-
1597
- for goal in goals {
1598
- if table. try_obligation ( goal) . is_none ( ) {
1599
- return IsValidCandidate :: No ;
1568
+ Some ( Solution :: Ambig ( Guidance :: Definite ( substs) ) ) => {
1569
+ canonicalized. apply_solution ( table, substs) ;
1600
1570
}
1571
+ Some ( _) => ( ) ,
1572
+ None => return IsValidCandidate :: No ,
1601
1573
}
1574
+ }
1602
1575
1603
- IsValidCandidate :: Yes
1604
- } else {
1605
- // For `ItemContainerId::TraitId`, we check if `self_ty` implements the trait in
1606
- // `iterate_trait_method_candidates()`.
1607
- // For others, this function shouldn't be called.
1608
- IsValidCandidate :: Yes
1576
+ for goal in goals {
1577
+ if table. try_obligation ( goal) . is_none ( ) {
1578
+ return IsValidCandidate :: No ;
1579
+ }
1609
1580
}
1581
+
1582
+ IsValidCandidate :: Yes
1610
1583
} )
1611
1584
}
1612
1585
0 commit comments