Skip to content

Commit 5a5089f

Browse files
Merge branch 'main' into field-access
2 parents 95b1409 + 6c984e4 commit 5a5089f

File tree

14 files changed

+462
-80
lines changed

14 files changed

+462
-80
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use std::rc::Rc;
2+
3+
use vstd::pervasive::runtime_assert;
4+
use vstd::prelude::*;
5+
6+
verus! {
7+
8+
fn try_unwrap_test() {
9+
let r1 = Rc::new(5);
10+
let r2 = r1.clone();
11+
let result1 = Rc::try_unwrap(r1);
12+
assert(result1 is Err ==> result1.unwrap_err() == 5);
13+
match result1 {
14+
Err(r3) => { runtime_assert(*r3 == 5); },
15+
Ok(five) => { assert(five == 5); }, // won't happen
16+
};
17+
let result2 = Rc::try_unwrap(r2);
18+
assert(result2 is Ok ==> result2.unwrap() == 5);
19+
match result2 {
20+
Err(r4) => { assert(r4 == 5); }, // won't happen
21+
Ok(five) => { runtime_assert(five == 5); },
22+
}
23+
24+
}
25+
26+
fn into_inner_test() {
27+
let r1 = Rc::new(5);
28+
let r2 = r1.clone();
29+
let result1 = Rc::into_inner(r1);
30+
match result1 {
31+
Some(five) => {
32+
assert(five == 5); // won't happen
33+
},
34+
None => {
35+
let result2 = Rc::into_inner(r2);
36+
match result2 {
37+
Some(five) => { runtime_assert(five == 5) },
38+
None => {},
39+
}
40+
},
41+
}
42+
}
43+
44+
} // verus!

source/rust_verify/src/config.rs

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ pub enum ShowTriggers {
1010
Silent,
1111
Selective,
1212
Module,
13+
AllModules,
1314
Verbose,
15+
VerboseAllModules,
1416
}
1517
impl Default for ShowTriggers {
1618
fn default() -> Self {
@@ -256,10 +258,32 @@ pub fn parse_args_with_imports(
256258
(LOG_CALL_GRAPH, "Log the call graph"),
257259
];
258260

259-
const OPT_TRIGGERS_SILENT: &str = "triggers-silent";
260-
const OPT_TRIGGERS_SELECTIVE: &str = "triggers-selective";
261261
const OPT_TRIGGERS: &str = "triggers";
262-
const OPT_TRIGGERS_VERBOSE: &str = "triggers-verbose";
262+
const OPT_TRIGGERS_MODE: &str = "triggers-mode";
263+
264+
const TRIGGERS_MODE_SILENT: &str = "silent";
265+
const TRIGGERS_MODE_SELECTIVE: &str = "selective";
266+
const TRIGGERS_MODE_ALL_MODULES: &str = "all-modules";
267+
const TRIGGERS_MODE_VERBOSE: &str = "verbose";
268+
const TRIGGERS_MODE_VERBOSE_ALL_MODULES: &str = "verbose-all-modules";
269+
270+
const TRIGGERS_MODE_ITEMS: &[(&str, &str)] = &[
271+
(TRIGGERS_MODE_SILENT, "Do not show automatically chosen triggers"),
272+
(
273+
TRIGGERS_MODE_SELECTIVE,
274+
"Show automatically chosen triggers for some potentially ambiguous cases in verified modules (this is the default behavior)",
275+
),
276+
(
277+
TRIGGERS_MODE_ALL_MODULES,
278+
"Show all automatically chosen triggers for verified modules and imported definitions from other modules",
279+
),
280+
(TRIGGERS_MODE_VERBOSE, "Show all triggers (manually or auto) for verified modules"),
281+
(
282+
TRIGGERS_MODE_VERBOSE_ALL_MODULES,
283+
"Show all triggers (manually or automatically chosen) for verified modules and imported definitions from other modules",
284+
),
285+
];
286+
263287
const OPT_PROFILE: &str = "profile";
264288
const OPT_PROFILE_ALL: &str = "profile-all";
265289
const OPT_COMPILE: &str = "compile";
@@ -385,10 +409,20 @@ pub fn parse_args_with_imports(
385409
"OPTION=VALUE",
386410
);
387411

388-
opts.optflag("", OPT_TRIGGERS_SILENT, "Do not show automatically chosen triggers");
389-
opts.optflag("", OPT_TRIGGERS_SELECTIVE, "Show automatically chosen triggers for some potentially ambiguous cases in verified modules (this is the default behavior)");
390412
opts.optflag("", OPT_TRIGGERS, "Show all automatically chosen triggers for verified modules");
391-
opts.optflag("", OPT_TRIGGERS_VERBOSE, "Show all automatically chosen triggers for verified modules and imported definitions from other modules");
413+
opts.optopt(
414+
"",
415+
OPT_TRIGGERS_MODE,
416+
{
417+
let mut s = "Display triggers:\n".to_owned();
418+
for (f, d) in TRIGGERS_MODE_ITEMS {
419+
s += format!("--{} {} : {}\n", OPT_TRIGGERS_MODE, *f, d).as_str();
420+
}
421+
s
422+
}
423+
.as_str(),
424+
&TRIGGERS_MODE_ITEMS.iter().map(|(x, _)| x.to_owned()).collect::<Vec<_>>().join("|"),
425+
);
392426
opts.optflag(
393427
"",
394428
OPT_PROFILE,
@@ -593,14 +627,20 @@ pub fn parse_args_with_imports(
593627
log_triggers: log.get(LOG_TRIGGERS).is_some(),
594628
log_call_graph: log.get(LOG_CALL_GRAPH).is_some(),
595629
},
596-
show_triggers: if matches.opt_present(OPT_TRIGGERS_VERBOSE) {
597-
ShowTriggers::Verbose
598-
} else if matches.opt_present(OPT_TRIGGERS) {
630+
show_triggers: if matches.opt_present(OPT_TRIGGERS) {
631+
if matches.opt_present(OPT_TRIGGERS_MODE) {
632+
error("--triggers and --triggers-mode are mutually exclusive".to_owned())
633+
}
599634
ShowTriggers::Module
600-
} else if matches.opt_present(OPT_TRIGGERS_SELECTIVE) {
601-
ShowTriggers::Selective
602-
} else if matches.opt_present(OPT_TRIGGERS_SILENT) {
603-
ShowTriggers::Silent
635+
} else if let Some(triggers_mode) = matches.opt_str(OPT_TRIGGERS_MODE) {
636+
match triggers_mode.as_str() {
637+
TRIGGERS_MODE_ALL_MODULES => ShowTriggers::AllModules,
638+
TRIGGERS_MODE_SELECTIVE => ShowTriggers::Selective,
639+
TRIGGERS_MODE_SILENT => ShowTriggers::Silent,
640+
TRIGGERS_MODE_VERBOSE_ALL_MODULES => ShowTriggers::VerboseAllModules,
641+
TRIGGERS_MODE_VERBOSE => ShowTriggers::Verbose,
642+
_ => error(format!("invalid --triggers-mode {triggers_mode}")),
643+
}
604644
} else {
605645
ShowTriggers::default()
606646
},

source/rust_verify/src/verifier.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,10 @@ pub struct Verifier {
308308
fn report_chosen_triggers(
309309
diagnostics: &impl air::messages::Diagnostics,
310310
chosen: &vir::context::ChosenTriggers,
311+
automatically: bool,
311312
) {
312-
diagnostics
313-
.report(&note(&chosen.span, "automatically chose triggers for this expression:").to_any());
313+
let s = if automatically { "automatically chose" } else { "selected" }.to_owned();
314+
diagnostics.report(&note(&chosen.span, s + " triggers for this expression:").to_any());
314315

315316
for (n, trigger) in chosen.triggers.iter().enumerate() {
316317
let note = format!(" trigger {} of {}:", n + 1, chosen.triggers.len());
@@ -1744,7 +1745,9 @@ impl Verifier {
17441745
}
17451746

17461747
if matches!(query_op, QueryOp::Body(Style::Normal)) {
1747-
if (any_invalid && !self.args.no_auto_recommends_check)
1748+
if (any_invalid
1749+
&& !self.args.no_auto_recommends_check
1750+
&& !any_timed_out)
17481751
|| function.x.attrs.check_recommends
17491752
{
17501753
function_opgen.retry_with_recommends(&op, any_invalid)?;
@@ -1772,7 +1775,9 @@ impl Verifier {
17721775
}
17731776

17741777
if matches!(query_op, QueryOp::SpecTermination) {
1775-
if (any_invalid && !self.args.no_auto_recommends_check)
1778+
if (any_invalid
1779+
&& !self.args.no_auto_recommends_check
1780+
&& !any_timed_out)
17761781
|| function.x.attrs.check_recommends
17771782
{
17781783
// Do recommends-checking for the body of the function.
@@ -2466,18 +2471,33 @@ impl Verifier {
24662471
match (
24672472
self.args.show_triggers,
24682473
modules_to_verify.iter().find(|m| &m.x.path == &chosen.module).is_some(),
2474+
chosen.manual,
24692475
) {
2470-
(ShowTriggers::Selective, true) if chosen.low_confidence => {
2471-
report_chosen_triggers(&reporter, &chosen);
2476+
(ShowTriggers::Selective, true, false) if chosen.low_confidence => {
2477+
report_chosen_triggers(&reporter, &chosen, true);
24722478
low_confidence_triggers = Some(chosen.span);
24732479
}
2474-
(ShowTriggers::Module, true) => {
2475-
report_chosen_triggers(&reporter, &chosen);
2480+
(ShowTriggers::Module, true, false) => {
2481+
report_chosen_triggers(&reporter, &chosen, true);
24762482
}
2477-
(ShowTriggers::Verbose, _) => {
2478-
report_chosen_triggers(&reporter, &chosen);
2483+
(ShowTriggers::AllModules, _, false) => {
2484+
report_chosen_triggers(&reporter, &chosen, true);
24792485
}
2480-
_ => {}
2486+
(ShowTriggers::Verbose, true, _) => {
2487+
report_chosen_triggers(&reporter, &chosen, !chosen.manual);
2488+
}
2489+
(ShowTriggers::VerboseAllModules, _, _) => {
2490+
report_chosen_triggers(&reporter, &chosen, !chosen.manual);
2491+
}
2492+
(
2493+
ShowTriggers::Selective
2494+
| ShowTriggers::Module
2495+
| ShowTriggers::AllModules
2496+
| ShowTriggers::Silent
2497+
| ShowTriggers::Verbose,
2498+
_,
2499+
_,
2500+
) => {}
24812501
}
24822502
}
24832503
if let Some(span) = low_confidence_triggers {

source/rust_verify_test/tests/seqs.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,26 +119,16 @@ test_verify_one_file! {
119119
use vstd::seq_lib::*;
120120

121121
proof fn test() {
122-
// TODO: seq! is currently defined via repeated pushes.
123-
// This has sometimes led to Z3 timeouts, including in this test.
124-
// It may be time for a more efficient definition of seq!
125-
// (for example, via if/else, as shown below).
126-
//let s1 = seq![10, 20, 30, 45, 55, 70];
127-
let s1 = Seq::new(6, |i: int|
128-
if i == 0 { 10 }
129-
else if i == 1 { 20 }
130-
else if i == 2 { 30 }
131-
else if i == 3 { 45 }
132-
else if i == 4 { 55 }
133-
else { 70 }
134-
);
122+
let s1 = seq![10, 20, 30, 45, 55, 70];
135123
let s2 = s1.filter(|x: int| x < 40);
136124
let s3 = seq![90, 100];
137125
let s4 = s3.filter(|x: int| x < 40);
138-
// Test for successful broadcast of filter_lemma_broadcast
126+
// Test for successful broadcast of filter_lemma
139127
assert(forall|i: nat| i < s2.len() ==> s2[i as int] < 40);
140128
// Test for successful broadcast of filter_distributes_over_add
141129
assert((s1 + s3).filter(|x: int| x < 40) == (s2 + s4));
130+
// TODO: the following test will verify even if
131+
// push_distributes_over_add is not broadcasted.
142132
// Test for successful broadcast of push_distributes_over_add
143133
assert((s2 + s4).push(120) == s2 + s4.push(120));
144134
}

source/rust_verify_test/tests/triggers.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,58 @@ test_verify_one_file! {
390390
}
391391
} => Ok(())
392392
}
393+
394+
test_verify_one_file! {
395+
#[test] test_self_in_trigger_in_clone_issue1347 verus_code! {
396+
use vstd::*;
397+
use vstd::prelude::*;
398+
399+
struct Node {
400+
child: Option<Box<Node>>,
401+
}
402+
403+
impl Node {
404+
pub spec fn map(self) -> Map<int, int>;
405+
}
406+
407+
impl Clone for Node {
408+
fn clone(&self) -> (res: Self)
409+
ensures forall |key: int| #[trigger] self.map().dom().contains(key) ==> key == 3
410+
{
411+
return Node { child: None }; // FAILS
412+
}
413+
}
414+
415+
fn test(n: Node) {
416+
let t = n.clone();
417+
assert(forall |key: int| n.map().dom().contains(key) ==> key == 3);
418+
}
419+
420+
fn test2(n: Node) {
421+
let c = Node::clone;
422+
let t = c(&n);
423+
assert(forall |key: int| n.map().dom().contains(key) ==> key == 3);
424+
}
425+
} => Err(err) => assert_one_fails(err)
426+
}
427+
428+
test_verify_one_file! {
429+
#[test] test_lets_and_nested_quantifiers_issue1347 verus_code! {
430+
spec fn llama(x: int) -> int;
431+
spec fn foo(x: int, y: int) -> bool;
432+
spec fn bar(x: int) -> bool;
433+
434+
proof fn test() {
435+
let b =
436+
forall |x: int| #[trigger] bar(x) ==> ({
437+
let y = llama(x);
438+
forall |z: int| #[trigger] foo(y, z)
439+
});
440+
441+
assume(b);
442+
assume(bar(7));
443+
assert(foo(llama(7), 20));
444+
assert(foo(llama(7), 21));
445+
}
446+
} => Ok(())
447+
}

source/state_machines_macros/src/to_token_stream.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ pub fn output_primary_stuff(
301301
let attrs = &bundle.sm.attrs;
302302
let code: TokenStream = quote_spanned! { sm.fields_named_ast.span() =>
303303
#[cfg_attr(verus_keep_ghost, verus::internal(verus_macro))]
304+
#[cfg_attr(verus_keep_ghost, verifier::ext_equal)]
304305
#(#attrs)*
305306
pub struct State #gen {
306307
#(#fields),*

source/vir/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct ChosenTriggers {
3131
pub span: Span,
3232
pub triggers: Vec<ChosenTrigger>,
3333
pub low_confidence: bool,
34+
pub manual: bool,
3435
}
3536

3637
/// Context for across all modules

0 commit comments

Comments
 (0)