don't ice when an extern static is too big

This commit is contained in:
asquared31415 2022-02-24 14:10:41 -05:00
parent 3d127e2040
commit 75b15c68f8
3 changed files with 88 additions and 4 deletions

View File

@ -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(

View File

@ -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() {}

View File

@ -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