mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-28 10:39:45 +00:00
Merge pull request #20717 from ShoyuVanilla/migrate-more
internal: Migrate more predicate things to next-solver
This commit is contained in:
commit
7d9af9f6a5
5 changed files with 118 additions and 149 deletions
|
|
@ -11,39 +11,35 @@ use hir_def::{AdtId, lang_item::LangItem};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use intern::sym;
|
use intern::sym;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use rustc_type_ir::inherent::Ty as _;
|
|
||||||
use rustc_type_ir::{
|
use rustc_type_ir::{
|
||||||
FloatVid, IntVid, TyVid, TypeVisitableExt,
|
FloatVid, IntVid, TyVid, TypeVisitableExt, UpcastFrom,
|
||||||
inherent::{IntoKind, Span, Term as _},
|
inherent::{IntoKind, Span, Term as _, Ty as _},
|
||||||
relate::{Relate, solver_relating::RelateExt},
|
relate::{Relate, solver_relating::RelateExt},
|
||||||
solve::{Certainty, GoalSource, NoSolution},
|
solve::{Certainty, GoalSource},
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use super::{InferResult, InferenceContext, TypeError};
|
use super::{InferResult, InferenceContext, TypeError};
|
||||||
use crate::next_solver::ErrorGuaranteed;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, GenericArg, GenericArgData,
|
AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, GenericArg, GenericArgData,
|
||||||
Goal, GoalData, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind,
|
InferenceVar, Interner, Lifetime, OpaqueTyId, ProjectionTy, Scalar, Substitution,
|
||||||
ProjectionTy, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
|
TraitEnvironment, Ty, TyExt, TyKind, VariableKind,
|
||||||
VariableKind, WhereClause,
|
|
||||||
consteval::unknown_const,
|
consteval::unknown_const,
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
fold_generic_args, fold_tys_and_consts,
|
fold_generic_args, fold_tys_and_consts,
|
||||||
next_solver::infer::InferOk,
|
|
||||||
next_solver::{
|
next_solver::{
|
||||||
self, ClauseKind, DbInterner, ParamEnv, Predicate, PredicateKind, SolverDefIds, Term,
|
self, ClauseKind, DbInterner, ErrorGuaranteed, ParamEnv, Predicate, PredicateKind,
|
||||||
|
SolverDefIds, Term, TraitRef,
|
||||||
fulfill::FulfillmentCtxt,
|
fulfill::FulfillmentCtxt,
|
||||||
infer::{
|
infer::{
|
||||||
DbInternerInferExt, InferCtxt,
|
DbInternerInferExt, InferCtxt, InferOk,
|
||||||
snapshot::CombinedSnapshot,
|
snapshot::CombinedSnapshot,
|
||||||
traits::{Obligation, ObligationCause},
|
traits::{Obligation, ObligationCause},
|
||||||
},
|
},
|
||||||
inspect::{InspectConfig, InspectGoal, ProofTreeVisitor},
|
inspect::{InspectConfig, InspectGoal, ProofTreeVisitor},
|
||||||
mapping::{ChalkToNextSolver, NextSolverToChalk},
|
mapping::{ChalkToNextSolver, NextSolverToChalk},
|
||||||
},
|
},
|
||||||
to_chalk_trait_id,
|
|
||||||
traits::{
|
traits::{
|
||||||
FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt,
|
FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt,
|
||||||
},
|
},
|
||||||
|
|
@ -877,26 +873,15 @@ impl<'db> InferenceTable<'db> {
|
||||||
/// whether a trait *might* be implemented before deciding to 'lock in' the
|
/// whether a trait *might* be implemented before deciding to 'lock in' the
|
||||||
/// choice (during e.g. method resolution or deref).
|
/// choice (during e.g. method resolution or deref).
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn try_obligation(&mut self, goal: Goal) -> NextTraitSolveResult {
|
pub(crate) fn try_obligation(&mut self, predicate: Predicate<'db>) -> NextTraitSolveResult {
|
||||||
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
let goal = next_solver::Goal { param_env: self.param_env, predicate };
|
||||||
let canonicalized = self.canonicalize(in_env.to_nextsolver(self.interner));
|
let canonicalized = self.canonicalize(goal);
|
||||||
|
|
||||||
next_trait_solve_canonical_in_ctxt(&self.infer_ctxt, canonicalized)
|
next_trait_solve_canonical_in_ctxt(&self.infer_ctxt, canonicalized)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
|
||||||
pub(crate) fn solve_obligation(&mut self, goal: Goal) -> Result<Certainty, NoSolution> {
|
|
||||||
let goal = InEnvironment::new(&self.trait_env.env, goal);
|
|
||||||
let goal = goal.to_nextsolver(self.interner);
|
|
||||||
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
|
|
||||||
result.map(|m| m.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn register_obligation(&mut self, predicate: Predicate<'db>) {
|
pub(crate) fn register_obligation(&mut self, predicate: Predicate<'db>) {
|
||||||
let goal = next_solver::Goal {
|
let goal = next_solver::Goal { param_env: self.param_env, predicate };
|
||||||
param_env: self.trait_env.env.to_nextsolver(self.interner),
|
|
||||||
predicate,
|
|
||||||
};
|
|
||||||
self.register_obligation_in_env(goal)
|
self.register_obligation_in_env(goal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -984,7 +969,7 @@ impl<'db> InferenceTable<'db> {
|
||||||
&mut self,
|
&mut self,
|
||||||
ty: &Ty,
|
ty: &Ty,
|
||||||
num_args: usize,
|
num_args: usize,
|
||||||
) -> Option<(FnTrait, Vec<crate::next_solver::Ty<'db>>, crate::next_solver::Ty<'db>)> {
|
) -> Option<(FnTrait, Vec<next_solver::Ty<'db>>, next_solver::Ty<'db>)> {
|
||||||
for (fn_trait_name, output_assoc_name, subtraits) in [
|
for (fn_trait_name, output_assoc_name, subtraits) in [
|
||||||
(FnTrait::FnOnce, sym::Output, &[FnTrait::Fn, FnTrait::FnMut][..]),
|
(FnTrait::FnOnce, sym::Output, &[FnTrait::Fn, FnTrait::FnMut][..]),
|
||||||
(FnTrait::AsyncFnMut, sym::CallRefFuture, &[FnTrait::AsyncFn]),
|
(FnTrait::AsyncFnMut, sym::CallRefFuture, &[FnTrait::AsyncFn]),
|
||||||
|
|
@ -997,42 +982,34 @@ impl<'db> InferenceTable<'db> {
|
||||||
trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
|
trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
|
||||||
|
|
||||||
let mut arg_tys = Vec::with_capacity(num_args);
|
let mut arg_tys = Vec::with_capacity(num_args);
|
||||||
let arg_ty = TyBuilder::tuple(num_args)
|
let arg_ty = next_solver::Ty::new_tup_from_iter(
|
||||||
.fill(|it| {
|
self.interner,
|
||||||
let arg = match it {
|
std::iter::repeat_with(|| {
|
||||||
ParamKind::Type => self.new_type_var(),
|
let ty = self.next_ty_var();
|
||||||
ParamKind::Lifetime => unreachable!("Tuple with lifetime parameter"),
|
arg_tys.push(ty);
|
||||||
ParamKind::Const(_) => unreachable!("Tuple with const parameter"),
|
ty
|
||||||
};
|
|
||||||
arg_tys.push(arg.to_nextsolver(self.interner));
|
|
||||||
arg.cast(Interner)
|
|
||||||
})
|
})
|
||||||
.build();
|
.take(num_args),
|
||||||
|
);
|
||||||
|
let args = [ty.to_nextsolver(self.interner), arg_ty];
|
||||||
|
let trait_ref = crate::next_solver::TraitRef::new(self.interner, fn_trait.into(), args);
|
||||||
|
|
||||||
let b = TyBuilder::trait_ref(self.db, fn_trait);
|
let projection = crate::next_solver::Ty::new_alias(
|
||||||
if b.remaining() != 2 {
|
self.interner,
|
||||||
return None;
|
rustc_type_ir::AliasTyKind::Projection,
|
||||||
}
|
crate::next_solver::AliasTy::new(self.interner, output_assoc_type.into(), args),
|
||||||
let mut trait_ref = b.push(ty.clone()).push(arg_ty).build();
|
);
|
||||||
|
|
||||||
let projection = TyBuilder::assoc_type_projection(
|
let pred = crate::next_solver::Predicate::upcast_from(trait_ref, self.interner);
|
||||||
self.db,
|
if !self.try_obligation(pred).no_solution() {
|
||||||
output_assoc_type,
|
self.register_obligation(pred);
|
||||||
Some(trait_ref.substitution.clone()),
|
let return_ty = self.normalize_alias_ty(projection);
|
||||||
)
|
|
||||||
.fill_with_unknown()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let goal: Goal = trait_ref.clone().cast(Interner);
|
|
||||||
if !self.try_obligation(goal.clone()).no_solution() {
|
|
||||||
self.register_obligation(goal.to_nextsolver(self.interner));
|
|
||||||
let return_ty =
|
|
||||||
self.normalize_projection_ty(projection).to_nextsolver(self.interner);
|
|
||||||
for &fn_x in subtraits {
|
for &fn_x in subtraits {
|
||||||
let fn_x_trait = fn_x.get_id(self.db, krate)?;
|
let fn_x_trait = fn_x.get_id(self.db, krate)?;
|
||||||
trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
|
let trait_ref =
|
||||||
let goal = trait_ref.clone().cast(Interner);
|
crate::next_solver::TraitRef::new(self.interner, fn_x_trait.into(), args);
|
||||||
if !self.try_obligation(goal).no_solution() {
|
let pred = crate::next_solver::Predicate::upcast_from(trait_ref, self.interner);
|
||||||
|
if !self.try_obligation(pred).no_solution() {
|
||||||
return Some((fn_x, arg_tys, return_ty));
|
return Some((fn_x, arg_tys, return_ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1171,12 +1148,11 @@ impl<'db> InferenceTable<'db> {
|
||||||
let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
|
let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let sized_pred = WhereClause::Implemented(TraitRef {
|
let sized_pred = Predicate::upcast_from(
|
||||||
trait_id: to_chalk_trait_id(sized),
|
TraitRef::new(self.interner, sized.into(), [ty.to_nextsolver(self.interner)]),
|
||||||
substitution: Substitution::from1(Interner, ty),
|
self.interner,
|
||||||
});
|
);
|
||||||
let goal = GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(sized_pred)).intern(Interner);
|
self.try_obligation(sized_pred).certain()
|
||||||
self.try_obligation(goal).certain()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,10 @@ use intern::{Symbol, sym};
|
||||||
use la_arena::{Arena, Idx};
|
use la_arena::{Arena, Idx};
|
||||||
use mir::{MirEvalError, VTableMap};
|
use mir::{MirEvalError, VTableMap};
|
||||||
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
|
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
|
||||||
use rustc_type_ir::inherent::SliceLike;
|
use rustc_type_ir::{
|
||||||
|
UpcastFrom,
|
||||||
|
inherent::{SliceLike, Ty as _},
|
||||||
|
};
|
||||||
use syntax::ast::{ConstArg, make};
|
use syntax::ast::{ConstArg, make};
|
||||||
use traits::FnTrait;
|
use traits::FnTrait;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
@ -106,7 +109,7 @@ use crate::{
|
||||||
infer::unify::InferenceTable,
|
infer::unify::InferenceTable,
|
||||||
next_solver::{
|
next_solver::{
|
||||||
DbInterner,
|
DbInterner,
|
||||||
mapping::{ChalkToNextSolver, convert_ty_for_result},
|
mapping::{ChalkToNextSolver, NextSolverToChalk, convert_ty_for_result},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -957,26 +960,32 @@ pub fn callable_sig_from_fn_trait(
|
||||||
// Register two obligations:
|
// Register two obligations:
|
||||||
// - Self: FnOnce<?args_ty>
|
// - Self: FnOnce<?args_ty>
|
||||||
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
|
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
|
||||||
let args_ty = table.new_type_var();
|
let args_ty = table.next_ty_var();
|
||||||
let mut trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
|
let args = [self_ty.to_nextsolver(table.interner), args_ty];
|
||||||
let projection = TyBuilder::assoc_type_projection(
|
let trait_ref = crate::next_solver::TraitRef::new(table.interner, fn_once_trait.into(), args);
|
||||||
db,
|
let projection = crate::next_solver::Ty::new_alias(
|
||||||
output_assoc_type,
|
table.interner,
|
||||||
Some(trait_ref.substitution.clone()),
|
rustc_type_ir::AliasTyKind::Projection,
|
||||||
)
|
crate::next_solver::AliasTy::new(table.interner, output_assoc_type.into(), args),
|
||||||
.build();
|
);
|
||||||
|
|
||||||
let goal: Goal = trait_ref.clone().cast(Interner);
|
let pred = crate::next_solver::Predicate::upcast_from(trait_ref, table.interner);
|
||||||
let pred = goal.to_nextsolver(table.interner);
|
if !table.try_obligation(pred).no_solution() {
|
||||||
if !table.try_obligation(goal).no_solution() {
|
|
||||||
table.register_obligation(pred);
|
table.register_obligation(pred);
|
||||||
let return_ty = table.normalize_projection_ty(projection);
|
let return_ty = table.normalize_alias_ty(projection);
|
||||||
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
|
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
|
||||||
let fn_x_trait = fn_x.get_id(db, krate)?;
|
let fn_x_trait = fn_x.get_id(db, krate)?;
|
||||||
trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
|
let trait_ref =
|
||||||
if !table.try_obligation(trait_ref.clone().cast(Interner)).no_solution() {
|
crate::next_solver::TraitRef::new(table.interner, fn_x_trait.into(), args);
|
||||||
let ret_ty = table.resolve_completely(return_ty);
|
if !table
|
||||||
let args_ty = table.resolve_completely(args_ty);
|
.try_obligation(crate::next_solver::Predicate::upcast_from(
|
||||||
|
trait_ref,
|
||||||
|
table.interner,
|
||||||
|
))
|
||||||
|
.no_solution()
|
||||||
|
{
|
||||||
|
let ret_ty = table.resolve_completely(return_ty.to_chalk(table.interner));
|
||||||
|
let args_ty = table.resolve_completely(args_ty.to_chalk(table.interner));
|
||||||
let params = args_ty
|
let params = args_ty
|
||||||
.as_tuple()?
|
.as_tuple()?
|
||||||
.iter(Interner)
|
.iter(Interner)
|
||||||
|
|
|
||||||
|
|
@ -1355,6 +1355,18 @@ pub(crate) fn generic_predicates_for_param_cycle_result(
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct GenericPredicates<'db>(Option<Arc<[Clause<'db>]>>);
|
pub struct GenericPredicates<'db>(Option<Arc<[Clause<'db>]>>);
|
||||||
|
|
||||||
|
impl<'db> GenericPredicates<'db> {
|
||||||
|
pub fn instantiate(
|
||||||
|
&self,
|
||||||
|
interner: DbInterner<'db>,
|
||||||
|
args: GenericArgs<'db>,
|
||||||
|
) -> Option<impl Iterator<Item = Clause<'db>>> {
|
||||||
|
self.0
|
||||||
|
.as_ref()
|
||||||
|
.map(|it| EarlyBinder::bind(it.iter().copied()).iter_instantiated(interner, args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'db> ops::Deref for GenericPredicates<'db> {
|
impl<'db> ops::Deref for GenericPredicates<'db> {
|
||||||
type Target = [Clause<'db>];
|
type Target = [Clause<'db>];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,12 @@ use crate::{
|
||||||
lang_items::is_box,
|
lang_items::is_box,
|
||||||
next_solver::{
|
next_solver::{
|
||||||
self, SolverDefId,
|
self, SolverDefId,
|
||||||
fulfill::FulfillmentCtxt,
|
infer::{
|
||||||
infer::DefineOpaqueTypes,
|
DefineOpaqueTypes,
|
||||||
|
traits::{ObligationCause, PredicateObligation},
|
||||||
|
},
|
||||||
mapping::{ChalkToNextSolver, NextSolverToChalk},
|
mapping::{ChalkToNextSolver, NextSolverToChalk},
|
||||||
|
obligation_ctxt::ObligationCtxt,
|
||||||
},
|
},
|
||||||
primitive::{FloatTy, IntTy, UintTy},
|
primitive::{FloatTy, IntTy, UintTy},
|
||||||
to_chalk_trait_id,
|
to_chalk_trait_id,
|
||||||
|
|
@ -907,10 +910,11 @@ fn find_matching_impl(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|b| -> Goal { b.cast(Interner) });
|
.map(|b| -> Goal { b.cast(Interner) });
|
||||||
for goal in wcs {
|
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;
|
return None;
|
||||||
}
|
}
|
||||||
table.register_obligation(goal.to_nextsolver(table.interner));
|
table.register_obligation(goal);
|
||||||
}
|
}
|
||||||
Some((
|
Some((
|
||||||
impl_.impl_items(db),
|
impl_.impl_items(db),
|
||||||
|
|
@ -1395,7 +1399,7 @@ fn iterate_trait_method_candidates(
|
||||||
let db = table.db;
|
let db = table.db;
|
||||||
|
|
||||||
let canonical_self_ty = table.canonicalize(self_ty.clone().to_nextsolver(table.interner));
|
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 {
|
'traits: for &t in traits_in_scope {
|
||||||
let data = db.trait_signature(t);
|
let data = db.trait_signature(t);
|
||||||
|
|
@ -1635,7 +1639,6 @@ pub(crate) fn resolve_indexing_op<'db>(
|
||||||
let ty = table.instantiate_canonical_ns(ty);
|
let ty = table.instantiate_canonical_ns(ty);
|
||||||
let deref_chain = autoderef_method_receiver(table, ty);
|
let deref_chain = autoderef_method_receiver(table, ty);
|
||||||
for (ty, adj) in deref_chain {
|
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);
|
let goal = generic_implements_goal_ns(table, index_trait, ty);
|
||||||
if !next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() {
|
if !next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() {
|
||||||
return Some(adj);
|
return Some(adj);
|
||||||
|
|
@ -1752,10 +1755,7 @@ fn is_valid_trait_method_candidate(
|
||||||
};
|
};
|
||||||
let res = table
|
let res = table
|
||||||
.infer_ctxt
|
.infer_ctxt
|
||||||
.at(
|
.at(&next_solver::infer::traits::ObligationCause::dummy(), table.param_env)
|
||||||
&next_solver::infer::traits::ObligationCause::dummy(),
|
|
||||||
table.trait_env.env.to_nextsolver(table.interner),
|
|
||||||
)
|
|
||||||
.relate(
|
.relate(
|
||||||
DefineOpaqueTypes::No,
|
DefineOpaqueTypes::No,
|
||||||
expected_receiver.to_nextsolver(table.interner),
|
expected_receiver.to_nextsolver(table.interner),
|
||||||
|
|
@ -1767,12 +1767,10 @@ fn is_valid_trait_method_candidate(
|
||||||
};
|
};
|
||||||
|
|
||||||
if !infer_ok.obligations.is_empty() {
|
if !infer_ok.obligations.is_empty() {
|
||||||
let mut ctxt = FulfillmentCtxt::new(&table.infer_ctxt);
|
let mut ctxt = ObligationCtxt::new(&table.infer_ctxt);
|
||||||
for pred in infer_ok.into_obligations() {
|
ctxt.register_obligations(infer_ok.into_obligations());
|
||||||
ctxt.register_predicate_obligation(&table.infer_ctxt, pred);
|
|
||||||
}
|
|
||||||
// FIXME: Are we doing this correctly? Probably better to follow rustc more closely.
|
// 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));
|
check_that!(table.unify(receiver_ty, &expected_receiver));
|
||||||
|
|
@ -1815,9 +1813,11 @@ fn is_valid_impl_fn_candidate(
|
||||||
}
|
}
|
||||||
table.run_in_snapshot(|table| {
|
table.run_in_snapshot(|table| {
|
||||||
let _p = tracing::info_span!("subst_for_def").entered();
|
let _p = tracing::info_span!("subst_for_def").entered();
|
||||||
let impl_subst =
|
let impl_subst = table.infer_ctxt.fresh_args_for_item(impl_id.into());
|
||||||
TyBuilder::subst_for_def(db, impl_id, None).fill_with_inference_vars(table).build();
|
let expect_self_ty = db
|
||||||
let expect_self_ty = db.impl_self_ty(impl_id).substitute(Interner, &impl_subst);
|
.impl_self_ty_ns(impl_id)
|
||||||
|
.instantiate(table.interner, &impl_subst)
|
||||||
|
.to_chalk(table.interner);
|
||||||
|
|
||||||
check_that!(table.unify(&expect_self_ty, self_ty));
|
check_that!(table.unify(&expect_self_ty, self_ty));
|
||||||
|
|
||||||
|
|
@ -1825,9 +1825,8 @@ fn is_valid_impl_fn_candidate(
|
||||||
let _p = tracing::info_span!("check_receiver_ty").entered();
|
let _p = tracing::info_span!("check_receiver_ty").entered();
|
||||||
check_that!(data.has_self_param());
|
check_that!(data.has_self_param());
|
||||||
|
|
||||||
let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst.clone()))
|
let fn_subst: crate::Substitution =
|
||||||
.fill_with_inference_vars(table)
|
table.infer_ctxt.fresh_args_for_item(fn_id.into()).to_chalk(table.interner);
|
||||||
.build();
|
|
||||||
|
|
||||||
let sig = db.callable_item_signature(fn_id.into());
|
let sig = db.callable_item_signature(fn_id.into());
|
||||||
let expected_receiver =
|
let expected_receiver =
|
||||||
|
|
@ -1838,48 +1837,25 @@ fn is_valid_impl_fn_candidate(
|
||||||
|
|
||||||
// We need to consider the bounds on the impl to distinguish functions of the same name
|
// We need to consider the bounds on the impl to distinguish functions of the same name
|
||||||
// for a type.
|
// for a type.
|
||||||
let predicates = db.generic_predicates(impl_id.into());
|
let predicates = db.generic_predicates_ns(impl_id.into());
|
||||||
let goals = predicates.iter().map(|p| {
|
let Some(predicates) = predicates.instantiate(table.interner, impl_subst) else {
|
||||||
let (p, b) = p
|
return IsValidCandidate::Yes;
|
||||||
.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)
|
let mut ctxt = ObligationCtxt::new(&table.infer_ctxt);
|
||||||
});
|
|
||||||
|
|
||||||
for goal in goals.clone() {
|
ctxt.register_obligations(predicates.into_iter().map(|p| {
|
||||||
match table.solve_obligation(goal) {
|
PredicateObligation::new(table.interner, ObligationCause::new(), table.param_env, p.0)
|
||||||
Ok(_) => {}
|
}));
|
||||||
Err(_) => {
|
|
||||||
return IsValidCandidate::No;
|
if ctxt.select_where_possible().is_empty() {
|
||||||
}
|
IsValidCandidate::Yes
|
||||||
}
|
} else {
|
||||||
|
IsValidCandidate::No
|
||||||
}
|
}
|
||||||
|
|
||||||
for goal in goals {
|
|
||||||
if table.try_obligation(goal).no_solution() {
|
|
||||||
return IsValidCandidate::No;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IsValidCandidate::Yes
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn implements_trait_unique(
|
pub fn implements_trait_unique(
|
||||||
ty: &Canonical<Ty>,
|
ty: &Canonical<Ty>,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
|
|
@ -1891,7 +1867,7 @@ pub fn implements_trait_unique(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This creates Substs for a trait with the given Self type and type variables
|
/// 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)]
|
#[tracing::instrument(skip_all)]
|
||||||
fn generic_implements_goal(
|
fn generic_implements_goal(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
|
|
@ -1934,11 +1910,7 @@ fn generic_implements_goal_ns<'db>(
|
||||||
let trait_ref =
|
let trait_ref =
|
||||||
rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args)
|
rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args)
|
||||||
.with_replaced_self_ty(table.infer_ctxt.interner, self_ty);
|
.with_replaced_self_ty(table.infer_ctxt.interner, self_ty);
|
||||||
let goal = next_solver::Goal::new(
|
let goal = next_solver::Goal::new(table.infer_ctxt.interner, table.param_env, trait_ref);
|
||||||
table.infer_ctxt.interner,
|
|
||||||
table.trait_env.env.to_nextsolver(table.infer_ctxt.interner),
|
|
||||||
trait_ref,
|
|
||||||
);
|
|
||||||
|
|
||||||
table.canonicalize(goal)
|
table.canonicalize(goal)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//! Trait solving using Chalk.
|
//! Trait solving using next trait solver.
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
@ -128,7 +128,7 @@ fn identity_subst(
|
||||||
chalk_ir::Canonical { binders, value: identity_subst }
|
chalk_ir::Canonical { binders, value: identity_subst }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Solve a trait goal using Chalk.
|
/// Solve a trait goal using next trait solver.
|
||||||
pub(crate) fn trait_solve_query(
|
pub(crate) fn trait_solve_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
|
|
@ -325,7 +325,7 @@ pub fn next_trait_solve_canonical_in_ctxt<'db>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Solve a trait goal using Chalk.
|
/// Solve a trait goal using next trait solver.
|
||||||
pub fn next_trait_solve_in_ctxt<'db, 'a>(
|
pub fn next_trait_solve_in_ctxt<'db, 'a>(
|
||||||
infer_ctxt: &'a InferCtxt<'db>,
|
infer_ctxt: &'a InferCtxt<'db>,
|
||||||
goal: crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>,
|
goal: crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue