about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Maeda <takoyaki0316@gmail.com>2023-12-04 21:19:44 +0900
committerGitHub <noreply@github.com>2023-12-04 21:19:44 +0900
commitda2fb8109e31fee7e858c6a7c3ce9255a035175c (patch)
treea90fb8ba307f2f864a8fe1137b0c47a7396ca5fb
parent87625dbf2b233be1105524d418a9628fc71adeef (diff)
parent5a20bac6b3ff61acc3cd68bed0eb3fa598181f17 (diff)
downloadrust-da2fb8109e31fee7e858c6a7c3ce9255a035175c.tar.gz
rust-da2fb8109e31fee7e858c6a7c3ce9255a035175c.zip
Rollup merge of #118551 - RalfJung:extern-types-bugs, r=compiler-errors
more targeted errors when extern types end up in places they should not

Cc https://github.com/rust-lang/rust/issues/115709 -- this does not fix that bug but it makes the panics less obscure and makes it more clear that this is a deeper issue than just a little codegen oversight. (In https://github.com/rust-lang/rust/pull/116115 we decided we'd stick to causing ICEs here for now, rather than nicer errors. We can't currently show any errors pre-mono and probably we don't want post-mono checks when this gets stabilized anyway.)
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs1
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs12
3 files changed, 22 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 7b259055d40..acd85dd9a2d 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -489,6 +489,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     #[instrument(level = "trace", skip(self))]
     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());
 
         if place.layout.is_zst() {
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 0ab2b7ecd9c..6661f1f81e6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -414,6 +414,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
                 // value is through `undef`/`poison`, and the store itself is useless.
             }
             OperandValue::Ref(r, None, source_align) => {
+                assert!(dest.layout.is_sized(), "cannot directly store unsized values");
                 if flags.contains(MemFlags::NONTEMPORAL) {
                     // HACK(nox): This is inefficient but there is no nontemporal memcpy.
                     let ty = bx.backend_type(dest.layout);
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index c6ff7e2a9ef..b28e3d5c412 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -424,11 +424,23 @@ fn fn_abi_sanity_check<'tcx>(
             }
             PassMode::Indirect { meta_attrs: None, .. } => {
                 // 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());
             }
             PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => {
                 // With metadata. Must be unsized and not on the 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");
+                }
             }
         }
     }