From 18487c3ff2949ce1210a3b2964291312eb00d110 Mon Sep 17 00:00:00 2001 From: Areredify Date: Thu, 30 Apr 2020 03:48:00 +0300 Subject: [PATCH] add const types --- chalk-integration/src/lowering.rs | 67 ++++++----- chalk-ir/src/cast.rs | 3 +- chalk-ir/src/debug.rs | 23 ++-- chalk-ir/src/fold.rs | 45 +++++--- chalk-ir/src/fold/boring_impls.rs | 9 +- chalk-ir/src/fold/shift.rs | 12 +- chalk-ir/src/fold/subst.rs | 7 +- chalk-ir/src/interner.rs | 29 +++-- chalk-ir/src/lib.rs | 145 ++++++++++++++---------- chalk-ir/src/visit.rs | 76 +++---------- chalk-ir/src/visit/boring_impls.rs | 6 +- chalk-ir/src/zip.rs | 18 ++- chalk-rust-ir/src/lib.rs | 40 +++---- chalk-solve/src/clauses/builder.rs | 2 +- chalk-solve/src/clauses/generalize.rs | 2 +- chalk-solve/src/infer.rs | 8 +- chalk-solve/src/infer/canonicalize.rs | 15 ++- chalk-solve/src/infer/instantiate.rs | 32 +++--- chalk-solve/src/infer/normalize_deep.rs | 3 +- chalk-solve/src/infer/ucanonicalize.rs | 16 +-- chalk-solve/src/infer/unify.rs | 35 ++++-- chalk-solve/src/infer/var.rs | 4 +- chalk-solve/src/recursive/fulfill.rs | 2 +- chalk-solve/src/solve/slg.rs | 42 +++++-- chalk-solve/src/solve/slg/aggregate.rs | 59 +++++++--- chalk-solve/src/solve/slg/resolvent.rs | 42 +++++-- 26 files changed, 428 insertions(+), 314 deletions(-) diff --git a/chalk-integration/src/lowering.rs b/chalk-integration/src/lowering.rs index e88ab6fad61..40f04cb06ea 100644 --- a/chalk-integration/src/lowering.rs +++ b/chalk-integration/src/lowering.rs @@ -26,7 +26,7 @@ type TraitKinds = BTreeMap, TypeKind>; type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId, Ident), AssociatedTyLookup>; type AssociatedTyValueIds = BTreeMap<(chalk_ir::ImplId, Ident), AssociatedTyValueId>; -type ParameterMap = BTreeMap>; +type ParameterMap = BTreeMap>; pub type LowerResult = Result; @@ -65,7 +65,7 @@ impl<'k> Env<'k> { #[derive(Debug, PartialEq, Eq)] struct AssociatedTyLookup { id: chalk_ir::AssocTypeId, - addl_parameter_kinds: Vec>, + addl_parameter_kinds: Vec>, } enum ApplyTypeLookup { @@ -80,16 +80,16 @@ impl<'k> Env<'k> { let interner = self.interner(); if let Some(p) = self.parameter_map.get(&name.str) { - return match *p { - chalk_ir::ParameterKind::Ty(b) => Ok(chalk_ir::TyData::BoundVar(b) + return match p { + chalk_ir::ParameterKind::Ty(b) => Ok(chalk_ir::TyData::BoundVar(*b) .intern(interner) .cast(interner)), - chalk_ir::ParameterKind::Lifetime(b) => Ok(chalk_ir::LifetimeData::BoundVar(b) - .intern(interner) - .cast(interner)), - chalk_ir::ParameterKind::Const(b) => Ok(chalk_ir::ConstData::BoundVar(b) + chalk_ir::ParameterKind::Lifetime(b) => Ok(chalk_ir::LifetimeData::BoundVar(*b) .intern(interner) .cast(interner)), + chalk_ir::ParameterKind::Const { ty, value: b } => { + Ok(b.to_const(interner, ty.clone()).cast(interner)) + } }; } @@ -173,7 +173,7 @@ impl<'k> Env<'k> { /// will be assigned in order as they are iterated. fn introduce(&self, binders: I) -> LowerResult where - I: IntoIterator>, + I: IntoIterator>, I::IntoIter: ExactSizeIterator, { // As binders to introduce we recieve `ParameterKind`, @@ -192,7 +192,7 @@ impl<'k> Env<'k> { let parameter_map: ParameterMap = self .parameter_map .iter() - .map(|(&k, &v)| (k, v.map(|b| b.shifted_in()))) + .map(|(k, v)| (*k, v.map_ref(|b| b.shifted_in()))) .chain(binders) .collect(); if parameter_map.len() != self.parameter_map.len() + len { @@ -206,7 +206,7 @@ impl<'k> Env<'k> { fn in_binders(&self, binders: I, op: OP) -> LowerResult> where - I: IntoIterator>, + I: IntoIterator>, I::IntoIter: ExactSizeIterator, T: HasInterner, OP: FnOnce(&Self) -> LowerResult, @@ -499,9 +499,9 @@ trait LowerTypeKind { } trait LowerParameterMap { - fn synthetic_parameters(&self) -> Option>; + fn synthetic_parameters(&self) -> Option>; fn declared_parameters(&self) -> &[ParameterKind]; - fn all_parameters(&self) -> Vec> { + fn all_parameters(&self) -> Vec> { self.synthetic_parameters() .into_iter() .chain(self.declared_parameters().iter().map(|id| id.lower())) @@ -550,7 +550,7 @@ trait LowerParameterMap { } impl LowerParameterMap for StructDefn { - fn synthetic_parameters(&self) -> Option> { + fn synthetic_parameters(&self) -> Option> { None } @@ -560,7 +560,7 @@ impl LowerParameterMap for StructDefn { } impl LowerParameterMap for Impl { - fn synthetic_parameters(&self) -> Option> { + fn synthetic_parameters(&self) -> Option> { None } @@ -570,7 +570,7 @@ impl LowerParameterMap for Impl { } impl LowerParameterMap for AssocTyDefn { - fn synthetic_parameters(&self) -> Option> { + fn synthetic_parameters(&self) -> Option> { None } @@ -580,7 +580,7 @@ impl LowerParameterMap for AssocTyDefn { } impl LowerParameterMap for AssocTyValue { - fn synthetic_parameters(&self) -> Option> { + fn synthetic_parameters(&self) -> Option> { None } @@ -590,7 +590,7 @@ impl LowerParameterMap for AssocTyValue { } impl LowerParameterMap for TraitDefn { - fn synthetic_parameters(&self) -> Option> { + fn synthetic_parameters(&self) -> Option> { Some(chalk_ir::ParameterKind::Ty(intern(SELF))) } @@ -600,7 +600,7 @@ impl LowerParameterMap for TraitDefn { } impl LowerParameterMap for Clause { - fn synthetic_parameters(&self) -> Option> { + fn synthetic_parameters(&self) -> Option> { None } @@ -609,16 +609,28 @@ impl LowerParameterMap for Clause { } } +fn get_type_of_u32() -> chalk_ir::Ty { + chalk_ir::ApplicationTy { + name: chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)), + substitution: Substitution::empty(&ChalkIr), + } + .cast(&ChalkIr) + .intern(&ChalkIr) +} + trait LowerParameterKind { - fn lower(&self) -> chalk_ir::ParameterKind; + fn lower(&self) -> chalk_ir::ParameterKind; } impl LowerParameterKind for ParameterKind { - fn lower(&self) -> chalk_ir::ParameterKind { + fn lower(&self) -> chalk_ir::ParameterKind { match *self { ParameterKind::Ty(ref n) => chalk_ir::ParameterKind::Ty(n.str), ParameterKind::Lifetime(ref n) => chalk_ir::ParameterKind::Lifetime(n.str), - ParameterKind::Const(ref n) => chalk_ir::ParameterKind::Const(n.str), + ParameterKind::Const(ref n) => chalk_ir::ParameterKind::Const { + ty: get_type_of_u32(), + value: n.str, + }, } } } @@ -1233,9 +1245,10 @@ impl LowerParameter for Parameter { Parameter::Ty(ref t) => Ok(t.lower(env)?.cast(interner)), Parameter::Lifetime(ref l) => Ok(l.lower(env)?.cast(interner)), Parameter::Id(name) => env.lookup_parameter(name), - Parameter::ConstValue(value) => Ok(chalk_ir::ConstData::Concrete( - chalk_ir::ConcreteConst { interned: value }, - ) + Parameter::ConstValue(value) => Ok(chalk_ir::ConstData { + ty: get_type_of_u32(), + value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: value }), + } .intern(interner) .cast(interner)), } @@ -1560,12 +1573,12 @@ impl Kinded for ParameterKind { } } -impl Kinded for chalk_ir::ParameterKind { +impl Kinded for chalk_ir::ParameterKind { fn kind(&self) -> Kind { match *self { chalk_ir::ParameterKind::Ty(_) => Kind::Ty, chalk_ir::ParameterKind::Lifetime(_) => Kind::Lifetime, - chalk_ir::ParameterKind::Const(_) => Kind::Const, + chalk_ir::ParameterKind::Const { .. } => Kind::Const, } } } diff --git a/chalk-ir/src/cast.rs b/chalk-ir/src/cast.rs index b9c287f41e9..2176730c575 100644 --- a/chalk-ir/src/cast.rs +++ b/chalk-ir/src/cast.rs @@ -177,7 +177,8 @@ impl CastTo> for Lifetime { impl CastTo> for Const { fn cast_to(self, interner: &I) -> Parameter { - Parameter::new(interner, ParameterKind::Const(self)) + let ty = self.data(interner).ty.clone(); + Parameter::new(interner, ParameterKind::Const { ty, value: self }) } } diff --git a/chalk-ir/src/debug.rs b/chalk-ir/src/debug.rs index d4d81f62cfc..3ef741f3fe3 100644 --- a/chalk-ir/src/debug.rs +++ b/chalk-ir/src/debug.rs @@ -265,7 +265,7 @@ impl<'a, I: Interner> Debug for ParameterKindsInnerDebug<'a, I> { match *binder { ParameterKind::Ty(()) => write!(fmt, "type")?, ParameterKind::Lifetime(()) => write!(fmt, "lifetime")?, - ParameterKind::Const(()) => write!(fmt, "const")?, + ParameterKind::Const { ref ty, value: () } => write!(fmt, "const: {:?}", ty)?, } } write!(fmt, ">") @@ -274,11 +274,11 @@ impl<'a, I: Interner> Debug for ParameterKindsInnerDebug<'a, I> { impl Debug for ConstData { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { - match self { - ConstData::BoundVar(db) => write!(fmt, "{:?}", db), - ConstData::InferenceVar(var) => write!(fmt, "{:?}", var), - ConstData::Placeholder(index) => write!(fmt, "{:?}", index), - ConstData::Concrete(evaluated) => write!(fmt, "{:?}", evaluated), + match &self.value { + ConstValue::BoundVar(db) => write!(fmt, "{:?}", db), + ConstValue::InferenceVar(var) => write!(fmt, "{:?}", var), + ConstValue::Placeholder(index) => write!(fmt, "{:?}", index), + ConstValue::Concrete(evaluated) => write!(fmt, "{:?}", evaluated), } } } @@ -338,7 +338,7 @@ impl<'a, I: Interner> Debug for ParameterDataInnerDebug<'a, I> { match self.0 { ParameterKind::Ty(n) => write!(fmt, "{:?}", n), ParameterKind::Lifetime(n) => write!(fmt, "{:?}", n), - ParameterKind::Const(n) => write!(fmt, "{:?}", n), + ParameterKind::Const { value: n, .. } => write!(fmt, "{:?}", n), } } } @@ -728,7 +728,7 @@ impl<'a, T: HasInterner + Display> Display for CanonicalDisplay<'a, T> { if i > 0 { write!(f, ",")?; } - write!(f, "?{}", pk.into_inner())?; + write!(f, "?{}", pk.as_ref().into_inner())?; } write!(f, "> {{ {} }}", value)?; @@ -738,12 +738,15 @@ impl<'a, T: HasInterner + Display> Display for CanonicalDisplay<'a, T> { } } -impl Debug for ParameterKind { +impl Debug for ParameterKind { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { match *self { ParameterKind::Ty(ref n) => write!(fmt, "Ty({:?})", n), ParameterKind::Lifetime(ref n) => write!(fmt, "Lifetime({:?})", n), - ParameterKind::Const(ref n) => write!(fmt, "Const({:?})", n), + ParameterKind::Const { + ref ty, + value: ref n, + } => write!(fmt, "Const({:?}: {:?})", n, ty), } } } diff --git a/chalk-ir/src/fold.rs b/chalk-ir/src/fold.rs index 86c5975496a..7148fd010ff 100644 --- a/chalk-ir/src/fold.rs +++ b/chalk-ir/src/fold.rs @@ -173,6 +173,7 @@ where fn fold_free_var_const( &mut self, + ty: &Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, ) -> Fallible> { @@ -183,7 +184,11 @@ where ) } else { let bound_var = bound_var.shifted_in_from(outer_binder); - Ok(ConstData::::BoundVar(bound_var).intern(self.target_interner())) + Ok(ConstData { + ty: ty.fold_with(self.as_dyn(), outer_binder)?, + value: ConstValue::::BoundVar(bound_var), + } + .intern(self.target_interner())) } } @@ -230,13 +235,17 @@ where #[allow(unused_variables)] fn fold_free_placeholder_const( &mut self, + ty: &Ty, universe: PlaceholderIndex, outer_binder: DebruijnIndex, ) -> Fallible> { if self.forbid_free_placeholders() { panic!("unexpected placeholder const `{:?}`", universe) } else { - Ok(universe.to_const(self.target_interner())) + Ok(universe.to_const( + self.target_interner(), + ty.fold_with(self.as_dyn(), outer_binder)?, + )) } } @@ -284,13 +293,17 @@ where #[allow(unused_variables)] fn fold_inference_const( &mut self, + ty: &Ty, var: InferenceVar, outer_binder: DebruijnIndex, ) -> Fallible> { if self.forbid_inference_vars() { panic!("unexpected inference const `{:?}`", var) } else { - Ok(var.to_const(self.target_interner())) + Ok(var.to_const( + self.target_interner(), + ty.fold_with(self.as_dyn(), outer_binder)?, + )) } } @@ -507,21 +520,27 @@ where TI: 'i, { let interner = folder.interner(); - match self.data(interner) { - ConstData::BoundVar(bound_var) => { + let target_interner = folder.target_interner(); + let ConstData { ref ty, ref value } = self.data(interner); + let mut fold_ty = || ty.fold_with(folder, outer_binder); + match value { + ConstValue::BoundVar(bound_var) => { if let Some(bound_var1) = bound_var.shifted_out_to(outer_binder) { - folder.fold_free_var_const(bound_var1, outer_binder) + folder.fold_free_var_const(ty, bound_var1, outer_binder) } else { - Ok(ConstData::::BoundVar(*bound_var).intern(folder.target_interner())) + Ok(bound_var.to_const(target_interner, fold_ty()?)) } } - ConstData::InferenceVar(var) => folder.fold_inference_const(*var, outer_binder), - ConstData::Placeholder(universe) => { - folder.fold_free_placeholder_const(*universe, outer_binder) + ConstValue::InferenceVar(var) => folder.fold_inference_const(ty, *var, outer_binder), + ConstValue::Placeholder(universe) => { + folder.fold_free_placeholder_const(ty, *universe, outer_binder) + } + ConstValue::Concrete(ev) => Ok(ConstData { + ty: fold_ty()?, + value: ConstValue::Concrete(ConcreteConst { + interned: folder.target_interner().transfer_const(&ev.interned), + }), } - ConstData::Concrete(ev) => Ok(ConstData::Concrete(ConcreteConst { - interned: folder.target_interner().transfer_const(&ev.interned), - }) .intern(folder.target_interner())), } } diff --git a/chalk-ir/src/fold/boring_impls.rs b/chalk-ir/src/fold/boring_impls.rs index dffe0404eb0..68144d89bb2 100644 --- a/chalk-ir/src/fold/boring_impls.rs +++ b/chalk-ir/src/fold/boring_impls.rs @@ -331,13 +331,13 @@ impl> Fold for PhantomData { } } -impl, T, L, C> Fold for ParameterKind +impl, T, L, C> Fold for ParameterKind where T: Fold, L: Fold, C: Fold, { - type Result = ParameterKind; + type Result = ParameterKind; fn fold_with<'i>( &self, @@ -353,7 +353,10 @@ where ParameterKind::Lifetime(a) => { Ok(ParameterKind::Lifetime(a.fold_with(folder, outer_binder)?)) } - ParameterKind::Const(a) => Ok(ParameterKind::Const(a.fold_with(folder, outer_binder)?)), + ParameterKind::Const { ty, value } => Ok(ParameterKind::Const { + ty: ty.fold_with(folder, outer_binder)?, + value: value.fold_with(folder, outer_binder)?, + }), } } } diff --git a/chalk-ir/src/fold/shift.rs b/chalk-ir/src/fold/shift.rs index eea9f2d052b..1c34f59fe41 100644 --- a/chalk-ir/src/fold/shift.rs +++ b/chalk-ir/src/fold/shift.rs @@ -95,10 +95,14 @@ impl<'i, I: Interner> Folder<'i, I> for Shifter<'i, I> { fn fold_free_var_const( &mut self, + ty: &Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, ) -> Fallible> { - Ok(ConstData::::BoundVar(self.adjust(bound_var, outer_binder)).intern(self.interner())) + // const types don't have free variables, so we can skip folding `ty` + Ok(self + .adjust(bound_var, outer_binder) + .to_const(self.interner(), ty.clone())) } fn interner(&self) -> &'i I { @@ -163,10 +167,14 @@ impl<'i, I: Interner> Folder<'i, I> for DownShifter<'i, I> { fn fold_free_var_const( &mut self, + ty: &Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, ) -> Fallible> { - Ok(ConstData::::BoundVar(self.adjust(bound_var, outer_binder)?).intern(self.interner())) + // const types don't have free variables, so we can skip folding `ty` + Ok(self + .adjust(bound_var, outer_binder)? + .to_const(self.interner(), ty.clone())) } fn interner(&self) -> &'i I { diff --git a/chalk-ir/src/fold/subst.rs b/chalk-ir/src/fold/subst.rs index 158fb1eac2f..8e940f09c00 100644 --- a/chalk-ir/src/fold/subst.rs +++ b/chalk-ir/src/fold/subst.rs @@ -89,12 +89,15 @@ impl<'i, I: Interner> Folder<'i, I> for Subst<'_, 'i, I> { /// see `fold_free_var_ty` fn fold_free_var_const( &mut self, + ty: &Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, ) -> Fallible> { if let Some(index) = bound_var.index_if_innermost() { match self.parameters[index].data(self.interner()) { - ParameterKind::Const(c) => Ok(c.shifted_in_from(self.interner(), outer_binder)), + ParameterKind::Const { value, .. } => { + Ok(value.shifted_in_from(self.interner(), outer_binder)) + } _ => panic!("mismatched kinds in substitution"), } } else { @@ -102,7 +105,7 @@ impl<'i, I: Interner> Folder<'i, I> for Subst<'_, 'i, I> { .shifted_out() .unwrap() .shifted_in_from(outer_binder) - .to_const(self.interner())) + .to_const(self.interner(), ty.clone())) } } diff --git a/chalk-ir/src/interner.rs b/chalk-ir/src/interner.rs index 5ec8d188a6f..e930b555fd7 100644 --- a/chalk-ir/src/interner.rs +++ b/chalk-ir/src/interner.rs @@ -524,7 +524,12 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { /// Lookup the `ConstData` that was interned to create a `InternedConst`. fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a ConstData; - fn const_eq(&self, c1: &Self::InternedConcreteConst, c2: &Self::InternedConcreteConst) -> bool; + fn const_eq( + &self, + ty: &Self::InternedType, + c1: &Self::InternedConcreteConst, + c2: &Self::InternedConcreteConst, + ) -> bool; /// Create an "interned" parameter from `data`. This is not /// normally invoked directly; instead, you invoke @@ -620,7 +625,7 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { /// method). fn intern_parameter_kinds( &self, - data: impl IntoIterator, E>>, + data: impl IntoIterator, E>>, ) -> Result; /// Lookup the slice of `ParameterKind` that was interned to @@ -628,7 +633,7 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { fn parameter_kinds_data<'a>( &self, parameter_kinds: &'a Self::InternedParameterKinds, - ) -> &'a [ParameterKind<()>]; + ) -> &'a [ParameterKind]; /// Create an "interned" parameter kinds with universe index from `data`. This is not /// normally invoked directly; instead, you invoke @@ -636,7 +641,7 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { /// method). fn intern_canonical_var_kinds( &self, - data: impl IntoIterator, E>>, + data: impl IntoIterator, E>>, ) -> Result; /// Lookup the slice of `ParameterKind` that was interned to @@ -644,7 +649,7 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash { fn canonical_var_kinds_data<'a>( &self, canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, - ) -> &'a [ParameterKind]; + ) -> &'a [ParameterKind]; } pub trait TargetInterner: Interner { @@ -735,8 +740,8 @@ mod default { type InternedProgramClause = ProgramClauseData; type InternedProgramClauses = Vec>; type InternedQuantifiedWhereClauses = Vec>; - type InternedParameterKinds = Vec>; - type InternedCanonicalVarKinds = Vec>; + type InternedParameterKinds = Vec>; + type InternedCanonicalVarKinds = Vec>; type DefId = RawId; type Identifier = Identifier; @@ -926,7 +931,7 @@ mod default { constant } - fn const_eq(&self, c1: &u32, c2: &u32) -> bool { + fn const_eq(&self, _ty: &Arc>, c1: &u32, c2: &u32) -> bool { c1 == c2 } @@ -1014,7 +1019,7 @@ mod default { } fn intern_parameter_kinds( &self, - data: impl IntoIterator, E>>, + data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect() } @@ -1022,13 +1027,13 @@ mod default { fn parameter_kinds_data<'a>( &self, parameter_kinds: &'a Self::InternedParameterKinds, - ) -> &'a [ParameterKind<()>] { + ) -> &'a [ParameterKind] { parameter_kinds } fn intern_canonical_var_kinds( &self, - data: impl IntoIterator, E>>, + data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect() } @@ -1036,7 +1041,7 @@ mod default { fn canonical_var_kinds_data<'a>( &self, canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, - ) -> &'a [ParameterKind] { + ) -> &'a [ParameterKind] { canonical_var_kinds } } diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index 33e96bfc31e..4f52ee3ab15 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -391,8 +391,12 @@ impl BoundVar { LifetimeData::::BoundVar(self).intern(interner) } - pub fn to_const(self, interner: &I) -> Const { - ConstData::::BoundVar(self).intern(interner) + pub fn to_const(self, interner: &I, ty: Ty) -> Const { + ConstData { + ty, + value: ConstValue::::BoundVar(self), + } + .intern(interner) } /// True if this variable is bound within the `amount` innermost binders. @@ -635,8 +639,12 @@ impl InferenceVar { LifetimeData::::InferenceVar(self).intern(interner) } - pub fn to_const(self, interner: &I) -> Const { - ConstData::::InferenceVar(self).intern(interner) + pub fn to_const(self, interner: &I, ty: Ty) -> Const { + ConstData { + ty, + value: ConstValue::::InferenceVar(self), + } + .intern(interner) } } @@ -670,7 +678,7 @@ impl Const { /// If this is a `ConstData::BoundVar(d)`, returns `Some(d)` else `None`. pub fn bound_var(&self, interner: &I) -> Option { - if let ConstData::BoundVar(bv) = self.data(interner) { + if let ConstValue::BoundVar(bv) = &self.data(interner).value { Some(*bv) } else { None @@ -679,7 +687,7 @@ impl Const { /// If this is a `ConstData::InferenceVar(d)`, returns `Some(d)` else `None`. pub fn inference_var(&self, interner: &I) -> Option { - if let ConstData::InferenceVar(iv) = self.data(interner) { + if let ConstValue::InferenceVar(iv) = &self.data(interner).value { Some(*iv) } else { None @@ -689,17 +697,23 @@ impl Const { /// True if this const is a "bound" const, and hence /// needs to be shifted across binders. Meant for debug assertions. pub fn needs_shift(&self, interner: &I) -> bool { - match self.data(interner) { - ConstData::BoundVar(_) => true, - ConstData::InferenceVar(_) => false, - ConstData::Placeholder(_) => false, - ConstData::Concrete(_) => false, + match &self.data(interner).value { + ConstValue::BoundVar(_) => true, + ConstValue::InferenceVar(_) => false, + ConstValue::Placeholder(_) => false, + ConstValue::Concrete(_) => false, } } } #[derive(Clone, PartialEq, Eq, Hash, HasInterner)] -pub enum ConstData { +pub struct ConstData { + pub ty: Ty, + pub value: ConstValue, +} + +#[derive(Clone, PartialEq, Eq, Hash, HasInterner)] +pub enum ConstValue { BoundVar(BoundVar), InferenceVar(InferenceVar), Placeholder(PlaceholderIndex), @@ -718,8 +732,8 @@ pub struct ConcreteConst { } impl ConcreteConst { - pub fn const_eq(&self, other: &ConcreteConst, interner: &I) -> bool { - interner.const_eq(&self.interned, &other.interned) + pub fn const_eq(&self, ty: &Ty, other: &ConcreteConst, interner: &I) -> bool { + interner.const_eq(&ty.interned, &self.interned, &other.interned) } } @@ -805,13 +819,15 @@ impl PlaceholderIndex { } pub fn to_ty(self, interner: &I) -> Ty { - let data: TyData = TyData::Placeholder(self); - data.intern(interner) + TyData::Placeholder(self).intern(interner) } - pub fn to_const(self, interner: &I) -> Const { - let data: ConstData = ConstData::Placeholder(self); - data.intern(interner) + pub fn to_const(self, interner: &I, ty: Ty) -> Const { + ConstData { + ty, + value: ConstValue::Placeholder(self), + } + .intern(interner) } } @@ -843,54 +859,57 @@ impl ApplicationTy { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum ParameterKind { +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum ParameterKind { Ty(T), Lifetime(L), - Const(C), + Const { ty: Ty, value: C }, } -impl ParameterKind { +impl ParameterKind { pub fn into_inner(self) -> T { match self { ParameterKind::Ty(t) => t, ParameterKind::Lifetime(t) => t, - ParameterKind::Const(t) => t, + ParameterKind::Const { value: t, .. } => t, } } - pub fn swap_inner(self, u: U) -> (T, ParameterKind) { + pub fn swap_inner(self, u: U) -> (T, ParameterKind) { match self { ParameterKind::Ty(t) => (t, ParameterKind::Ty(u)), ParameterKind::Lifetime(t) => (t, ParameterKind::Lifetime(u)), - ParameterKind::Const(t) => (t, ParameterKind::Const(u)), + ParameterKind::Const { ty, value: t } => (t, ParameterKind::Const { ty, value: u }), } } - pub fn map(self, op: OP) -> ParameterKind + pub fn map(self, op: OP) -> ParameterKind where OP: FnOnce(T) -> U, { match self { ParameterKind::Ty(t) => ParameterKind::Ty(op(t)), ParameterKind::Lifetime(t) => ParameterKind::Lifetime(op(t)), - ParameterKind::Const(t) => ParameterKind::Const(op(t)), + ParameterKind::Const { ty, value: t } => ParameterKind::Const { ty, value: op(t) }, } } - pub fn map_ref(&self, op: OP) -> ParameterKind + pub fn map_ref(&self, op: OP) -> ParameterKind where OP: FnOnce(&T) -> U, { match self { ParameterKind::Ty(t) => ParameterKind::Ty(op(t)), ParameterKind::Lifetime(t) => ParameterKind::Lifetime(op(t)), - ParameterKind::Const(t) => ParameterKind::Const(op(t)), + ParameterKind::Const { ty, value: t } => ParameterKind::Const { + ty: ty.clone(), + value: op(t), + }, } } } -impl ParameterKind { +impl ParameterKind { pub fn assert_ty_ref(&self) -> &T { self.as_ref().ty().unwrap() } @@ -899,11 +918,14 @@ impl ParameterKind { self.as_ref().lifetime().unwrap() } - pub fn as_ref(&self) -> ParameterKind<&T, &L, &C> { + pub fn as_ref(&self) -> ParameterKind { match *self { ParameterKind::Ty(ref t) => ParameterKind::Ty(t), ParameterKind::Lifetime(ref l) => ParameterKind::Lifetime(l), - ParameterKind::Const(ref c) => ParameterKind::Const(c), + ParameterKind::Const { ref ty, ref value } => ParameterKind::Const { + ty: ty.clone(), + value, + }, } } @@ -911,7 +933,7 @@ impl ParameterKind { match self { ParameterKind::Ty(_) => true, ParameterKind::Lifetime(_) => false, - ParameterKind::Const(_) => false, + ParameterKind::Const { .. } => false, } } @@ -929,9 +951,9 @@ impl ParameterKind { } } - pub fn constant(self) -> Option { + pub fn constant(self) -> Option<(C, Ty)> { match self { - ParameterKind::Const(c) => Some(c), + ParameterKind::Const { ty, value } => Some((value, ty)), _ => None, } } @@ -965,14 +987,17 @@ impl Parameter { } pub fn assert_const_ref(&self, interner: &I) -> &Const { - self.as_ref(interner).constant().unwrap() + self.as_ref(interner).constant().unwrap().0 } - pub fn as_ref(&self, interner: &I) -> ParameterKind<&Ty, &Lifetime, &Const> { + pub fn as_ref(&self, interner: &I) -> ParameterKind, &Lifetime, &Const> { match self.data(interner) { ParameterKind::Ty(t) => ParameterKind::Ty(t), ParameterKind::Lifetime(l) => ParameterKind::Lifetime(l), - ParameterKind::Const(c) => ParameterKind::Const(c), + ParameterKind::Const { ty, value } => ParameterKind::Const { + ty: ty.clone(), + value, + }, } } @@ -980,7 +1005,7 @@ impl Parameter { match self.data(interner) { ParameterKind::Ty(_) => true, ParameterKind::Lifetime(_) => false, - ParameterKind::Const(_) => false, + ParameterKind::Const { .. } => false, } } @@ -1000,14 +1025,14 @@ impl Parameter { pub fn constant(&self, interner: &I) -> Option<&Const> { match self.data(interner) { - ParameterKind::Const(c) => Some(c), + ParameterKind::Const { value, .. } => Some(value), _ => None, } } } #[allow(type_alias_bounds)] -pub type ParameterData = ParameterKind, Lifetime, Const>; +pub type ParameterData = ParameterKind, Lifetime, Const>; impl ParameterData { pub fn intern(self, interner: &I) -> Parameter { @@ -1678,7 +1703,7 @@ pub struct ParameterKinds { impl ParameterKinds { pub fn new(interner: &I) -> Self { - Self::from(interner, None::>) + Self::from(interner, None::>) } pub fn interned(&self) -> &I::InternedParameterKinds { @@ -1687,27 +1712,27 @@ impl ParameterKinds { pub fn from( interner: &I, - parameter_kinds: impl IntoIterator>, + parameter_kinds: impl IntoIterator>, ) -> Self { Self::from_fallible( interner, parameter_kinds .into_iter() - .map(|p| -> Result, ()> { Ok(p) }), + .map(|p| -> Result, ()> { Ok(p) }), ) .unwrap() } pub fn from_fallible( interner: &I, - parameter_kinds: impl IntoIterator, E>>, + parameter_kinds: impl IntoIterator, E>>, ) -> Result { Ok(ParameterKinds { interned: I::intern_parameter_kinds(interner, parameter_kinds.into_iter())?, }) } - pub fn iter(&self, interner: &I) -> std::slice::Iter<'_, ParameterKind<()>> { + pub fn iter(&self, interner: &I) -> std::slice::Iter<'_, ParameterKind> { self.as_slice(interner).iter() } @@ -1719,7 +1744,7 @@ impl ParameterKinds { self.as_slice(interner).len() } - pub fn as_slice(&self, interner: &I) -> &[ParameterKind<()>] { + pub fn as_slice(&self, interner: &I) -> &[ParameterKind] { interner.parameter_kinds_data(&self.interned) } } @@ -1731,7 +1756,7 @@ pub struct CanonicalVarKinds { impl CanonicalVarKinds { pub fn new(interner: &I) -> Self { - Self::from(interner, None::>) + Self::from(interner, None::>) } pub fn interned(&self) -> &I::InternedCanonicalVarKinds { @@ -1740,27 +1765,27 @@ impl CanonicalVarKinds { pub fn from( interner: &I, - parameter_kinds: impl IntoIterator>, + parameter_kinds: impl IntoIterator>, ) -> Self { Self::from_fallible( interner, parameter_kinds .into_iter() - .map(|p| -> Result, ()> { Ok(p) }), + .map(|p| -> Result, ()> { Ok(p) }), ) .unwrap() } pub fn from_fallible( interner: &I, - parameter_kinds: impl IntoIterator, E>>, + parameter_kinds: impl IntoIterator, E>>, ) -> Result { Ok(CanonicalVarKinds { interned: I::intern_canonical_var_kinds(interner, parameter_kinds.into_iter())?, }) } - pub fn iter(&self, interner: &I) -> std::slice::Iter<'_, ParameterKind> { + pub fn iter(&self, interner: &I) -> std::slice::Iter<'_, ParameterKind> { self.as_slice(interner).iter() } @@ -1772,7 +1797,7 @@ impl CanonicalVarKinds { self.as_slice(interner).len() } - pub fn as_slice(&self, interner: &I) -> &[ParameterKind] { + pub fn as_slice(&self, interner: &I) -> &[ParameterKind] { interner.canonical_var_kinds_data(&self.interned) } } @@ -1836,10 +1861,11 @@ impl UCanonical { LifetimeData::BoundVar(bound_var).intern(interner), ) .intern(interner), - ParameterKind::Const(_) => { - ParameterKind::Const(ConstData::BoundVar(bound_var).intern(interner)) - .intern(interner) + ParameterKind::Const { ty, .. } => ParameterKind::Const { + ty: ty.clone(), + value: bound_var.to_const(interner, ty.clone()), } + .intern(interner), } }) .collect::>(), @@ -2137,8 +2163,8 @@ impl Substitution { LifetimeData::BoundVar(depth) => index_db == *depth, _ => false, }, - ParameterKind::Const(constant) => match &constant.data(interner) { - ConstData::BoundVar(depth) => index_db == *depth, + ParameterKind::Const { value, .. } => match &value.data(interner).value { + ConstValue::BoundVar(depth) => index_db == *depth, _ => false, }, } @@ -2241,6 +2267,7 @@ impl<'i, I: Interner> Folder<'i, I> for &SubstFolder<'i, I> { fn fold_free_var_const( &mut self, + _ty: &Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, ) -> Fallible> { diff --git a/chalk-ir/src/visit.rs b/chalk-ir/src/visit.rs index 23ad55b9e2b..0d59b6d8506 100644 --- a/chalk-ir/src/visit.rs +++ b/chalk-ir/src/visit.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use crate::{ - BoundVar, Const, ConstData, DebruijnIndex, DomainGoal, Goal, InferenceVar, Interner, Lifetime, + BoundVar, Const, ConstValue, DebruijnIndex, DomainGoal, Goal, InferenceVar, Interner, Lifetime, LifetimeData, PlaceholderIndex, ProgramClause, Ty, TyData, WhereClause, }; @@ -160,7 +160,7 @@ where /// Invoked for each occurrence of a placeholder type; these are /// used when we instantiate binders universally. - fn visit_free_placeholder_ty( + fn visit_free_placeholder( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -180,31 +180,6 @@ where where_clause.super_visit_with(self.as_dyn(), outer_binder) } - /// As with `visit_free_placeholder_ty`, but for lifetimes. - fn visit_free_placeholder_lifetime( - &mut self, - universe: PlaceholderIndex, - _outer_binder: DebruijnIndex, - ) -> Self::Result { - if self.forbid_free_placeholders() { - panic!("unexpected placeholder lifetime `{:?}`", universe) - } else { - Self::Result::new() - } - } - - fn visit_free_placeholder_const( - &mut self, - universe: PlaceholderIndex, - _outer_binder: DebruijnIndex, - ) -> Self::Result { - if self.forbid_free_placeholders() { - panic!("unexpected placeholder const `{:?}`", universe) - } else { - Self::Result::new() - } - } - /// If overridden to return true, inference variables will trigger /// panics when visited. Used when inference variables are /// unexpected. @@ -214,7 +189,7 @@ where /// Invoked for each occurrence of a inference type; these are /// used when we instantiate binders universally. - fn visit_inference_ty( + fn visit_inference_var( &mut self, var: InferenceVar, _outer_binder: DebruijnIndex, @@ -226,31 +201,6 @@ where } } - /// As with `visit_free_inference_ty`, but for lifetimes. - fn visit_inference_lifetime( - &mut self, - var: InferenceVar, - _outer_binder: DebruijnIndex, - ) -> Self::Result { - if self.forbid_inference_vars() { - panic!("unexpected inference lifetime `'{:?}`", var) - } else { - Self::Result::new() - } - } - - fn visit_inference_const( - &mut self, - var: InferenceVar, - _outer_binder: DebruijnIndex, - ) -> Self::Result { - if self.forbid_inference_vars() { - panic!("unexpected inference lifetime `'{:?}`", var) - } else { - Self::Result::new() - } - } - fn interner(&self) -> &'i I; } @@ -323,9 +273,9 @@ where } } TyData::Dyn(clauses) => clauses.visit_with(visitor, outer_binder), - TyData::InferenceVar(var) => visitor.visit_inference_ty(*var, outer_binder), + TyData::InferenceVar(var) => visitor.visit_inference_var(*var, outer_binder), TyData::Apply(apply) => apply.visit_with(visitor, outer_binder), - TyData::Placeholder(ui) => visitor.visit_free_placeholder_ty(*ui, outer_binder), + TyData::Placeholder(ui) => visitor.visit_free_placeholder(*ui, outer_binder), TyData::Alias(proj) => proj.visit_with(visitor, outer_binder), TyData::Function(fun) => fun.visit_with(visitor, outer_binder), } @@ -363,9 +313,9 @@ impl SuperVisit for Lifetime { R::new() } } - LifetimeData::InferenceVar(var) => visitor.visit_inference_lifetime(*var, outer_binder), + LifetimeData::InferenceVar(var) => visitor.visit_inference_var(*var, outer_binder), LifetimeData::Placeholder(universe) => { - visitor.visit_free_placeholder_lifetime(*universe, outer_binder) + visitor.visit_free_placeholder(*universe, outer_binder) } LifetimeData::Phantom(..) => unreachable!(), } @@ -395,19 +345,19 @@ impl SuperVisit for Const { I: 'i, { let interner = visitor.interner(); - match self.data(interner) { - ConstData::BoundVar(bound_var) => { + match &self.data(interner).value { + ConstValue::BoundVar(bound_var) => { if let Some(_) = bound_var.shifted_out_to(outer_binder) { visitor.visit_free_var(*bound_var, outer_binder) } else { R::new() } } - ConstData::InferenceVar(var) => visitor.visit_inference_const(*var, outer_binder), - ConstData::Placeholder(universe) => { - visitor.visit_free_placeholder_const(*universe, outer_binder) + ConstValue::InferenceVar(var) => visitor.visit_inference_var(*var, outer_binder), + ConstValue::Placeholder(universe) => { + visitor.visit_free_placeholder(*universe, outer_binder) } - ConstData::Concrete(_) => R::new(), + ConstValue::Concrete(_) => R::new(), } } } diff --git a/chalk-ir/src/visit/boring_impls.rs b/chalk-ir/src/visit/boring_impls.rs index bb7c131611d..2b20d8b51a2 100644 --- a/chalk-ir/src/visit/boring_impls.rs +++ b/chalk-ir/src/visit/boring_impls.rs @@ -297,7 +297,7 @@ impl Visit for PhantomData { } } -impl Visit for ParameterKind +impl Visit for ParameterKind where T: Visit, L: Visit, @@ -314,7 +314,9 @@ where match self { ParameterKind::Ty(a) => a.visit_with(visitor, outer_binder), ParameterKind::Lifetime(a) => a.visit_with(visitor, outer_binder), - ParameterKind::Const(a) => a.visit_with(visitor, outer_binder), + ParameterKind::Const { ty, value } => R::new() + .and_then(|| ty.visit_with(visitor, outer_binder)) + .and_then(|| value.visit_with(visitor, outer_binder)), } } } diff --git a/chalk-ir/src/zip.rs b/chalk-ir/src/zip.rs index d036e29cc17..0eec232a9a8 100644 --- a/chalk-ir/src/zip.rs +++ b/chalk-ir/src/zip.rs @@ -302,7 +302,7 @@ impl Zip for Goal { } // I'm too lazy to make `enum_zip` support type parameters. -impl, L: Zip, C: Zip, I: Interner> Zip for ParameterKind { +impl, L: Zip, C: Zip, I: Interner> Zip for ParameterKind { fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()> where I: 'i, @@ -310,10 +310,22 @@ impl, L: Zip, C: Zip, I: Interner> Zip for ParameterKind Zip::zip_with(zipper, a, b), (ParameterKind::Lifetime(a), ParameterKind::Lifetime(b)) => Zip::zip_with(zipper, a, b), - (ParameterKind::Const(a), ParameterKind::Const(b)) => Zip::zip_with(zipper, a, b), + ( + ParameterKind::Const { + ty: a_ty, + value: a_value, + }, + ParameterKind::Const { + ty: b_ty, + value: b_value, + }, + ) => { + Zip::zip_with(zipper, a_ty, b_ty)?; + Zip::zip_with(zipper, a_value, b_value) + } (ParameterKind::Ty(_), _) | (ParameterKind::Lifetime(_), _) - | (ParameterKind::Const(_), _) => panic!("zipping things of mixed kind"), + | (ParameterKind::Const { .. }, _) => panic!("zipping things of mixed kind"), } } } diff --git a/chalk-rust-ir/src/lib.rs b/chalk-rust-ir/src/lib.rs index f9f56425fb2..02973ea30da 100644 --- a/chalk-rust-ir/src/lib.rs +++ b/chalk-rust-ir/src/lib.rs @@ -9,9 +9,9 @@ use chalk_ir::cast::Cast; use chalk_ir::fold::shift::Shift; use chalk_ir::interner::{Interner, TargetInterner}; use chalk_ir::{ - AliasEq, AliasTy, AssocTypeId, Binders, BoundVar, ConstData, DebruijnIndex, ImplId, - LifetimeData, OpaqueTyId, Parameter, ParameterKind, ProjectionTy, QuantifiedWhereClause, - StructId, Substitution, TraitId, TraitRef, Ty, TyData, TypeName, WhereClause, + AliasEq, AliasTy, AssocTypeId, Binders, BoundVar, DebruijnIndex, ImplId, LifetimeData, + OpaqueTyId, Parameter, ParameterKind, ProjectionTy, QuantifiedWhereClause, StructId, + Substitution, TraitId, TraitRef, Ty, TyData, TypeName, WhereClause, }; use std::iter; @@ -317,43 +317,35 @@ impl AliasEqBound { } } -pub trait Anonymize { +pub trait Anonymize { /// Utility function that converts from a list of generic parameters /// which *have* names (`ParameterKind`) to a list of /// "anonymous" generic parameters that just preserves their - /// kinds (`ParameterKind<()>`). Often convenient in lowering. - fn anonymize(&self) -> Vec>; + /// kinds (`ParameterKind`). Often convenient in lowering. + fn anonymize(&self) -> Vec>; } -impl Anonymize for [ParameterKind] { - fn anonymize(&self) -> Vec> { +impl Anonymize for [ParameterKind] { + fn anonymize(&self) -> Vec> { self.iter().map(|pk| pk.map_ref(|_| ())).collect() } } -pub trait ToParameter { +pub trait ToParameter { /// Utility for converting a list of all the binders into scope /// into references to those binders. Simply pair the binders with /// the indices, and invoke `to_parameter()` on the `(binder, /// index)` pair. The result will be a reference to a bound /// variable of appropriate kind at the corresponding index. - fn to_parameter(&self, interner: &I) -> Parameter { + fn to_parameter(&self, interner: &I) -> Parameter { self.to_parameter_at_depth(interner, DebruijnIndex::INNERMOST) } - fn to_parameter_at_depth( - &self, - interner: &I, - debruijn: DebruijnIndex, - ) -> Parameter; + fn to_parameter_at_depth(&self, interner: &I, debruijn: DebruijnIndex) -> Parameter; } -impl<'a> ToParameter for (&'a ParameterKind<()>, usize) { - fn to_parameter_at_depth( - &self, - interner: &I, - debruijn: DebruijnIndex, - ) -> Parameter { +impl<'a, I: Interner> ToParameter for (&'a ParameterKind, usize) { + fn to_parameter_at_depth(&self, interner: &I, debruijn: DebruijnIndex) -> Parameter { let &(binder, index) = self; let bound_var = BoundVar::new(debruijn, index); match *binder { @@ -361,9 +353,9 @@ impl<'a> ToParameter for (&'a ParameterKind<()>, usize) { .intern(interner) .cast(interner), ParameterKind::Ty(_) => TyData::BoundVar(bound_var).intern(interner).cast(interner), - ParameterKind::Const(_) => ConstData::BoundVar(bound_var) - .intern(interner) - .cast(interner), + ParameterKind::Const { ref ty, .. } => { + bound_var.to_const(interner, ty.clone()).cast(interner) + } } } } diff --git a/chalk-solve/src/clauses/builder.rs b/chalk-solve/src/clauses/builder.rs index 755e635041c..d91cd8a079c 100644 --- a/chalk-solve/src/clauses/builder.rs +++ b/chalk-solve/src/clauses/builder.rs @@ -13,7 +13,7 @@ use std::marker::PhantomData; pub struct ClauseBuilder<'me, I: Interner> { pub db: &'me dyn RustIrDatabase, clauses: &'me mut Vec>, - binders: Vec>, + binders: Vec>, parameters: Vec>, } diff --git a/chalk-solve/src/clauses/generalize.rs b/chalk-solve/src/clauses/generalize.rs index 934ef70df2e..273d2cddb56 100644 --- a/chalk-solve/src/clauses/generalize.rs +++ b/chalk-solve/src/clauses/generalize.rs @@ -16,7 +16,7 @@ use chalk_ir::{ use rustc_hash::FxHashMap; pub struct Generalize<'i, I: Interner> { - binders: Vec>, + binders: Vec>, mapping: FxHashMap, interner: &'i I, } diff --git a/chalk-solve/src/infer.rs b/chalk-solve/src/infer.rs index 027b7310eb9..52e68dd5fa8 100644 --- a/chalk-solve/src/infer.rs +++ b/chalk-solve/src/infer.rs @@ -27,7 +27,7 @@ pub(crate) struct InferenceSnapshot { } #[allow(type_alias_bounds)] -pub(crate) type ParameterEnaVariable = ParameterKind>; +pub(crate) type ParameterEnaVariable = ParameterKind>; impl InferenceTable { /// Create an empty inference table with no variables. @@ -195,8 +195,8 @@ impl InferenceTable { } } - ParameterKind::Const(constant) => { - if let Some(var) = constant.inference_var(interner) { + ParameterKind::Const { value, .. } => { + if let Some(var) = value.inference_var(interner) { if self.var_is_bound(var) { return false; } @@ -218,7 +218,7 @@ impl ParameterEnaVariableExt for ParameterEnaVariable { match self { ParameterKind::Ty(v) => v.to_ty(interner).cast(interner), ParameterKind::Lifetime(v) => v.to_lifetime(interner).cast(interner), - ParameterKind::Const(v) => v.to_const(interner).cast(interner), + ParameterKind::Const { ty, value } => value.to_const(interner, ty).cast(interner), } } } diff --git a/chalk-solve/src/infer/canonicalize.rs b/chalk-solve/src/infer/canonicalize.rs index 310c09aa22e..2968eaa304e 100644 --- a/chalk-solve/src/infer/canonicalize.rs +++ b/chalk-solve/src/infer/canonicalize.rs @@ -92,7 +92,7 @@ impl<'q, I: Interner> Canonicalizer<'q, I> { fn add(&mut self, free_var: ParameterEnaVariable) -> usize { self.free_vars .iter() - .position(|&v| v == free_var) + .position(|v| v == &free_var) .unwrap_or_else(|| { let next_index = self.free_vars.len(); self.free_vars.push(free_var); @@ -131,12 +131,13 @@ where fn fold_free_placeholder_const( &mut self, + ty: &Ty, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, ) -> Fallible> { let interner = self.interner; self.max_universe = max(self.max_universe, universe.ui); - Ok(universe.to_const(interner)) + Ok(universe.to_const(interner, ty.clone())) } fn forbid_free_vars(&self) -> bool { @@ -207,6 +208,7 @@ where fn fold_inference_const( &mut self, + ty: &Ty, var: InferenceVar, outer_binder: DebruijnIndex, ) -> Fallible> { @@ -224,10 +226,15 @@ where .shifted_in_from(interner, outer_binder)) } None => { - let free_var = ParameterKind::Const(self.table.unify.find(var)); + let free_var = ParameterKind::Const { + ty: ty.clone(), + value: self.table.unify.find(var), + }; let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.add(free_var)); debug!("not yet unified: position={:?}", bound_var); - Ok(ConstData::BoundVar(bound_var.shifted_in_from(outer_binder)).intern(interner)) + Ok(bound_var + .shifted_in_from(outer_binder) + .to_const(interner, ty.clone())) } } } diff --git a/chalk-solve/src/infer/instantiate.rs b/chalk-solve/src/infer/instantiate.rs index 8f31a16c251..180afa8f12d 100644 --- a/chalk-solve/src/infer/instantiate.rs +++ b/chalk-solve/src/infer/instantiate.rs @@ -13,12 +13,12 @@ impl InferenceTable { pub(crate) fn fresh_subst( &mut self, interner: &I, - binders: &[ParameterKind], + binders: &[ParameterKind], ) -> Substitution { Substitution::from( interner, binders.iter().map(|kind| { - let param_infer_var = kind.map(|ui| self.new_variable(ui)); + let param_infer_var = kind.map_ref(|&ui| self.new_variable(ui)); param_infer_var.to_parameter(interner) }), ) @@ -51,7 +51,7 @@ impl InferenceTable { ) -> T::Result where T: Fold, - U: IntoIterator>, + U: IntoIterator>, { let binders: Vec<_> = binders .into_iter() @@ -96,7 +96,9 @@ impl InferenceTable { lt.cast(interner) } ParameterKind::Ty(()) => placeholder_idx.to_ty(interner).cast(interner), - ParameterKind::Const(()) => placeholder_idx.to_const(interner).cast(interner), + ParameterKind::Const { ty, value: () } => { + placeholder_idx.to_const(interner, ty).cast(interner) + } } }) .collect(); @@ -105,7 +107,7 @@ impl InferenceTable { } pub(crate) trait IntoBindersAndValue<'a, I: Interner> { - type Binders: IntoIterator>; + type Binders: IntoIterator>; type Value; fn into_binders_and_value(self, interner: &'a I) -> (Self::Binders, Self::Value); @@ -115,8 +117,9 @@ impl<'a, I, T> IntoBindersAndValue<'a, I> for &'a Binders where I: Interner, T: HasInterner, + I: 'a, { - type Binders = std::iter::Cloned>>; + type Binders = std::iter::Cloned>>; type Value = &'a T; fn into_binders_and_value(self, interner: &'a I) -> (Self::Binders, Self::Value) { @@ -128,21 +131,22 @@ impl<'a, I> IntoBindersAndValue<'a, I> for &'a Fn where I: Interner, { - type Binders = std::iter::Map, fn(usize) -> chalk_ir::ParameterKind<()>>; + type Binders = + std::iter::Map, fn(usize) -> chalk_ir::ParameterKind>; type Value = &'a Substitution; fn into_binders_and_value(self, _interner: &'a I) -> (Self::Binders, Self::Value) { - fn make_lifetime(_: usize) -> ParameterKind<()> { - ParameterKind::Lifetime(()) - } - - let p: fn(usize) -> ParameterKind<()> = make_lifetime; + let p: fn(usize) -> ParameterKind = make_lifetime; ((0..self.num_binders).map(p), &self.substitution) } } -impl<'a, T, I: Interner> IntoBindersAndValue<'a, I> for (&'a Vec>, &'a T) { - type Binders = std::iter::Cloned>>; +fn make_lifetime(_: usize) -> ParameterKind { + ParameterKind::Lifetime(()) +} + +impl<'a, T, I: Interner> IntoBindersAndValue<'a, I> for (&'a Vec>, &'a T) { + type Binders = std::iter::Cloned>>; type Value = &'a T; fn into_binders_and_value(self, _interner: &'a I) -> (Self::Binders, Self::Value) { diff --git a/chalk-solve/src/infer/normalize_deep.rs b/chalk-solve/src/infer/normalize_deep.rs index c5e7950f5ee..de9b2230371 100644 --- a/chalk-solve/src/infer/normalize_deep.rs +++ b/chalk-solve/src/infer/normalize_deep.rs @@ -76,6 +76,7 @@ where fn fold_inference_const( &mut self, + ty: &Ty, var: InferenceVar, _outer_binder: DebruijnIndex, ) -> Fallible> { @@ -85,7 +86,7 @@ where .assert_const_ref(interner) .fold_with(self, DebruijnIndex::INNERMOST)? .shifted_in(interner)), - None => Ok(var.to_const(interner)), // FIXME shift + None => Ok(var.to_const(interner, ty.clone())), // FIXME shift } } diff --git a/chalk-solve/src/infer/ucanonicalize.rs b/chalk-solve/src/infer/ucanonicalize.rs index 84df92fb90c..c49f5d1945c 100644 --- a/chalk-solve/src/infer/ucanonicalize.rs +++ b/chalk-solve/src/infer/ucanonicalize.rs @@ -46,7 +46,7 @@ impl InferenceTable { value0 .binders .iter(interner) - .map(|pk| pk.map(|ui| universes.map_universe_to_canonical(ui))), + .map(|pk| pk.map_ref(|&ui| universes.map_universe_to_canonical(ui))), ); UCanonicalized { @@ -253,19 +253,7 @@ where self } - fn visit_free_placeholder_ty( - &mut self, - universe: PlaceholderIndex, - _outer_binder: DebruijnIndex, - ) { - self.universes.add(universe.ui); - } - - fn visit_free_placeholder_lifetime( - &mut self, - universe: PlaceholderIndex, - _outer_binder: DebruijnIndex, - ) { + fn visit_free_placeholder(&mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex) { self.universes.add(universe.ui); } diff --git a/chalk-solve/src/infer/unify.rs b/chalk-solve/src/infer/unify.rs index e6df362a826..bb929438a9e 100644 --- a/chalk-solve/src/infer/unify.rs +++ b/chalk-solve/src/infer/unify.rs @@ -348,10 +348,21 @@ impl<'t, I: Interner> Unifier<'t, I> { b ); - match (a.data(interner), b.data(interner)) { + let ConstData { + ty: a_ty, + value: a_val, + } = a.data(interner); + let ConstData { + ty: b_ty, + value: b_val, + } = b.data(interner); + + self.unify_ty_ty(a_ty, b_ty)?; + + match (a_val, b_val) { // Unifying two inference variables: unify them in the underlying // ena table. - (&ConstData::InferenceVar(var1), &ConstData::InferenceVar(var2)) => { + (&ConstValue::InferenceVar(var1), &ConstValue::InferenceVar(var2)) => { debug!("unify_ty_ty: unify_var_var({:?}, {:?})", var1, var2); let var1 = EnaVariable::from(var1); let var2 = EnaVariable::from(var2); @@ -363,35 +374,35 @@ impl<'t, I: Interner> Unifier<'t, I> { } // Unifying an inference variables with a non-inference variable. - (&ConstData::InferenceVar(var), &ConstData::Concrete(_)) - | (&ConstData::InferenceVar(var), &ConstData::Placeholder(_)) => { + (&ConstValue::InferenceVar(var), &ConstValue::Concrete(_)) + | (&ConstValue::InferenceVar(var), &ConstValue::Placeholder(_)) => { debug!("unify_var_ty(var={:?}, ty={:?})", var, b); self.unify_var_const(var, b) } - (&ConstData::Concrete(_), &ConstData::InferenceVar(var)) - | (&ConstData::Placeholder(_), &ConstData::InferenceVar(var)) => { + (&ConstValue::Concrete(_), &ConstValue::InferenceVar(var)) + | (&ConstValue::Placeholder(_), &ConstValue::InferenceVar(var)) => { debug!("unify_var_ty(var={:?}, ty={:?})", var, a); self.unify_var_const(var, a) } - (&ConstData::Placeholder(p1), &ConstData::Placeholder(p2)) => { + (&ConstValue::Placeholder(p1), &ConstValue::Placeholder(p2)) => { Zip::zip_with(self, &p1, &p2) } - (&ConstData::Concrete(ref ev1), &ConstData::Concrete(ref ev2)) => { - if ev1.const_eq(ev2, interner) { + (&ConstValue::Concrete(ref ev1), &ConstValue::Concrete(ref ev2)) => { + if ev1.const_eq(a_ty, ev2, interner) { Ok(()) } else { Err(NoSolution) } } - (&ConstData::Concrete(_), &ConstData::Placeholder(_)) - | (&ConstData::Placeholder(_), &ConstData::Concrete(_)) => Err(NoSolution), + (&ConstValue::Concrete(_), &ConstValue::Placeholder(_)) + | (&ConstValue::Placeholder(_), &ConstValue::Concrete(_)) => Err(NoSolution), - (ConstData::BoundVar(_), _) | (_, ConstData::BoundVar(_)) => panic!( + (ConstValue::BoundVar(_), _) | (_, ConstValue::BoundVar(_)) => panic!( "unification encountered bound variable: a={:?} b={:?}", a, b ), diff --git a/chalk-solve/src/infer/var.rs b/chalk-solve/src/infer/var.rs index 5c12a96d36f..01ba18761d3 100644 --- a/chalk-solve/src/infer/var.rs +++ b/chalk-solve/src/infer/var.rs @@ -68,8 +68,8 @@ impl EnaVariable { /// Convert this inference variable into a const. When using this /// method, naturally you should know from context that the kind /// of this inference variable is a const (we can't check it). - pub(crate) fn to_const(self, interner: &I) -> Const { - self.var.to_const(interner) + pub(crate) fn to_const(self, interner: &I, ty: Ty) -> Const { + self.var.to_const(interner, ty) } } diff --git a/chalk-solve/src/recursive/fulfill.rs b/chalk-solve/src/recursive/fulfill.rs index 69696e53494..8ebd46e7881 100644 --- a/chalk-solve/src/recursive/fulfill.rs +++ b/chalk-solve/src/recursive/fulfill.rs @@ -307,7 +307,7 @@ impl<'s, 'db, I: Interner> Fulfill<'s, 'db, I> { for (i, free_var) in free_vars.into_iter().enumerate() { let subst_value = subst.at(self.interner(), i); - let free_value = free_var.to_parameter(self.interner()); + let free_value = free_var.clone().to_parameter(self.interner()); self.unify(empty_env, &free_value, subst_value) .unwrap_or_else(|err| { panic!( diff --git a/chalk-solve/src/solve/slg.rs b/chalk-solve/src/solve/slg.rs index f9249ad8419..21917e14830 100644 --- a/chalk-solve/src/solve/slg.rs +++ b/chalk-solve/src/solve/slg.rs @@ -456,10 +456,19 @@ impl MayInvalidate<'_, I> { (ParameterKind::Lifetime(l1), ParameterKind::Lifetime(l2)) => { self.aggregate_lifetimes(l1, l2) } - (ParameterKind::Const(c1), ParameterKind::Const(c2)) => self.aggregate_consts(c1, c2), + ( + ParameterKind::Const { + ty: ty1, + value: value1, + }, + ParameterKind::Const { + ty: ty2, + value: value2, + }, + ) => self.aggregate_tys(ty1, ty2) || self.aggregate_consts(value1, value2), (ParameterKind::Ty(_), _) | (ParameterKind::Lifetime(_), _) - | (ParameterKind::Const(_), _) => panic!( + | (ParameterKind::Const { .. }, _) => panic!( "mismatched parameter kinds: new={:?} current={:?}", new, current ), @@ -538,32 +547,47 @@ impl MayInvalidate<'_, I> { /// Returns true if the two consts could be unequal. fn aggregate_consts(&mut self, new: &Const, current: &Const) -> bool { let interner = self.interner; - match (new.data(interner), current.data(interner)) { - (_, ConstData::BoundVar(_)) => { + let ConstData { + ty: new_ty, + value: new_value, + } = new.data(interner); + let ConstData { + ty: current_ty, + value: current_value, + } = current.data(interner); + + if self.aggregate_tys(new_ty, current_ty) { + return true; + } + + match (new_value, current_value) { + (_, ConstValue::BoundVar(_)) => { // see comment in aggregate_tys false } - (ConstData::BoundVar(_), _) => { + (ConstValue::BoundVar(_), _) => { // see comment in aggregate_tys true } - (ConstData::InferenceVar(_), _) | (_, ConstData::InferenceVar(_)) => { + (ConstValue::InferenceVar(_), _) | (_, ConstValue::InferenceVar(_)) => { panic!( "unexpected free inference variable in may-invalidate: {:?} vs {:?}", new, current, ); } - (ConstData::Placeholder(p1), ConstData::Placeholder(p2)) => { + (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) => { self.aggregate_placeholders(p1, p2) } - (ConstData::Concrete(c1), ConstData::Concrete(c2)) => !c1.const_eq(c2, interner), + (ConstValue::Concrete(c1), ConstValue::Concrete(c2)) => { + !c1.const_eq(new_ty, c2, interner) + } // Only variants left are placeholder = concrete, which always fails - (ConstData::Placeholder(_), _) | (ConstData::Concrete(_), _) => true, + (ConstValue::Placeholder(_), _) | (ConstValue::Concrete(_), _) => true, } } diff --git a/chalk-solve/src/solve/slg/aggregate.rs b/chalk-solve/src/solve/slg/aggregate.rs index 33351d1b6be..4b53ca5931b 100644 --- a/chalk-solve/src/solve/slg/aggregate.rs +++ b/chalk-solve/src/solve/slg/aggregate.rs @@ -146,7 +146,9 @@ fn merge_into_guidance( // We have two values for some variable X that // appears in the root goal. Find out the universe // of X. - let universe = root_goal.binders.as_slice(interner)[index].into_inner(); + let universe = *root_goal.binders.as_slice(interner)[index] + .as_ref() + .into_inner(); match p1.data(interner) { ParameterKind::Ty(_) => (), @@ -158,7 +160,7 @@ fn merge_into_guidance( .to_lifetime(interner) .cast(interner); } - ParameterKind::Const(_) => (), + ParameterKind::Const { .. } => (), }; // Combine the two types into a new type. @@ -199,7 +201,7 @@ fn is_trivial(interner: &I, subst: &Canonical>) -> // has been canonicalized, those will also be the first N // variables. ParameterKind::Ty(t) => is_trivial(t.bound_var(interner)), - ParameterKind::Const(t) => is_trivial(t.bound_var(interner)), + ParameterKind::Const { value, .. } => is_trivial(value.bound_var(interner)), // And no lifetime mappings. (This is too strict, but we never // product substs with lifetimes.) @@ -400,12 +402,15 @@ impl AntiUnifier<'_, '_, I> { (ParameterKind::Lifetime(l1), ParameterKind::Lifetime(l2)) => { self.aggregate_lifetimes(l1, l2).cast(interner) } - (ParameterKind::Const(c1), ParameterKind::Const(c2)) => { + (ParameterKind::Const { value: c1, .. }, ParameterKind::Const { value: c2, .. }) => { + // we can ignore types here, because types inside c1 c2 + // will be matched in aggregate_consts + self.aggregate_consts(c1, c2).cast(interner) } (ParameterKind::Ty(_), _) | (ParameterKind::Lifetime(_), _) - | (ParameterKind::Const(_), _) => { + | (ParameterKind::Const { .. }, _) => { panic!("mismatched parameter kinds: p1={:?} p2={:?}", p1, p2) } } @@ -436,30 +441,46 @@ impl AntiUnifier<'_, '_, I> { fn aggregate_consts(&mut self, c1: &Const, c2: &Const) -> Const { let interner = self.interner; - match (c1.data(interner), c2.data(interner)) { - (ConstData::InferenceVar(_), _) | (_, ConstData::InferenceVar(_)) => { - self.new_const_variable() + + // FIXME actually check that c1 and c2 have the same type + + let ConstData { + ty: c1_ty, + value: c1_value, + } = c1.data(interner); + let ConstData { + ty: _c2_ty, + value: c2_value, + } = c2.data(interner); + + let ty = c1_ty.clone(); + + match (c1_value, c2_value) { + (ConstValue::InferenceVar(_), _) | (_, ConstValue::InferenceVar(_)) => { + self.new_const_variable(ty) } - (ConstData::BoundVar(_), _) | (_, ConstData::BoundVar(_)) => self.new_const_variable(), + (ConstValue::BoundVar(_), _) | (_, ConstValue::BoundVar(_)) => { + self.new_const_variable(ty.clone()) + } - (ConstData::Placeholder(_), ConstData::Placeholder(_)) => { + (ConstValue::Placeholder(_), ConstValue::Placeholder(_)) => { if c1 == c2 { c1.clone() } else { - self.new_const_variable() + self.new_const_variable(ty) } } - (ConstData::Concrete(e1), ConstData::Concrete(e2)) => { - if e1.const_eq(e2, interner) { + (ConstValue::Concrete(e1), ConstValue::Concrete(e2)) => { + if e1.const_eq(&ty, e2, interner) { c1.clone() } else { - self.new_const_variable() + self.new_const_variable(ty) } } - (ConstData::Placeholder(_), _) | (_, ConstData::Placeholder(_)) => { - self.new_const_variable() + (ConstValue::Placeholder(_), _) | (_, ConstValue::Placeholder(_)) => { + self.new_const_variable(ty) } } } @@ -474,9 +495,11 @@ impl AntiUnifier<'_, '_, I> { self.infer.new_variable(self.universe).to_lifetime(interner) } - fn new_const_variable(&mut self) -> Const { + fn new_const_variable(&mut self, ty: Ty) -> Const { let interner = self.interner; - self.infer.new_variable(self.universe).to_const(interner) + self.infer + .new_variable(self.universe) + .to_const(interner, ty) } } diff --git a/chalk-solve/src/solve/slg/resolvent.rs b/chalk-solve/src/solve/slg/resolvent.rs index 8cd714be62e..7279cbcface 100644 --- a/chalk-solve/src/solve/slg/resolvent.rs +++ b/chalk-solve/src/solve/slg/resolvent.rs @@ -314,7 +314,7 @@ impl AnswerSubstitutor<'_, I> { &mut self, interner: &I, answer_var: BoundVar, - pending: ParameterKind<&Ty, &Lifetime, &Const>, + pending: ParameterKind, &Lifetime, &Const>, ) -> Fallible { let answer_index = match answer_var.index_if_bound_at(self.outer_binder) { Some(index) => index, @@ -487,35 +487,53 @@ impl<'i, I: Interner> Zipper<'i, I> for AnswerSubstitutor<'i, I> { return Zip::zip_with(self, answer, &pending); } - if let ConstData::BoundVar(answer_depth) = answer.data(interner) { - if self.unify_free_answer_var(interner, *answer_depth, ParameterKind::Const(pending))? { + let ConstData { + ty: answer_ty, + value: answer_value, + } = answer.data(interner); + let ConstData { + ty: pending_ty, + value: pending_value, + } = pending.data(interner); + + self.zip_tys(answer_ty, pending_ty)?; + + if let ConstValue::BoundVar(answer_depth) = answer_value { + if self.unify_free_answer_var( + interner, + *answer_depth, + ParameterKind::Const { + ty: answer_ty.clone(), + value: pending, + }, + )? { return Ok(()); } } - match (answer.data(interner), pending.data(interner)) { - (ConstData::BoundVar(answer_depth), ConstData::BoundVar(pending_depth)) => { + match (answer_value, pending_value) { + (ConstValue::BoundVar(answer_depth), ConstValue::BoundVar(pending_depth)) => { self.assert_matching_vars(*answer_depth, *pending_depth) } - (ConstData::Placeholder(_), ConstData::Placeholder(_)) => { + (ConstValue::Placeholder(_), ConstValue::Placeholder(_)) => { assert_eq!(answer, pending); Ok(()) } - (ConstData::Concrete(c1), ConstData::Concrete(c2)) => { - assert!(c1.const_eq(c2, interner)); + (ConstValue::Concrete(c1), ConstValue::Concrete(c2)) => { + assert!(c1.const_eq(answer_ty, c2, interner)); Ok(()) } - (ConstData::InferenceVar(_), _) | (_, ConstData::InferenceVar(_)) => panic!( + (ConstValue::InferenceVar(_), _) | (_, ConstValue::InferenceVar(_)) => panic!( "unexpected inference var in answer `{:?}` or pending goal `{:?}`", answer, pending, ), - (ConstData::BoundVar(_), _) - | (ConstData::Placeholder(_), _) - | (ConstData::Concrete(_), _) => panic!( + (ConstValue::BoundVar(_), _) + | (ConstValue::Placeholder(_), _) + | (ConstValue::Concrete(_), _) => panic!( "structural mismatch between answer `{:?}` and pending goal `{:?}`", answer, pending, ),