Skip to content

Commit 07f713e

Browse files
authored
Merge pull request #49 from scalexm/elaborate
Elaborating where clauses directly in the logic
2 parents 646699c + 6345f7d commit 07f713e

File tree

7 files changed

+238
-107
lines changed

7 files changed

+238
-107
lines changed

chalk-parse/src/ast.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,10 @@ pub struct Field {
162162
pub enum Goal {
163163
ForAll(Vec<ParameterKind>, Box<Goal>),
164164
Exists(Vec<ParameterKind>, Box<Goal>),
165-
Implies(Vec<WhereClause>, Box<Goal>),
165+
166+
// The `bool` flag indicates whether we should elaborate where clauses or not
167+
Implies(Vec<WhereClause>, Box<Goal>, bool),
168+
166169
And(Box<Goal>, Box<Goal>),
167170
Not(Box<Goal>),
168171

chalk-parse/src/parser.lalrpop

+6-1
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,16 @@ pub Goal: Box<Goal> = {
2828
Goal1: Box<Goal> = {
2929
"forall" "<" <p:Comma<ParameterKind>> ">" "{" <g:Goal> "}" => Box::new(Goal::ForAll(p, g)),
3030
"exists" "<" <p:Comma<ParameterKind>> ">" "{" <g:Goal> "}" => Box::new(Goal::Exists(p, g)),
31-
"if" "(" <w:Comma<WhereClause>> ")" "{" <g:Goal> "}" => Box::new(Goal::Implies(w, g)),
31+
<i:IfKeyword> "(" <w:Comma<WhereClause>> ")" "{" <g:Goal> "}" => Box::new(Goal::Implies(w, g, i)),
3232
"not" "{" <g:Goal> "}" => Box::new(Goal::Not(g)),
3333
<w:WhereClause> => Box::new(Goal::Leaf(w)),
3434
};
3535

36+
IfKeyword: bool = {
37+
"if" => true,
38+
"if_raw" => false,
39+
};
40+
3641
StructDefn: StructDefn = {
3742
"struct" <n:Id><p:Angle<ParameterKind>> <w:WhereClauses> "{" <f:Fields> "}" => StructDefn {
3843
name: n,

src/cast.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use ir::*;
2+
use std::marker::PhantomData;
23

34
pub trait Cast<T>: Sized {
45
fn cast(self) -> T;
@@ -130,7 +131,7 @@ impl<T, U> Cast<Vec<U>> for Vec<T>
130131
where T: Cast<U>
131132
{
132133
fn cast(self) -> Vec<U> {
133-
self.into_iter().map(|v| v.cast()).collect()
134+
self.into_iter().casted().collect()
134135
}
135136
}
136137

@@ -145,3 +146,33 @@ impl Cast<Parameter> for Lifetime {
145146
ParameterKind::Lifetime(self)
146147
}
147148
}
149+
150+
pub struct Casted<I, U> {
151+
iterator: I,
152+
_cast: PhantomData<U>,
153+
}
154+
155+
impl<I: Iterator, U> Iterator for Casted<I, U> where I::Item: Cast<U> {
156+
type Item = U;
157+
158+
fn next(&mut self) -> Option<Self::Item> {
159+
self.iterator.next().map(|item| item.cast())
160+
}
161+
162+
fn size_hint(&self) -> (usize, Option<usize>) {
163+
self.iterator.size_hint()
164+
}
165+
}
166+
167+
pub trait Caster<U>: Sized {
168+
fn casted(self) -> Casted<Self, U>;
169+
}
170+
171+
impl<I: Iterator, U> Caster<U> for I {
172+
fn casted(self) -> Casted<Self, U> {
173+
Casted {
174+
iterator: self,
175+
_cast: PhantomData,
176+
}
177+
}
178+
}

src/ir/mod.rs

+24-54
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use cast::Cast;
22
use chalk_parse::ast;
3-
use fold::Subst;
43
use lalrpop_intern::InternedString;
54
use solve::infer::{TyInferenceVariable, LifetimeInferenceVariable};
6-
use std::collections::{HashSet, HashMap, BTreeMap};
5+
use std::collections::{HashMap, BTreeMap};
76
use std::sync::Arc;
87

98
pub type Identifier = InternedString;
@@ -95,58 +94,6 @@ impl Environment {
9594
env.universe = UniverseIndex { counter: self.universe.counter + 1 };
9695
Arc::new(env)
9796
}
98-
99-
/// Generate the full set of clauses that are "syntactically implied" by the
100-
/// clauses in this environment. Currently this consists of two kinds of expansions:
101-
///
102-
/// - Supertraits are added, so `T: Ord` would expand to `T: Ord, T: PartialOrd`
103-
/// - Projections imply that a trait is implemented, to `T: Iterator<Item=Foo>` expands to
104-
/// `T: Iterator, T: Iterator<Item=Foo>`
105-
pub fn elaborated_clauses(&self, program: &ProgramEnvironment) -> impl Iterator<Item = DomainGoal> {
106-
let mut set = HashSet::new();
107-
set.extend(self.clauses.iter().cloned());
108-
109-
let mut stack: Vec<_> = set.iter().cloned().collect();
110-
111-
while let Some(clause) = stack.pop() {
112-
let mut push_clause = |clause: DomainGoal| {
113-
if !set.contains(&clause) {
114-
set.insert(clause.clone());
115-
stack.push(clause);
116-
}
117-
};
118-
119-
match clause {
120-
DomainGoal::Implemented(ref trait_ref) => {
121-
// trait Foo<A> where Self: Bar<A> { }
122-
// T: Foo<U>
123-
// ----------------------------------------------------------
124-
// T: Bar<U>
125-
126-
let trait_datum = &program.trait_data[&trait_ref.trait_id];
127-
for where_clause in &trait_datum.binders.value.where_clauses {
128-
let where_clause = Subst::apply(&trait_ref.parameters, where_clause);
129-
push_clause(where_clause);
130-
}
131-
}
132-
DomainGoal::Normalize(Normalize { ref projection, ty: _ }) => {
133-
// <T as Trait<U>>::Foo ===> V
134-
// ----------------------------------------------------------
135-
// T: Trait<U>
136-
137-
let (associated_ty_data, trait_params, _) = program.split_projection(projection);
138-
let trait_ref = TraitRef {
139-
trait_id: associated_ty_data.trait_id,
140-
parameters: trait_params.to_owned()
141-
};
142-
push_clause(trait_ref.cast());
143-
}
144-
_ => {}
145-
}
146-
}
147-
148-
set.into_iter()
149-
}
15097
}
15198

15299
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -249,6 +196,7 @@ pub struct StructDatum {
249196
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
250197
pub struct StructDatumBound {
251198
pub self_ty: ApplicationTy,
199+
pub fields: Vec<Ty>,
252200
pub where_clauses: Vec<DomainGoal>,
253201
}
254202

@@ -420,6 +368,28 @@ impl DomainGoal {
420368
fallback_clause: false,
421369
}
422370
}
371+
372+
/// A clause of the form (T: Foo) expands to (T: Foo), WF(T: Foo).
373+
/// A clause of the form (T: Foo<Item = U>) expands to (T: Foo<Item = U>), WF(T: Foo).
374+
pub fn expanded(self, program: &Program) -> impl Iterator<Item = DomainGoal> {
375+
let mut expanded = vec![];
376+
match self {
377+
DomainGoal::Implemented(ref trait_ref) => {
378+
expanded.push(WellFormed::TraitRef(trait_ref.clone()).cast());
379+
}
380+
DomainGoal::Normalize(Normalize { ref projection, .. }) => {
381+
let (associated_ty_data, trait_params, _) = program.split_projection(&projection);
382+
let trait_ref = TraitRef {
383+
trait_id: associated_ty_data.trait_id,
384+
parameters: trait_params.to_owned()
385+
};
386+
expanded.push(WellFormed::TraitRef(trait_ref).cast());
387+
}
388+
_ => ()
389+
};
390+
expanded.push(self.cast());
391+
expanded.into_iter()
392+
}
423393
}
424394

425395
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]

0 commit comments

Comments
 (0)