Skip to content

Commit fff7516

Browse files
committed
Auto merge of #114483 - RalfJung:unsized-fields, r=oli-obk
interpret: fix projecting into an unsized field of a local See the new Miri testcase that didn't work before. r? `@oli-obk`
2 parents 115b4dd + 3f7164d commit fff7516

File tree

5 files changed

+37
-16
lines changed

5 files changed

+37
-16
lines changed

src/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ pub fn report_error<'tcx, 'mir>(
283283
"resource exhaustion",
284284
Unsupported(
285285
// We list only the ones that can actually happen.
286-
UnsupportedOpInfo::Unsupported(_)
286+
UnsupportedOpInfo::Unsupported(_) | UnsupportedOpInfo::UnsizedLocal
287287
) =>
288288
"unsupported operation",
289289
InvalidProgram(

src/helpers.rs

+10-13
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::mir;
1414
use rustc_middle::ty::{
1515
self,
1616
layout::{IntegerExt as _, LayoutOf, TyAndLayout},
17-
List, Ty, TyCtxt,
17+
Ty, TyCtxt,
1818
};
1919
use rustc_span::{def_id::CrateNum, sym, Span, Symbol};
2020
use rustc_target::abi::{Align, FieldIdx, FieldsShape, Integer, Size, Variants};
@@ -282,13 +282,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
282282
Ok(ptr.addr().bytes() == 0)
283283
}
284284

285-
/// Get the `Place` for a local
286-
fn local_place(&self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Provenance>> {
287-
let this = self.eval_context_ref();
288-
let place = mir::Place { local, projection: List::empty() };
289-
this.eval_place(place)
290-
}
291-
292285
/// Generate some random bytes, and write them to `dest`.
293286
fn gen_random(&mut self, ptr: Pointer<Option<Provenance>>, len: u64) -> InterpResult<'tcx> {
294287
// Some programs pass in a null pointer and a length of 0
@@ -350,17 +343,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
350343
// Initialize arguments.
351344
let mut callee_args = this.frame().body.args_iter();
352345
for arg in args {
353-
let callee_arg = this.local_place(
354-
callee_args
355-
.next()
356-
.ok_or_else(|| err_ub_format!("callee has fewer arguments than expected"))?,
357-
)?;
346+
let local = callee_args
347+
.next()
348+
.ok_or_else(|| err_ub_format!("callee has fewer arguments than expected"))?;
349+
// Make the local live, and insert the initial value.
350+
this.storage_live(local)?;
351+
let callee_arg = this.local_to_place(this.frame_idx(), local)?;
358352
this.write_immediate(*arg, &callee_arg)?;
359353
}
360354
if callee_args.next().is_some() {
361355
throw_ub_format!("callee has more arguments than expected");
362356
}
363357

358+
// Initialize remaining locals.
359+
this.storage_live_for_always_live_locals()?;
360+
364361
Ok(())
365362
}
366363

tests/fail/type-too-large.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ignore-32bit
22

33
fn main() {
4-
let _fat: [u8; (1 << 61) + (1 << 31)];
4+
let _fat: [u8; (1 << 61) + (1 << 31)]; // ideally we'd error here, but we avoid computing the layout until absolutely necessary
55
_fat = [0; (1u64 << 61) as usize + (1u64 << 31) as usize]; //~ ERROR: post-monomorphization error
66
}

tests/fail/unsized-local.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: unsupported operation: unsized locals are not supported
22
--> $DIR/unsized-local.rs:LL:CC
33
|
44
LL | let x = *(Box::new(A) as Box<dyn Foo>);
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsized locals are not supported
5+
| ^ unsized locals are not supported
66
|
77
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
88
= note: BACKTRACE:

tests/pass/unsized.rs

+24
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//@[tree]compile-flags: -Zmiri-tree-borrows
33
#![feature(unsized_tuple_coercion)]
44
#![feature(unsized_fn_params)]
5+
#![feature(custom_mir, core_intrinsics)]
56

67
use std::mem;
78

@@ -32,7 +33,30 @@ fn unsized_params() {
3233
f3(*p);
3334
}
3435

36+
fn unsized_field_projection() {
37+
use std::intrinsics::mir::*;
38+
39+
pub struct S<T: ?Sized>(T);
40+
41+
#[custom_mir(dialect = "runtime", phase = "optimized")]
42+
fn f(x: S<[u8]>) {
43+
mir! {
44+
{
45+
let idx = 0;
46+
// Project to an unsized field of an unsized local.
47+
x.0[idx] = 0;
48+
let _val = x.0[idx];
49+
Return()
50+
}
51+
}
52+
}
53+
54+
let x: Box<S<[u8]>> = Box::new(S([0]));
55+
f(*x);
56+
}
57+
3558
fn main() {
3659
unsized_tuple();
3760
unsized_params();
61+
unsized_field_projection();
3862
}

0 commit comments

Comments
 (0)