Skip to content

Commit 2a1d367

Browse files
committed
fix array access after mutslice
1 parent 86b9cc6 commit 2a1d367

2 files changed

Lines changed: 53 additions & 9 deletions

File tree

‎prusti-encoder/src/encoders/mir_builtin.rs‎

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -275,16 +275,48 @@ impl MirBuiltinEnc {
275275
}
276276

277277
match dst_ty_inner.kind() {
278-
ty::TyKind::Slice(_) => {
278+
ty::TyKind::Slice(elem_ty) => {
279279
let src_value = match &src_ref_pure.specifics {
280280
TySpecifics::ImmRef(data) => data.value_access(snap_src.downcast_ty()),
281-
TySpecifics::MutRef(data) => data.value_access(snap_src.downcast_ty()),
281+
TySpecifics::MutRef(data) => {
282+
let normalized = src_ty
283+
.ty
284+
.expect_mutref()
285+
.decompose_compare_normalize(src_ty.ty.params, src_ty.args);
286+
let caster = deps
287+
.require_dep::<crate::GArgsCastEnc<crate::Pure>>(normalized)
288+
.unwrap();
289+
let ty_task_param = src_ty
290+
.ty
291+
.expect_mutref()
292+
.decompose_context(src_ty.ty.params, src_ty.args);
293+
let src_param_impure = deps.require_dep::<TyUseImpureEnc>(ty_task_param)?;
294+
caster.cast_to_caller_ctx(
295+
src_param_impure.ref_to_snap(data.deref_access(snap_src.downcast_ty())),
296+
)
297+
}
282298
_ => unreachable!(),
283299
}
284300
.downcast_ty();
285301
let dst_value = match &dst_ref_pure.specifics {
286302
TySpecifics::ImmRef(data) => data.value_access(snap_dst.downcast_ty()),
287-
TySpecifics::MutRef(data) => data.value_access(snap_dst.downcast_ty()),
303+
TySpecifics::MutRef(data) => {
304+
let normalized = dst_ty
305+
.ty
306+
.expect_mutref()
307+
.decompose_compare_normalize(dst_ty.ty.params, dst_ty.args);
308+
let caster = deps
309+
.require_dep::<crate::GArgsCastEnc<crate::Pure>>(normalized)
310+
.unwrap();
311+
let ty_task_param = dst_ty
312+
.ty
313+
.expect_mutref()
314+
.decompose_context(src_ty.ty.params, dst_ty.args);
315+
let dst_param_impure = deps.require_dep::<TyUseImpureEnc>(ty_task_param)?;
316+
caster.cast_to_caller_ctx(
317+
dst_param_impure.ref_to_snap(data.deref_access(snap_dst.downcast_ty())),
318+
)
319+
}
288320
_ => unreachable!(),
289321
}
290322
.downcast_ty();
@@ -312,11 +344,23 @@ impl MirBuiltinEnc {
312344
== (old([src_array_pure.index(src_value, idx)]))
313345
},
314346
]);
315-
posts_undo.push(vir::expr! {
316-
forall idx: Int :: {[src_array_pure.index(src_value, idx)]}
317-
([src_array_pure.index(src_value, idx)])
318-
== (old([dst_array_pure.index(dst_value, idx)]))
319-
});
347+
348+
let elem_ty_task = RustTyDecomposition::from_ty(*elem_ty, params);
349+
let elem_pure = deps.require_dep::<TyUsePureEnc>(elem_ty_task)?;
350+
posts_undo.extend(&[
351+
vir::expr! {
352+
forall idx: Int :: {[src_array_pure.index(src_value, idx)]}
353+
([src_array_pure.index(src_value, idx)])
354+
== (old([dst_array_pure.index(dst_value, idx)]))
355+
},
356+
// TODO: this is very hacky! we let-bind an array access to
357+
// make sure the quantifier is triggered at least once
358+
vcx.mk_let_expr(
359+
vcx.mk_local_decl("_trigger_hack", elem_pure.snapshot),
360+
src_array_pure.index(src_value, vcx.mk_int::<0>()),
361+
vcx.mk_bool::<true>(),
362+
),
363+
]);
320364
}
321365
_ => {
322366
return Err(EncodeFullError::EncodingError(

‎prusti-tests/tests/v2/pass/arrays_slices.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn test5() {
2828
test5_2(x);
2929
}
3030

31-
//#[requires(x[1] == 3)]
31+
#[requires(x[1] == 3)]
3232
fn test5_2(x: [i32; 3]) {}
3333

3434
fn main() {

0 commit comments

Comments
 (0)