mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
Merge #8139
8139: Align `Canonical` and `InEnvironment` with the Chalk versions r=flodiebold a=flodiebold Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
commit
e220d3d507
11 changed files with 193 additions and 178 deletions
|
@ -16,8 +16,8 @@ use crate::{
|
|||
to_assoc_type_id, to_chalk_trait_id,
|
||||
traits::{InEnvironment, Solution},
|
||||
utils::generics,
|
||||
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution,
|
||||
TraitRef, Ty, TyKind,
|
||||
AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
|
||||
ProjectionTy, Substitution, TraitRef, Ty, TyKind,
|
||||
};
|
||||
|
||||
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
||||
|
@ -27,9 +27,9 @@ pub fn autoderef<'a>(
|
|||
krate: Option<CrateId>,
|
||||
ty: InEnvironment<Canonical<Ty>>,
|
||||
) -> impl Iterator<Item = Canonical<Ty>> + 'a {
|
||||
let InEnvironment { value: ty, environment } = ty;
|
||||
let InEnvironment { goal: ty, environment } = ty;
|
||||
successors(Some(ty), move |ty| {
|
||||
deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() })
|
||||
deref(db, krate?, InEnvironment { goal: ty, environment: environment.clone() })
|
||||
})
|
||||
.take(AUTODEREF_RECURSION_LIMIT)
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ pub(crate) fn deref(
|
|||
krate: CrateId,
|
||||
ty: InEnvironment<&Canonical<Ty>>,
|
||||
) -> Option<Canonical<Ty>> {
|
||||
if let Some(derefed) = ty.value.value.builtin_deref() {
|
||||
Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() })
|
||||
if let Some(derefed) = ty.goal.value.builtin_deref() {
|
||||
Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
|
||||
} else {
|
||||
deref_by_trait(db, krate, ty)
|
||||
}
|
||||
|
@ -67,15 +67,15 @@ fn deref_by_trait(
|
|||
// FIXME make the Canonical / bound var handling nicer
|
||||
|
||||
let parameters =
|
||||
Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build();
|
||||
Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
|
||||
|
||||
// Check that the type implements Deref at all
|
||||
let trait_ref =
|
||||
TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
|
||||
let implements_goal = Canonical {
|
||||
kinds: ty.value.kinds.clone(),
|
||||
binders: ty.goal.binders.clone(),
|
||||
value: InEnvironment {
|
||||
value: trait_ref.cast(&Interner),
|
||||
goal: trait_ref.cast(&Interner),
|
||||
environment: ty.environment.clone(),
|
||||
},
|
||||
};
|
||||
|
@ -89,18 +89,27 @@ fn deref_by_trait(
|
|||
associated_ty_id: to_assoc_type_id(target),
|
||||
substitution: parameters,
|
||||
}),
|
||||
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len()))
|
||||
.intern(&Interner),
|
||||
ty: TyKind::BoundVar(BoundVar::new(
|
||||
DebruijnIndex::INNERMOST,
|
||||
ty.goal.binders.len(&Interner),
|
||||
))
|
||||
.intern(&Interner),
|
||||
};
|
||||
|
||||
let obligation = projection.cast(&Interner);
|
||||
|
||||
let in_env = InEnvironment { value: obligation, environment: ty.environment };
|
||||
let in_env = InEnvironment { goal: obligation, environment: ty.environment };
|
||||
|
||||
let canonical = Canonical::new(
|
||||
in_env,
|
||||
ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)),
|
||||
);
|
||||
let canonical = Canonical {
|
||||
value: in_env,
|
||||
binders: CanonicalVarKinds::from_iter(
|
||||
&Interner,
|
||||
ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
|
||||
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
|
||||
chalk_ir::UniverseIndex::ROOT,
|
||||
))),
|
||||
),
|
||||
};
|
||||
|
||||
let solution = db.trait_solve(krate, canonical)?;
|
||||
|
||||
|
@ -121,21 +130,21 @@ fn deref_by_trait(
|
|||
// assumptions will be broken. We would need to properly introduce
|
||||
// new variables in that case
|
||||
|
||||
for i in 1..vars.0.kinds.len() {
|
||||
for i in 1..vars.0.binders.len(&Interner) {
|
||||
if vars.0.value[i - 1].interned(&Interner)
|
||||
!= &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
|
||||
{
|
||||
warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
|
||||
warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(Canonical {
|
||||
value: vars.0.value[vars.0.value.len() - 1].clone(),
|
||||
kinds: vars.0.kinds.clone(),
|
||||
binders: vars.0.binders.clone(),
|
||||
})
|
||||
}
|
||||
Solution::Ambig(_) => {
|
||||
info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution);
|
||||
info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -331,7 +331,7 @@ impl<'a> InferenceContext<'a> {
|
|||
fn resolve_obligations_as_possible(&mut self) {
|
||||
let obligations = mem::replace(&mut self.obligations, Vec::new());
|
||||
for obligation in obligations {
|
||||
let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone());
|
||||
let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone());
|
||||
let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
|
||||
let solution =
|
||||
self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
|
||||
|
|
|
@ -142,7 +142,7 @@ impl<'a> InferenceContext<'a> {
|
|||
.build();
|
||||
let trait_ref =
|
||||
TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
|
||||
let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner));
|
||||
let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner));
|
||||
|
||||
let canonicalizer = self.canonicalizer();
|
||||
let canonicalized = canonicalizer.canonicalize_obligation(goal);
|
||||
|
@ -170,8 +170,8 @@ impl<'a> InferenceContext<'a> {
|
|||
self.db,
|
||||
self.resolver.krate(),
|
||||
InEnvironment {
|
||||
value: canonicalized.value.clone(),
|
||||
environment: self.trait_env.clone(),
|
||||
goal: canonicalized.value.clone(),
|
||||
environment: self.trait_env.env.clone(),
|
||||
},
|
||||
) {
|
||||
let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value);
|
||||
|
|
|
@ -90,12 +90,12 @@ impl<'a> InferenceContext<'a> {
|
|||
let substs =
|
||||
Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
|
||||
|
||||
let trait_env = Arc::clone(&self.trait_env);
|
||||
let trait_env = self.trait_env.env.clone();
|
||||
let implements_fn_trait: DomainGoal =
|
||||
TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() }
|
||||
.cast(&Interner);
|
||||
let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
|
||||
value: implements_fn_trait.clone(),
|
||||
goal: implements_fn_trait.clone(),
|
||||
environment: trait_env,
|
||||
});
|
||||
if self.db.trait_solve(krate, goal.value).is_some() {
|
||||
|
@ -299,8 +299,8 @@ impl<'a> InferenceContext<'a> {
|
|||
self.db,
|
||||
self.resolver.krate(),
|
||||
InEnvironment {
|
||||
value: canonicalized.value.clone(),
|
||||
environment: self.trait_env.clone(),
|
||||
goal: canonicalized.value.clone(),
|
||||
environment: self.trait_env.env.clone(),
|
||||
},
|
||||
);
|
||||
let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
|
||||
|
@ -438,8 +438,8 @@ impl<'a> InferenceContext<'a> {
|
|||
self.db,
|
||||
self.resolver.krate(),
|
||||
InEnvironment {
|
||||
value: canonicalized.value.clone(),
|
||||
environment: self.trait_env.clone(),
|
||||
goal: canonicalized.value.clone(),
|
||||
environment: self.trait_env.env.clone(),
|
||||
},
|
||||
)
|
||||
.find_map(|derefed_ty| {
|
||||
|
@ -538,8 +538,8 @@ impl<'a> InferenceContext<'a> {
|
|||
self.db,
|
||||
krate,
|
||||
InEnvironment {
|
||||
value: &canonicalized.value,
|
||||
environment: self.trait_env.clone(),
|
||||
goal: &canonicalized.value,
|
||||
environment: self.trait_env.env.clone(),
|
||||
},
|
||||
) {
|
||||
Some(derefed_ty) => {
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use chalk_ir::{FloatTy, IntTy, TyVariableKind};
|
||||
use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind};
|
||||
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
||||
|
||||
use super::{DomainGoal, InferenceContext};
|
||||
use crate::{
|
||||
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar,
|
||||
Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
|
||||
AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer,
|
||||
InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
|
||||
};
|
||||
|
||||
impl<'a> InferenceContext<'a> {
|
||||
|
@ -76,8 +76,17 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
|
|||
}
|
||||
|
||||
fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
|
||||
let kinds = self.free_vars.iter().map(|&(_, k)| k).collect();
|
||||
Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars }
|
||||
let kinds = self
|
||||
.free_vars
|
||||
.iter()
|
||||
.map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT));
|
||||
Canonicalized {
|
||||
value: Canonical {
|
||||
value: result,
|
||||
binders: CanonicalVarKinds::from_iter(&Interner, kinds),
|
||||
},
|
||||
free_vars: self.free_vars,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
|
||||
|
@ -89,15 +98,12 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
|
|||
mut self,
|
||||
obligation: InEnvironment<DomainGoal>,
|
||||
) -> Canonicalized<InEnvironment<DomainGoal>> {
|
||||
let result = match obligation.value {
|
||||
let result = match obligation.goal {
|
||||
DomainGoal::Holds(wc) => {
|
||||
DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
|
||||
}
|
||||
};
|
||||
self.into_canonicalized(InEnvironment {
|
||||
value: result,
|
||||
environment: obligation.environment,
|
||||
})
|
||||
self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,12 +131,19 @@ impl<T> Canonicalized<T> {
|
|||
// the solution may contain new variables, which we need to convert to new inference vars
|
||||
let new_vars = Substitution(
|
||||
solution
|
||||
.kinds
|
||||
.iter()
|
||||
.map(|k| match k {
|
||||
TyVariableKind::General => ctx.table.new_type_var(),
|
||||
TyVariableKind::Integer => ctx.table.new_integer_var(),
|
||||
TyVariableKind::Float => ctx.table.new_float_var(),
|
||||
.binders
|
||||
.iter(&Interner)
|
||||
.map(|k| match k.kind {
|
||||
VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(),
|
||||
VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(),
|
||||
VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(),
|
||||
// HACK: Chalk can sometimes return new lifetime variables. We
|
||||
// want to just skip them, but to not mess up the indices of
|
||||
// other variables, we'll just create a new type variable in
|
||||
// their place instead. This should not matter (we never see the
|
||||
// actual *uses* of the lifetime variable).
|
||||
VariableKind::Lifetime => ctx.table.new_type_var(),
|
||||
_ => panic!("const variable in solution"),
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
|
@ -147,8 +160,8 @@ impl<T> Canonicalized<T> {
|
|||
pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
|
||||
let mut table = InferenceTable::new();
|
||||
let vars = Substitution(
|
||||
tys.kinds
|
||||
.iter()
|
||||
tys.binders
|
||||
.iter(&Interner)
|
||||
// we always use type vars here because we want everything to
|
||||
// fallback to Unknown in the end (kind of hacky, as below)
|
||||
.map(|_| table.new_type_var())
|
||||
|
@ -170,7 +183,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
|
|||
}
|
||||
}
|
||||
Some(
|
||||
Substitution::builder(tys.kinds.len())
|
||||
Substitution::builder(tys.binders.len(&Interner))
|
||||
.fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
|
||||
.build(),
|
||||
)
|
||||
|
|
|
@ -61,6 +61,8 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>;
|
|||
pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
|
||||
pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
|
||||
|
||||
pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
|
||||
|
||||
pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
|
@ -662,12 +664,18 @@ impl QuantifiedWhereClauses {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Canonical<T> {
|
||||
pub value: T,
|
||||
pub kinds: Arc<[TyVariableKind]>,
|
||||
pub binders: CanonicalVarKinds,
|
||||
}
|
||||
|
||||
impl<T> Canonical<T> {
|
||||
pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self {
|
||||
Self { value, kinds: kinds.into_iter().collect() }
|
||||
let kinds = kinds.into_iter().map(|tk| {
|
||||
chalk_ir::CanonicalVarKind::new(
|
||||
chalk_ir::VariableKind::Ty(tk),
|
||||
chalk_ir::UniverseIndex::ROOT,
|
||||
)
|
||||
});
|
||||
Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{iter, sync::Arc};
|
|||
|
||||
use arrayvec::ArrayVec;
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::{cast::Cast, Mutability};
|
||||
use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
|
||||
use hir_def::{
|
||||
lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
|
||||
ImplId, Lookup, ModuleId, TraitId,
|
||||
|
@ -21,8 +21,9 @@ use crate::{
|
|||
primitive::{self, FloatTy, IntTy, UintTy},
|
||||
to_chalk_trait_id,
|
||||
utils::all_super_traits,
|
||||
AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner,
|
||||
Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
|
||||
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId,
|
||||
InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind,
|
||||
TypeWalk,
|
||||
};
|
||||
|
||||
/// This is used as a key for indexing impls.
|
||||
|
@ -375,7 +376,7 @@ fn iterate_method_candidates_impl(
|
|||
// Also note that when we've got a receiver like &S, even if the method we
|
||||
// find in the end takes &self, we still do the autoderef step (just as
|
||||
// rustc does an autoderef and then autoref again).
|
||||
let ty = InEnvironment { value: ty.clone(), environment: env.clone() };
|
||||
let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() };
|
||||
|
||||
// We have to be careful about the order we're looking at candidates
|
||||
// in here. Consider the case where we're resolving `x.clone()`
|
||||
|
@ -443,7 +444,7 @@ fn iterate_method_candidates_with_autoref(
|
|||
return true;
|
||||
}
|
||||
let refed = Canonical {
|
||||
kinds: deref_chain[0].kinds.clone(),
|
||||
binders: deref_chain[0].binders.clone(),
|
||||
value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
|
||||
};
|
||||
if iterate_method_candidates_by_receiver(
|
||||
|
@ -459,7 +460,7 @@ fn iterate_method_candidates_with_autoref(
|
|||
return true;
|
||||
}
|
||||
let ref_muted = Canonical {
|
||||
kinds: deref_chain[0].kinds.clone(),
|
||||
binders: deref_chain[0].binders.clone(),
|
||||
value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
|
||||
};
|
||||
if iterate_method_candidates_by_receiver(
|
||||
|
@ -621,7 +622,7 @@ pub fn resolve_indexing_op(
|
|||
krate: CrateId,
|
||||
index_trait: TraitId,
|
||||
) -> Option<Canonical<Ty>> {
|
||||
let ty = InEnvironment { value: ty.clone(), environment: env.clone() };
|
||||
let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() };
|
||||
let deref_chain = autoderef_method_receiver(db, krate, ty);
|
||||
for ty in deref_chain {
|
||||
let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone());
|
||||
|
@ -677,19 +678,28 @@ pub(crate) fn inherent_impl_substs(
|
|||
// we create a var for each type parameter of the impl; we need to keep in
|
||||
// mind here that `self_ty` might have vars of its own
|
||||
let vars = Substitution::build_for_def(db, impl_id)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len())
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner))
|
||||
.build();
|
||||
let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
|
||||
let mut kinds = self_ty.kinds.to_vec();
|
||||
kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(vars.len()));
|
||||
let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) };
|
||||
let mut kinds = self_ty.binders.interned().to_vec();
|
||||
kinds.extend(
|
||||
iter::repeat(chalk_ir::WithKind::new(
|
||||
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
|
||||
UniverseIndex::ROOT,
|
||||
))
|
||||
.take(vars.len()),
|
||||
);
|
||||
let tys = Canonical {
|
||||
binders: CanonicalVarKinds::from_iter(&Interner, kinds),
|
||||
value: (self_ty_with_vars, self_ty.value.clone()),
|
||||
};
|
||||
let substs = super::infer::unify(&tys);
|
||||
// We only want the substs for the vars we added, not the ones from self_ty.
|
||||
// Also, if any of the vars we added are still in there, we replace them by
|
||||
// Unknown. I think this can only really happen if self_ty contained
|
||||
// Unknown, and in that case we want the result to contain Unknown in those
|
||||
// places again.
|
||||
substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len()))
|
||||
substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.binders.len(&Interner)))
|
||||
}
|
||||
|
||||
/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
|
||||
|
@ -768,15 +778,24 @@ fn generic_implements_goal(
|
|||
trait_: TraitId,
|
||||
self_ty: Canonical<Ty>,
|
||||
) -> Canonical<InEnvironment<super::DomainGoal>> {
|
||||
let mut kinds = self_ty.kinds.to_vec();
|
||||
let mut kinds = self_ty.binders.interned().to_vec();
|
||||
let substs = super::Substitution::build_for_def(db, trait_)
|
||||
.push(self_ty.value)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
|
||||
.build();
|
||||
kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
|
||||
kinds.extend(
|
||||
iter::repeat(chalk_ir::WithKind::new(
|
||||
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
|
||||
UniverseIndex::ROOT,
|
||||
))
|
||||
.take(substs.len() - 1),
|
||||
);
|
||||
let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
|
||||
let obligation = trait_ref.cast(&Interner);
|
||||
Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
|
||||
Canonical {
|
||||
binders: CanonicalVarKinds::from_iter(&Interner, kinds),
|
||||
value: InEnvironment::new(env.env.clone(), obligation),
|
||||
}
|
||||
}
|
||||
|
||||
fn autoderef_method_receiver(
|
||||
|
@ -789,9 +808,9 @@ fn autoderef_method_receiver(
|
|||
if let Some(TyKind::Array(parameters)) =
|
||||
deref_chain.last().map(|ty| ty.value.interned(&Interner))
|
||||
{
|
||||
let kinds = deref_chain.last().unwrap().kinds.clone();
|
||||
let kinds = deref_chain.last().unwrap().binders.clone();
|
||||
let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
|
||||
deref_chain.push(Canonical { value: unsized_ty, kinds })
|
||||
deref_chain.push(Canonical { value: unsized_ty, binders: kinds })
|
||||
}
|
||||
deref_chain
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
//! Trait solving using Chalk.
|
||||
use std::env::var;
|
||||
use std::sync::Arc;
|
||||
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::cast::Cast;
|
||||
|
@ -44,7 +43,7 @@ pub struct TraitEnvironment {
|
|||
// When we're using Chalk's Ty we can make this a BTreeMap since it's Ord,
|
||||
// but for now it's too annoying...
|
||||
pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>,
|
||||
pub(crate) env: chalk_ir::Environment<Interner>,
|
||||
pub env: chalk_ir::Environment<Interner>,
|
||||
}
|
||||
|
||||
impl TraitEnvironment {
|
||||
|
@ -74,13 +73,13 @@ impl Default for TraitEnvironment {
|
|||
/// Something (usually a goal), along with an environment.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct InEnvironment<T> {
|
||||
pub environment: Arc<TraitEnvironment>,
|
||||
pub value: T,
|
||||
pub environment: chalk_ir::Environment<Interner>,
|
||||
pub goal: T,
|
||||
}
|
||||
|
||||
impl<T> InEnvironment<T> {
|
||||
pub fn new(environment: Arc<TraitEnvironment>, value: T) -> InEnvironment<T> {
|
||||
InEnvironment { environment, value }
|
||||
pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
|
||||
InEnvironment { environment, goal: value }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,18 +125,18 @@ pub(crate) fn trait_solve_query(
|
|||
krate: CrateId,
|
||||
goal: Canonical<InEnvironment<DomainGoal>>,
|
||||
) -> Option<Solution> {
|
||||
let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
|
||||
let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal {
|
||||
DomainGoal::Holds(WhereClause::Implemented(it)) => {
|
||||
db.trait_data(it.hir_trait_id()).name.to_string()
|
||||
}
|
||||
DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
|
||||
});
|
||||
log::info!("trait_solve_query({})", goal.value.value.display(db));
|
||||
log::info!("trait_solve_query({})", goal.value.goal.display(db));
|
||||
|
||||
if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
|
||||
alias: AliasTy::Projection(projection_ty),
|
||||
..
|
||||
})) = &goal.value.value
|
||||
})) = &goal.value.goal
|
||||
{
|
||||
if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
|
||||
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
|
||||
|
|
|
@ -439,35 +439,12 @@ where
|
|||
type Chalk = chalk_ir::Canonical<T::Chalk>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
|
||||
let kinds = self.kinds.iter().map(|&tk| {
|
||||
chalk_ir::CanonicalVarKind::new(
|
||||
chalk_ir::VariableKind::Ty(tk),
|
||||
chalk_ir::UniverseIndex::ROOT,
|
||||
)
|
||||
});
|
||||
let value = self.value.to_chalk(db);
|
||||
chalk_ir::Canonical {
|
||||
value,
|
||||
binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds),
|
||||
}
|
||||
chalk_ir::Canonical { value, binders: self.binders }
|
||||
}
|
||||
|
||||
fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
|
||||
let kinds = canonical
|
||||
.binders
|
||||
.iter(&Interner)
|
||||
.map(|k| match k.kind {
|
||||
chalk_ir::VariableKind::Ty(tk) => tk,
|
||||
// HACK: Chalk can sometimes return new lifetime variables. We
|
||||
// want to just skip them, but to not mess up the indices of
|
||||
// other variables, we'll just create a new type variable in
|
||||
// their place instead. This should not matter (we never see the
|
||||
// actual *uses* of the lifetime variable).
|
||||
chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General,
|
||||
chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
|
||||
})
|
||||
.collect();
|
||||
Canonical { kinds, value: from_chalk(db, canonical.value) }
|
||||
Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,10 +455,7 @@ where
|
|||
type Chalk = chalk_ir::InEnvironment<T::Chalk>;
|
||||
|
||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
|
||||
chalk_ir::InEnvironment {
|
||||
environment: self.environment.env.clone(),
|
||||
goal: self.value.to_chalk(db),
|
||||
}
|
||||
chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) }
|
||||
}
|
||||
|
||||
fn from_chalk(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue