1
Fork 0

fix ICE when promoted has layout size overflow

This commit is contained in:
Ralf Jung 2024-12-01 14:47:10 +01:00
parent 6c76ed5503
commit a17294dc0f
25 changed files with 218 additions and 79 deletions

View file

@ -139,12 +139,14 @@ 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.
_ => {
@ -152,7 +154,12 @@ where
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);
@ -160,8 +167,8 @@ where
// 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)
};

View file

@ -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)
}
@ -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");