Skip to content

Commit a13c808

Browse files
authored
report multiple errors from modes.rs (#2771)
1 parent 0fd7399 commit a13c808

6 files changed

Lines changed: 75 additions & 34 deletions

File tree

source/rust_verify/src/verifier.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2857,7 +2857,7 @@ impl Verifier {
28572857
let vir_crate =
28582858
vir::autospec::resolve_autospec(&vir_crate).map_err(|e| (vec![e], Vec::new()))?;
28592859
let (vir_crate, erasure_modes, _read_kind_finals) =
2860-
vir::modes::check_crate(&vir_crate).map_err(|e| (vec![e], Vec::new()))?;
2860+
vir::modes::check_crate(&vir_crate).map_err(|es| (es, Vec::new()))?;
28612861

28622862
self.vir_crate = Some(vir_crate.clone());
28632863
self.warning_ctx = Some(Arc::new(warning_ctx));

source/rust_verify_test/tests/consts.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,10 @@ test_verify_one_file! {
261261
proof { let x = E; }
262262
0
263263
}
264-
} => Err(err) => assert_vir_error_msg(err, "cannot read static with mode exec")
264+
} => Err(err) => assert_vir_error_msgs(err, &[
265+
"cannot read static with mode exec",
266+
"cannot read static with mode exec",
267+
])
265268
}
266269

267270
test_verify_one_file! {
@@ -275,7 +278,10 @@ test_verify_one_file! {
275278
proof { let x = E; }
276279
0
277280
}
278-
} => Err(err) => assert_vir_error_msg(err, "cannot read const with mode exec")
281+
} => Err(err) => assert_vir_error_msgs(err, &[
282+
"cannot read const with mode exec",
283+
"cannot read const with mode exec",
284+
])
279285
}
280286

281287
test_verify_one_file! {

source/rust_verify_test/tests/modes.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,10 @@ test_verify_one_file! {
484484
}
485485
assert(e);
486486
}
487-
} => Err(err) => assert_vir_error_msg(err, "cannot mutate through a spec-mode mutable reference")
487+
} => Err(err) => assert_vir_error_msgs(err, &[
488+
"cannot mutate through a spec-mode mutable reference",
489+
"mutable borrow is not allowed in spec context",
490+
])
488491
}
489492

490493
test_verify_one_file! {

source/rust_verify_test/tests/mut_refs_modes.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1897,7 +1897,10 @@ test_verify_one_file_with_options! {
18971897
}
18981898
assert(u.u == 20);
18991899
}
1900-
} => Err(err) => assert_vir_error_msg(err, "cannot mutate exec-mode place in proof-code")
1900+
} => Err(err) => assert_vir_error_msgs(err, &[
1901+
"cannot mutate exec-mode place in proof-code",
1902+
"cannot mutate exec-mode place in proof-code",
1903+
])
19011904
}
19021905

19031906
test_verify_one_file_with_options! {

source/rust_verify_test/tests/mut_refs_old.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,10 @@ test_verify_one_file_with_options! {
374374
assert(*x == 0 && *old(x) == 5) by(nonlinear_arith)
375375
requires *x == 0 && *old(x) == 5;
376376
}
377-
} => Err(err) => assert_vir_error_msg(err, "`old` is not supported in `nonlinear_arith` assert")
377+
} => Err(err) => assert_vir_error_msgs(err, &[
378+
"`old` is not supported in `nonlinear_arith` assert",
379+
"`old` is not supported in `nonlinear_arith` assert",
380+
])
378381
}
379382

380383
test_verify_one_file_with_options! {

source/vir/src/modes.rs

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3630,11 +3630,24 @@ fn check_function(
36303630
function: &mut Function,
36313631
rtypes: &ResolutionTypes,
36323632
) -> Result<(), VirErr> {
3633-
// Reset this, we only need it per-function
3634-
record.type_inv_info = TypeInvInfo { ctor_needs_check: HashMap::new() };
3635-
record.var_modes = HashMap::new();
3636-
record.temporary_modes = HashMap::new();
3637-
record.mut_bor_place_modes = HashMap::new();
3633+
let Record {
3634+
// Global fields
3635+
erasure_modes: _,
3636+
// Per-function fields
3637+
type_inv_info,
3638+
read_kind_finals,
3639+
var_modes,
3640+
temporary_modes,
3641+
infer_spec_for_implicit_reborrows,
3642+
mut_bor_place_modes,
3643+
} = record;
3644+
// Reset the fields that are per-function
3645+
*type_inv_info = TypeInvInfo { ctor_needs_check: HashMap::new() };
3646+
*read_kind_finals = HashMap::new();
3647+
*var_modes = HashMap::new();
3648+
*temporary_modes = HashMap::new();
3649+
*infer_spec_for_implicit_reborrows = None;
3650+
*mut_bor_place_modes = HashMap::new();
36383651

36393652
let mut fun_typing = typing.push_var_scope();
36403653

@@ -3837,6 +3850,11 @@ fn check_function(
38373850
let mut body_typing = fun_typing.push_ret_mode(ret_mode);
38383851
let mut body_typing = body_typing.push_block_ghostness(Ghost::of_mode(function.x.mode));
38393852
let mut body_typing = body_typing.push_in_pure(pure_spec_fn);
3853+
let mut body_typing = if function.x.attrs.atomic {
3854+
body_typing.push_atomic_insts(Some(AtomicInstCollector::new()))
3855+
} else {
3856+
body_typing
3857+
};
38403858

38413859
assert!(record.infer_spec_for_implicit_reborrows.is_none());
38423860
record.infer_spec_for_implicit_reborrows = Some(HashMap::new());
@@ -3862,6 +3880,14 @@ fn check_function(
38623880
)?;
38633881
}
38643882

3883+
if function.x.attrs.atomic {
3884+
body_typing
3885+
.atomic_insts
3886+
.as_ref()
3887+
.expect("atomic_insts")
3888+
.validate(&function.span, ValidateCtx::AtomicFunction)?;
3889+
}
3890+
38653891
let borrow_spec = record.infer_spec_for_implicit_reborrows.as_ref().expect("borrow_spec");
38663892
if borrow_spec.len() > 0 {
38673893
let mut functionx = function.x.clone();
@@ -3948,7 +3974,7 @@ fn check_function(
39483974
Ok(())
39493975
}
39503976

3951-
pub fn check_crate(krate: &Krate) -> Result<(Krate, ErasureModes, ReadKindFinals), VirErr> {
3977+
pub fn check_crate(krate: &Krate) -> Result<(Krate, ErasureModes, ReadKindFinals), Vec<VirErr>> {
39523978
let mut funs: HashMap<Fun, Function> = HashMap::new();
39533979
let mut datatypes: HashMap<Path, Datatype> = HashMap::new();
39543980
for function in krate.functions.iter() {
@@ -3984,33 +4010,33 @@ pub fn check_crate(krate: &Krate) -> Result<(Krate, ErasureModes, ReadKindFinals
39844010
infer_spec_for_implicit_reborrows: None,
39854011
mut_bor_place_modes: HashMap::new(),
39864012
};
3987-
let mut state = State {
3988-
vars: ScopeMap::new(),
3989-
in_forall_stmt: false,
3990-
in_proof_in_spec: false,
3991-
block_ghostness: Ghost::Exec,
3992-
ret_mode: None,
3993-
atomic_insts: None,
3994-
in_pure: false,
3995-
in_assert_query: None,
3996-
};
3997-
let mut typing = Typing::new(&mut state);
4013+
39984014
let mut kratex = (**krate).clone();
39994015
let rtypes = ResolutionTypes::new(&ctxt.datatypes);
4016+
let mut errors = vec![];
40004017
for function in kratex.functions.iter_mut() {
40014018
ctxt.check_ghost_blocks = function.x.attrs.uses_ghost_blocks;
40024019
ctxt.fun_mode = function.x.mode;
4003-
if function.x.attrs.atomic {
4004-
let mut typing = typing.push_atomic_insts(Some(AtomicInstCollector::new()));
4005-
check_function(&ctxt, &mut record, &mut typing, function, &rtypes)?;
4006-
typing
4007-
.atomic_insts
4008-
.as_ref()
4009-
.expect("atomic_insts")
4010-
.validate(&function.span, ValidateCtx::AtomicFunction)?;
4011-
} else {
4012-
check_function(&ctxt, &mut record, &mut typing, function, &rtypes)?;
4020+
4021+
let mut state = State {
4022+
vars: ScopeMap::new(),
4023+
in_forall_stmt: false,
4024+
in_proof_in_spec: false,
4025+
block_ghostness: Ghost::Exec,
4026+
ret_mode: None,
4027+
atomic_insts: None,
4028+
in_pure: false,
4029+
in_assert_query: None,
4030+
};
4031+
let mut typing = Typing::new(&mut state);
4032+
4033+
if let Err(err) = check_function(&ctxt, &mut record, &mut typing, function, &rtypes) {
4034+
errors.push(err);
40134035
}
40144036
}
4015-
Ok((Arc::new(kratex), record.erasure_modes, record.read_kind_finals))
4037+
if errors.len() > 0 {
4038+
Err(errors)
4039+
} else {
4040+
Ok((Arc::new(kratex), record.erasure_modes, record.read_kind_finals))
4041+
}
40164042
}

0 commit comments

Comments
 (0)