@@ -1176,11 +1176,12 @@ fn iterate_trait_method_candidates(
11761176 for & ( _, item) in data. items . iter ( ) {
11771177 // Don't pass a `visible_from_module` down to `is_valid_candidate`,
11781178 // 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+ } ;
11841185 if !known_implemented {
11851186 let goal = generic_implements_goal ( db, env. clone ( ) , t, & canonical_self_ty) ;
11861187 if db. trait_solve ( env. krate , env. block , goal. cast ( Interner ) ) . is_none ( ) {
@@ -1302,12 +1303,18 @@ fn iterate_inherent_methods(
13021303 let data = db. trait_data ( t) ;
13031304 for & ( _, item) in data. items . iter ( ) {
13041305 // 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+ } ;
13111318 callback ( receiver_adjustments. clone ( ) . unwrap_or_default ( ) , item, visible) ?;
13121319 }
13131320 }
@@ -1325,17 +1332,16 @@ fn iterate_inherent_methods(
13251332 visible_from_module : Option < ModuleId > ,
13261333 callback : & mut dyn FnMut ( ReceiverAdjustments , AssocItemId , bool ) -> ControlFlow < ( ) > ,
13271334 ) -> 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 (
13331338 table,
1334- name,
1335- receiver_ty,
1336- item,
13371339 self_ty,
1340+ receiver_ty,
13381341 visible_from_module,
1342+ name,
1343+ impl_id,
1344+ item,
13391345 ) {
13401346 IsValidCandidate :: Yes => true ,
13411347 IsValidCandidate :: NotVisible => false ,
@@ -1378,21 +1384,34 @@ macro_rules! check_that {
13781384 } ;
13791385}
13801386
1387+ enum IsValidCandidate {
1388+ Yes ,
1389+ No ,
1390+ NotVisible ,
1391+ }
1392+
13811393#[ tracing:: instrument( skip_all, fields( name) ) ]
1382- fn is_valid_candidate (
1394+ fn is_valid_impl_method_candidate (
13831395 table : & mut InferenceTable < ' _ > ,
1384- name : Option < & Name > ,
1385- receiver_ty : Option < & Ty > ,
1386- item : AssocItemId ,
13871396 self_ty : & Ty ,
1397+ receiver_ty : Option < & Ty > ,
13881398 visible_from_module : Option < ModuleId > ,
1399+ name : Option < & Name > ,
1400+ impl_id : ImplId ,
1401+ item : AssocItemId ,
13891402) -> IsValidCandidate {
1390- let db = table. db ;
13911403 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+ ) ,
13951413 AssocItemId :: ConstId ( c) => {
1414+ let db = table. db ;
13961415 check_that ! ( receiver_ty. is_none( ) ) ;
13971416 check_that ! ( name. map_or( true , |n| db. const_data( c) . name. as_ref( ) == Some ( n) ) ) ;
13981417
@@ -1402,17 +1421,14 @@ fn is_valid_candidate(
14021421 return IsValidCandidate :: NotVisible ;
14031422 }
14041423 }
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 ;
14161432 }
14171433 IsValidCandidate :: Yes
14181434 }
@@ -1421,12 +1437,10 @@ fn is_valid_candidate(
14211437}
14221438
14231439/// 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.
14271440#[ tracing:: instrument( skip_all, fields( name) ) ]
1428- fn is_valid_method_candidate (
1441+ fn is_valid_trait_method_candidate (
14291442 table : & mut InferenceTable < ' _ > ,
1443+ trait_id : TraitId ,
14301444 name : Option < & Name > ,
14311445 receiver_ty : Option < & Ty > ,
14321446 item : AssocItemId ,
@@ -1440,24 +1454,10 @@ fn is_valid_method_candidate(
14401454 check_that ! ( name. map_or( true , |n| n == & data. name) ) ;
14411455
14421456 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 ( ) ;
14611461
14621462 check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
14631463
@@ -1488,15 +1488,10 @@ fn is_valid_method_candidate(
14881488 }
14891489}
14901490
1491- enum IsValidCandidate {
1492- Yes ,
1493- No ,
1494- NotVisible ,
1495- }
1496-
14971491#[ tracing:: instrument( skip_all, fields( name) ) ]
1498- fn is_valid_fn_candidate (
1492+ fn is_valid_impl_fn_candidate (
14991493 table : & mut InferenceTable < ' _ > ,
1494+ impl_id : ImplId ,
15001495 fn_id : FunctionId ,
15011496 name : Option < & Name > ,
15021497 receiver_ty : Option < & Ty > ,
@@ -1514,24 +1509,10 @@ fn is_valid_fn_candidate(
15141509 }
15151510 }
15161511 table. run_in_snapshot ( |table| {
1517- let container = fn_id. lookup ( db. upcast ( ) ) . container ;
1518-
15191512 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) ;
15351516
15361517 check_that ! ( table. unify( & expect_self_ty, self_ty) ) ;
15371518
@@ -1550,63 +1531,55 @@ fn is_valid_fn_candidate(
15501531 check_that ! ( table. unify( receiver_ty, & expected_receiver) ) ;
15511532 }
15521533
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+ ) ;
15941567 }
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) ;
16001570 }
1571+ Some ( _) => ( ) ,
1572+ None => return IsValidCandidate :: No ,
16011573 }
1574+ }
16021575
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+ }
16091580 }
1581+
1582+ IsValidCandidate :: Yes
16101583 } )
16111584}
16121585
0 commit comments