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.rs196
1 files changed, 97 insertions, 99 deletions
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 7fa3d31fe5..61d3091a0c 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -31,10 +31,13 @@ use crate::{
infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable},
lang_items::is_box,
next_solver::{
- self, SolverDefId,
- fulfill::FulfillmentCtxt,
- infer::DefineOpaqueTypes,
+ self, DbInterner, SolverDefId,
+ infer::{
+ DefineOpaqueTypes,
+ traits::{ObligationCause, PredicateObligation},
+ },
mapping::{ChalkToNextSolver, NextSolverToChalk},
+ obligation_ctxt::ObligationCtxt,
},
primitive::{FloatTy, IntTy, UintTy},
to_chalk_trait_id,
@@ -294,11 +297,12 @@ impl TraitImpls {
continue;
}
let target_trait = match db.impl_trait(impl_id) {
- Some(tr) => tr.skip_binders().hir_trait_id(),
+ Some(tr) => tr.skip_binder().def_id.0,
None => continue,
};
- let self_ty = db.impl_self_ty(impl_id);
- let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
+ let interner = DbInterner::new_with(db, None, None);
+ let self_ty = db.impl_self_ty(impl_id).instantiate_identity().to_chalk(interner);
+ let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty);
map.entry(target_trait).or_default().entry(self_ty_fp).or_default().push(impl_id);
}
@@ -411,8 +415,8 @@ impl InherentImpls {
continue;
}
- let self_ty = db.impl_self_ty(impl_id);
- let self_ty = self_ty.skip_binders();
+ let interner = DbInterner::new_with(db, None, None);
+ let self_ty = &db.impl_self_ty(impl_id).instantiate_identity().to_chalk(interner);
match is_inherent_impl_coherent(db, def_map, impl_id, self_ty) {
true => {
@@ -542,7 +546,7 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma
pub(crate) fn lookup_method<'db>(
db: &'db dyn HirDatabase,
ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
- env: Arc<TraitEnvironment>,
+ env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: &Name,
@@ -711,7 +715,7 @@ impl ReceiverAdjustments {
pub(crate) fn iterate_method_candidates<'db, T>(
ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
@@ -739,9 +743,9 @@ pub(crate) fn iterate_method_candidates<'db, T>(
slot
}
-pub fn lookup_impl_const(
- db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+pub fn lookup_impl_const<'db>(
+ db: &'db dyn HirDatabase,
+ env: Arc<TraitEnvironment<'db>>,
const_id: ConstId,
subs: Substitution,
) -> (ConstId, Substitution) {
@@ -767,9 +771,9 @@ pub fn lookup_impl_const(
/// Checks if the self parameter of `Trait` method is the `dyn Trait` and we should
/// call the method using the vtable.
-pub fn is_dyn_method(
- db: &dyn HirDatabase,
- _env: Arc<TraitEnvironment>,
+pub fn is_dyn_method<'db>(
+ db: &'db dyn HirDatabase,
+ _env: Arc<TraitEnvironment<'db>>,
func: FunctionId,
fn_subst: Substitution,
) -> Option<usize> {
@@ -809,9 +813,9 @@ pub fn is_dyn_method(
/// Looks up the impl method that actually runs for the trait method `func`.
///
/// Returns `func` if it's not a method defined in a trait or the lookup failed.
-pub(crate) fn lookup_impl_method_query(
- db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+pub(crate) fn lookup_impl_method_query<'db>(
+ db: &'db dyn HirDatabase,
+ env: Arc<TraitEnvironment<'db>>,
func: FunctionId,
fn_subst: Substitution,
) -> (FunctionId, Substitution) {
@@ -842,10 +846,10 @@ pub(crate) fn lookup_impl_method_query(
)
}
-fn lookup_impl_assoc_item_for_trait_ref(
+fn lookup_impl_assoc_item_for_trait_ref<'db>(
trait_ref: TraitRef,
- db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ db: &'db dyn HirDatabase,
+ env: Arc<TraitEnvironment<'db>>,
name: &Name,
) -> Option<(AssocItemId, Substitution)> {
let hir_trait_id = trait_ref.hir_trait_id();
@@ -894,10 +898,13 @@ fn find_matching_impl(
table.run_in_snapshot(|table| {
let impl_substs =
TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build();
+ let args: crate::next_solver::GenericArgs<'_> =
+ impl_substs.to_nextsolver(table.interner);
let trait_ref = db
.impl_trait(impl_)
.expect("non-trait method in find_matching_impl")
- .substitute(Interner, &impl_substs);
+ .instantiate(table.interner, args)
+ .to_chalk(table.interner);
if !table.unify(&trait_ref, &actual_trait_ref) {
return None;
@@ -907,10 +914,11 @@ fn find_matching_impl(
.into_iter()
.map(|b| -> Goal { b.cast(Interner) });
for goal in wcs {
- if table.try_obligation(goal.clone()).no_solution() {
+ let goal = goal.to_nextsolver(table.interner);
+ if table.try_obligation(goal).no_solution() {
return None;
}
- table.register_obligation(goal.to_nextsolver(table.interner));
+ table.register_obligation(goal);
}
Some((
impl_.impl_items(db),
@@ -1014,7 +1022,9 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
let local_crate = impl_.lookup(db).container.krate();
let is_local = |tgt_crate| tgt_crate == local_crate;
- let trait_ref = impl_trait.substitute(Interner, &substs);
+ let interner = DbInterner::new_with(db, None, None);
+ let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
+ let trait_ref = impl_trait.instantiate(interner, args).to_chalk(interner);
let trait_id = from_chalk_trait_id(trait_ref.trait_id);
if is_local(trait_id.module(db).krate()) {
// trait to be implemented is local
@@ -1063,7 +1073,7 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
pub fn iterate_path_candidates<'db>(
ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
@@ -1085,7 +1095,7 @@ pub fn iterate_path_candidates<'db>(
pub fn iterate_method_candidates_dyn<'db>(
ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
@@ -1347,7 +1357,7 @@ fn iterate_method_candidates_by_receiver<'db>(
fn iterate_method_candidates_for_self_ty<'db>(
self_ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment>,
+ env: Arc<TraitEnvironment<'db>>,
traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule,
name: Option<&Name>,
@@ -1395,7 +1405,7 @@ fn iterate_trait_method_candidates(
let db = table.db;
let canonical_self_ty = table.canonicalize(self_ty.clone().to_nextsolver(table.interner));
- let TraitEnvironment { krate, .. } = *table.trait_env;
+ let krate = table.trait_env.krate;
'traits: for &t in traits_in_scope {
let data = db.trait_signature(t);
@@ -1635,7 +1645,6 @@ pub(crate) fn resolve_indexing_op<'db>(
let ty = table.instantiate_canonical_ns(ty);
let deref_chain = autoderef_method_receiver(table, ty);
for (ty, adj) in deref_chain {
- //let goal = generic_implements_goal_ns(db, &table.trait_env, index_trait, &ty);
let goal = generic_implements_goal_ns(table, index_trait, ty);
if !next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() {
return Some(adj);
@@ -1694,8 +1703,10 @@ fn is_valid_impl_method_candidate(
return IsValidCandidate::NotVisible;
}
let self_ty_matches = table.run_in_snapshot(|table| {
- let expected_self_ty =
- TyBuilder::impl_self_ty(db, impl_id).fill_with_inference_vars(table).build();
+ let expected_self_ty = TyBuilder::impl_self_ty(db, impl_id)
+ .fill_with_inference_vars(table)
+ .build(DbInterner::conjure())
+ .to_chalk(DbInterner::conjure());
table.unify(&expected_self_ty, self_ty)
});
if !self_ty_matches {
@@ -1741,9 +1752,13 @@ fn is_valid_trait_method_candidate(
.fill_with_inference_vars(table)
.build();
+ let args: crate::next_solver::GenericArgs<'_> =
+ fn_subst.to_nextsolver(table.interner);
let sig = db.callable_item_signature(fn_id.into());
- let expected_receiver =
- sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst);
+ let expected_receiver = sig
+ .map_bound(|s| s.skip_binder().inputs_and_output.as_slice()[0])
+ .instantiate(table.interner, args)
+ .to_chalk(table.interner);
// FIXME: Clean up this mess with some context struct like rustc's `ProbeContext`
let variance = match mode {
@@ -1754,7 +1769,7 @@ fn is_valid_trait_method_candidate(
.infer_ctxt
.at(
&next_solver::infer::traits::ObligationCause::dummy(),
- table.trait_env.env.to_nextsolver(table.interner),
+ table.trait_env.env,
)
.relate(
DefineOpaqueTypes::No,
@@ -1767,12 +1782,10 @@ fn is_valid_trait_method_candidate(
};
if !infer_ok.obligations.is_empty() {
- let mut ctxt = FulfillmentCtxt::new(&table.infer_ctxt);
- for pred in infer_ok.into_obligations() {
- ctxt.register_predicate_obligation(&table.infer_ctxt, pred);
- }
+ let mut ctxt = ObligationCtxt::new(&table.infer_ctxt);
+ ctxt.register_obligations(infer_ok.into_obligations());
// FIXME: Are we doing this correctly? Probably better to follow rustc more closely.
- check_that!(ctxt.select_where_possible(&table.infer_ctxt).is_empty());
+ check_that!(ctxt.select_where_possible().is_empty());
}
check_that!(table.unify(receiver_ty, &expected_receiver));
@@ -1815,9 +1828,11 @@ fn is_valid_impl_fn_candidate(
}
table.run_in_snapshot(|table| {
let _p = tracing::info_span!("subst_for_def").entered();
- let impl_subst =
- TyBuilder::subst_for_def(db, impl_id, None).fill_with_inference_vars(table).build();
- let expect_self_ty = db.impl_self_ty(impl_id).substitute(Interner, &impl_subst);
+ let impl_subst = table.infer_ctxt.fresh_args_for_item(impl_id.into());
+ let expect_self_ty = db
+ .impl_self_ty(impl_id)
+ .instantiate(table.interner, &impl_subst)
+ .to_chalk(table.interner);
check_that!(table.unify(&expect_self_ty, self_ty));
@@ -1825,65 +1840,49 @@ fn is_valid_impl_fn_candidate(
let _p = tracing::info_span!("check_receiver_ty").entered();
check_that!(data.has_self_param());
- let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst.clone()))
- .fill_with_inference_vars(table)
- .build();
+ let fn_subst: crate::Substitution =
+ table.infer_ctxt.fresh_args_for_item(fn_id.into()).to_chalk(table.interner);
+ let args: crate::next_solver::GenericArgs<'_> = fn_subst.to_nextsolver(table.interner);
let sig = db.callable_item_signature(fn_id.into());
- let expected_receiver =
- sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst);
+ let expected_receiver = sig
+ .map_bound(|s| s.skip_binder().inputs_and_output.as_slice()[0])
+ .instantiate(table.interner, args)
+ .to_chalk(table.interner);
check_that!(table.unify(receiver_ty, &expected_receiver));
}
// We need to consider the bounds on the impl to distinguish functions of the same name
// for a type.
- let predicates = db.generic_predicates(impl_id.into());
- let goals = predicates.iter().map(|p| {
- let (p, b) = p
- .clone()
- .substitute(Interner, &impl_subst)
- // Skipping the inner binders is ok, as we don't handle quantified where
- // clauses yet.
- .into_value_and_skipped_binders();
- stdx::always!(b.len(Interner) == 0);
-
- p.cast::<Goal>(Interner)
- });
-
- for goal in goals.clone() {
- match table.solve_obligation(goal) {
- Ok(_) => {}
- Err(_) => {
- return IsValidCandidate::No;
- }
- }
- }
+ let predicates = db.generic_predicates_ns(impl_id.into());
+ let Some(predicates) = predicates.instantiate(table.interner, impl_subst) else {
+ return IsValidCandidate::Yes;
+ };
- for goal in goals {
- if table.try_obligation(goal).no_solution() {
- return IsValidCandidate::No;
- }
- }
+ let mut ctxt = ObligationCtxt::new(&table.infer_ctxt);
- IsValidCandidate::Yes
- })
-}
+ ctxt.register_obligations(predicates.into_iter().map(|p| {
+ PredicateObligation::new(
+ table.interner,
+ ObligationCause::new(),
+ table.trait_env.env,
+ p.0,
+ )
+ }));
-pub fn implements_trait(
- ty: &Canonical<Ty>,
- db: &dyn HirDatabase,
- env: &TraitEnvironment,
- trait_: TraitId,
-) -> bool {
- let goal = generic_implements_goal(db, env, trait_, ty);
- !db.trait_solve(env.krate, env.block, goal.cast(Interner)).no_solution()
+ if ctxt.select_where_possible().is_empty() {
+ IsValidCandidate::Yes
+ } else {
+ IsValidCandidate::No
+ }
+ })
}
-pub fn implements_trait_unique(
+pub fn implements_trait_unique<'db>(
ty: &Canonical<Ty>,
- db: &dyn HirDatabase,
- env: &TraitEnvironment,
+ db: &'db dyn HirDatabase,
+ env: &TraitEnvironment<'db>,
trait_: TraitId,
) -> bool {
let goal = generic_implements_goal(db, env, trait_, ty);
@@ -1891,11 +1890,11 @@ pub fn implements_trait_unique(
}
/// This creates Substs for a trait with the given Self type and type variables
-/// for all other parameters, to query Chalk with it.
+/// for all other parameters, to query next solver with it.
#[tracing::instrument(skip_all)]
-fn generic_implements_goal(
- db: &dyn HirDatabase,
- env: &TraitEnvironment,
+fn generic_implements_goal<'db>(
+ db: &'db dyn HirDatabase,
+ env: &TraitEnvironment<'db>,
trait_: TraitId,
self_ty: &Canonical<Ty>,
) -> Canonical<InEnvironment<super::DomainGoal>> {
@@ -1917,7 +1916,10 @@ fn generic_implements_goal(
let binders = CanonicalVarKinds::from_iter(Interner, kinds);
let obligation = trait_ref.cast(Interner);
- let value = InEnvironment::new(&env.env, obligation);
+ let value = InEnvironment::new(
+ &env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)),
+ obligation,
+ );
Canonical { binders, value }
}
@@ -1934,11 +1936,7 @@ fn generic_implements_goal_ns<'db>(
let trait_ref =
rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args)
.with_replaced_self_ty(table.infer_ctxt.interner, self_ty);
- let goal = next_solver::Goal::new(
- table.infer_ctxt.interner,
- table.trait_env.env.to_nextsolver(table.infer_ctxt.interner),
- trait_ref,
- );
+ let goal = next_solver::Goal::new(table.infer_ctxt.interner, table.trait_env.env, trait_ref);
table.canonicalize(goal)
}