about summary refs log tree commit diff
diff options
context:
space:
mode:
authorasquared31415 <34665709+asquared31415@users.noreply.github.com>2022-02-24 14:10:41 -0500
committerasquared31415 <34665709+asquared31415@users.noreply.github.com>2022-02-24 14:10:41 -0500
commit75b15c68f81094ad6f1da6f29bd42a1197585257 (patch)
tree680347d5833b71ea6315139c629900616b453d75
parent3d127e2040b57157936f5f24e114a8b4c9a505ef (diff)
downloadrust-75b15c68f81094ad6f1da6f29bd42a1197585257.tar.gz
rust-75b15c68f81094ad6f1da6f29bd42a1197585257.zip
don't ice when an extern static is too big
-rw-r--r--compiler/rustc_typeck/src/check/check.rs29
-rw-r--r--src/test/ui/extern/extern-static-size-overflow.rs43
-rw-r--r--src/test/ui/extern/extern-static-size-overflow.stderr20
3 files changed, 88 insertions, 4 deletions
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 30ae382de42..158c3e261b8 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -14,7 +14,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::layout::MAX_SIMD_LANES;
+use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, Ty, TyCtxt};
@@ -415,10 +415,31 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Spa
     // have UB during initialization if they are uninhabited, but there also seems to be no good
     // reason to allow any statics to be uninhabited.
     let ty = tcx.type_of(def_id);
-    let Ok(layout) = tcx.layout_of(ParamEnv::reveal_all().and(ty)) else {
+    let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
+        Ok(l) => l,
+        // Foreign statics that overflow their allowed size should emit an error
+        Err(LayoutError::SizeOverflow(_))
+            if {
+                let node = tcx.hir().get_by_def_id(def_id);
+                matches!(
+                    node,
+                    hir::Node::ForeignItem(hir::ForeignItem {
+                        kind: hir::ForeignItemKind::Static(..),
+                        ..
+                    })
+                )
+            } =>
+        {
+            tcx.sess
+                .struct_span_err(span, "extern static is too large for the current architecture")
+                .emit();
+            return;
+        }
         // Generic statics are rejected, but we still reach this case.
-        tcx.sess.delay_span_bug(span, "generic static must be rejected");
-        return;
+        Err(e) => {
+            tcx.sess.delay_span_bug(span, &e.to_string());
+            return;
+        }
     };
     if layout.abi.is_uninhabited() {
         tcx.struct_span_lint_hir(
diff --git a/src/test/ui/extern/extern-static-size-overflow.rs b/src/test/ui/extern/extern-static-size-overflow.rs
new file mode 100644
index 00000000000..30a0c445466
--- /dev/null
+++ b/src/test/ui/extern/extern-static-size-overflow.rs
@@ -0,0 +1,43 @@
+#[repr(C)]
+struct ReallyBig {
+    _a: [u8; usize::MAX],
+}
+
+// The limit for "too big for the current architecture" is dependent on the target pointer size
+// however it's artifically limited on 64 bits
+// logic copied from rustc_target::abi::TargetDataLayout::obj_size_bound()
+const fn max_size() -> usize {
+    #[cfg(target_pointer_width = "16")]
+    {
+        1 << 15
+    }
+
+    #[cfg(target_pointer_width = "32")]
+    {
+        1 << 31
+    }
+
+    #[cfg(target_pointer_width = "64")]
+    {
+        1 << 47
+    }
+
+    #[cfg(not(any(
+        target_pointer_width = "16",
+        target_pointer_width = "32",
+        target_pointer_width = "64"
+    )))]
+    {
+        isize::MAX as usize
+    }
+}
+
+extern "C" {
+    static FOO: [u8; 1];
+    static BAR: [u8; max_size() - 1];
+    static BAZ: [u8; max_size()]; //~ ERROR extern static is too large
+    static UWU: [usize; usize::MAX]; //~ ERROR extern static is too large
+    static A: ReallyBig; //~ ERROR extern static is too large
+}
+
+fn main() {}
diff --git a/src/test/ui/extern/extern-static-size-overflow.stderr b/src/test/ui/extern/extern-static-size-overflow.stderr
new file mode 100644
index 00000000000..f5173feec75
--- /dev/null
+++ b/src/test/ui/extern/extern-static-size-overflow.stderr
@@ -0,0 +1,20 @@
+error: extern static is too large for the current architecture
+  --> $DIR/extern-static-size-overflow.rs:38:5
+   |
+LL |     static BAZ: [u8; max_size()];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: extern static is too large for the current architecture
+  --> $DIR/extern-static-size-overflow.rs:39:5
+   |
+LL |     static UWU: [usize; usize::MAX];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: extern static is too large for the current architecture
+  --> $DIR/extern-static-size-overflow.rs:40:5
+   |
+LL |     static A: ReallyBig;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+