Skip to content

Commit fd57268

Browse files
committed
Auto merge of #63152 - estebank:big-array, r=<try>
Always error on `SizeOverflow` during mir evaluation Fix #55878, fix #25116. r? @oli-obk
2 parents 188ab5c + 613c0a8 commit fd57268

29 files changed

+166
-74
lines changed

src/librustc/mir/interpret/error.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -137,17 +137,17 @@ impl<'tcx> ConstEvalErr<'tcx> {
137137
message: &str,
138138
lint_root: Option<hir::HirId>,
139139
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
140-
match self.error {
140+
let must_error = match self.error {
141141
err_inval!(Layout(LayoutError::Unknown(_))) |
142142
err_inval!(TooGeneric) =>
143143
return Err(ErrorHandled::TooGeneric),
144-
err_inval!(Layout(LayoutError::SizeOverflow(_))) |
145144
err_inval!(TypeckError) =>
146145
return Err(ErrorHandled::Reported),
147-
_ => {},
148-
}
146+
err_inval!(Layout(LayoutError::SizeOverflow(_))) => true,
147+
_ => false,
148+
};
149149
trace!("reporting const eval failure at {:?}", self.span);
150-
let mut err = if let Some(lint_root) = lint_root {
150+
let mut err = if let (Some(lint_root), false) = (lint_root, must_error) {
151151
let hir_id = self.stacktrace
152152
.iter()
153153
.rev()
@@ -160,10 +160,14 @@ impl<'tcx> ConstEvalErr<'tcx> {
160160
tcx.span,
161161
message,
162162
)
163+
} else if must_error {
164+
struct_error(tcx, &self.error.to_string())
163165
} else {
164166
struct_error(tcx, message)
165167
};
166-
err.span_label(self.span, self.error.to_string());
168+
if !must_error {
169+
err.span_label(self.span, self.error.to_string());
170+
}
167171
// Skip the last, which is just the environment of the constant. The stacktrace
168172
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
169173
// on constant values.
@@ -335,7 +339,7 @@ impl fmt::Debug for InvalidProgramInfo<'tcx> {
335339
TypeckError =>
336340
write!(f, "encountered constants with type errors, stopping evaluation"),
337341
Layout(ref err) =>
338-
write!(f, "rustc layout computation failed: {:?}", err),
342+
write!(f, "{}", err),
339343
}
340344
}
341345
}

src/librustc_codegen_llvm/context.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use std::iter;
3030
use std::str;
3131
use std::sync::Arc;
3232
use syntax::symbol::LocalInternedString;
33+
use syntax::source_map::{DUMMY_SP, Span};
3334
use crate::abi::Abi;
3435

3536
/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
@@ -860,9 +861,13 @@ impl LayoutOf for CodegenCx<'ll, 'tcx> {
860861
type TyLayout = TyLayout<'tcx>;
861862

862863
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
864+
self.spanned_layout_of(ty, DUMMY_SP)
865+
}
866+
867+
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::TyLayout {
863868
self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty))
864869
.unwrap_or_else(|e| if let LayoutError::SizeOverflow(_) = e {
865-
self.sess().fatal(&e.to_string())
870+
self.sess().span_fatal(span, &e.to_string())
866871
} else {
867872
bug!("failed to get layout for `{}`: {}", ty, e)
868873
})

src/librustc_codegen_ssa/mir/analyze.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUs
99
use rustc::mir::traversal;
1010
use rustc::ty;
1111
use rustc::ty::layout::{LayoutOf, HasTyCtxt};
12+
use syntax_pos::DUMMY_SP;
1213
use super::FunctionCx;
1314
use crate::traits::*;
1415

@@ -20,10 +21,13 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
2021

2122
analyzer.visit_body(mir);
2223

23-
for (index, ty) in mir.local_decls.iter().map(|l| l.ty).enumerate() {
24+
for (index, (ty, span)) in mir.local_decls.iter()
25+
.map(|l| (l.ty, l.source_info.span))
26+
.enumerate()
27+
{
2428
let ty = fx.monomorphize(&ty);
2529
debug!("local {} has type {:?}", index, ty);
26-
let layout = fx.cx.layout_of(ty);
30+
let layout = fx.cx.spanned_layout_of(ty, span);
2731
if fx.cx.is_backend_immediate(layout) {
2832
// These sorts of types are immediates that we can store
2933
// in an Value without an alloca.
@@ -93,10 +97,12 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
9397
}
9498
}
9599

96-
fn process_place(&mut self,
97-
place_ref: &mir::PlaceRef<'_, 'tcx>,
98-
context: PlaceContext,
99-
location: Location) {
100+
fn process_place(
101+
&mut self,
102+
place_ref: &mir::PlaceRef<'_, 'tcx>,
103+
context: PlaceContext,
104+
location: Location,
105+
) {
100106
let cx = self.fx.cx;
101107

102108
if let Some(proj) = place_ref.projection {
@@ -116,12 +122,17 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
116122
.projection_ty(cx.tcx(), &proj.elem)
117123
.ty;
118124
let elem_ty = self.fx.monomorphize(&elem_ty);
119-
if cx.layout_of(elem_ty).is_zst() {
125+
let span = if let mir::PlaceBase::Local(index) = place_ref.base {
126+
self.fx.mir.local_decls[*index].source_info.span
127+
} else {
128+
DUMMY_SP
129+
};
130+
if cx.spanned_layout_of(elem_ty, span).is_zst() {
120131
return;
121132
}
122133

123134
if let mir::ProjectionElem::Field(..) = proj.elem {
124-
let layout = cx.layout_of(base_ty.ty);
135+
let layout = cx.spanned_layout_of(base_ty.ty, span);
125136
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
126137
// Recurse with the same context, instead of `Projection`,
127138
// potentially stopping at non-operand projections,
@@ -188,7 +199,8 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
188199
projection: None,
189200
} = *place {
190201
self.assign(index, location);
191-
if !self.fx.rvalue_creates_operand(rvalue) {
202+
let decl_span = self.fx.mir.local_decls[index].source_info.span;
203+
if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
192204
self.not_ssa(index);
193205
}
194206
} else {

src/librustc_codegen_ssa/mir/rvalue.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc::middle::lang_items::ExchangeMallocFnLangItem;
66
use rustc_apfloat::{ieee, Float, Status, Round};
77
use std::{u128, i128};
88
use syntax::symbol::sym;
9+
use syntax::source_map::{DUMMY_SP, Span};
910

1011
use crate::base;
1112
use crate::MemFlags;
@@ -136,7 +137,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
136137
}
137138

138139
_ => {
139-
assert!(self.rvalue_creates_operand(rvalue));
140+
assert!(self.rvalue_creates_operand(rvalue, DUMMY_SP));
140141
let (mut bx, temp) = self.codegen_rvalue_operand(bx, rvalue);
141142
temp.val.store(&mut bx, dest);
142143
bx
@@ -169,7 +170,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
169170
mut bx: Bx,
170171
rvalue: &mir::Rvalue<'tcx>
171172
) -> (Bx, OperandRef<'tcx, Bx::Value>) {
172-
assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue);
173+
assert!(
174+
self.rvalue_creates_operand(rvalue, DUMMY_SP),
175+
"cannot codegen {:?} to operand",
176+
rvalue,
177+
);
173178

174179
match *rvalue {
175180
mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => {
@@ -691,7 +696,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
691696
}
692697

693698
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
694-
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool {
699+
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool {
695700
match *rvalue {
696701
mir::Rvalue::Ref(..) |
697702
mir::Rvalue::Len(..) |
@@ -707,7 +712,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
707712
mir::Rvalue::Aggregate(..) => {
708713
let ty = rvalue.ty(self.mir, self.cx.tcx());
709714
let ty = self.monomorphize(&ty);
710-
self.cx.layout_of(ty).is_zst()
715+
self.cx.spanned_layout_of(ty, span).is_zst()
711716
}
712717
}
713718

src/librustc_mir/interpret/eval_context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
506506
pub fn push_stack_frame(
507507
&mut self,
508508
instance: ty::Instance<'tcx>,
509-
span: source_map::Span,
509+
span: Span,
510510
body: &'mir mir::Body<'tcx>,
511511
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
512512
return_to_block: StackPopCleanup,

src/librustc_target/abi/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
99
use rustc_data_structures::newtype_index;
1010
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
1111
use syntax_pos::symbol::{sym, Symbol};
12+
use syntax_pos::Span;
1213

1314
pub mod call;
1415

@@ -1012,6 +1013,9 @@ pub trait LayoutOf {
10121013
type TyLayout;
10131014

10141015
fn layout_of(&self, ty: Self::Ty) -> Self::TyLayout;
1016+
fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyLayout {
1017+
self.layout_of(ty)
1018+
}
10151019
}
10161020

10171021
#[derive(Copy, Clone, PartialEq, Eq)]
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// normalize-stderr-64bit "18446744073709551615" -> "SIZE"
2+
// normalize-stderr-32bit "4294967295" -> "SIZE"
3+
4+
// error-pattern: is too big for the current architecture
5+
fn main() {
6+
println!("Size: {}", std::mem::size_of::<[u8; std::u64::MAX as usize]>());
7+
}

src/test/ui/huge-array-simple-32.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// ignore-32bit
2+
3+
// FIXME https://github.com/rust-lang/rust/issues/59774
4+
// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
5+
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
6+
#![allow(exceeding_bitshifts)]
7+
8+
fn main() {
9+
let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the current architecture
10+
[0; (1u64<<61) as usize +(1u64<<31) as usize];
11+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: the type `[u8; 2305843011361177600]` is too big for the current architecture
2+
--> $DIR/huge-array-simple-32.rs:9:9
3+
|
4+
LL | let _fat: [u8; (1<<61)+(1<<31)] =
5+
| ^^^^
6+
7+
error: aborting due to previous error
8+

src/test/ui/huge-array-simple-64.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// ignore-64bit
2+
3+
// FIXME https://github.com/rust-lang/rust/issues/59774
4+
// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
5+
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
6+
#![allow(exceeding_bitshifts)]
7+
8+
fn main() {
9+
let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the current architecture
10+
[0; (1u32<<31) as usize +(1u32<<15) as usize];
11+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: the type `[u8; 2147516416]` is too big for the current architecture
2+
--> $DIR/huge-array-simple-64.rs:9:9
3+
|
4+
LL | let _fat: [u8; (1<<31)+(1<<15)] =
5+
| ^^^^
6+
7+
error: aborting due to previous error
8+

src/test/ui/huge-array-simple.rs

-20
This file was deleted.

src/test/ui/huge-array-simple.stderr

-4
This file was deleted.

src/test/ui/huge-array.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
// error-pattern:; 1518600000
2-
31
// FIXME https://github.com/rust-lang/rust/issues/59774
42
// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
53
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
64

75
fn generic<T: Copy>(t: T) {
86
let s: [T; 1518600000] = [t; 1518600000];
7+
//~^ ERROR the type `[[u8; 1518599999]; 1518600000]` is too big for the current architecture
98
}
109

1110
fn main() {

src/test/ui/huge-array.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
error: the type `[[u8; 1518599999]; 1518600000]` is too big for the current architecture
2+
--> $DIR/huge-array.rs:6:9
3+
|
4+
LL | let s: [T; 1518600000] = [t; 1518600000];
5+
| ^
26

37
error: aborting due to previous error
48

src/test/ui/huge-enum.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
77

88
#[cfg(target_pointer_width = "32")]
9-
fn main() {
10-
let big: Option<[u32; (1<<29)-1]> = None;
11-
}
9+
type BIG = Option<[u32; (1<<29)-1]>;
1210

1311
#[cfg(target_pointer_width = "64")]
12+
type BIG = Option<[u32; (1<<45)-1]>;
13+
1414
fn main() {
15-
let big: Option<[u32; (1<<45)-1]> = None;
15+
let big: BIG = None;
16+
//~^ ERROR is too big for the current architecture
1617
}

src/test/ui/huge-enum.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
error: the type `TYPE` is too big for the current architecture
2+
--> $DIR/huge-enum.rs:15:9
3+
|
4+
LL | let big: BIG = None;
5+
| ^^^
26

37
error: aborting due to previous error
48

src/test/ui/huge-struct.rs

+2
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,6 @@ struct S1M<T> { val: S1k<S1k<T>> }
4747

4848
fn main() {
4949
let fat: Option<S1M<S1M<S1M<u32>>>> = None;
50+
//~^ ERROR the type `S32<S1M<S1M<u32>>>` is too big for the current architecture
51+
5052
}

src/test/ui/huge-struct.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
error: the type `SXX<SXX<SXX<u32>>>` is too big for the current architecture
2+
--> $DIR/huge-struct.rs:49:9
3+
|
4+
LL | let fat: Option<SXX<SXX<SXX<u32>>>> = None;
5+
| ^^^
26

37
error: aborting due to previous error
48

src/test/ui/issues/issue-15919-32.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// ignore-64bit
2+
3+
// FIXME https://github.com/rust-lang/rust/issues/59774
4+
// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
5+
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
6+
7+
fn main() {
8+
let x = [0usize; 0xffff_ffff]; //~ ERROR too big
9+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: the type `[usize; 4294967295]` is too big for the current architecture
2+
--> $DIR/issue-15919-32.rs:8:9
3+
|
4+
LL | let x = [0usize; 0xffff_ffff];
5+
| ^
6+
7+
error: aborting due to previous error
8+

src/test/ui/issues/issue-15919-64.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// ignore-32bit
2+
3+
// FIXME https://github.com/rust-lang/rust/issues/59774
4+
// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
5+
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
6+
7+
fn main() {
8+
let x = [0usize; 0xffff_ffff_ffff_ffff]; //~ ERROR too big
9+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: the type `[usize; 18446744073709551615]` is too big for the current architecture
2+
--> $DIR/issue-15919-64.rs:8:9
3+
|
4+
LL | let x = [0usize; 0xffff_ffff_ffff_ffff];
5+
| ^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)