Skip to content

Commit 29f01cd

Browse files
committed
Various cleanups
- remove Valid, it serves no purpose and just obscures the diff - rename some things - don't use is_valid_candidate when searching for impl, it's not necessary
1 parent 1064c75 commit 29f01cd

File tree

2 files changed

+122
-145
lines changed

2 files changed

+122
-145
lines changed

crates/hir-ty/src/method_resolution.rs

Lines changed: 120 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -576,30 +576,57 @@ pub(crate) fn iterate_method_candidates<T>(
576576
slot
577577
}
578578

579-
pub fn lookup_trait_m_for_self_ty(
579+
pub fn lookup_impl_method(
580580
self_ty: &Ty,
581581
db: &dyn HirDatabase,
582582
env: Arc<TraitEnvironment>,
583-
implied_trait: TraitId,
583+
trait_: TraitId,
584584
name: &Name,
585585
) -> Option<FunctionId> {
586-
let self_ty_tp = TyFingerprint::for_trait_impl(self_ty)?;
586+
let self_ty_fp = TyFingerprint::for_trait_impl(self_ty)?;
587587
let trait_impls = TraitImpls::trait_impls_in_deps_query(db, env.krate);
588-
let impls = trait_impls.for_trait_and_self_ty(implied_trait, self_ty_tp);
588+
let impls = trait_impls.for_trait_and_self_ty(trait_, self_ty_fp);
589589
let mut table = InferenceTable::new(db, env.clone());
590-
if let Some(data) = Valid::valid_impl(impls, &mut table, &self_ty) {
591-
for &impl_item in data.items.iter() {
592-
if Valid::is_valid_item(&mut table, Some(name), None, impl_item, self_ty, None) {
593-
match impl_item {
594-
AssocItemId::FunctionId(f) => {
595-
return Some(f);
596-
}
597-
_ => (),
598-
}
599-
}
590+
find_matching_impl(impls, &mut table, &self_ty).and_then(|data| {
591+
data.items.iter().find_map(|it| match it {
592+
AssocItemId::FunctionId(f) => (db.function_data(*f).name == *name).then_some(*f),
593+
_ => None,
594+
})
595+
})
596+
}
597+
598+
fn find_matching_impl(
599+
mut impls: impl Iterator<Item = ImplId>,
600+
table: &mut InferenceTable,
601+
self_ty: &Ty,
602+
) -> Option<Arc<ImplData>> {
603+
let db = table.db;
604+
loop {
605+
let impl_ = impls.next()?;
606+
let r = table.run_in_snapshot(|table| {
607+
let impl_data = db.impl_data(impl_);
608+
let substs =
609+
TyBuilder::subst_for_def(db, impl_).fill_with_inference_vars(table).build();
610+
let impl_ty = db.impl_self_ty(impl_).substitute(Interner, &substs);
611+
612+
table
613+
.unify(self_ty, &impl_ty)
614+
.then(|| {
615+
let wh_goals =
616+
crate::chalk_db::convert_where_clauses(db, impl_.into(), &substs)
617+
.into_iter()
618+
.map(|b| b.into_well_formed_goal(Interner).cast(Interner));
619+
620+
let goal = crate::Goal::all(Interner, wh_goals);
621+
622+
table.try_obligation(goal).map(|_| impl_data)
623+
})
624+
.flatten()
625+
});
626+
if r.is_some() {
627+
break r;
600628
}
601629
}
602-
None
603630
}
604631

605632
pub fn iterate_path_candidates(
@@ -877,7 +904,7 @@ fn iterate_trait_method_candidates(
877904
for &(_, item) in data.items.iter() {
878905
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
879906
// since only inherent methods should be included into visibility checking.
880-
if !Valid::is_valid_item(table, name, receiver_ty, item, self_ty, None) {
907+
if !is_valid_candidate(table, name, receiver_ty, item, self_ty, None) {
881908
continue;
882909
}
883910
if !known_implemented {
@@ -959,14 +986,8 @@ fn iterate_inherent_methods(
959986
let impls_for_self_ty = impls.for_self_ty(self_ty);
960987
for &impl_def in impls_for_self_ty {
961988
for &item in &db.impl_data(impl_def).items {
962-
if !Valid::is_valid_item(
963-
table,
964-
name,
965-
receiver_ty,
966-
item,
967-
self_ty,
968-
visible_from_module,
969-
) {
989+
if !is_valid_candidate(table, name, receiver_ty, item, self_ty, visible_from_module)
990+
{
970991
continue;
971992
}
972993
callback(receiver_adjustments.clone().unwrap_or_default(), item)?;
@@ -994,130 +1015,92 @@ pub fn resolve_indexing_op(
9941015
}
9951016
None
9961017
}
997-
struct Valid;
998-
impl Valid {
999-
fn valid_impl(
1000-
mut impls: impl Iterator<Item = ImplId>,
1001-
table: &mut InferenceTable,
1002-
self_ty: &Ty,
1003-
) -> Option<Arc<ImplData>> {
1004-
let db = table.db;
1005-
loop {
1006-
let impl_ = impls.next()?;
1007-
let r = table.run_in_snapshot(|table| {
1008-
let impl_data = db.impl_data(impl_);
1009-
let substs =
1010-
TyBuilder::subst_for_def(db, impl_).fill_with_inference_vars(table).build();
1011-
let impl_ty = substs
1012-
.apply(db.impl_self_ty(impl_).into_value_and_skipped_binders().0, Interner);
1013-
1014-
table
1015-
.unify(self_ty, &impl_ty)
1016-
.then(|| {
1017-
let wh_goals =
1018-
crate::chalk_db::convert_where_clauses(db, impl_.into(), &substs)
1019-
.into_iter()
1020-
.map(|b| b.into_well_formed_goal(Interner).cast(Interner));
1021-
1022-
let goal = crate::Goal::all(Interner, wh_goals);
1023-
1024-
table.try_obligation(goal).map(|_| impl_data)
1025-
})
1026-
.flatten()
1027-
});
1028-
if r.is_some() {
1029-
break r;
1018+
1019+
fn is_valid_candidate(
1020+
table: &mut InferenceTable,
1021+
name: Option<&Name>,
1022+
receiver_ty: Option<&Ty>,
1023+
item: AssocItemId,
1024+
self_ty: &Ty,
1025+
visible_from_module: Option<ModuleId>,
1026+
) -> bool {
1027+
macro_rules! check_that {
1028+
($cond:expr) => {
1029+
if !$cond {
1030+
return false;
10301031
}
1031-
}
1032+
};
10321033
}
10331034

1034-
fn is_valid_item(
1035-
table: &mut InferenceTable,
1036-
name: Option<&Name>,
1037-
receiver_ty: Option<&Ty>,
1038-
item: AssocItemId,
1039-
self_ty: &Ty,
1040-
visible_from_module: Option<ModuleId>,
1041-
) -> bool {
1042-
macro_rules! assert {
1043-
($cond:expr) => {
1044-
if !$cond {
1045-
return false;
1035+
let db = table.db;
1036+
match item {
1037+
AssocItemId::FunctionId(m) => {
1038+
let data = db.function_data(m);
1039+
1040+
check_that!(name.map_or(true, |n| n == &data.name));
1041+
check_that!(visible_from_module.map_or(true, |from_module| {
1042+
let v = db.function_visibility(m).is_visible_from(db.upcast(), from_module);
1043+
if !v {
1044+
cov_mark::hit!(autoderef_candidate_not_visible);
10461045
}
1047-
};
1048-
}
1049-
1050-
let db = table.db;
1051-
match item {
1052-
AssocItemId::FunctionId(m) => {
1053-
let data = db.function_data(m);
1054-
1055-
assert!(name.map_or(true, |n| n == &data.name));
1056-
assert!(visible_from_module.map_or(true, |from_module| {
1057-
let v = db.function_visibility(m).is_visible_from(db.upcast(), from_module);
1058-
if !v {
1059-
cov_mark::hit!(autoderef_candidate_not_visible);
1060-
}
1061-
v
1062-
}));
1063-
1064-
table.run_in_snapshot(|table| {
1065-
let subst =
1066-
TyBuilder::subst_for_def(db, m).fill_with_inference_vars(table).build();
1067-
let expect_self_ty = match m.lookup(db.upcast()).container {
1068-
ItemContainerId::TraitId(_) => {
1069-
subst.at(Interner, 0).assert_ty_ref(Interner).clone()
1070-
}
1071-
ItemContainerId::ImplId(impl_id) => {
1072-
subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner)
1073-
}
1074-
// We should only get called for associated items (impl/trait)
1075-
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
1076-
unreachable!()
1077-
}
1078-
};
1079-
assert!(table.unify(&expect_self_ty, self_ty));
1080-
if let Some(receiver_ty) = receiver_ty {
1081-
assert!(data.has_self_param());
1082-
1083-
let sig = db.callable_item_signature(m.into());
1084-
let expected_receiver =
1085-
sig.map(|s| s.params()[0].clone()).substitute(Interner, &subst);
1086-
1087-
assert!(table.unify(&receiver_ty, &expected_receiver));
1046+
v
1047+
}));
1048+
1049+
table.run_in_snapshot(|table| {
1050+
let subst = TyBuilder::subst_for_def(db, m).fill_with_inference_vars(table).build();
1051+
let expect_self_ty = match m.lookup(db.upcast()).container {
1052+
ItemContainerId::TraitId(_) => {
1053+
subst.at(Interner, 0).assert_ty_ref(Interner).clone()
10881054
}
1089-
true
1090-
})
1091-
}
1092-
AssocItemId::ConstId(c) => {
1093-
let data = db.const_data(c);
1094-
assert!(receiver_ty.is_none());
1095-
1096-
assert!(name.map_or(true, |n| data.name.as_ref() == Some(n)));
1097-
assert!(visible_from_module.map_or(true, |from_module| {
1098-
let v = db.const_visibility(c).is_visible_from(db.upcast(), from_module);
1099-
if !v {
1100-
cov_mark::hit!(const_candidate_not_visible);
1055+
ItemContainerId::ImplId(impl_id) => {
1056+
subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner)
11011057
}
1102-
v
1103-
}));
1104-
if let ItemContainerId::ImplId(impl_id) = c.lookup(db.upcast()).container {
1105-
let self_ty_matches = table.run_in_snapshot(|table| {
1106-
let subst =
1107-
TyBuilder::subst_for_def(db, c).fill_with_inference_vars(table).build();
1108-
let expected_self_ty =
1109-
subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner);
1110-
table.unify(&expected_self_ty, &self_ty)
1111-
});
1112-
if !self_ty_matches {
1113-
cov_mark::hit!(const_candidate_self_type_mismatch);
1114-
return false;
1058+
// We should only get called for associated items (impl/trait)
1059+
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
1060+
unreachable!()
11151061
}
1062+
};
1063+
check_that!(table.unify(&expect_self_ty, self_ty));
1064+
if let Some(receiver_ty) = receiver_ty {
1065+
check_that!(data.has_self_param());
1066+
1067+
let sig = db.callable_item_signature(m.into());
1068+
let expected_receiver =
1069+
sig.map(|s| s.params()[0].clone()).substitute(Interner, &subst);
1070+
1071+
check_that!(table.unify(&receiver_ty, &expected_receiver));
11161072
}
11171073
true
1074+
})
1075+
}
1076+
AssocItemId::ConstId(c) => {
1077+
let data = db.const_data(c);
1078+
check_that!(receiver_ty.is_none());
1079+
1080+
check_that!(name.map_or(true, |n| data.name.as_ref() == Some(n)));
1081+
check_that!(visible_from_module.map_or(true, |from_module| {
1082+
let v = db.const_visibility(c).is_visible_from(db.upcast(), from_module);
1083+
if !v {
1084+
cov_mark::hit!(const_candidate_not_visible);
1085+
}
1086+
v
1087+
}));
1088+
if let ItemContainerId::ImplId(impl_id) = c.lookup(db.upcast()).container {
1089+
let self_ty_matches = table.run_in_snapshot(|table| {
1090+
let subst =
1091+
TyBuilder::subst_for_def(db, c).fill_with_inference_vars(table).build();
1092+
let expected_self_ty =
1093+
subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner);
1094+
table.unify(&expected_self_ty, &self_ty)
1095+
});
1096+
if !self_ty_matches {
1097+
cov_mark::hit!(const_candidate_self_type_mismatch);
1098+
return false;
1099+
}
11181100
}
1119-
_ => false,
1101+
true
11201102
}
1103+
_ => false,
11211104
}
11221105
}
11231106

crates/hir/src/source_analyzer.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl SourceAnalyzer {
281281
_ => (),
282282
};
283283
let (func, self_ty) = fun_info?;
284-
let implied_trait = match func.lookup(db.upcast()).container {
284+
let impled_trait = match func.lookup(db.upcast()).container {
285285
ItemContainerId::TraitId(trait_id) => trait_id,
286286
_ => return None,
287287
};
@@ -293,13 +293,7 @@ impl SourceAnalyzer {
293293
);
294294

295295
let fun_data = db.function_data(func);
296-
method_resolution::lookup_trait_m_for_self_ty(
297-
&self_ty,
298-
db,
299-
trait_env,
300-
implied_trait,
301-
&fun_data.name,
302-
)
296+
method_resolution::lookup_impl_method(&self_ty, db, trait_env, impled_trait, &fun_data.name)
303297
}
304298

305299
pub(crate) fn resolve_field(

0 commit comments

Comments
 (0)