Skip to content

Commit e529c60

Browse files
authored
Merge pull request #826 from xldenis/tyinv-gen-param-min
Do not consider generic fields to have trivial invariants
2 parents 84fb8d3 + 0096e13 commit e529c60

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1636
-1075
lines changed

creusot-contracts/src/std/ops.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{invariant::Invariant, *};
1+
use crate::{
2+
invariant::{inv, Invariant},
3+
*,
4+
};
25
use ::std::marker::Tuple;
36
pub use ::std::ops::*;
47

@@ -158,7 +161,9 @@ extern_spec! {
158161

159162
trait FnMut<Args> where Self : FnMutExt<Args>, Args : Tuple {
160163
#[requires((*self).precondition(arg))]
164+
#[requires(inv(*self))]
161165
#[ensures(self.postcondition_mut(arg, result))]
166+
#[ensures(inv(^self))]
162167
fn call_mut(&mut self, arg: Args) -> Self::Output;
163168
}
164169

creusot/src/backend/ty_inv.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub(crate) fn is_tyinv_trivial<'tcx>(
9090
tcx: TyCtxt<'tcx>,
9191
param_env: ParamEnv<'tcx>,
9292
ty: Ty<'tcx>,
93+
default_trivial: bool,
9394
) -> bool {
9495
if ty.is_closure() {
9596
return true;
@@ -99,7 +100,10 @@ pub(crate) fn is_tyinv_trivial<'tcx>(
99100
let mut visited_adts = IndexSet::new();
100101
let mut stack = vec![ty];
101102
while let Some(ty) = stack.pop() {
102-
if resolve_user_inv(tcx, ty, param_env).is_some() {
103+
if resolve_user_inv(tcx, ty, param_env).is_some()
104+
// HACK we should never consider invariants of param types trivial
105+
|| (!default_trivial && matches!(ty.kind(), TyKind::Param(_)))
106+
{
103107
return false;
104108
}
105109

@@ -187,7 +191,7 @@ fn build_inv_exp<'tcx>(
187191
) -> Option<Exp> {
188192
let ty = ctx.tcx.normalize_erasing_regions(param_env, ty);
189193

190-
if mode == Mode::Field && is_tyinv_trivial(ctx.tcx, param_env, ty) {
194+
if mode == Mode::Field && is_tyinv_trivial(ctx.tcx, param_env, ty, false) {
191195
return None;
192196
}
193197

creusot/src/ctx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ impl<'tcx, 'sess> TranslationCtx<'tcx> {
210210
let ty = self.try_normalize_erasing_regions(param_env, ty).ok()?;
211211

212212
if util::is_open_ty_inv(self.tcx, def_id)
213-
|| ty_inv::is_tyinv_trivial(self.tcx, param_env, ty)
213+
|| ty_inv::is_tyinv_trivial(self.tcx, param_env, ty, true)
214214
{
215215
None
216216
} else {

creusot/tests/should_fail/bug/692.mlcfg

Lines changed: 33 additions & 33 deletions
Large diffs are not rendered by default.

creusot/tests/should_fail/bug/695.mlcfg

Lines changed: 37 additions & 37 deletions
Large diffs are not rendered by default.

creusot/tests/should_succeed/100doors.mlcfg

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,11 @@ end
417417
module Core_Ops_Range_Range_Type_Inv
418418
type idx
419419
use Core_Ops_Range_Range_Type as Core_Ops_Range_Range_Type
420+
clone CreusotContracts_Invariant_Inv_Stub as Inv1 with
421+
type t = idx
420422
clone CreusotContracts_Invariant_Inv_Stub as Inv0 with
421423
type t = Core_Ops_Range_Range_Type.t_range idx
422-
axiom inv_t_range : forall self : Core_Ops_Range_Range_Type.t_range idx . Inv0.inv self = true
424+
axiom inv_t_range [@rewrite] : forall self : Core_Ops_Range_Range_Type.t_range idx . Inv0.inv self = (Inv1.inv (Core_Ops_Range_Range_Type.range_start self) /\ Inv1.inv (Core_Ops_Range_Range_Type.range_end self))
423425
end
424426
module CreusotContracts_Std1_Iter_Iterator_Completed_Stub
425427
type self
@@ -997,6 +999,12 @@ module CreusotContracts_Std1_Slice_Impl5_ResolveElswhere
997999
ensures { result = resolve_elswhere self old' fin }
9981000

9991001
end
1002+
module TyInv_Trivial
1003+
type t
1004+
clone CreusotContracts_Invariant_Inv_Stub as Inv0 with
1005+
type t = t
1006+
axiom inv_trivial : forall self : t . Inv0.inv self = true
1007+
end
10001008
module C100doors_F_Interface
10011009
val f [#"../100doors.rs" 18 0 18 10] (_1 : ()) : ()
10021010
end
@@ -1006,6 +1014,12 @@ module C100doors_F
10061014
use prelude.Ghost
10071015
use seq.Seq
10081016
use prelude.Borrow
1017+
clone CreusotContracts_Invariant_Inv_Interface as Inv1 with
1018+
type t = usize
1019+
clone TyInv_Trivial as TyInv_Trivial0 with
1020+
type t = usize,
1021+
predicate Inv0.inv = Inv1.inv,
1022+
axiom .
10091023
clone CreusotContracts_Std1_Slice_Impl5_ResolveElswhere as ResolveElswhere0 with
10101024
type t = bool
10111025
use Alloc_Alloc_Global_Type as Alloc_Alloc_Global_Type
@@ -1056,6 +1070,7 @@ module C100doors_F
10561070
clone Core_Ops_Range_Range_Type_Inv as Core_Ops_Range_Range_Type_Inv0 with
10571071
type idx = usize,
10581072
predicate Inv0.inv = Inv0.inv,
1073+
predicate Inv1.inv = Inv1.inv,
10591074
axiom .
10601075
clone CreusotContracts_Std1_Iter_Impl0_IntoIterPost as IntoIterPost0 with
10611076
type i = Core_Ops_Range_Range_Type.t_range usize

creusot/tests/should_succeed/100doors/why3session.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<path name=".."/><path name="100doors.mlcfg"/>
88
<theory name="C100doors_F" proved="true">
99
<goal name="f&#39;vc" expl="VC for f" proved="true">
10-
<proof prover="1"><result status="valid" time="0.220000" steps="45466"/></proof>
10+
<proof prover="1"><result status="valid" time="0.220000" steps="49042"/></proof>
1111
</goal>
1212
</theory>
1313
</file>
23 Bytes
Binary file not shown.

creusot/tests/should_succeed/closures/03_generic_bound.mlcfg

Lines changed: 35 additions & 35 deletions
Large diffs are not rendered by default.

creusot/tests/should_succeed/closures/04_generic_closure.mlcfg

Lines changed: 35 additions & 35 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)