Skip to content

Commit ee50ea2

Browse files
authored
Merge pull request creusot-rs#801 from xldenis/tyinv-gen
Generate structural type invariants
2 parents 88eff84 + f41ad35 commit ee50ea2

Some content is hidden

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

72 files changed

+2602
-1485
lines changed

creusot-contracts/src/invariant.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,29 @@ pub trait Invariant {
2121
}
2222
}
2323

24+
#[predicate]
25+
#[open(self)]
26+
#[rustc_diagnostic_item = "creusot_invariant_internal"]
27+
pub fn inv<T>(_x: T) -> bool {
28+
true
29+
}
30+
31+
pub trait UserInv {
32+
#[predicate]
33+
#[rustc_diagnostic_item = "creusot_invariant_user"]
34+
fn user_inv(self) -> bool;
35+
}
36+
37+
#[cfg(creusot)]
38+
impl<T> UserInv for T {
39+
#[predicate]
40+
#[open]
41+
#[rustc_diagnostic_item = "creusot_invariant_user_default"]
42+
default fn user_inv(self) -> bool {
43+
true
44+
}
45+
}
46+
2447
impl<'a, T: Invariant + ?Sized> Invariant for &'a T {
2548
#[predicate]
2649
#[open]

creusot/src/backend.rs

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use indexmap::{IndexMap, IndexSet};
22
use rustc_hir::{def::DefKind, def_id::DefId};
3+
use rustc_span::DUMMY_SP;
34

45
use crate::{
56
ctx::{TranslatedItem, TranslationCtx},
@@ -9,6 +10,8 @@ use std::ops::{Deref, DerefMut};
910

1011
pub(crate) use clone_map::*;
1112

13+
use self::{dependency::Dependency, ty_inv::TyInvKind};
14+
1215
pub(crate) mod clone_map;
1316
pub(crate) mod constant;
1417
pub(crate) mod dependency;
@@ -21,13 +24,26 @@ pub(crate) mod signature;
2124
pub(crate) mod term;
2225
pub(crate) mod traits;
2326
pub(crate) mod ty;
27+
pub(crate) mod ty_inv;
28+
29+
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
30+
pub(crate) enum TransId {
31+
Item(DefId),
32+
TyInv(TyInvKind),
33+
}
34+
35+
impl From<DefId> for TransId {
36+
fn from(def_id: DefId) -> Self {
37+
TransId::Item(def_id)
38+
}
39+
}
2440

2541
pub struct Why3Generator<'tcx> {
2642
ctx: TranslationCtx<'tcx>,
27-
dependencies: IndexMap<DefId, CloneSummary<'tcx>>,
28-
functions: IndexMap<DefId, TranslatedItem>,
29-
translated_items: IndexSet<DefId>,
30-
in_translation: Vec<IndexSet<DefId>>,
43+
dependencies: IndexMap<TransId, CloneSummary<'tcx>>,
44+
functions: IndexMap<TransId, TranslatedItem>,
45+
translated_items: IndexSet<TransId>,
46+
in_translation: Vec<IndexSet<TransId>>,
3147
}
3248

3349
impl<'tcx> Deref for Why3Generator<'tcx> {
@@ -56,12 +72,13 @@ impl<'tcx> Why3Generator<'tcx> {
5672
}
5773

5874
// Checks if we are allowed to recurse into
59-
fn safe_cycle(&self, def_id: DefId) -> bool {
60-
self.in_translation.last().map(|l| l.contains(&def_id)).unwrap_or_default()
75+
fn safe_cycle(&self, trans_id: TransId) -> bool {
76+
self.in_translation.last().map(|l| l.contains(&trans_id)).unwrap_or_default()
6177
}
6278

6379
pub(crate) fn translate(&mut self, def_id: DefId) {
64-
if self.translated_items.contains(&def_id) || self.safe_cycle(def_id) {
80+
let tid = def_id.into();
81+
if self.translated_items.contains(&tid) || self.safe_cycle(tid) {
6582
return;
6683
}
6784
debug!("translating {:?}", def_id);
@@ -72,17 +89,17 @@ impl<'tcx> Why3Generator<'tcx> {
7289
ItemType::Trait => {
7390
self.start(def_id);
7491
let tr = self.translate_trait(def_id);
75-
self.dependencies.insert(def_id, CloneSummary::new());
76-
self.functions.insert(def_id, tr);
92+
self.dependencies.insert(tid, CloneSummary::new());
93+
self.functions.insert(tid, tr);
7794
self.finish(def_id);
7895
}
7996
ItemType::Impl => {
8097
if self.tcx.impl_trait_ref(def_id).is_some() {
8198
self.start(def_id);
8299
let impl_ = traits::lower_impl(self, def_id);
83100

84-
self.dependencies.insert(def_id, CloneSummary::new());
85-
self.functions.insert(def_id, TranslatedItem::Impl { modl: impl_ });
101+
self.dependencies.insert(tid, CloneSummary::new());
102+
self.functions.insert(tid, TranslatedItem::Impl { modl: impl_ });
86103
self.finish(def_id);
87104
}
88105
}
@@ -95,15 +112,15 @@ impl<'tcx> Why3Generator<'tcx> {
95112
self.start(def_id);
96113
let (modl, dependencies) = self.translate_assoc_ty(def_id);
97114
self.finish(def_id);
98-
self.dependencies.insert(def_id, dependencies);
99-
self.functions.insert(def_id, TranslatedItem::AssocTy { modl });
115+
self.dependencies.insert(tid, dependencies);
116+
self.functions.insert(tid, TranslatedItem::AssocTy { modl });
100117
}
101118
ItemType::Constant => {
102119
self.start(def_id);
103120
let (constant, dependencies) = self.translate_constant(def_id);
104121
self.finish(def_id);
105-
self.dependencies.insert(def_id, dependencies);
106-
self.functions.insert(def_id, constant);
122+
self.dependencies.insert(tid, dependencies);
123+
self.functions.insert(tid, constant);
107124
}
108125
ItemType::Type => {
109126
let bg = self.binding_group(def_id).clone();
@@ -116,7 +133,7 @@ impl<'tcx> Why3Generator<'tcx> {
116133
self.finish(*d);
117134
}
118135

119-
let repr = self.representative_type(def_id);
136+
let repr = self.representative_type(def_id).into();
120137
if let Some(modl) = modl {
121138
self.functions
122139
.insert(repr, TranslatedItem::Type { modl, accessors: Default::default() });
@@ -148,31 +165,31 @@ impl<'tcx> Why3Generator<'tcx> {
148165
debug!("translating {:?} as logical", def_id);
149166
let (stub, modl, proof_modl, has_axioms, deps) =
150167
crate::backend::logic::translate_logic_or_predicate(self, def_id);
151-
self.dependencies.insert(def_id, deps);
168+
self.dependencies.insert(def_id.into(), deps);
152169

153170
TranslatedItem::Logic { stub, interface, modl, proof_modl, has_axioms }
154171
}
155172
ItemType::Closure => {
156173
let (ty_modl, modl) = program::translate_closure(self, def_id);
157-
self.dependencies.insert(def_id, deps);
174+
self.dependencies.insert(def_id.into(), deps);
158175

159176
TranslatedItem::Closure { interface: vec![ty_modl, interface], modl }
160177
}
161178
ItemType::Program => {
162179
debug!("translating {def_id:?} as program");
163180

164-
self.dependencies.insert(def_id, deps);
181+
self.dependencies.insert(def_id.into(), deps);
165182
let modl = program::translate_function(self, def_id);
166183
TranslatedItem::Program { interface, modl }
167184
}
168185
_ => unreachable!(),
169186
};
170187

171-
self.functions.insert(def_id, translated);
188+
self.functions.insert(def_id.into(), translated);
172189
}
173190

174191
pub(crate) fn translate_accessor(&mut self, field_id: DefId) {
175-
if !self.translated_items.insert(field_id) {
192+
if !self.translated_items.insert(field_id.into()) {
176193
return;
177194
}
178195

@@ -187,30 +204,52 @@ impl<'tcx> Why3Generator<'tcx> {
187204
self.translate(adt_did);
188205

189206
let accessor = ty::translate_accessor(self, adt_did, variant_did, field_id);
190-
let repr_id = self.representative_type(adt_did);
207+
let repr_id: TransId = self.representative_type(adt_did).into();
191208
if let TranslatedItem::Type { ref mut accessors, .. } = &mut self.functions[&repr_id] {
192209
accessors.entry(variant_did).or_default().insert(field_id, accessor);
193210
};
194211
// self.types[&repr_id].accessors;
195212
}
196213

214+
pub(crate) fn translate_tyinv(&mut self, inv_kind: TyInvKind) {
215+
let tid = TransId::TyInv(inv_kind);
216+
if self.dependencies.contains_key(&tid) {
217+
return;
218+
}
219+
220+
if let TyInvKind::Adt(adt_did) = inv_kind {
221+
self.translate(adt_did);
222+
}
223+
224+
let (modl, deps) = ty_inv::build_inv_module(self, inv_kind);
225+
self.dependencies.insert(tid, deps);
226+
self.functions.insert(tid, TranslatedItem::TyInv { modl });
227+
}
228+
197229
pub(crate) fn item(&self, def_id: DefId) -> Option<&TranslatedItem> {
198-
let def_id = if matches!(util::item_type(***self, def_id), ItemType::Type) {
230+
let tid: TransId = if matches!(util::item_type(***self, def_id), ItemType::Type) {
199231
self.representative_type(def_id)
200232
} else {
201233
def_id
202-
};
203-
self.functions.get(&def_id)
234+
}
235+
.into();
236+
self.functions.get(&tid)
204237
}
205238

206-
pub(crate) fn modules(self) -> impl Iterator<Item = (DefId, TranslatedItem)> + 'tcx {
239+
pub(crate) fn modules(self) -> impl Iterator<Item = (TransId, TranslatedItem)> + 'tcx {
207240
self.functions.into_iter()
208241
}
209242

210243
pub(crate) fn start_group(&mut self, ids: IndexSet<DefId>) {
211244
assert!(!ids.is_empty());
245+
let ids = ids.into_iter().map(Into::into).collect();
212246
if self.in_translation.iter().rev().any(|s| !s.is_disjoint(&ids)) {
213-
let span = self.def_span(ids.first().unwrap());
247+
let span = if let TransId::Item(def_id) = ids.first().unwrap() {
248+
self.def_span(def_id)
249+
} else {
250+
DUMMY_SP
251+
};
252+
214253
self.in_translation.push(ids);
215254

216255
self.crash_and_error(
@@ -229,7 +268,8 @@ impl<'tcx> Why3Generator<'tcx> {
229268

230269
// Indicate we have finished translating a given id
231270
pub(crate) fn finish(&mut self, def_id: DefId) {
232-
if !self.in_translation.last_mut().unwrap().remove(&def_id) {
271+
let tid = def_id.into();
272+
if !self.in_translation.last_mut().unwrap().remove(&tid) {
233273
self.crash_and_error(
234274
self.def_span(def_id),
235275
&format!("{:?} is not in translation", def_id),
@@ -240,10 +280,14 @@ impl<'tcx> Why3Generator<'tcx> {
240280
self.in_translation.pop();
241281
}
242282

243-
self.translated_items.insert(def_id);
283+
self.translated_items.insert(tid);
244284
}
245285

246-
pub(crate) fn dependencies(&self, def_id: DefId) -> Option<&CloneSummary<'tcx>> {
247-
self.dependencies.get(&def_id)
286+
pub(crate) fn dependencies(&self, key: Dependency<'tcx>) -> Option<&CloneSummary<'tcx>> {
287+
let tid = match key {
288+
Dependency::TyInv(ty) => TransId::TyInv(TyInvKind::from_ty(ty)),
289+
_ => key.did().map(|(def_id, _)| TransId::Item(def_id))?,
290+
};
291+
self.dependencies.get(&tid)
248292
}
249293
}

0 commit comments

Comments
 (0)