diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 9f6d7be4839..97a78ca2521 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -217,7 +217,7 @@ impl HirDisplay for Variant { 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 a325b6691a0..30b96d7e2ed 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -56,9 +56,9 @@ use hir_ty::{ 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 @@ impl Function { .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 @@ impl Impl { inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() } - pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec<Impl> { - let def_crates = match ty.value.def_crates(db, krate) { + pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { + let def_crates = match ty.def_crates(db, krate) { Some(def_crates) => def_crates, None => return Vec::new(), }; @@ -1549,14 +1543,14 @@ impl Impl { 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 @@ impl Impl { #[derive(Clone, PartialEq, Eq, Debug)] pub struct Type { krate: CrateId, - ty: InEnvironment<Ty>, + env: Arc<TraitEnvironment>, + ty: Ty, } impl Type { @@ -1663,14 +1658,14 @@ impl Type { ) -> 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 @@ impl Type { } 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<Type> { - 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 @@ impl Type { 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 @@ impl Type { 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 @@ impl 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 @@ impl Type { alias: TypeAlias, ) -> Option<Type> { 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 @@ impl 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 @@ impl Type { } pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { - 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 @@ impl Type { } 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 @@ impl Type { } 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 @@ impl Type { } pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { - 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 @@ impl Type { pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + '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 @@ impl Type { krate: Crate, mut callback: impl FnMut(AssocItem) -> Option<T>, ) -> Option<T> { - 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 @@ impl Type { pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { self.ty - .value .strip_references() .substs() .into_iter() @@ -1962,9 +1956,10 @@ impl Type { // 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 @@ impl Type { // 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 @@ impl Type { } pub fn as_adt(&self) -> Option<Adt> { - 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<Trait> { - 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<Vec<Trait>> { - 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 @@ impl Type { } pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { - 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 @@ impl Type { } 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 23ab042c158..dc5fc759a29 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs @@ -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 } } diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b9e434c78a0..8f9cf74808f 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -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()); diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 07eb9657396..9c62932b12f 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -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); diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 05cbde4e3fb..19249973c9d 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -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) => { diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 35b0a20597a..75250a3694c 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 @@ 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(), ) diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 90b5b17e2a4..0f49dd39b5d 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -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) } } } diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index da6bc2a4a17..8e986ddde26 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -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 } diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 7dadd1ffba7..ccee0e5ad2b 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<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 diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 7209dd14ec9..aef6b8a1563 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -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(