Skip to content

Commit 75b15c6

Browse files
committed
don't ice when an extern static is too big
1 parent 3d127e2 commit 75b15c6

File tree

3 files changed

+88
-4
lines changed

3 files changed

+88
-4
lines changed

Diff for: compiler/rustc_typeck/src/check/check.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
1414
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1515
use rustc_middle::hir::nested_filter;
1616
use rustc_middle::ty::fold::TypeFoldable;
17-
use rustc_middle::ty::layout::MAX_SIMD_LANES;
17+
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
1818
use rustc_middle::ty::subst::GenericArgKind;
1919
use rustc_middle::ty::util::{Discr, IntTypeExt};
2020
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
415415
// have UB during initialization if they are uninhabited, but there also seems to be no good
416416
// reason to allow any statics to be uninhabited.
417417
let ty = tcx.type_of(def_id);
418-
let Ok(layout) = tcx.layout_of(ParamEnv::reveal_all().and(ty)) else {
418+
let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
419+
Ok(l) => l,
420+
// Foreign statics that overflow their allowed size should emit an error
421+
Err(LayoutError::SizeOverflow(_))
422+
if {
423+
let node = tcx.hir().get_by_def_id(def_id);
424+
matches!(
425+
node,
426+
hir::Node::ForeignItem(hir::ForeignItem {
427+
kind: hir::ForeignItemKind::Static(..),
428+
..
429+
})
430+
)
431+
} =>
432+
{
433+
tcx.sess
434+
.struct_span_err(span, "extern static is too large for the current architecture")
435+
.emit();
436+
return;
437+
}
419438
// Generic statics are rejected, but we still reach this case.
420-
tcx.sess.delay_span_bug(span, "generic static must be rejected");
421-
return;
439+
Err(e) => {
440+
tcx.sess.delay_span_bug(span, &e.to_string());
441+
return;
442+
}
422443
};
423444
if layout.abi.is_uninhabited() {
424445
tcx.struct_span_lint_hir(

Diff for: src/test/ui/extern/extern-static-size-overflow.rs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#[repr(C)]
2+
struct ReallyBig {
3+
_a: [u8; usize::MAX],
4+
}
5+
6+
// The limit for "too big for the current architecture" is dependent on the target pointer size
7+
// however it's artifically limited on 64 bits
8+
// logic copied from rustc_target::abi::TargetDataLayout::obj_size_bound()
9+
const fn max_size() -> usize {
10+
#[cfg(target_pointer_width = "16")]
11+
{
12+
1 << 15
13+
}
14+
15+
#[cfg(target_pointer_width = "32")]
16+
{
17+
1 << 31
18+
}
19+
20+
#[cfg(target_pointer_width = "64")]
21+
{
22+
1 << 47
23+
}
24+
25+
#[cfg(not(any(
26+
target_pointer_width = "16",
27+
target_pointer_width = "32",
28+
target_pointer_width = "64"
29+
)))]
30+
{
31+
isize::MAX as usize
32+
}
33+
}
34+
35+
extern "C" {
36+
static FOO: [u8; 1];
37+
static BAR: [u8; max_size() - 1];
38+
static BAZ: [u8; max_size()]; //~ ERROR extern static is too large
39+
static UWU: [usize; usize::MAX]; //~ ERROR extern static is too large
40+
static A: ReallyBig; //~ ERROR extern static is too large
41+
}
42+
43+
fn main() {}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: extern static is too large for the current architecture
2+
--> $DIR/extern-static-size-overflow.rs:38:5
3+
|
4+
LL | static BAZ: [u8; max_size()];
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: extern static is too large for the current architecture
8+
--> $DIR/extern-static-size-overflow.rs:39:5
9+
|
10+
LL | static UWU: [usize; usize::MAX];
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: extern static is too large for the current architecture
14+
--> $DIR/extern-static-size-overflow.rs:40:5
15+
|
16+
LL | static A: ReallyBig;
17+
| ^^^^^^^^^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
20+

0 commit comments

Comments
 (0)