Skip to content

fix ICE when promoted has layout size overflow #133704

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions compiler/rustc_const_eval/src/const_eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,29 +139,36 @@ where
match error {
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
// should remain silent.
err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span),
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
ErrorHandled::TooGeneric(span)
}
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span),
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span)
// This can occur in infallible promoteds e.g. when a non-existent type or field is
// encountered.
ErrorHandled::Reported(ReportedErrorInfo::allowed_in_infallible(guar), span)
}
// Report remaining errors.
_ => {
let (our_span, frames) = get_span_and_frames();
let span = span.substitute_dummy(our_span);
let err = mk(span, frames);
let mut err = tcx.dcx().create_err(err);
let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_));
// We allow invalid programs in infallible promoteds since invalid layouts can occur
// anyway (e.g. due to size overflow). And we allow OOM as that can happen any time.
let allowed_in_infallible = matches!(
error,
InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
);

let msg = error.diagnostic_message();
error.add_args(&mut err);

// Use *our* span to label the interp error
err.span_label(our_span, msg);
let g = err.emit();
let reported = if can_be_spurious {
ReportedErrorInfo::spurious(g)
let reported = if allowed_in_infallible {
ReportedErrorInfo::allowed_in_infallible(g)
} else {
ReportedErrorInfo::from(g)
};
Expand Down
11 changes: 4 additions & 7 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
};
// do not continue if typeck errors occurred (can only occur in local crate)
if let Some(err) = body.tainted_by_errors {
throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err)));
throw_inval!(AlreadyReported(ReportedErrorInfo::from(err)));
}
interp_ok(body)
}
Expand Down Expand Up @@ -585,13 +585,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
match err {
ErrorHandled::TooGeneric(..) => {},
ErrorHandled::Reported(reported, span) => {
if reported.is_tainted_by_errors() {
// const-eval will return "tainted" errors if e.g. the layout cannot
// be computed as the type references non-existing names.
// See <https://github.com/rust-lang/rust/issues/124348>.
} else if reported.can_be_spurious() {
if reported.is_allowed_in_infallible() {
// These errors can just sometimes happen, even when the expression
// is nominally "infallible", e.g. when running out of memory.
// is nominally "infallible", e.g. when running out of memory
// or when some layout could not be computed.
} else {
// Looks like the const is not captured by `required_consts`, that's bad.
span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts");
Expand Down
26 changes: 9 additions & 17 deletions compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl ErrorHandled {
pub fn emit_note(&self, tcx: TyCtxt<'_>) {
match self {
&ErrorHandled::Reported(err, span) => {
if !err.is_tainted_by_errors && !span.is_dummy() {
if !err.allowed_in_infallible && !span.is_dummy() {
tcx.dcx().emit_note(error::ErroneousConstant { span });
}
}
Expand All @@ -58,34 +58,26 @@ impl ErrorHandled {
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
pub struct ReportedErrorInfo {
error: ErrorGuaranteed,
is_tainted_by_errors: bool,
/// Whether this is the kind of error that can sometimes occur, and sometimes not.
/// Used for resource exhaustion errors.
can_be_spurious: bool,
/// Whether this error is allowed to show up even in otherwise "infallible" promoteds.
/// This is for things like overflows during size computation or resource exhaustion.
allowed_in_infallible: bool,
}

impl ReportedErrorInfo {
#[inline]
pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error }
}
#[inline]
pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo {
ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error }
pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo {
ReportedErrorInfo { allowed_in_infallible: true, error }
}

pub fn is_tainted_by_errors(&self) -> bool {
self.is_tainted_by_errors
}
pub fn can_be_spurious(&self) -> bool {
self.can_be_spurious
pub fn is_allowed_in_infallible(&self) -> bool {
self.allowed_in_infallible
}
}

impl From<ErrorGuaranteed> for ReportedErrorInfo {
#[inline]
fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error }
ReportedErrorInfo { allowed_in_infallible: false, error }
}
}

Expand Down
4 changes: 0 additions & 4 deletions tests/crashes/125476.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|

note: erroneous constant encountered
--> $DIR/unevaluated-const-ice-119731.rs:22:19
|
LL | impl v17<512, v0> {
| ^^

note: erroneous constant encountered
--> $DIR/unevaluated-const-ice-119731.rs:22:19
|
LL | impl v17<512, v0> {
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:28:37
|
Expand Down
60 changes: 60 additions & 0 deletions tests/ui/consts/const-integer-bool-ops.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ error[E0308]: mismatched types
LL | const X: usize = 42 && 39;
| ^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:8:18
|
LL | const ARR: [i32; X] = [99; 34];
| ^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:10:19
|
Expand All @@ -34,6 +40,12 @@ error[E0308]: mismatched types
LL | const X1: usize = 42 || 39;
| ^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:17:19
|
LL | const ARR1: [i32; X1] = [99; 47];
| ^^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:19:19
|
Expand All @@ -52,6 +64,12 @@ error[E0308]: mismatched types
LL | const X2: usize = -42 || -39;
| ^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:26:19
|
LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
| ^^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:28:19
|
Expand All @@ -70,42 +88,84 @@ error[E0308]: mismatched types
LL | const X3: usize = -42 && -39;
| ^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:35:19
|
LL | const ARR3: [i32; X3] = [99; 6];
| ^^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:37:18
|
LL | const Y: usize = 42.0 == 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:40:19
|
LL | const ARRR: [i32; Y] = [99; 1];
| ^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:42:19
|
LL | const Y1: usize = 42.0 >= 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:45:20
|
LL | const ARRR1: [i32; Y1] = [99; 1];
| ^^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:47:19
|
LL | const Y2: usize = 42.0 <= 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:50:20
|
LL | const ARRR2: [i32; Y2] = [99; 1];
| ^^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:52:19
|
LL | const Y3: usize = 42.0 > 42.0;
| ^^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:55:20
|
LL | const ARRR3: [i32; Y3] = [99; 0];
| ^^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:57:19
|
LL | const Y4: usize = 42.0 < 42.0;
| ^^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:60:20
|
LL | const ARRR4: [i32; Y4] = [99; 0];
| ^^

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:62:19
|
LL | const Y5: usize = 42.0 != 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

note: erroneous constant encountered
--> $DIR/const-integer-bool-ops.rs:65:20
|
LL | const ARRR5: [i32; Y5] = [99; 0];
| ^^

error: aborting due to 18 previous errors

For more information about this error, try `rustc --explain E0308`.
6 changes: 6 additions & 0 deletions tests/ui/consts/const-mut-refs/issue-76510.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ error[E0764]: mutable references are not allowed in the final value of constants
LL | const S: &'static mut str = &mut " hello ";
| ^^^^^^^^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-76510.rs:7:70
|
LL | let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
| ^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0764`.
6 changes: 6 additions & 0 deletions tests/ui/consts/const-tup-index-span.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ help: use a trailing comma to create a tuple with one element
LL | const TUP: (usize,) = (5usize << 64,);
| + ++

note: erroneous constant encountered
--> $DIR/const-tup-index-span.rs:6:18
|
LL | const ARR: [i32; TUP.0] = [];
| ^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
18 changes: 18 additions & 0 deletions tests/ui/consts/issue-54954.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,24 @@ LL | | core::mem::size_of::<T>()
LL | | }
| |_____- `Tt::const_val` defined here

note: erroneous constant encountered
--> $DIR/issue-54954.rs:11:15
|
LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
| ^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-54954.rs:11:34
|
LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
| ^^^^^^^

note: erroneous constant encountered
--> $DIR/issue-54954.rs:16:22
|
LL | let _ = f([1f32; ARR_LEN]);
| ^^^^^^^

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0379, E0790.
Expand Down
6 changes: 6 additions & 0 deletions tests/ui/consts/missing_assoc_const_type2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@ error: missing type for `const` item
LL | const FIRST: = 10;
| ^ help: provide a type for the associated constant: `u8`

note: erroneous constant encountered
--> $DIR/missing_assoc_const_type2.rs:18:5
|
LL | TwoDigits::FIRST as usize
| ^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ error[E0080]: evaluation of constant value failed
LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
| ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler

note: erroneous constant encountered
--> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:26
|
LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0080`.
7 changes: 7 additions & 0 deletions tests/ui/consts/promoted_size_overflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//@ only-64bit
pub struct Data([u8; usize::MAX >> 2]);
const _: &'static [Data] = &[];
//~^ERROR: evaluation of constant value failed
//~| too big for the target architecture

fn main() {}
9 changes: 9 additions & 0 deletions tests/ui/consts/promoted_size_overflow.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0080]: evaluation of constant value failed
--> $DIR/promoted_size_overflow.rs:3:29
|
LL | const _: &'static [Data] = &[];
| ^^ values of the type `[u8; 4611686018427387903]` are too big for the target architecture

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0080`.
6 changes: 3 additions & 3 deletions tests/ui/consts/uninhabited-const-issue-61744.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ pub const unsafe fn fake_type<T>() -> T {
}

pub const unsafe fn hint_unreachable() -> ! {
fake_type()
fake_type() //~ inside
}

trait Const {
const CONSTANT: i32 = unsafe { fake_type() };
const CONSTANT: i32 = unsafe { fake_type() }; //~ inside
}

impl<T> Const for T {}

pub fn main() -> () {
dbg!(i32::CONSTANT); //~ constant
dbg!(i32::CONSTANT);
}
Loading
Loading