Skip to content

Commit ee0f517

Browse files
committed
put env/constraints together
1 parent 9f81ffe commit ee0f517

17 files changed

+187
-266
lines changed

crates/formality-prove/src/prove.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn prove(
2323
env: impl Upcast<Env>,
2424
assumptions: impl Upcast<Wcs>,
2525
goal: impl Upcast<Wcs>,
26-
) -> Set<(Env, Constraints)> {
26+
) -> Set<Constraints> {
2727
let program: Program = program.upcast();
2828
let env0: Env = env.upcast();
2929
let assumptions: Wcs = assumptions.upcast();
@@ -39,18 +39,15 @@ pub fn prove(
3939
term_in.size(),
4040
program.max_size
4141
);
42-
return set![(env0, Constraints::default().ambiguous())];
42+
return set![Constraints::none(env0).ambiguous()];
4343
}
4444

4545
env0.assert_encloses(term_in);
4646

4747
let result_set = prove_wc_list(program, &env0, assumptions, goal);
4848

49-
result_set.iter().for_each(|(env1, constraints1)| {
50-
env1.assert_valid();
51-
env1.assert_valid_extension_of(&env0);
52-
env1.assert_encloses(&constraints1);
53-
constraints1.assert_valid();
49+
result_set.iter().for_each(|constraints1| {
50+
constraints1.assert_valid_extension_of(&env0);
5451
});
5552

5653
tracing::debug!(?result_set);

crates/formality-prove/src/prove/constraints.rs

Lines changed: 59 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use formality_types::{
22
cast::{Downcast, Upcast},
33
cast_impl,
44
derive_links::UpcastFrom,
5-
fold::Fold,
65
grammar::{InferenceVar, Parameter, Substitution, Variable},
76
visit::Visit,
87
};
@@ -11,51 +10,49 @@ use super::env::Env;
1110

1211
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
1312
pub struct Constraints {
13+
env: Env,
1414
known_true: bool,
1515
substitution: Substitution,
1616
}
1717

1818
cast_impl!(Constraints);
1919

20-
impl<A, B> UpcastFrom<(A, B)> for Constraints
20+
impl<A, B> UpcastFrom<(Env, (A, B))> for Constraints
2121
where
2222
A: Upcast<Variable>,
2323
B: Upcast<Parameter>,
2424
{
25-
fn upcast_from(term: (A, B)) -> Self {
26-
Constraints {
27-
substitution: term.upcast(),
28-
known_true: true,
29-
}
25+
fn upcast_from((env, pair): (Env, (A, B))) -> Self {
26+
Constraints::from(env, std::iter::once(pair))
3027
}
3128
}
3229

33-
impl<A, B> FromIterator<(A, B)> for Constraints
34-
where
35-
A: Upcast<Variable>,
36-
B: Upcast<Parameter>,
37-
{
38-
fn from_iter<T: IntoIterator<Item = (A, B)>>(iter: T) -> Self {
39-
let substitution = iter.into_iter().collect();
30+
impl Constraints {
31+
pub fn none(env: Env) -> Self {
32+
let v: Vec<(Variable, Parameter)> = vec![];
33+
Self::from(env, v)
34+
}
35+
36+
pub fn from(
37+
env: Env,
38+
iter: impl IntoIterator<Item = (impl Upcast<Variable>, impl Upcast<Parameter>)>,
39+
) -> Self {
40+
let substitution: Substitution = iter.into_iter().collect();
41+
env.assert_encloses(substitution.range());
42+
env.assert_encloses(substitution.domain());
4043
let c2 = Constraints {
44+
env,
4145
substitution,
4246
known_true: true,
4347
};
4448
c2.assert_valid();
4549
c2
4650
}
47-
}
4851

49-
impl Default for Constraints {
50-
fn default() -> Self {
51-
Self {
52-
known_true: true,
53-
substitution: Default::default(),
54-
}
52+
pub fn env(&self) -> &Env {
53+
&self.env
5554
}
56-
}
5755

58-
impl Constraints {
5956
pub fn substitution(&self) -> &Substitution {
6057
&self.substitution
6158
}
@@ -78,6 +75,7 @@ impl Constraints {
7875

7976
self.assert_valid();
8077
c2.assert_valid();
78+
c2.assert_valid_extension_of(&self.env);
8179

8280
// This substitution should have already been applied to produce
8381
// `c2`, therefore we don't expect any bindings for *our* variables.
@@ -99,114 +97,93 @@ impl Constraints {
9997
let c1_substitution = c2.substitution.apply(&self.substitution);
10098

10199
Constraints {
100+
env: c2.env,
102101
known_true: self.known_true && c2.known_true,
103102
substitution: c1_substitution.into_iter().chain(c2.substitution).collect(),
104103
}
105104
}
106105

107-
pub fn assert_valid_in(&self, env: &Env) {
108-
self.assert_valid();
109-
110-
// Each variable `x` is only bound to a term of strictly lower universe.
111-
// This implies that `x` does not appear in `p`.
112-
for (x, p) in self.substitution.iter() {
113-
let fvs = p.free_variables();
114-
fvs.iter()
115-
.for_each(|fv| assert!(env.universe(fv) < env.universe(x)));
116-
}
117-
}
118-
119-
pub fn pop_subst<V>(mut self, mut env: Env, v: &[V]) -> (Env, Self)
106+
pub fn pop_subst<V>(mut self, v: &[V]) -> Self
120107
where
121108
V: Upcast<Variable> + Copy,
122109
{
123-
self.assert_valid_in(&env);
124-
125110
if v.len() == 0 {
126-
return (env, self);
111+
return self;
127112
}
128113

129-
let vars = env.pop_vars(v);
114+
let vars = self.env.pop_vars(v);
130115
self.substitution -= vars;
131116

132-
(env, self)
117+
self
133118
}
134-
}
135-
136-
impl Fold for Constraints {
137-
fn substitute(&self, substitution_fn: formality_types::fold::SubstitutionFn<'_>) -> Self {
138-
let c2 = Constraints {
139-
known_true: self.known_true,
140-
substitution: self.substitution.substitute(substitution_fn),
141-
};
142119

143-
// not all substitutions preserve the constraint set invariant
144-
c2.assert_valid();
145-
146-
c2
120+
pub fn assert_valid_extension_of(&self, env0: &Env) {
121+
self.env.assert_valid_extension_of(env0)
147122
}
148123
}
149124

150125
impl Visit for Constraints {
151126
fn free_variables(&self) -> Vec<Variable> {
152127
let Constraints {
128+
env,
153129
known_true: _,
154130
substitution,
155131
} = self;
156132

157-
substitution.free_variables().into_iter().collect()
133+
// Debatable if `env.free_variables()` should be considered
134+
// free here, env kind of acts as a binder. Don't think it matters.
135+
136+
env.free_variables()
137+
.into_iter()
138+
.chain(substitution.free_variables())
139+
.collect()
158140
}
159141

160142
fn size(&self) -> usize {
161143
let Constraints {
144+
env,
162145
known_true: _,
163146
substitution,
164147
} = self;
165-
substitution.size()
148+
env.size() + substitution.size()
166149
}
167150

168151
fn assert_valid(&self) {
169152
let Constraints {
153+
env,
170154
known_true: _,
171155
substitution,
172156
} = self;
173157

174158
let domain = substitution.domain();
159+
let range = substitution.range();
175160

176-
for &v in &domain {
177-
assert!(v.downcast::<InferenceVar>().is_some());
178-
assert!(v.is_free());
179-
assert!(is_valid_binding(v, &substitution[v]));
180-
}
161+
env.assert_encloses(&domain);
162+
env.assert_encloses(&range);
181163

182-
let range = substitution.range();
164+
// No variable in the domain appears in any part of the range;
165+
// this prevents the obvious occurs check violations like `X = Vec<X>`
166+
// but also indirect ones like `X = Vec<Y>, Y = X`; it also implies that
167+
// the substitution has been fully applied, so we don't have `X = Vec<Y>, Y = u32`.
183168
range
184169
.iter()
185-
.for_each(|t| assert!(domain.iter().all(|&v| !occurs_in(v, t))));
170+
.for_each(|p| assert!(domain.iter().all(|&v| !occurs_in(v, p))));
171+
172+
// Each variable `x` is only bound to a term of strictly lower universe.
173+
// This implies that `x` does not appear in `p`.
174+
for (x, p) in substitution.iter() {
175+
assert!(x.is_a::<InferenceVar>());
176+
177+
assert!(!occurs_in(x, &p));
178+
179+
let fvs = p.free_variables();
180+
fvs.iter()
181+
.for_each(|fv| assert!(env.universe(fv) < env.universe(x)));
182+
}
186183
}
187184
}
188185

189186
pub fn occurs_in(v: impl Upcast<Variable>, t: &impl Visit) -> bool {
190187
let v: Variable = v.upcast();
191188
t.free_variables().contains(&v)
192189
}
193-
194-
/// True if `t` would be a valid binding for `v`, meaning...
195-
/// * `v` does not appear in `t`; and,
196-
/// * all free variables in `t` are within the universe of `v`
197-
pub fn is_valid_binding(v: impl Upcast<Variable>, t: &impl Visit) -> bool {
198-
let v: Variable = v.upcast();
199-
assert!(v.is_free());
200-
201-
let v_universe = v.max_universe();
202-
t.free_variables()
203-
.into_iter()
204-
.all(|fv| fv != v && fv.max_universe() <= v_universe)
205-
}
206-
207-
pub fn no_constraints() -> Constraints {
208-
Constraints {
209-
known_true: true,
210-
substitution: Substitution::default(),
211-
}
212-
}
Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
use formality_types::{grammar::Wcs, judgment_fn};
22

3-
use crate::{
4-
program::Program,
5-
prove::{env::Env, prove},
6-
};
3+
use crate::{program::Program, prove::prove};
74

85
use super::constraints::Constraints;
96

107
judgment_fn! {
118
pub fn prove_after(
129
program: Program,
13-
env: Env,
1410
constraints: Constraints,
1511
assumptions: Wcs,
1612
goal: Wcs,
17-
) => (Env, Constraints) {
13+
) => Constraints {
1814
(
1915
(let (assumptions, goal) = c1.substitution().apply(&(assumptions, goal)))
20-
(prove(program, env, assumptions, goal) => (env, c2))
16+
(prove(program, c1.env(), assumptions, goal) => c2)
2117
--- ("prove_after")
22-
(prove_after(program, env, c1, assumptions, goal) => (env, c1.seq(c2)))
18+
(prove_after(program, c1, assumptions, goal) => c1.seq(c2))
2319
)
2420
}
2521
}

crates/formality-prove/src/prove/prove_apr.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ judgment_fn! {
2222
env: Env,
2323
assumptions: Wcs,
2424
goal: APR,
25-
) => (Env, Constraints) {
25+
) => Constraints {
2626
(
2727
(&assumptions => a)
2828
(prove_apr_via(&program, &env, &assumptions, a, &goal) => c)
@@ -36,22 +36,20 @@ judgment_fn! {
3636
(let i = i.binder.instantiate_with(&subst).unwrap())
3737
(let t = program.trait_decl(&i.trait_ref.trait_id).binder.instantiate_with(&i.trait_ref.parameters).unwrap())
3838
(let assumptions_c = (&assumptions, &trait_ref))
39-
(prove(&program, env, &assumptions_c, all_eq(&trait_ref.parameters, &i.trait_ref.parameters)) => (env, c))
40-
(prove_after(&program, env, c, &assumptions_c, (&i.where_clause, &t.where_clause)) => (env, c))
41-
(let (env, c) = c.pop_subst(env, &subst))
39+
(prove(&program, env, &assumptions_c, all_eq(&trait_ref.parameters, &i.trait_ref.parameters)) => c)
40+
(prove_after(&program, c, &assumptions_c, (&i.where_clause, &t.where_clause)) => c)
4241
----------------------------- ("impl")
43-
(prove_apr(program, env, assumptions, AtomicPredicate::IsImplemented(trait_ref)) => (env, c))
42+
(prove_apr(program, env, assumptions, AtomicPredicate::IsImplemented(trait_ref)) => c.pop_subst(&subst))
4443
)
4544

4645
(
4746
(program.trait_invariants() => ti)
4847
(let (env, subst) = env.existential_substitution(&ti.binder))
4948
(let ti = ti.binder.instantiate_with(&subst).unwrap())
50-
(prove_apr_via(&program, env, &assumptions, &ti.where_clause, &trait_ref) => (env, c))
51-
(prove_after(&program, env, c, &assumptions, &ti.trait_ref) => (env, c))
52-
(let (env, c) = c.pop_subst(env, &subst))
49+
(prove_apr_via(&program, env, &assumptions, &ti.where_clause, &trait_ref) => c)
50+
(prove_after(&program, c, &assumptions, &ti.trait_ref) => c)
5351
----------------------------- ("trait implied bound")
54-
(prove_apr(program, env, assumptions, AtomicPredicate::IsImplemented(trait_ref)) => (env, c))
52+
(prove_apr(program, env, assumptions, AtomicPredicate::IsImplemented(trait_ref)) => c.pop_subst(&subst))
5553
)
5654

5755
(

0 commit comments

Comments
 (0)