Skip to content

Commit 17b0aff

Browse files
committed
Reomve ignore_type_invariant
1 parent 5cb7c88 commit 17b0aff

File tree

8 files changed

+32
-111
lines changed

8 files changed

+32
-111
lines changed

creusot-contracts/src/invariant.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ pub trait Invariant {
2424
impl<'a, T: Invariant + ?Sized> Invariant for &'a T {
2525
#[predicate]
2626
#[open]
27-
#[creusot::ignore_type_invariant = "maybe"]
2827
fn invariant(self) -> bool {
2928
pearlite! { (*self).invariant() }
3029
}
@@ -33,7 +32,6 @@ impl<'a, T: Invariant + ?Sized> Invariant for &'a T {
3332
impl<'a, T: Invariant + ?Sized> Invariant for &'a mut T {
3433
#[predicate]
3534
#[open]
36-
#[creusot::ignore_type_invariant = "maybe"]
3735
fn invariant(self) -> bool {
3836
pearlite! { (*self).invariant() }
3937
}
@@ -42,7 +40,6 @@ impl<'a, T: Invariant + ?Sized> Invariant for &'a mut T {
4240
impl<T: Invariant + ?Sized> Invariant for Box<T> {
4341
#[predicate]
4442
#[open]
45-
#[creusot::ignore_type_invariant = "maybe"]
4643
fn invariant(self) -> bool {
4744
pearlite! { (*self).invariant() }
4845
}
@@ -51,7 +48,6 @@ impl<T: Invariant + ?Sized> Invariant for Box<T> {
5148
impl<T: Invariant, U: Invariant> Invariant for (T, U) {
5249
#[predicate]
5350
#[open]
54-
#[creusot::ignore_type_invariant = "maybe"]
5551
fn invariant(self) -> bool {
5652
pearlite! { self.0.invariant() && self.1.invariant() }
5753
}
@@ -60,7 +56,6 @@ impl<T: Invariant, U: Invariant> Invariant for (T, U) {
6056
impl<T: Invariant> Invariant for Option<T> {
6157
#[predicate]
6258
#[open]
63-
#[creusot::ignore_type_invariant = "maybe"]
6459
fn invariant(self) -> bool {
6560
pearlite! {
6661
match self {

creusot-contracts/src/std/iter/map_inv.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ impl<I: Iterator, B, F: FnMut(I::Item, Ghost<Seq<I::Item>>) -> B> Invariant
6565
// Should not quantify over self or the `invariant` cannot be made into a type invariant
6666
#[open(self)]
6767
#[predicate]
68-
#[creusot::ignore_type_invariant]
6968
fn invariant(self) -> bool {
7069
pearlite! {
7170
Self::reinitialize() &&
@@ -108,6 +107,7 @@ impl<I: Iterator, B, F: FnMut(I::Item, Ghost<Seq<I::Item>>) -> B> ::std::iter::I
108107
impl<I: Iterator, B, F: FnMut(I::Item, Ghost<Seq<I::Item>>) -> B> MapInv<I, I::Item, F> {
109108
#[open]
110109
#[predicate]
110+
#[creusot::open_inv]
111111
pub fn next_precondition(self) -> bool {
112112
pearlite! {
113113
forall<e: I::Item, i: I>
@@ -131,6 +131,7 @@ impl<I: Iterator, B, F: FnMut(I::Item, Ghost<Seq<I::Item>>) -> B> MapInv<I, I::I
131131
#[open(self)]
132132
#[predicate]
133133
#[ensures(self.produced.inner() == Seq::EMPTY ==> result == Self::preservation(self.iter, self.func))]
134+
#[creusot::open_inv]
134135
pub fn preservation_inv(self) -> bool {
135136
pearlite! {
136137
forall<s: Seq<I::Item>, e1: I::Item, e2: I::Item, f: &mut F, b: B, i: I>

creusot-contracts/src/std/slice.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,6 @@ extern_spec! {
279279
fn iter(&self) -> Iter<'_, T>;
280280

281281
#[ensures(result@ == self)]
282-
#[ensures(result.invariant())]
283282
fn iter_mut(&mut self) -> IterMut<'_, T>;
284283

285284
#[ensures(result == None ==> self@.len() == 0)]
@@ -400,6 +399,7 @@ impl<'a, T> ShallowModel for IterMut<'a, T> {
400399
#[open(self)]
401400
#[trusted]
402401
#[ensures((^result)@.len() == (*result)@.len())]
402+
#[creusot::open_inv]
403403
fn shallow_model(self) -> Self::ShallowModelTy {
404404
absurd
405405
}
@@ -417,7 +417,6 @@ impl<'a, T> Resolve for IterMut<'a, T> {
417417
impl<'a, T> Invariant for IterMut<'a, T> {
418418
#[predicate]
419419
#[open]
420-
#[creusot::ignore_type_invariant]
421420
fn invariant(self) -> bool {
422421
// Property that is always true but we must carry around..
423422
pearlite! { (^self@)@.len() == (*self@)@.len() }

creusot/src/ctx.rs

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@ use rustc_infer::traits::{Obligation, ObligationCause};
2929
use rustc_middle::{
3030
mir::{Body, Promoted},
3131
thir,
32-
ty::{
33-
subst::{GenericArgKind, InternalSubsts},
34-
GenericArg, ParamEnv, SubstsRef, Ty, TyCtxt, Visibility,
35-
},
32+
ty::{subst::InternalSubsts, GenericArg, ParamEnv, SubstsRef, Ty, TyCtxt, Visibility},
3633
};
3734
use rustc_span::{RealFileName, Span, Symbol, DUMMY_SP};
3835
use rustc_trait_selection::traits::SelectionContext;
@@ -225,41 +222,7 @@ impl<'tcx, 'sess> TranslationCtx<'tcx> {
225222
return None;
226223
}
227224

228-
match util::ignore_type_invariant(self.tcx, inv.0) {
229-
util::TypeInvariantAttr::None => return Some(inv),
230-
util::TypeInvariantAttr::AlwaysIgnore => return None,
231-
util::TypeInvariantAttr::MaybeIgnore => {}
232-
}
233-
234-
let mut walker = ty.walk();
235-
walker.next(); // skip root type
236-
while let Some(arg) = walker.next() {
237-
if !matches!(arg.unpack(), GenericArgKind::Type(_)) {
238-
walker.skip_current_subtree();
239-
continue;
240-
}
241-
242-
let substs = self.mk_substs(&[arg]);
243-
let Some(arg_inv) = traits::resolve_opt(self.tcx, param_env, trait_did, substs) else {
244-
walker.skip_current_subtree();
245-
continue;
246-
};
247-
248-
if arg_inv.0 == trait_did
249-
&& !traits::still_specializable(self.tcx, param_env, arg_inv.0, arg_inv.1)
250-
{
251-
walker.skip_current_subtree();
252-
continue;
253-
}
254-
255-
match util::ignore_type_invariant(self.tcx, arg_inv.0) {
256-
util::TypeInvariantAttr::None => return Some(inv),
257-
util::TypeInvariantAttr::AlwaysIgnore => walker.skip_current_subtree(),
258-
util::TypeInvariantAttr::MaybeIgnore => {}
259-
}
260-
}
261-
262-
None
225+
Some(inv)
263226
}
264227

265228
pub(crate) fn crash_and_error(&self, span: Span, msg: &str) -> ! {

creusot/src/util.rs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -118,24 +118,6 @@ pub(crate) fn opacity_witness_name(tcx: TyCtxt, def_id: DefId) -> Option<Symbol>
118118
})
119119
}
120120

121-
pub(crate) enum TypeInvariantAttr {
122-
None,
123-
MaybeIgnore,
124-
AlwaysIgnore,
125-
}
126-
127-
pub(crate) fn ignore_type_invariant(tcx: TyCtxt, def_id: DefId) -> TypeInvariantAttr {
128-
match get_attr(tcx.get_attrs_unchecked(def_id), &["creusot", "ignore_type_invariant"]) {
129-
None => TypeInvariantAttr::None,
130-
Some(AttrItem { args: AttrArgs::Eq(_, AttrArgsEq::Hir(v)), .. })
131-
if v.symbol.as_str() == "maybe" =>
132-
{
133-
TypeInvariantAttr::MaybeIgnore
134-
}
135-
_ => TypeInvariantAttr::AlwaysIgnore,
136-
}
137-
}
138-
139121
pub(crate) fn why3_attrs(tcx: TyCtxt, def_id: DefId) -> Vec<why3::declaration::Attribute> {
140122
let matches = get_attrs(tcx.get_attrs_unchecked(def_id), &["why3", "attr"]);
141123
matches
@@ -494,8 +476,9 @@ fn elaborate_type_invariants<'tcx>(
494476
let arg = Term { ty: *ty, span: *span, kind: TermKind::Var(*name) };
495477
let arg =
496478
Term { ty: inner, span: *span, kind: TermKind::Fin { term: Box::new(arg) } };
497-
let term =
498-
pearlite::type_invariant_term_with_arg(ctx, def_id, arg, *span, inner).unwrap();
479+
// FIXME: why can this be none?
480+
let Some(term) =
481+
pearlite::type_invariant_term_with_arg(ctx, def_id, arg, *span, inner) else {continue; };
499482
pre_sig.contract.ensures.push(term);
500483
}
501484

creusot/tests/should_succeed/iterators/05_map.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,11 @@ impl<I: Iterator, B, F: FnMut(I::Item) -> B> Iterator for Map<I, F> {
2424

2525
#[law]
2626
#[open]
27-
#[requires(a.invariant())]
2827
#[ensures(a.produces(Seq::EMPTY, a))]
2928
fn produces_refl(a: Self) {}
3029

3130
#[law]
3231
#[open]
33-
#[requires(a.invariant())]
34-
#[requires(b.invariant())]
35-
#[requires(c.invariant())]
3632
#[requires(a.produces(ab, b))]
3733
#[requires(b.produces(bc, c))]
3834
#[ensures(a.produces(ab.concat(bc), c))]
@@ -76,14 +72,14 @@ impl<I: Iterator, B, F: FnMut(I::Item) -> B> Iterator for Map<I, F> {
7672

7773
impl<I: Iterator, B, F: FnMut(I::Item) -> B> Map<I, F> {
7874
#[predicate]
79-
fn next_precondition(self) -> bool {
75+
fn next_precondition(#[creusot::open_inv] self) -> bool {
8076
pearlite! {
81-
forall<e: I::Item, i: I> i.invariant() ==>
82-
self.iter.produces(Seq::singleton(e), i) ==> self.func.precondition((e,))
77+
forall<e: I::Item, i: I> self.iter.produces(Seq::singleton(e), i) ==> self.func.precondition((e,))
8378
}
8479
}
8580

8681
#[predicate]
82+
#[creusot::open_inv]
8783
fn reinitialize() -> bool {
8884
pearlite! {
8985
forall<reset : &mut Map<I, F>> (^reset).iter.invariant() ==>
@@ -93,10 +89,9 @@ impl<I: Iterator, B, F: FnMut(I::Item) -> B> Map<I, F> {
9389

9490
#[predicate]
9591
#[ensures(result == Self::preservation(self.iter, self.func))]
96-
fn preservation_inv(self) -> bool {
92+
fn preservation_inv(#[creusot::open_inv] self) -> bool {
9793
pearlite! {
9894
forall<s: Seq<I::Item>, e1: I::Item, e2: I::Item, f: &mut F, b: B, i: I>
99-
i.invariant() ==>
10095
self.func.unnest(*f) ==>
10196
self.iter.produces(s.push(e1).push(e2), i) ==>
10297
(*f).precondition((e1,)) ==>
@@ -109,7 +104,6 @@ impl<I: Iterator, B, F: FnMut(I::Item) -> B> Map<I, F> {
109104
fn preservation(iter: I, func: F) -> bool {
110105
pearlite! {
111106
forall<s: Seq<I::Item>, e1: I::Item, e2: I::Item, f: &mut F, b: B, i: I>
112-
i.invariant() ==>
113107
func.unnest(*f) ==>
114108
iter.produces(s.push(e1).push(e2), i) ==>
115109
(*f).precondition((e1,)) ==>
@@ -119,15 +113,18 @@ impl<I: Iterator, B, F: FnMut(I::Item) -> B> Map<I, F> {
119113
}
120114

121115
#[logic]
122-
#[requires(self.invariant())]
123116
#[requires(self.produces_one(e, other))]
124117
#[requires(other.iter.invariant())]
125118
#[ensures(other.invariant())]
126-
fn produces_one_invariant(self, e: B, other: Self) {}
119+
fn produces_one_invariant(self, e: B, #[creusot::open_inv] other: Self) {}
127120

128121
#[predicate]
129122
#[ensures(result == self.produces(Seq::singleton(visited), succ))]
130-
fn produces_one(self, visited: B, succ: Self) -> bool {
123+
fn produces_one(
124+
#[creusot::open_inv] self,
125+
visited: B,
126+
#[creusot::open_inv] succ: Self,
127+
) -> bool {
131128
pearlite! {
132129
exists<f: &mut F> *f == self.func && ^f == succ.func
133130
&& { exists<e : I::Item> self.iter.produces(Seq::singleton(e), succ.iter)
@@ -140,7 +137,6 @@ impl<I: Iterator, B, F: FnMut(I::Item) -> B> Map<I, F> {
140137
impl<I: Iterator, B, F: FnMut(I::Item) -> B> Invariant for Map<I, F> {
141138
// Should not quantify over self or the `invariant` cannot be made into a type invariant
142139
#[predicate]
143-
#[creusot::ignore_type_invariant]
144140
#[open(self)]
145141
fn invariant(self) -> bool {
146142
pearlite! {
@@ -152,11 +148,9 @@ impl<I: Iterator, B, F: FnMut(I::Item) -> B> Invariant for Map<I, F> {
152148
}
153149
}
154150

155-
#[requires(forall<e : I::Item, i2 : I> i2.invariant() ==> iter.produces(Seq::singleton(e), i2) ==> func.precondition((e,)))]
151+
#[requires(forall<e : I::Item, i2 : I> iter.produces(Seq::singleton(e), i2) ==> func.precondition((e,)))]
156152
#[requires(Map::<I, F>::reinitialize())]
157-
#[requires(iter.invariant())]
158153
#[requires(Map::<I, F>::preservation(iter, func))]
159-
#[ensures(result.invariant())]
160154
#[ensures(result == Map { iter, func })]
161155
pub fn map<I: Iterator, B, F: FnMut(I::Item) -> B>(iter: I, func: F) -> Map<I, F> {
162156
Map { iter, func }

0 commit comments

Comments
 (0)