Skip to content

Commit 338ab7c

Browse files
committed
const implementation mvp
1 parent b64e5a8 commit 338ab7c

28 files changed

+967
-202
lines changed

chalk-integration/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ impl std::error::Error for ChalkError {}
5656
pub enum RustIrError {
5757
InvalidTypeName(Identifier),
5858
InvalidLifetimeName(Identifier),
59+
InvalidConstName(Identifier),
5960
NotTrait(Identifier),
6061
NotStruct(Identifier),
6162
DuplicateOrShadowedParameters,
@@ -98,6 +99,7 @@ impl std::fmt::Display for RustIrError {
9899
match self {
99100
RustIrError::InvalidTypeName(name) => write!(f, "invalid type name `{}`", name),
100101
RustIrError::InvalidLifetimeName(name) => write!(f, "invalid lifetime name `{}`", name),
102+
RustIrError::InvalidConstName(name) => write!(f, "invalid const name `{}`", name),
101103
RustIrError::NotTrait(name) => write!(
102104
f,
103105
"expected a trait, found `{}`, which is not a trait",

chalk-integration/src/lowering.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ enum LifetimeLookup {
8080
GenericArg(BoundVar),
8181
}
8282

83+
enum ConstLookup {
84+
Parameter(BoundVar),
85+
}
86+
8387
const SELF: &str = "Self";
8488
const FIXME_SELF: &str = "__FIXME_SELF__";
8589

@@ -136,6 +140,17 @@ impl<'k> Env<'k> {
136140
Err(RustIrError::InvalidLifetimeName(name.clone()))
137141
}
138142

143+
fn lookup_const(&self, name: Identifier) -> LowerResult<ConstLookup> {
144+
if let Some(k) = self
145+
.parameter_map
146+
.get(&chalk_ir::ParameterKind::Const(name.str))
147+
{
148+
return Ok(ConstLookup::Parameter(*k));
149+
}
150+
151+
Err(RustIrError::InvalidConstName(name))
152+
}
153+
139154
fn struct_kind(&self, id: chalk_ir::StructId<ChalkIr>) -> &TypeKind {
140155
&self.struct_kinds[&id]
141156
}
@@ -803,6 +818,11 @@ impl LowerLeafGoal for LeafGoal {
803818
b: b.lower(env)?.cast(interner),
804819
}
805820
.cast::<chalk_ir::Goal<ChalkIr>>(interner),
821+
LeafGoal::UnifyConsts { ref a, ref b } => chalk_ir::EqGoal {
822+
a: a.lower(env)?.cast(interner),
823+
b: b.lower(env)?.cast(interner),
824+
}
825+
.cast::<chalk_ir::Goal<ChalkIr>>(interner),
806826
})
807827
}
808828
}
@@ -1289,6 +1309,28 @@ impl LowerGenericArg for GenericArg {
12891309
match *self {
12901310
GenericArg::Ty(ref t) => Ok(t.lower(env)?.cast(interner)),
12911311
GenericArg::Lifetime(ref l) => Ok(l.lower(env)?.cast(interner)),
1312+
GenericArg::Const(ref c) => Ok(c.lower(env)?.cast(interner)),
1313+
}
1314+
}
1315+
}
1316+
1317+
trait LowerConst {
1318+
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>>;
1319+
}
1320+
1321+
impl LowerConst for Const {
1322+
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>> {
1323+
let interner = env.interner();
1324+
match *self {
1325+
Const::Id { name } => match env.lookup_const(name)? {
1326+
ConstLookup::Parameter(d) => Ok(chalk_ir::ConstData::BoundVar(d).intern(interner)),
1327+
},
1328+
Const::Value { value } => {
1329+
Ok(
1330+
chalk_ir::ConstData::Concrete(chalk_ir::ConcreteConst { interned: value })
1331+
.intern(interner),
1332+
)
1333+
}
12921334
}
12931335
}
12941336
}
@@ -1600,6 +1642,7 @@ impl Kinded for VariableKind {
16001642
match *self {
16011643
VariableKind::Ty(_) => Kind::Ty,
16021644
VariableKind::Lifetime(_) => Kind::Lifetime,
1645+
VariableKind::Const(_) => Kind::Const,
16031646
}
16041647
}
16051648
}
@@ -1609,6 +1652,7 @@ impl Kinded for GenericArg {
16091652
match *self {
16101653
GenericArg::Ty(_) => Kind::Ty,
16111654
GenericArg::Lifetime(_) => Kind::Lifetime,
1655+
GenericArg::Const(_) => Kind::Const,
16121656
}
16131657
}
16141658
}
@@ -1618,7 +1662,7 @@ impl Kinded for chalk_ir::VariableKind<ChalkIr> {
16181662
match self {
16191663
chalk_ir::VariableKind::Ty => Kind::Ty,
16201664
chalk_ir::VariableKind::Lifetime => Kind::Lifetime,
1621-
chalk_ir::VariableKind::Phantom(..) => unreachable!(),
1665+
chalk_ir::VariableKind::Const(_) => Kind::Const,
16221666
}
16231667
}
16241668
}

chalk-ir/src/cast.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ macro_rules! reflexive_impl {
7676

7777
reflexive_impl!(for(I: Interner) TyData<I>);
7878
reflexive_impl!(for(I: Interner) LifetimeData<I>);
79+
reflexive_impl!(for(I: Interner) ConstData<I>);
7980
reflexive_impl!(for(I: Interner) TraitRef<I>);
8081
reflexive_impl!(for(I: Interner) DomainGoal<I>);
8182
reflexive_impl!(for(I: Interner) Goal<I>);
@@ -174,6 +175,12 @@ impl<I: Interner> CastTo<GenericArg<I>> for Lifetime<I> {
174175
}
175176
}
176177

178+
impl<I: Interner> CastTo<Parameter<I>> for Const<I> {
179+
fn cast_to(self, interner: &I) -> Parameter<I> {
180+
Parameter::new(interner, ParameterKind::Const(self))
181+
}
182+
}
183+
177184
impl<I: Interner> CastTo<GenericArg<I>> for GenericArg<I> {
178185
fn cast_to(self, _interner: &I) -> GenericArg<I> {
179186
self

chalk-ir/src/could_match.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ where
4848
Ok(())
4949
}
5050

51+
fn zip_consts(&mut self, _: &Const<I>, _: &Const<I>) -> Fallible<()> {
52+
Ok(())
53+
}
54+
5155
fn zip_binders<T>(&mut self, a: &Binders<T>, b: &Binders<T>) -> Fallible<()>
5256
where
5357
T: HasInterner + Zip<I>,

chalk-ir/src/debug.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ impl<I: Interner> Debug for Lifetime<I> {
3333
}
3434
}
3535

36+
impl<I: Interner> Debug for Const<I> {
37+
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
38+
I::debug_const(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned))
39+
}
40+
}
41+
42+
impl<I: Interner> Debug for ConcreteConst<I> {
43+
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
44+
write!(fmt, "{:?}", self.interned)
45+
}
46+
}
47+
3648
impl<I: Interner> Debug for GenericArg<I> {
3749
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
3850
I::debug_generic_arg(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned))
@@ -257,13 +269,24 @@ impl<'a, I: Interner> Debug for VariableKindsInnerDebug<'a, I> {
257269
match *binder {
258270
VariableKind::Ty => write!(fmt, "type")?,
259271
VariableKind::Lifetime => write!(fmt, "lifetime")?,
260-
VariableKind::Phantom(..) => unreachable!(),
272+
VariableKind::Const(()) => write!(fmt, "const")?,
261273
}
262274
}
263275
write!(fmt, ">")
264276
}
265277
}
266278

279+
impl<I: Interner> Debug for ConstData<I> {
280+
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
281+
match self {
282+
ConstData::BoundVar(db) => write!(fmt, "{:?}", db),
283+
ConstData::InferenceVar(var) => write!(fmt, "{:?}", var),
284+
ConstData::Placeholder(index) => write!(fmt, "{:?}", index),
285+
ConstData::Concrete(evaluated) => write!(fmt, "{:?}", evaluated),
286+
}
287+
}
288+
}
289+
267290
impl<I: Interner> Debug for GoalData<I> {
268291
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
269292
match self {
@@ -319,6 +342,7 @@ impl<'a, I: Interner> Debug for GenericArgDataInnerDebug<'a, I> {
319342
match self.0 {
320343
GenericArgData::Ty(n) => write!(fmt, "{:?}", n),
321344
GenericArgData::Lifetime(n) => write!(fmt, "{:?}", n),
345+
GenericArgData::Const(n) => write!(fmt, "{:?}", n),
322346
}
323347
}
324348
}
@@ -724,6 +748,7 @@ impl<I: Interner> Debug for GenericArgData<I> {
724748
match self {
725749
GenericArgData::Ty(t) => write!(fmt, "Ty({:?})", t),
726750
GenericArgData::Lifetime(l) => write!(fmt, "Lifetime({:?})", l),
751+
GenericArgData::Const(c) => write!(fmt, "Const({:?})", c),
727752
}
728753
}
729754
}
@@ -733,7 +758,7 @@ impl<I: Interner> Debug for VariableKind<I> {
733758
match *self {
734759
VariableKind::Ty => write!(fmt, "type"),
735760
VariableKind::Lifetime => write!(fmt, "lifetime"),
736-
VariableKind::Phantom(..) => unreachable!(),
761+
VariableKind::Const(ty) => write!(fmt, "const: {:?}", ty),
737762
}
738763
}
739764
}
@@ -744,7 +769,7 @@ impl<I: Interner, T: Debug> Debug for WithKind<I, T> {
744769
match &self.kind {
745770
VariableKind::Ty => write!(fmt, "{:?} with kind type", value),
746771
VariableKind::Lifetime => write!(fmt, "{:?} with kind lifetime", value),
747-
VariableKind::Phantom(..) => unreachable!(),
772+
VariableKind::Const(ty) => write!(fmt, "{:?} with kind {:?}", ty),
748773
}
749774
}
750775
}

chalk-ir/src/fold.rs

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ where
8787
/// Top-level callback: invoked for each `Lifetime<I>` that is
8888
/// encountered when folding. By default, invokes
8989
/// `super_fold_with`, which will in turn invoke the more
90-
/// specialized folding methods below, like `fold_free_lifetime_ty`.
90+
/// specialized folding methods below, like `fold_free_var_lifetime`.
9191
fn fold_lifetime(
9292
&mut self,
9393
lifetime: &Lifetime<I>,
@@ -96,6 +96,18 @@ where
9696
lifetime.super_fold_with(self.as_dyn(), outer_binder)
9797
}
9898

99+
/// Top-level callback: invoked for each `Const<I>` that is
100+
/// encountered when folding. By default, invokes
101+
/// `super_fold_with`, which will in turn invoke the more
102+
/// specialized folding methods below, like `fold_free_var_const`.
103+
fn fold_const(
104+
&mut self,
105+
constant: &Const<I>,
106+
outer_binder: DebruijnIndex,
107+
) -> Fallible<Const<TI>> {
108+
constant.super_fold_with(self.as_dyn(), outer_binder)
109+
}
110+
99111
/// Invoked for every program clause. By default, recursively folds the goals contents.
100112
fn fold_program_clause(
101113
&mut self,
@@ -159,8 +171,24 @@ where
159171
}
160172
}
161173

162-
/// If overriden to return true, we will panic when a free
163-
/// placeholder type/lifetime is encountered.
174+
fn fold_free_var_const(
175+
&mut self,
176+
bound_var: BoundVar,
177+
outer_binder: DebruijnIndex,
178+
) -> Fallible<Const<TI>> {
179+
if self.forbid_free_vars() {
180+
panic!(
181+
"unexpected free variable with depth `{:?}` with outer binder {:?}",
182+
bound_var, outer_binder
183+
)
184+
} else {
185+
let bound_var = bound_var.shifted_in_from(outer_binder);
186+
Ok(ConstData::<TI>::BoundVar(bound_var).intern(self.target_interner()))
187+
}
188+
}
189+
190+
/// If overridden to return true, we will panic when a free
191+
/// placeholder type/lifetime/const is encountered.
164192
fn forbid_free_placeholders(&self) -> bool {
165193
false
166194
}
@@ -199,6 +227,19 @@ where
199227
}
200228
}
201229

230+
#[allow(unused_variables)]
231+
fn fold_free_placeholder_const(
232+
&mut self,
233+
universe: PlaceholderIndex,
234+
outer_binder: DebruijnIndex,
235+
) -> Fallible<Const<TI>> {
236+
if self.forbid_free_placeholders() {
237+
panic!("unexpected placeholder const `{:?}`", universe)
238+
} else {
239+
Ok(universe.to_const(self.target_interner()))
240+
}
241+
}
242+
202243
/// If overridden to return true, inference variables will trigger
203244
/// panics when folded. Used when inference variables are
204245
/// unexpected.
@@ -240,6 +281,19 @@ where
240281
}
241282
}
242283

284+
#[allow(unused_variables)]
285+
fn fold_inference_const(
286+
&mut self,
287+
var: InferenceVar,
288+
outer_binder: DebruijnIndex,
289+
) -> Fallible<Const<TI>> {
290+
if self.forbid_inference_vars() {
291+
panic!("unexpected inference const `{:?}`", var)
292+
} else {
293+
Ok(var.to_const(self.target_interner()))
294+
}
295+
}
296+
243297
fn interner(&self) -> &'i I;
244298

245299
fn target_interner(&self) -> &'i TI;
@@ -419,6 +473,60 @@ where
419473
}
420474
}
421475

476+
/// "Folding" a const invokes the `fold_const` method on the folder; this
477+
/// usually (in turn) invokes `super_fold_const` to fold the individual
478+
/// parts.
479+
impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for Const<I> {
480+
type Result = Const<TI>;
481+
482+
fn fold_with<'i>(
483+
&self,
484+
folder: &mut dyn Folder<'i, I, TI>,
485+
outer_binder: DebruijnIndex,
486+
) -> Fallible<Self::Result>
487+
where
488+
I: 'i,
489+
TI: 'i,
490+
{
491+
folder.fold_const(self, outer_binder)
492+
}
493+
}
494+
495+
impl<I, TI> SuperFold<I, TI> for Const<I>
496+
where
497+
I: Interner,
498+
TI: TargetInterner<I>,
499+
{
500+
fn super_fold_with<'i>(
501+
&self,
502+
folder: &mut dyn Folder<'i, I, TI>,
503+
outer_binder: DebruijnIndex,
504+
) -> Fallible<Const<TI>>
505+
where
506+
I: 'i,
507+
TI: 'i,
508+
{
509+
let interner = folder.interner();
510+
match self.data(interner) {
511+
ConstData::BoundVar(bound_var) => {
512+
if let Some(bound_var1) = bound_var.shifted_out_to(outer_binder) {
513+
folder.fold_free_var_const(bound_var1, outer_binder)
514+
} else {
515+
Ok(ConstData::<TI>::BoundVar(*bound_var).intern(folder.target_interner()))
516+
}
517+
}
518+
ConstData::InferenceVar(var) => folder.fold_inference_const(*var, outer_binder),
519+
ConstData::Placeholder(universe) => {
520+
folder.fold_free_placeholder_const(*universe, outer_binder)
521+
}
522+
ConstData::Concrete(ev) => Ok(ConstData::Concrete(ConcreteConst {
523+
interned: folder.target_interner().transfer_const(&ev.interned),
524+
})
525+
.intern(folder.target_interner())),
526+
}
527+
}
528+
}
529+
422530
/// Folding a goal invokes the `fold_goal` callback (which will, by
423531
/// default, invoke super-fold).
424532
impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for Goal<I> {

0 commit comments

Comments
 (0)