Skip to content

Commit b25d74f

Browse files
authored
Rollup merge of rust-lang#62982 - oli-obk:static_cycle, r=RalfJung
Don't access a static just for its size and alignment cc @RalfJung fixes rust-lang#62189
2 parents a13f1f8 + 0cd7167 commit b25d74f

File tree

2 files changed

+52
-34
lines changed

2 files changed

+52
-34
lines changed

src/librustc_mir/interpret/memory.rs

+41-34
Original file line numberDiff line numberDiff line change
@@ -535,41 +535,48 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
535535
id: AllocId,
536536
liveness: AllocCheck,
537537
) -> InterpResult<'static, (Size, Align)> {
538-
// Regular allocations.
539-
if let Ok(alloc) = self.get(id) {
540-
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
541-
}
542-
// Function pointers.
543-
if let Ok(_) = self.get_fn_alloc(id) {
544-
return if let AllocCheck::Dereferencable = liveness {
545-
// The caller requested no function pointers.
546-
err!(DerefFunctionPointer)
547-
} else {
548-
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
549-
};
550-
}
551-
// Foreign statics.
552-
// Can't do this in the match argument, we may get cycle errors since the lock would
553-
// be held throughout the match.
554-
let alloc = self.tcx.alloc_map.lock().get(id);
555-
match alloc {
556-
Some(GlobalAlloc::Static(did)) => {
557-
assert!(self.tcx.is_foreign_item(did));
558-
// Use size and align of the type
559-
let ty = self.tcx.type_of(did);
560-
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
561-
return Ok((layout.size, layout.align.abi));
538+
// Don't use `self.get` here as that will
539+
// a) cause cycles in case `id` refers to a static
540+
// b) duplicate a static's allocation in miri
541+
match self.alloc_map.get_or(id, || Err(())) {
542+
Ok((_, alloc)) => Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
543+
Err(()) => {
544+
// Not a local allocation, check the global `tcx.alloc_map`.
545+
546+
// Can't do this in the match argument, we may get cycle errors since the lock would
547+
// be held throughout the match.
548+
let alloc = self.tcx.alloc_map.lock().get(id);
549+
match alloc {
550+
Some(GlobalAlloc::Static(did)) => {
551+
// Use size and align of the type.
552+
let ty = self.tcx.type_of(did);
553+
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
554+
Ok((layout.size, layout.align.abi))
555+
},
556+
Some(GlobalAlloc::Memory(alloc)) =>
557+
// Need to duplicate the logic here, because the global allocations have
558+
// different associated types than the interpreter-local ones.
559+
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
560+
Some(GlobalAlloc::Function(_)) => {
561+
if let AllocCheck::Dereferencable = liveness {
562+
// The caller requested no function pointers.
563+
err!(DerefFunctionPointer)
564+
} else {
565+
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
566+
}
567+
},
568+
// The rest must be dead.
569+
None => if let AllocCheck::MaybeDead = liveness {
570+
// Deallocated pointers are allowed, we should be able to find
571+
// them in the map.
572+
Ok(*self.dead_alloc_map.get(&id)
573+
.expect("deallocated pointers should all be recorded in \
574+
`dead_alloc_map`"))
575+
} else {
576+
err!(DanglingPointerDeref)
577+
},
578+
}
562579
}
563-
_ => {}
564-
}
565-
// The rest must be dead.
566-
if let AllocCheck::MaybeDead = liveness {
567-
// Deallocated pointers are allowed, we should be able to find
568-
// them in the map.
569-
Ok(*self.dead_alloc_map.get(&id)
570-
.expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
571-
} else {
572-
err!(DanglingPointerDeref)
573580
}
574581
}
575582

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
3+
struct Foo {
4+
foo: Option<&'static Foo>
5+
}
6+
7+
static FOO: Foo = Foo {
8+
foo: Some(&FOO),
9+
};
10+
11+
fn main() {}

0 commit comments

Comments
 (0)