diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 9f6d7be48393..97a78ca2521c 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -217,7 +217,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
impl HirDisplay for Type {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
- self.ty.value.hir_fmt(f)
+ self.ty.hir_fmt(f)
}
}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index a325b6691a00..30b96d7e2ed7 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -56,9 +56,9 @@
primitive::UintTy,
to_assoc_type_id,
traits::{FnTrait, Solution, SolutionVariables},
- AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex,
- InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, Ty,
- TyDefId, TyKind, TyVariableKind, WhereClause,
+ AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
+ DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar,
+ Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause,
};
use itertools::Itertools;
use rustc_hash::FxHashSet;
@@ -851,13 +851,7 @@ pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec {
.iter()
.enumerate()
.map(|(idx, type_ref)| {
- let ty = Type {
- krate,
- ty: InEnvironment {
- value: ctx.lower_ty(type_ref),
- environment: environment.clone(),
- },
- };
+ let ty = Type { krate, env: environment.clone(), ty: ctx.lower_ty(type_ref) };
Param { func: self, ty, idx }
})
.collect()
@@ -1540,8 +1534,8 @@ pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec {
inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
}
- pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec {
- let def_crates = match ty.value.def_crates(db, krate) {
+ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec {
+ let def_crates = match ty.def_crates(db, krate) {
Some(def_crates) => def_crates,
None => return Vec::new(),
};
@@ -1549,14 +1543,14 @@ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec
let filter = |impl_def: &Impl| {
let target_ty = impl_def.target_ty(db);
let rref = target_ty.remove_ref();
- ty.value.equals_ctor(rref.as_ref().map_or(&target_ty.ty.value, |it| &it.ty.value))
+ ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty))
};
let mut all = Vec::new();
def_crates.iter().for_each(|&id| {
all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
});
- let fp = TyFingerprint::for_impl(&ty.value);
+ let fp = TyFingerprint::for_impl(&ty);
for id in def_crates
.iter()
.flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
@@ -1643,7 +1637,8 @@ pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Type {
krate: CrateId,
- ty: InEnvironment,
+ env: Arc,
+ ty: Ty,
}
impl Type {
@@ -1663,14 +1658,14 @@ pub(crate) fn new_with_resolver_inner(
) -> Type {
let environment =
resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d));
- Type { krate, ty: InEnvironment { value: ty, environment } }
+ Type { krate, env: environment, ty }
}
fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type {
let resolver = lexical_env.resolver(db.upcast());
let environment =
resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d));
- Type { krate, ty: InEnvironment { value: ty, environment } }
+ Type { krate, env: environment, ty }
}
fn from_def(
@@ -1684,29 +1679,29 @@ fn from_def(
}
pub fn is_unit(&self) -> bool {
- matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..))
+ matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..))
}
pub fn is_bool(&self) -> bool {
- matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool))
+ matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool))
}
pub fn is_mutable_reference(&self) -> bool {
- matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
+ matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
}
pub fn is_usize(&self) -> bool {
- matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
+ matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
}
pub fn remove_ref(&self) -> Option {
- match &self.ty.value.interned(&Interner) {
+ match &self.ty.interned(&Interner) {
TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
_ => None,
}
}
pub fn is_unknown(&self) -> bool {
- self.ty.value.is_unknown()
+ self.ty.is_unknown()
}
/// Checks that particular type `ty` implements `std::future::Future`.
@@ -1723,11 +1718,12 @@ pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
None => return false,
};
- let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
+ let canonical_ty =
+ Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) };
method_resolution::implements_trait(
&canonical_ty,
db,
- self.ty.environment.clone(),
+ self.env.clone(),
krate,
std_future_trait,
)
@@ -1745,11 +1741,12 @@ pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
None => return false,
};
- let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
+ let canonical_ty =
+ Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) };
method_resolution::implements_trait_unique(
&canonical_ty,
db,
- self.ty.environment.clone(),
+ self.env.clone(),
krate,
fnonce_trait,
)
@@ -1759,17 +1756,14 @@ pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) ->
let trait_ref = hir_ty::TraitRef {
trait_id: hir_ty::to_chalk_trait_id(trait_.id),
substitution: Substitution::build_for_def(db, trait_.id)
- .push(self.ty.value.clone())
- .fill(args.iter().map(|t| t.ty.value.clone()))
+ .push(self.ty.clone())
+ .fill(args.iter().map(|t| t.ty.clone()))
.build(),
};
let goal = Canonical {
- value: hir_ty::InEnvironment::new(
- self.ty.environment.clone(),
- trait_ref.cast(&Interner),
- ),
- kinds: Arc::new([]),
+ value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)),
+ binders: CanonicalVarKinds::empty(&Interner),
};
db.trait_solve(self.krate, goal).is_some()
@@ -1783,12 +1777,12 @@ pub fn normalize_trait_assoc_type(
alias: TypeAlias,
) -> Option {
let subst = Substitution::build_for_def(db, trait_.id)
- .push(self.ty.value.clone())
- .fill(args.iter().map(|t| t.ty.value.clone()))
+ .push(self.ty.clone())
+ .fill(args.iter().map(|t| t.ty.clone()))
.build();
- let goal = Canonical {
- value: InEnvironment::new(
- self.ty.environment.clone(),
+ let goal = Canonical::new(
+ InEnvironment::new(
+ self.env.env.clone(),
AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(alias.id),
@@ -1799,8 +1793,8 @@ pub fn normalize_trait_assoc_type(
}
.cast(&Interner),
),
- kinds: Arc::new([TyVariableKind::General]),
- };
+ [TyVariableKind::General].iter().copied(),
+ );
match db.trait_solve(self.krate, goal)? {
Solution::Unique(SolutionVariables(subst)) => {
@@ -1820,22 +1814,22 @@ pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
}
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option {
- let def = self.ty.value.callable_def(db);
+ let def = self.ty.callable_def(db);
- let sig = self.ty.value.callable_sig(db)?;
+ let sig = self.ty.callable_sig(db)?;
Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
}
pub fn is_closure(&self) -> bool {
- matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. })
+ matches!(&self.ty.interned(&Interner), TyKind::Closure { .. })
}
pub fn is_fn(&self) -> bool {
- matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
+ matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
}
pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
- let adt_id = match self.ty.value.interned(&Interner) {
+ let adt_id = match self.ty.interned(&Interner) {
&TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
_ => return false,
};
@@ -1848,11 +1842,11 @@ pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
}
pub fn is_raw_ptr(&self) -> bool {
- matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..))
+ matches!(&self.ty.interned(&Interner), TyKind::Raw(..))
}
pub fn contains_unknown(&self) -> bool {
- return go(&self.ty.value);
+ return go(&self.ty);
fn go(ty: &Ty) -> bool {
match ty.interned(&Interner) {
@@ -1884,7 +1878,7 @@ fn go(ty: &Ty) -> bool {
}
pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
- let (variant_id, substs) = match self.ty.value.interned(&Interner) {
+ let (variant_id, substs) = match self.ty.interned(&Interner) {
&TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
&TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
_ => return Vec::new(),
@@ -1901,7 +1895,7 @@ pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
}
pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec {
- if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) {
+ if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) {
substs.iter().map(|ty| self.derived(ty.clone())).collect()
} else {
Vec::new()
@@ -1911,9 +1905,10 @@ pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec {
pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator- + 'a {
// There should be no inference vars in types passed here
// FIXME check that?
- let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
- let environment = self.ty.environment.clone();
- let ty = InEnvironment { value: canonical, environment };
+ let canonical =
+ Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) };
+ let environment = self.env.env.clone();
+ let ty = InEnvironment { goal: canonical, environment };
autoderef(db, Some(self.krate), ty)
.map(|canonical| canonical.value)
.map(move |ty| self.derived(ty))
@@ -1927,10 +1922,10 @@ pub fn iterate_assoc_items(
krate: Crate,
mut callback: impl FnMut(AssocItem) -> Option,
) -> Option {
- for krate in self.ty.value.def_crates(db, krate.id)? {
+ for krate in self.ty.def_crates(db, krate.id)? {
let impls = db.inherent_impls_in_crate(krate);
- for impl_def in impls.for_self_ty(&self.ty.value) {
+ for impl_def in impls.for_self_ty(&self.ty) {
for &item in db.impl_data(*impl_def).items.iter() {
if let Some(result) = callback(item.into()) {
return Some(result);
@@ -1943,7 +1938,6 @@ pub fn iterate_assoc_items(
pub fn type_parameters(&self) -> impl Iterator
- + '_ {
self.ty
- .value
.strip_references()
.substs()
.into_iter()
@@ -1962,9 +1956,10 @@ pub fn iterate_method_candidates(
// There should be no inference vars in types passed here
// FIXME check that?
// FIXME replace Unknown by bound vars here
- let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
+ let canonical =
+ Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) };
- let env = self.ty.environment.clone();
+ let env = self.env.clone();
let krate = krate.id;
method_resolution::iterate_method_candidates(
@@ -1993,9 +1988,10 @@ pub fn iterate_path_candidates(
// There should be no inference vars in types passed here
// FIXME check that?
// FIXME replace Unknown by bound vars here
- let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
+ let canonical =
+ Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) };
- let env = self.ty.environment.clone();
+ let env = self.env.clone();
let krate = krate.id;
method_resolution::iterate_method_candidates(
@@ -2011,16 +2007,16 @@ pub fn iterate_path_candidates(
}
pub fn as_adt(&self) -> Option {
- let (adt, _subst) = self.ty.value.as_adt()?;
+ let (adt, _subst) = self.ty.as_adt()?;
Some(adt.into())
}
pub fn as_dyn_trait(&self) -> Option {
- self.ty.value.dyn_trait().map(Into::into)
+ self.ty.dyn_trait().map(Into::into)
}
pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option> {
- self.ty.value.impl_trait_bounds(db).map(|it| {
+ self.ty.impl_trait_bounds(db).map(|it| {
it.into_iter()
.filter_map(|pred| match pred.skip_binders() {
hir_ty::WhereClause::Implemented(trait_ref) => {
@@ -2033,14 +2029,11 @@ pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option> {
}
pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option {
- self.ty.value.associated_type_parent_trait(db).map(Into::into)
+ self.ty.associated_type_parent_trait(db).map(Into::into)
}
fn derived(&self, ty: Ty) -> Type {
- Type {
- krate: self.krate,
- ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
- }
+ Type { krate: self.krate, env: self.env.clone(), ty }
}
pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
@@ -2079,7 +2072,7 @@ fn walk_bounds(
}
fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
- let ty = type_.ty.value.strip_references();
+ let ty = type_.ty.strip_references();
match ty.interned(&Interner) {
TyKind::Adt(..) => {
cb(type_.derived(ty.clone()));
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 23ab042c158e..dc5fc759a29f 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -16,8 +16,8 @@
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,
ty: InEnvironment>,
) -> impl Iterator
- > + '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>,
) -> Option> {
- 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
}
}
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index b9e434c78a0f..8f9cf74808f9 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -331,7 +331,7 @@ fn insert_type_vars(&mut self, ty: Ty) -> Ty {
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());
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 07eb96573960..9c62932b12f3 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -142,7 +142,7 @@ fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> Option {
.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 @@ fn unify_autoderef_behind_ref(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool {
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);
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 05cbde4e3fb6..19249973c9d3 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -90,12 +90,12 @@ fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Ve
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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) = derefs
@@ -438,8 +438,8 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
self.db,
krate,
InEnvironment {
- value: &canonicalized.value,
- environment: self.trait_env.clone(),
+ goal: &canonicalized.value,
+ environment: self.trait_env.env.clone(),
},
) {
Some(derefed_ty) => {
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 35b0a20597ac..75250a3694c6 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -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 @@ fn do_canonicalize(&mut self, t: T, binders: DebruijnIndex) -> T {
}
fn into_canonicalized(self, result: T) -> Canonicalized {
- 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 {
@@ -89,15 +98,12 @@ pub(crate) fn canonicalize_obligation(
mut self,
obligation: InEnvironment,
) -> Canonicalized> {
- 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 @@ pub(super) fn apply_solution(
// 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 @@ pub(super) fn apply_solution(
pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option {
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 {
}
}
Some(
- Substitution::builder(tys.kinds.len())
+ Substitution::builder(tys.binders.len(&Interner))
.fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
.build(),
)
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 90b5b17e2a41..0f49dd39b5d6 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -61,6 +61,8 @@ macro_rules! eprintln {
pub type OpaqueTyId = chalk_ir::OpaqueTyId;
pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
+pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds;
+
pub type ChalkTraitId = chalk_ir::TraitId;
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -662,12 +664,18 @@ pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Canonical {
pub value: T,
- pub kinds: Arc<[TyVariableKind]>,
+ pub binders: CanonicalVarKinds,
}
impl Canonical {
pub fn new(value: T, kinds: impl IntoIterator
- ) -> 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) }
}
}
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index da6bc2a4a174..8e986ddde264 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -6,7 +6,7 @@
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 @@
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> {
- 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,
) -> Canonical> {
- 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
}
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index 7dadd1ffba70..ccee0e5ad2bc 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -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,
+ pub env: chalk_ir::Environment,
}
impl TraitEnvironment {
@@ -74,13 +73,13 @@ fn default() -> Self {
/// Something (usually a goal), along with an environment.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct InEnvironment {
- pub environment: Arc,
- pub value: T,
+ pub environment: chalk_ir::Environment,
+ pub goal: T,
}
impl InEnvironment {
- pub fn new(environment: Arc, value: T) -> InEnvironment {
- InEnvironment { environment, value }
+ pub fn new(environment: chalk_ir::Environment, value: T) -> InEnvironment {
+ InEnvironment { environment, goal: value }
}
}
@@ -126,18 +125,18 @@ pub(crate) fn trait_solve_query(
krate: CrateId,
goal: Canonical>,
) -> Option {
- 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
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 7209dd14ec9e..aef6b8a15638 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -439,35 +439,12 @@ impl ToChalk for Canonical
type Chalk = chalk_ir::Canonical;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical {
- 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) -> Canonical {
- 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 @@ impl ToChalk for InEnvironment
type Chalk = chalk_ir::InEnvironment;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment {
- 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(