Skip to content

Commit c0afedb

Browse files
authored
Merge pull request #107 from scalexm/assoc-types
Add higher-ranked trait bounds
2 parents f3eac03 + eedeb47 commit c0afedb

File tree

10 files changed

+291
-92
lines changed

10 files changed

+291
-92
lines changed

chalk-parse/src/ast.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub enum Item {
2727
pub struct StructDefn {
2828
pub name: Identifier,
2929
pub parameter_kinds: Vec<ParameterKind>,
30-
pub where_clauses: Vec<WhereClause>,
30+
pub where_clauses: Vec<QuantifiedWhereClause>,
3131
pub fields: Vec<Field>,
3232
pub flags: StructFlags,
3333
}
@@ -39,7 +39,7 @@ pub struct StructFlags {
3939
pub struct TraitDefn {
4040
pub name: Identifier,
4141
pub parameter_kinds: Vec<ParameterKind>,
42-
pub where_clauses: Vec<WhereClause>,
42+
pub where_clauses: Vec<QuantifiedWhereClause>,
4343
pub assoc_ty_defns: Vec<AssocTyDefn>,
4444
pub flags: TraitFlags,
4545
}
@@ -107,7 +107,7 @@ impl Kinded for Parameter {
107107
pub struct Impl {
108108
pub parameter_kinds: Vec<ParameterKind>,
109109
pub trait_ref: PolarizedTraitRef,
110-
pub where_clauses: Vec<WhereClause>,
110+
pub where_clauses: Vec<QuantifiedWhereClause>,
111111
pub assoc_ty_values: Vec<AssocTyValue>,
112112
}
113113

@@ -194,6 +194,11 @@ pub enum WhereClause {
194194
TraitInScope { trait_name: Identifier },
195195
}
196196

197+
pub struct QuantifiedWhereClause {
198+
pub parameter_kinds: Vec<ParameterKind>,
199+
pub where_clause: WhereClause,
200+
}
201+
197202
pub struct Field {
198203
pub name: Identifier,
199204
pub ty: Ty,

chalk-parse/src/parser.lalrpop

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ AutoKeyword: () = "#" "[" "auto" "]";
4040
MarkerKeyword: () = "#" "[" "marker" "]";
4141

4242
StructDefn: StructDefn = {
43-
<external:ExternalKeyword?> "struct" <n:Id><p:Angle<ParameterKind>> <w:WhereClauses> "{" <f:Fields> "}" => StructDefn {
43+
<external:ExternalKeyword?> "struct" <n:Id><p:Angle<ParameterKind>>
44+
<w:QuantifiedWhereClauses> "{" <f:Fields> "}" => StructDefn
45+
{
4446
name: n,
4547
parameter_kinds: p,
4648
where_clauses: w,
@@ -52,9 +54,9 @@ StructDefn: StructDefn = {
5254
};
5355

5456
TraitDefn: TraitDefn = {
55-
<external:ExternalKeyword?> <auto:AutoKeyword?> <marker:MarkerKeyword?> "trait" <n:Id><p:Angle<ParameterKind>> <w:WhereClauses> "{"
56-
<a:AssocTyDefn*> "}" =>
57-
TraitDefn {
57+
<external:ExternalKeyword?> <auto:AutoKeyword?> <marker:MarkerKeyword?> "trait" <n:Id><p:Angle<ParameterKind>>
58+
<w:QuantifiedWhereClauses> "{" <a:AssocTyDefn*> "}" => TraitDefn
59+
{
5860
name: n,
5961
parameter_kinds: p,
6062
where_clauses: w,
@@ -75,8 +77,8 @@ AssocTyDefn: AssocTyDefn = {
7577
};
7678

7779
Impl: Impl = {
78-
"impl" <p:Angle<ParameterKind>> <mark:"!"?> <t:Id> <a:Angle<Parameter>> "for" <s:Ty> <w:WhereClauses> "{"
79-
<assoc:AssocTyValue*> "}" =>
80+
"impl" <p:Angle<ParameterKind>> <mark:"!"?> <t:Id> <a:Angle<Parameter>> "for" <s:Ty>
81+
<w:QuantifiedWhereClauses> "{" <assoc:AssocTyValue*> "}" =>
8082
{
8183
let mut args = vec![Parameter::Ty(s)];
8284
args.extend(a);
@@ -160,58 +162,53 @@ Field: Field = {
160162
};
161163

162164
Clause: Clause = {
163-
"forall" <pk:Angle<ParameterKind>> "{" <wc:WhereClause> "if" <g:Comma<Goal1>> "}" => {
164-
Clause {
165-
parameter_kinds: pk,
166-
consequence: wc,
167-
conditions: g,
168-
}
165+
"forall" <pk:Angle<ParameterKind>> "{" <wc:WhereClause> "if" <g:Comma<Goal1>> "}" => Clause {
166+
parameter_kinds: pk,
167+
consequence: wc,
168+
conditions: g,
169169
},
170170

171-
"forall" <pk:Angle<ParameterKind>> "{" <wc:WhereClause> "}" => {
172-
Clause {
173-
parameter_kinds: pk,
174-
consequence: wc,
175-
conditions: vec![],
176-
}
171+
"forall" <pk:Angle<ParameterKind>> "{" <wc:WhereClause> "}" => Clause {
172+
parameter_kinds: pk,
173+
consequence: wc,
174+
conditions: vec![],
177175
},
178176
};
179177

180178
InlineClause1: Clause = {
181-
<wc:WhereClause> => {
182-
Clause {
183-
parameter_kinds: vec![],
184-
consequence: wc,
185-
conditions: vec![],
186-
}
179+
<wc:WhereClause> => Clause {
180+
parameter_kinds: vec![],
181+
consequence: wc,
182+
conditions: vec![],
187183
},
188184

189-
<wc:WhereClause> ":" "-" <g:Comma<Goal1>> => {
190-
Clause {
191-
parameter_kinds: vec![],
192-
consequence: wc,
193-
conditions: g,
194-
}
185+
<wc:WhereClause> ":" "-" <g:Comma<Goal1>> => Clause {
186+
parameter_kinds: vec![],
187+
consequence: wc,
188+
conditions: g,
195189
},
196190
};
197191

198192
InlineClause: Clause = {
199193
<InlineClause1>,
200194

201-
"forall" "<" <pk:Comma<ParameterKind>> ">" "{" <c:InlineClause1> "}" => {
202-
Clause {
203-
parameter_kinds: pk,
204-
consequence: c.consequence,
205-
conditions: c.conditions,
206-
}
207-
},
195+
"forall" "<" <pk:Comma<ParameterKind>> ">" "{" <c:InlineClause1> "}" => Clause {
196+
parameter_kinds: pk,
197+
consequence: c.consequence,
198+
conditions: c.conditions,
199+
}
208200
};
209201

210202
WhereClauses: Vec<WhereClause> = {
211203
"where" <Comma<WhereClause>>,
212204
() => vec![],
213205
};
214206

207+
QuantifiedWhereClauses: Vec<QuantifiedWhereClause> = {
208+
"where" <Comma<QuantifiedWhereClause>>,
209+
() => vec![],
210+
};
211+
215212
WhereClause: WhereClause = {
216213
<t:TraitRef<":">> => WhereClause::Implemented { trait_ref: t },
217214

@@ -244,6 +241,18 @@ WhereClause: WhereClause = {
244241
"InScope" "(" <t:Id> ")" => WhereClause::TraitInScope { trait_name: t },
245242
};
246243

244+
QuantifiedWhereClause: QuantifiedWhereClause = {
245+
<wc:WhereClause> => QuantifiedWhereClause {
246+
parameter_kinds: vec![],
247+
where_clause: wc,
248+
},
249+
250+
"forall" "<" <pk:Comma<ParameterKind>> ">" <wc:WhereClause> => QuantifiedWhereClause {
251+
parameter_kinds: pk,
252+
where_clause: wc,
253+
},
254+
};
255+
247256
TraitRef<S>: TraitRef = {
248257
<s:Ty> S <t:Id> <a:Angle<Parameter>> => {
249258
let mut args = vec![Parameter::Ty(s)];

src/bin/chalki.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(match_default_bindings)]
2-
31
extern crate chalk;
42
extern crate chalk_parse;
53
extern crate docopt;

src/cast.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,34 @@ impl Cast<LeafGoal> for EqGoal {
100100
}
101101
}
102102

103+
impl Cast<Goal> for QuantifiedDomainGoal {
104+
fn cast(self) -> Goal {
105+
if self.binders.is_empty() {
106+
self.value.cast()
107+
} else {
108+
Goal::Quantified(
109+
QuantifierKind::ForAll,
110+
self.map(|bound| Box::new(bound.cast()))
111+
)
112+
}
113+
}
114+
}
115+
116+
impl Cast<ProgramClause> for QuantifiedDomainGoal {
117+
fn cast(self) -> ProgramClause {
118+
if self.binders.is_empty() {
119+
self.value.cast()
120+
} else {
121+
ProgramClause::ForAll(
122+
self.map(|bound| ProgramClauseImplication {
123+
consequence: bound,
124+
conditions: vec![],
125+
})
126+
)
127+
}
128+
}
129+
}
130+
103131
impl Cast<Ty> for ApplicationTy {
104132
fn cast(self) -> Ty {
105133
Ty::Apply(self)

src/coherence/solve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ impl OverlapSolver {
143143
// Create a goal for each clause in both where clauses
144144
let wc_goals = lhs_where_clauses
145145
.chain(rhs_where_clauses)
146-
.map(|wc| Goal::Leaf(LeafGoal::DomainGoal(wc)));
146+
.map(|wc| wc.cast());
147147

148148
// Join all the goals we've created together with And, then quantify them
149149
// over the joined binders. This is our query.
@@ -216,7 +216,7 @@ impl OverlapSolver {
216216
.value
217217
.where_clauses
218218
.iter()
219-
.map(|wc| Goal::Leaf(LeafGoal::DomainGoal(wc.up_shift(more_len))));
219+
.map(|wc| wc.up_shift(more_len).cast());
220220

221221
// Join all of the goals together.
222222
let goal = params_goals

src/ir/mod.rs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ pub struct ImplDatum {
193193
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
194194
pub struct ImplDatumBound {
195195
crate trait_ref: PolarizedTraitRef,
196-
crate where_clauses: Vec<DomainGoal>,
196+
crate where_clauses: Vec<QuantifiedDomainGoal>,
197197
crate associated_ty_values: Vec<AssociatedTyValue>,
198198
crate specialization_priority: usize,
199199
}
@@ -218,7 +218,7 @@ pub struct StructDatum {
218218
pub struct StructDatumBound {
219219
crate self_ty: ApplicationTy,
220220
crate fields: Vec<Ty>,
221-
crate where_clauses: Vec<DomainGoal>,
221+
crate where_clauses: Vec<QuantifiedDomainGoal>,
222222
crate flags: StructFlags,
223223
}
224224

@@ -235,7 +235,7 @@ pub struct TraitDatum {
235235
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
236236
pub struct TraitDatumBound {
237237
crate trait_ref: TraitRef,
238-
crate where_clauses: Vec<DomainGoal>,
238+
crate where_clauses: Vec<QuantifiedDomainGoal>,
239239
crate flags: TraitFlags,
240240
}
241241

@@ -518,6 +518,8 @@ pub enum DomainGoal {
518518
InScope(ItemId),
519519
}
520520

521+
pub type QuantifiedDomainGoal = Binders<DomainGoal>;
522+
521523
impl DomainGoal {
522524
/// Turn a where clause into the WF version of it i.e.:
523525
/// * `Implemented(T: Trait)` maps to `WellFormed(T: Trait)`
@@ -610,14 +612,19 @@ pub struct Binders<T> {
610612
}
611613

612614
impl<T> Binders<T> {
613-
crate fn map_ref<U, OP>(&self, op: OP) -> Binders<U>
614-
where
615-
OP: FnOnce(&T) -> U,
616-
{
615+
crate fn map<U, OP>(self, op: OP) -> Binders<U> where OP: FnOnce(T) -> U {
616+
let value = op(self.value);
617+
Binders {
618+
binders: self.binders,
619+
value,
620+
}
621+
}
622+
623+
crate fn map_ref<U, OP>(&self, op: OP) -> Binders<U> where OP: FnOnce(&T) -> U {
617624
let value = op(&self.value);
618625
Binders {
619626
binders: self.binders.clone(),
620-
value: value,
627+
value,
621628
}
622629
}
623630

@@ -730,21 +737,7 @@ impl UCanonical<InEnvironment<Goal>> {
730737
/// with WF requirements and cyclic traits, which generates cycles in the proof tree which must
731738
/// not be rejected but instead must be treated as a success.
732739
crate fn is_coinductive(&self, program: &ProgramEnvironment) -> bool {
733-
match &self.canonical.value.goal {
734-
Goal::Leaf(LeafGoal::DomainGoal(DomainGoal::Holds(wca))) => {
735-
match wca {
736-
WhereClauseAtom::Implemented(tr) => {
737-
let trait_datum = &program.trait_data[&tr.trait_id];
738-
trait_datum.binders.value.flags.auto
739-
}
740-
WhereClauseAtom::ProjectionEq(..) => false,
741-
}
742-
}
743-
Goal::Leaf(LeafGoal::DomainGoal(DomainGoal::WellFormed(..))) => {
744-
true
745-
}
746-
_ => false,
747-
}
740+
self.canonical.value.goal.is_coinductive(program)
748741
}
749742
}
750743

@@ -843,6 +836,25 @@ impl Goal {
843836
let canonical_goal = infer.canonicalize(&env_goal).quantified;
844837
infer.u_canonicalize(&canonical_goal).quantified
845838
}
839+
840+
crate fn is_coinductive(&self, program: &ProgramEnvironment) -> bool {
841+
match self {
842+
Goal::Leaf(LeafGoal::DomainGoal(DomainGoal::Holds(wca))) => {
843+
match wca {
844+
WhereClauseAtom::Implemented(tr) => {
845+
let trait_datum = &program.trait_data[&tr.trait_id];
846+
trait_datum.binders.value.flags.auto
847+
}
848+
WhereClauseAtom::ProjectionEq(..) => false,
849+
}
850+
}
851+
Goal::Leaf(LeafGoal::DomainGoal(DomainGoal::WellFormed(..))) => {
852+
true
853+
}
854+
Goal::Quantified(QuantifierKind::ForAll, goal) => goal.value.is_coinductive(program),
855+
_ => false,
856+
}
857+
}
846858
}
847859

848860
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]

0 commit comments

Comments
 (0)