Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/method_resolution.rs')
-rw-r--r--crates/hir-ty/src/method_resolution.rs156
1 files changed, 75 insertions, 81 deletions
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index e68dbe7b02..a679a114b4 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -213,7 +213,7 @@ impl TraitImpls {
// To better support custom derives, collect impls in all unnamed const items.
// const _: () = { ... };
- for konst in module_data.scope.unnamed_consts(db.upcast()) {
+ for konst in module_data.scope.unnamed_consts() {
let body = db.body(konst.into());
for (_, block_def_map) in body.blocks(db.upcast()) {
Self::collect_def_map(db, map, &block_def_map);
@@ -337,7 +337,7 @@ impl InherentImpls {
// To better support custom derives, collect impls in all unnamed const items.
// const _: () = { ... };
- for konst in module_data.scope.unnamed_consts(db.upcast()) {
+ for konst in module_data.scope.unnamed_consts() {
let body = db.body(konst.into());
for (_, block_def_map) in body.blocks(db.upcast()) {
self.collect_def_map(db, &block_def_map);
@@ -972,10 +972,9 @@ pub fn iterate_method_candidates_dyn(
deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
iterate_method_candidates_with_autoref(
- &receiver_ty,
+ &mut table,
+ receiver_ty,
adj,
- db,
- env.clone(),
traits_in_scope,
visible_from_module,
name,
@@ -1000,10 +999,9 @@ pub fn iterate_method_candidates_dyn(
#[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_with_autoref(
- receiver_ty: &Canonical<Ty>,
+ table: &mut InferenceTable<'_>,
+ receiver_ty: Canonical<Ty>,
first_adjustment: ReceiverAdjustments,
- db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
@@ -1016,10 +1014,9 @@ fn iterate_method_candidates_with_autoref(
let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| {
iterate_method_candidates_by_receiver(
+ table,
receiver_ty,
first_adjustment,
- db,
- env.clone(),
traits_in_scope,
visible_from_module,
name,
@@ -1034,7 +1031,7 @@ fn iterate_method_candidates_with_autoref(
maybe_reborrowed.autoderefs += 1;
}
- iterate_method_candidates_by_receiver(receiver_ty, maybe_reborrowed)?;
+ iterate_method_candidates_by_receiver(receiver_ty.clone(), maybe_reborrowed)?;
let refed = Canonical {
value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone())
@@ -1042,7 +1039,7 @@ fn iterate_method_candidates_with_autoref(
binders: receiver_ty.binders.clone(),
};
- iterate_method_candidates_by_receiver(&refed, first_adjustment.with_autoref(Mutability::Not))?;
+ iterate_method_candidates_by_receiver(refed, first_adjustment.with_autoref(Mutability::Not))?;
let ref_muted = Canonical {
value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value.clone())
@@ -1050,58 +1047,53 @@ fn iterate_method_candidates_with_autoref(
binders: receiver_ty.binders.clone(),
};
- iterate_method_candidates_by_receiver(
- &ref_muted,
- first_adjustment.with_autoref(Mutability::Mut),
- )
+ iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
}
#[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_by_receiver(
- receiver_ty: &Canonical<Ty>,
+ table: &mut InferenceTable<'_>,
+ receiver_ty: Canonical<Ty>,
receiver_adjustments: ReceiverAdjustments,
- db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
) -> ControlFlow<()> {
- let mut table = InferenceTable::new(db, env);
let receiver_ty = table.instantiate_canonical(receiver_ty.clone());
- let snapshot = table.snapshot();
// We're looking for methods with *receiver* type receiver_ty. These could
// be found in any of the derefs of receiver_ty, so we have to go through
// that, including raw derefs.
- let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone(), true);
- while let Some((self_ty, _)) = autoderef.next() {
- iterate_inherent_methods(
- &self_ty,
- autoderef.table,
- name,
- Some(&receiver_ty),
- Some(receiver_adjustments.clone()),
- visible_from_module,
- &mut callback,
- )?
- }
-
- table.rollback_to(snapshot);
-
- let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone(), true);
- while let Some((self_ty, _)) = autoderef.next() {
- iterate_trait_method_candidates(
- &self_ty,
- autoderef.table,
- traits_in_scope,
- name,
- Some(&receiver_ty),
- Some(receiver_adjustments.clone()),
- &mut callback,
- )?
- }
-
- ControlFlow::Continue(())
+ table.run_in_snapshot(|table| {
+ let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
+ while let Some((self_ty, _)) = autoderef.next() {
+ iterate_inherent_methods(
+ &self_ty,
+ autoderef.table,
+ name,
+ Some(&receiver_ty),
+ Some(receiver_adjustments.clone()),
+ visible_from_module,
+ &mut callback,
+ )?
+ }
+ ControlFlow::Continue(())
+ })?;
+ table.run_in_snapshot(|table| {
+ let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
+ while let Some((self_ty, _)) = autoderef.next() {
+ iterate_trait_method_candidates(
+ &self_ty,
+ autoderef.table,
+ traits_in_scope,
+ name,
+ Some(&receiver_ty),
+ Some(receiver_adjustments.clone()),
+ &mut callback,
+ )?
+ }
+ ControlFlow::Continue(())
+ })
}
#[tracing::instrument(skip_all, fields(name = ?name))]
@@ -1147,9 +1139,9 @@ fn iterate_trait_method_candidates(
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
) -> ControlFlow<()> {
let db = table.db;
- let env = table.trait_env.clone();
- let canonical_self_ty = table.canonicalize(self_ty.clone()).value;
+ let canonical_self_ty = table.canonicalize(self_ty.clone());
+ let TraitEnvironment { krate, block, .. } = *table.trait_env;
'traits: for &t in traits_in_scope {
let data = db.trait_data(t);
@@ -1164,7 +1156,7 @@ fn iterate_trait_method_candidates(
{
// FIXME: this should really be using the edition of the method name's span, in case it
// comes from a macro
- if db.crate_graph()[env.krate].edition < Edition::Edition2021 {
+ if db.crate_graph()[krate].edition < Edition::Edition2021 {
continue;
}
}
@@ -1183,8 +1175,8 @@ fn iterate_trait_method_candidates(
IsValidCandidate::No => continue,
};
if !known_implemented {
- let goal = generic_implements_goal(db, env.clone(), t, &canonical_self_ty);
- if db.trait_solve(env.krate, env.block, goal.cast(Interner)).is_none() {
+ let goal = generic_implements_goal(db, &table.trait_env, t, &canonical_self_ty);
+ if db.trait_solve(krate, block, goal.cast(Interner)).is_none() {
continue 'traits;
}
}
@@ -1365,7 +1357,7 @@ pub(crate) fn resolve_indexing_op(
let ty = table.instantiate_canonical(ty);
let deref_chain = autoderef_method_receiver(&mut table, ty);
for (ty, adj) in deref_chain {
- let goal = generic_implements_goal(db, table.trait_env.clone(), index_trait, &ty);
+ let goal = generic_implements_goal(db, &table.trait_env, index_trait, &ty);
if db
.trait_solve(table.trait_env.krate, table.trait_env.block, goal.cast(Interner))
.is_some()
@@ -1548,7 +1540,7 @@ fn is_valid_impl_fn_candidate(
for goal in goals.clone() {
let in_env = InEnvironment::new(&table.trait_env.env, goal);
- let canonicalized = table.canonicalize(in_env);
+ let canonicalized = table.canonicalize_with_free_vars(in_env);
let solution = table.db.trait_solve(
table.trait_env.krate,
table.trait_env.block,
@@ -1586,10 +1578,10 @@ fn is_valid_impl_fn_candidate(
pub fn implements_trait(
ty: &Canonical<Ty>,
db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ env: &TraitEnvironment,
trait_: TraitId,
) -> bool {
- let goal = generic_implements_goal(db, env.clone(), trait_, ty);
+ let goal = generic_implements_goal(db, env, trait_, ty);
let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
solution.is_some()
@@ -1598,10 +1590,10 @@ pub fn implements_trait(
pub fn implements_trait_unique(
ty: &Canonical<Ty>,
db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ env: &TraitEnvironment,
trait_: TraitId,
) -> bool {
- let goal = generic_implements_goal(db, env.clone(), trait_, ty);
+ let goal = generic_implements_goal(db, env, trait_, ty);
let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
matches!(solution, Some(crate::Solution::Unique(_)))
@@ -1612,32 +1604,34 @@ pub fn implements_trait_unique(
#[tracing::instrument(skip_all)]
fn generic_implements_goal(
db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ env: &TraitEnvironment,
trait_: TraitId,
self_ty: &Canonical<Ty>,
) -> Canonical<InEnvironment<super::DomainGoal>> {
- let mut kinds = self_ty.binders.interned().to_vec();
+ let binders = self_ty.binders.interned();
let trait_ref = TyBuilder::trait_ref(db, trait_)
.push(self_ty.value.clone())
- .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
+ .fill_with_bound_vars(DebruijnIndex::INNERMOST, binders.len())
.build();
- kinds.extend(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
- let vk = match it.data(Interner) {
- chalk_ir::GenericArgData::Ty(_) => {
- chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
- }
- chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
- chalk_ir::GenericArgData::Const(c) => {
- chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
- }
- };
- chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
- }));
+
+ let kinds =
+ binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
+ let vk = match it.data(Interner) {
+ chalk_ir::GenericArgData::Ty(_) => {
+ chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
+ }
+ chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
+ chalk_ir::GenericArgData::Const(c) => {
+ chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
+ }
+ };
+ chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
+ }));
+ let binders = CanonicalVarKinds::from_iter(Interner, kinds);
+
let obligation = trait_ref.cast(Interner);
- Canonical {
- binders: CanonicalVarKinds::from_iter(Interner, kinds),
- value: InEnvironment::new(&env.env, obligation),
- }
+ let value = InEnvironment::new(&env.env, obligation);
+ Canonical { binders, value }
}
fn autoderef_method_receiver(
@@ -1648,7 +1642,7 @@ fn autoderef_method_receiver(
let mut autoderef = autoderef::Autoderef::new(table, ty, false);
while let Some((ty, derefs)) = autoderef.next() {
deref_chain.push((
- autoderef.table.canonicalize(ty).value,
+ autoderef.table.canonicalize(ty),
ReceiverAdjustments { autoref: None, autoderefs: derefs, unsize_array: false },
));
}