Skip to content

Commit a01be61

Browse files
committed
add an assert_valid method to Visit
1 parent bdeac66 commit a01be61

File tree

10 files changed

+97
-33
lines changed

10 files changed

+97
-33
lines changed

crates/formality-macros/src/visit.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub(crate) fn derive_visit(mut s: synstructure::Structure) -> TokenStream {
1111

1212
let size_body = s.each(|field| quote!(__sum += Visit::size(#field)));
1313

14+
let assert_valid_body = s.each(|field| quote!(Visit::assert_valid(#field)));
15+
1416
// s.add_bounds(synstructure::AddBounds::None);
1517
s.gen_impl(quote! {
1618
use crate::derive_links::{Visit, Variable};
@@ -32,6 +34,12 @@ pub(crate) fn derive_visit(mut s: synstructure::Structure) -> TokenStream {
3234
}
3335
__sum
3436
}
37+
38+
fn assert_valid(&self) {
39+
match self {
40+
#assert_valid_body
41+
}
42+
}
3543
}
3644
})
3745
}

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

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use contracts::requires;
21
use formality_types::{
32
cast::Upcast,
43
cast_impl,
5-
collections::Set,
64
derive_links::UpcastFrom,
75
fold::Fold,
8-
grammar::{AtomicRelation, Binder, InferenceVar, Parameter, Substitution, Variable},
6+
grammar::{Binder, InferenceVar, Parameter, Substitution, Variable},
97
visit::Visit,
108
};
119

@@ -40,31 +38,10 @@ impl Default for Constraints {
4038
}
4139

4240
impl Constraints {
43-
/// Check type invariant:
44-
///
45-
/// * Domain of substitution is disjoint from range: meaning we don't have
46-
/// a substitution like `[X := Vec<Y>, Y := u32]`, but instead
47-
/// `[X := Vec<u32>, Y := u32]`
48-
pub fn is_valid(&self) -> bool {
49-
let domain = self.substitution.domain();
50-
let range = self.substitution.range();
51-
range
52-
.iter()
53-
.all(|t| domain.iter().all(|&v| !occurs_in(v, t)))
54-
}
55-
5641
pub fn substitution(&self) -> &Substitution {
5742
&self.substitution
5843
}
5944

60-
#[requires(self.is_valid())]
61-
pub fn as_relations(&self) -> Set<AtomicRelation> {
62-
self.substitution
63-
.iter()
64-
.map(|(v, p)| AtomicRelation::eq(v, p))
65-
.collect()
66-
}
67-
6845
pub fn ambiguous(self) -> Constraints {
6946
Self {
7047
known_true: false,
@@ -79,10 +56,10 @@ pub fn merge_constraints(
7956
c1: Binder<Constraints>,
8057
) -> Binder<Constraints> {
8158
let c0: Constraints = c0.upcast();
82-
assert!(c0.is_valid());
59+
c0.assert_valid();
8360

8461
let (c1_bound_vars, c1) = c1.open();
85-
assert!(c1.is_valid());
62+
c1.assert_valid();
8663

8764
assert!(c0
8865
.substitution
@@ -125,10 +102,7 @@ impl Fold for Constraints {
125102
};
126103

127104
// not all substitutions preserve the constraint set invariant
128-
assert!(
129-
c.is_valid(),
130-
"folding `{self:?}` yielded invalid constraint set `{c:?}`"
131-
);
105+
c.assert_valid();
132106

133107
c
134108
}
@@ -150,6 +124,14 @@ impl Visit for Constraints {
150124
} = self;
151125
substitution.size()
152126
}
127+
128+
fn assert_valid(&self) {
129+
let domain = self.substitution.domain();
130+
let range = self.substitution.range();
131+
range
132+
.iter()
133+
.for_each(|t| assert!(domain.iter().all(|&v| !occurs_in(v, t))));
134+
}
153135
}
154136

155137
pub fn occurs_in(v: impl Upcast<Variable>, t: &impl Visit) -> bool {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use formality_types::{
55

66
use crate::{
77
program::Program,
8-
prove::{constraints::merge_constraints, prove, prove_wc_list::prove_wc_list},
8+
prove::{constraints::merge_constraints, prove},
99
};
1010

1111
use super::{constraints::Constraints, subst::existential_substitution};

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use crate::{
1111
prove_after::prove_after,
1212
prove_apr_via::prove_apr_via,
1313
prove_eq::{all_eq, prove_ty_eq},
14-
prove_wc_list::prove_wc_list,
1514
subst::existential_substitution,
1615
},
1716
};

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
},
1818
};
1919

20-
use super::{constraints::Constraints, prove_wc_list::prove_wc_list};
20+
use super::constraints::Constraints;
2121

2222
/// Goal(s) to prove `a` and `b` are equal (they must have equal length)
2323
pub fn all_eq(a: impl Upcast<Vec<Parameter>>, b: impl Upcast<Vec<Parameter>>) -> Wcs {

crates/formality-rust/src/trait_binder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ where
5252
fn size(&self) -> usize {
5353
self.explicit_binder.size()
5454
}
55+
56+
fn assert_valid(&self) {
57+
self.explicit_binder.assert_valid()
58+
}
5559
}
5660

5761
impl<T> Fold for TraitBinder<T>

crates/formality-types/src/grammar/binder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ impl<T: Visit> Visit for Binder<T> {
177177
fn size(&self) -> usize {
178178
self.term.size()
179179
}
180+
181+
fn assert_valid(&self) {
182+
self.term.assert_valid();
183+
}
180184
}
181185

182186
impl<T: Fold> Fold for Binder<T> {

crates/formality-types/src/grammar/ids.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ macro_rules! id {
3636
fn size(&self) -> usize {
3737
1
3838
}
39+
40+
fn assert_valid(&self) {}
3941
}
4042

4143
impl Fold for $n {

crates/formality-types/src/grammar/ty.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ impl Visit for InferenceVar {
147147
fn size(&self) -> usize {
148148
1
149149
}
150+
151+
fn assert_valid(&self) {}
150152
}
151153

152154
#[term((rigid $name $*parameters))]
@@ -421,6 +423,13 @@ impl Visit for LtData {
421423
LtData::Static => 1,
422424
}
423425
}
426+
427+
fn assert_valid(&self) {
428+
match self {
429+
LtData::Variable(v) => v.assert_valid(),
430+
LtData::Static => (),
431+
}
432+
}
424433
}
425434

426435
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -519,6 +528,8 @@ impl Visit for Variable {
519528
fn size(&self) -> usize {
520529
1
521530
}
531+
532+
fn assert_valid(&self) {}
522533
}
523534

524535
impl UpcastFrom<Variable> for Parameter {
@@ -704,6 +715,10 @@ impl Visit for Substitution {
704715
fn size(&self) -> usize {
705716
self.range().iter().map(|r| r.size()).sum()
706717
}
718+
719+
fn assert_valid(&self) {
720+
self.range().assert_valid()
721+
}
707722
}
708723

709724
/// A substitution that is only between variables.

crates/formality-types/src/visit.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ pub trait Visit: Sized {
2121
/// Used to determine overflow.
2222
fn size(&self) -> usize;
2323

24+
/// Asserts various validity constraints and panics if they are not held.
25+
/// These validition constraints should never fail unless there is a bug in our logic.
26+
/// This is to aid with fuzzing and bug detection.
27+
fn assert_valid(&self);
28+
2429
/// True if this term references only placeholder variables.
2530
/// This means that it contains no inference variables.
2631
/// If this is a goal, then when we prove it true, we don't expect any substitution.
@@ -57,6 +62,10 @@ impl<T: Visit> Visit for Vec<T> {
5762
fn size(&self) -> usize {
5863
self.iter().map(|e| e.size()).sum()
5964
}
65+
66+
fn assert_valid(&self) {
67+
self.iter().for_each(|e| e.assert_valid());
68+
}
6069
}
6170

6271
impl<T: Visit + Ord> Visit for Set<T> {
@@ -67,6 +76,10 @@ impl<T: Visit + Ord> Visit for Set<T> {
6776
fn size(&self) -> usize {
6877
self.iter().map(|e| e.size()).sum()
6978
}
79+
80+
fn assert_valid(&self) {
81+
self.iter().for_each(|e| e.assert_valid());
82+
}
7083
}
7184

7285
impl<T: Visit> Visit for Option<T> {
@@ -77,6 +90,10 @@ impl<T: Visit> Visit for Option<T> {
7790
fn size(&self) -> usize {
7891
self.as_ref().map(|e| e.size()).unwrap_or(0)
7992
}
93+
94+
fn assert_valid(&self) {
95+
self.iter().for_each(|e| e.assert_valid());
96+
}
8097
}
8198

8299
impl<T: Visit> Visit for Arc<T> {
@@ -87,6 +104,10 @@ impl<T: Visit> Visit for Arc<T> {
87104
fn size(&self) -> usize {
88105
T::size(self)
89106
}
107+
108+
fn assert_valid(&self) {
109+
T::assert_valid(self)
110+
}
90111
}
91112

92113
impl Visit for Ty {
@@ -97,6 +118,10 @@ impl Visit for Ty {
97118
fn size(&self) -> usize {
98119
self.data().size()
99120
}
121+
122+
fn assert_valid(&self) {
123+
self.data().assert_valid()
124+
}
100125
}
101126

102127
impl Visit for Lt {
@@ -107,6 +132,10 @@ impl Visit for Lt {
107132
fn size(&self) -> usize {
108133
self.data().size()
109134
}
135+
136+
fn assert_valid(&self) {
137+
self.data().assert_valid()
138+
}
110139
}
111140

112141
impl Visit for usize {
@@ -117,6 +146,8 @@ impl Visit for usize {
117146
fn size(&self) -> usize {
118147
1
119148
}
149+
150+
fn assert_valid(&self) {}
120151
}
121152

122153
impl Visit for u32 {
@@ -127,6 +158,8 @@ impl Visit for u32 {
127158
fn size(&self) -> usize {
128159
1
129160
}
161+
162+
fn assert_valid(&self) {}
130163
}
131164

132165
impl<A: Visit, B: Visit> Visit for (A, B) {
@@ -142,6 +175,12 @@ impl<A: Visit, B: Visit> Visit for (A, B) {
142175
let (a, b) = self;
143176
a.size() + b.size()
144177
}
178+
179+
fn assert_valid(&self) {
180+
let (a, b) = self;
181+
a.assert_valid();
182+
b.assert_valid();
183+
}
145184
}
146185

147186
impl<A: Visit, B: Visit, C: Visit> Visit for (A, B, C) {
@@ -158,6 +197,13 @@ impl<A: Visit, B: Visit, C: Visit> Visit for (A, B, C) {
158197
let (a, b, c) = self;
159198
a.size() + b.size() + c.size()
160199
}
200+
201+
fn assert_valid(&self) {
202+
let (a, b, c) = self;
203+
a.assert_valid();
204+
b.assert_valid();
205+
c.assert_valid();
206+
}
161207
}
162208

163209
impl<A: Visit> Visit for &A {
@@ -168,4 +214,8 @@ impl<A: Visit> Visit for &A {
168214
fn size(&self) -> usize {
169215
A::size(self)
170216
}
217+
218+
fn assert_valid(&self) {
219+
A::assert_valid(self)
220+
}
171221
}

0 commit comments

Comments
 (0)