Skip to content

Commit ea82cc4

Browse files
committed
Auto merge of rust-lang#16692 - Veykril:methres, r=Veykril
internal: Remove dead branches in `method_resolution::is_valid_candidate`
2 parents d4d9d0c + 3a1b4c2 commit ea82cc4

File tree

1 file changed

+109
-136
lines changed

1 file changed

+109
-136
lines changed

crates/hir-ty/src/method_resolution.rs

Lines changed: 109 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)