more targeted errors when extern types end up in places they should not
This commit is contained in:
parent
0908f173fd
commit
5a20bac6b3
@ -489,6 +489,15 @@ fn atomic_load(
|
|||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
|
fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
|
||||||
|
if place.layout.is_unsized() {
|
||||||
|
let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {});
|
||||||
|
if matches!(tail.kind(), ty::Foreign(..)) {
|
||||||
|
// Unsized locals and, at least conceptually, even unsized arguments must be copied
|
||||||
|
// around, which requires dynamically determining their size. Therefore, we cannot
|
||||||
|
// allow `extern` types here. Consult t-opsem before removing this check.
|
||||||
|
panic!("unsized locals must not be `extern` types");
|
||||||
|
}
|
||||||
|
}
|
||||||
assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
|
assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
|
||||||
|
|
||||||
if place.layout.is_zst() {
|
if place.layout.is_zst() {
|
||||||
|
@ -414,6 +414,7 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
|||||||
// value is through `undef`/`poison`, and the store itself is useless.
|
// value is through `undef`/`poison`, and the store itself is useless.
|
||||||
}
|
}
|
||||||
OperandValue::Ref(r, None, source_align) => {
|
OperandValue::Ref(r, None, source_align) => {
|
||||||
|
assert!(dest.layout.is_sized(), "cannot directly store unsized values");
|
||||||
if flags.contains(MemFlags::NONTEMPORAL) {
|
if flags.contains(MemFlags::NONTEMPORAL) {
|
||||||
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
||||||
let ty = bx.backend_type(dest.layout);
|
let ty = bx.backend_type(dest.layout);
|
||||||
|
@ -424,11 +424,23 @@ fn fn_arg_sanity_check<'tcx>(
|
|||||||
}
|
}
|
||||||
PassMode::Indirect { meta_attrs: None, .. } => {
|
PassMode::Indirect { meta_attrs: None, .. } => {
|
||||||
// No metadata, must be sized.
|
// No metadata, must be sized.
|
||||||
|
// Conceptually, unsized arguments must be copied around, which requires dynamically
|
||||||
|
// determining their size, which we cannot do without metadata. Consult
|
||||||
|
// t-opsem before removing this check.
|
||||||
assert!(arg.layout.is_sized());
|
assert!(arg.layout.is_sized());
|
||||||
}
|
}
|
||||||
PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => {
|
PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => {
|
||||||
// With metadata. Must be unsized and not on the stack.
|
// With metadata. Must be unsized and not on the stack.
|
||||||
assert!(arg.layout.is_unsized() && !on_stack);
|
assert!(arg.layout.is_unsized() && !on_stack);
|
||||||
|
// Also, must not be `extern` type.
|
||||||
|
let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {});
|
||||||
|
if matches!(tail.kind(), ty::Foreign(..)) {
|
||||||
|
// These types do not have metadata, so having `meta_attrs` is bogus.
|
||||||
|
// Conceptually, unsized arguments must be copied around, which requires dynamically
|
||||||
|
// determining their size. Therefore, we cannot allow `extern` types here. Consult
|
||||||
|
// t-opsem before removing this check.
|
||||||
|
panic!("unsized arguments must not be `extern` types");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user