Skip to content

Commit 0bf6ec0

Browse files
committed
Merge branch 'master' into update_toolchain_2023-06-25
2 parents 6a8b7cc + e529c60 commit 0bf6ec0

File tree

170 files changed

+3432
-2356
lines changed

Some content is hidden

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

170 files changed

+3432
-2356
lines changed

creusot-contracts/src/logic/ops.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@ impl<T> IndexLogic<Int> for Ghost<Seq<T>> {
3333
type Item = T;
3434

3535
#[logic]
36-
#[trusted]
37-
#[open(self)]
38-
#[creusot::builtins = "seq.Seq.get"]
39-
fn index_logic(self, _: Int) -> Self::Item {
40-
absurd
36+
#[open]
37+
#[why3::attr = "inline:trivial"]
38+
fn index_logic(self, ix: Int) -> Self::Item {
39+
pearlite! { (*self)[ix] }
4140
}
4241
}

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.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ fn build_ty_decl<'tcx>(
372372
.fields
373373
.iter()
374374
.map(|f| {
375-
let ty = field_ty(ctx, names, param_env, f, substs);
375+
let ty = field_ty(ctx, names, param_env, did, f, substs);
376376
Field { ty, ghost: false }
377377
})
378378
.collect();
@@ -410,14 +410,34 @@ fn field_ty<'tcx>(
410410
ctx: &mut Why3Generator<'tcx>,
411411
names: &mut CloneMap<'tcx>,
412412
param_env: ParamEnv<'tcx>,
413+
adt_did: DefId,
413414
field: &FieldDef,
414415
substs: SubstsRef<'tcx>,
415416
) -> MlT {
416417
let ty = field.ty(ctx.tcx, substs);
417418
let ty = ctx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
419+
420+
if !validate_field_ty(ctx, adt_did, ty) {
421+
ctx.crash_and_error(ctx.def_span(field.did), "Illegal use of the Ghost type")
422+
}
423+
418424
translate_ty_inner(TyTranslation::Declaration, ctx, names, ctx.def_span(field.did), ty)
419425
}
420426

427+
fn validate_field_ty<'tcx>(ctx: &mut Why3Generator<'tcx>, adt_did: DefId, ty: Ty<'tcx>) -> bool {
428+
let tcx = ctx.tcx;
429+
let bg = ctx.binding_group(adt_did);
430+
431+
!ty.walk().filter_map(ty::GenericArg::as_type).any(|ty| {
432+
util::is_ghost_ty(tcx, ty)
433+
&& ty.walk().filter_map(ty::GenericArg::as_type).any(|ty| match ty.kind() {
434+
TyKind::Adt(adt_def, _) => bg.contains(&adt_def.did()),
435+
// TyKind::Param(_) => true,
436+
_ => false,
437+
})
438+
})
439+
}
440+
421441
pub(crate) fn translate_accessor(
422442
ctx: &mut Why3Generator<'_>,
423443
adt_did: DefId,
@@ -457,7 +477,8 @@ pub(crate) fn translate_accessor(
457477
let acc_name = format!("{}_{}", variant.name.as_str().to_ascii_lowercase(), field.name);
458478

459479
let param_env = ctx.param_env(adt_did);
460-
let target_ty = field_ty(ctx, &mut names, param_env, &variant.fields[ix.into()], substs);
480+
let target_ty =
481+
field_ty(ctx, &mut names, param_env, adt_did, &variant.fields[ix.into()], substs);
461482

462483
let variant_arities: Vec<_> = adt_def
463484
.variants()

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/src/translation/function.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ impl<'body, 'tcx> BodyTranslator<'body, 'tcx> {
285285
fn resolve_locals(&mut self, mut locals: BitSet<Local>) {
286286
locals.subtract(&self.erased_locals.to_hybrid());
287287

288-
for local in locals.iter() {
288+
// TODO determine resolution order based on outlives relation
289+
let locals = locals.iter().collect::<Vec<_>>();
290+
for local in locals.into_iter().rev() {
289291
self.emit_resolve(local.into());
290292
}
291293
}

creusot/src/util.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ pub(crate) fn is_ghost_closure<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<
7575
} else { None }
7676
}
7777

78+
pub(crate) fn is_ghost_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
79+
let r: Option<bool> = try {
80+
let adt = ty.ty_adt_def()?;
81+
let builtin = get_builtin(tcx, adt.did())?;
82+
builtin.as_str() == "prelude.Ghost.ghost_ty"
83+
};
84+
r.unwrap_or(false)
85+
}
86+
7887
pub(crate) fn is_spec_logic(tcx: TyCtxt, def_id: DefId) -> bool {
7988
get_attr(tcx.get_attrs_unchecked(def_id), &["creusot", "decl", "spec_logic"]).is_some()
8089
}

creusot/tests/should_fail/bug/436.stderr renamed to creusot/tests/should_fail/bug/436_0.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[creusot]: called Logic function in Ghost context "creusot_contracts::__stubs::fin"
2-
--> 436.rs:10:5
2+
--> 436_0.rs:10:5
33
|
44
10 | pearlite! { *(^x).g }
55
| ^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)