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.rs | 156 |
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 }, )); } |