Skip to content

Commit 343d36b

Browse files
committed
Don't panic on layout errors
1 parent 52f2f8a commit 343d36b

File tree

2 files changed

+62
-57
lines changed

2 files changed

+62
-57
lines changed

src/librustc_mir/const_eval.rs

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,12 @@ pub fn const_eval_provider<'tcx>(
615615
ty::FnDef(_, substs) => substs,
616616
_ => bug!("intrinsic with type {:?}", ty),
617617
};
618-
return Ok(eval_nullary_intrinsic(tcx, key.param_env, def_id, substs));
618+
return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
619+
.map_err(|error| {
620+
let span = tcx.def_span(def_id);
621+
let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
622+
error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
623+
})
619624
}
620625

621626
tcx.const_eval_raw(key).and_then(|val| {
@@ -680,63 +685,63 @@ pub fn const_eval_raw_provider<'tcx>(
680685
})
681686
}).map_err(|error| {
682687
let err = error_to_const_error(&ecx, error);
683-
// errors in statics are always emitted as fatal errors
684-
if tcx.is_static(def_id) {
685-
// Ensure that if the above error was either `TooGeneric` or `Reported`
686-
// an error must be reported.
688+
// errors in statics are always emitted as fatal errors
689+
if tcx.is_static(def_id) {
690+
// Ensure that if the above error was either `TooGeneric` or `Reported`
691+
// an error must be reported.
687692
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
688-
tcx.sess.delay_span_bug(
689-
err.span,
690-
&format!("static eval failure did not emit an error: {:#?}", v)
691-
);
692-
v
693-
} else if def_id.is_local() {
694-
// constant defined in this crate, we can figure out a lint level!
695-
match tcx.def_kind(def_id) {
696-
// constants never produce a hard error at the definition site. Anything else is
697-
// a backwards compatibility hazard (and will break old versions of winapi for sure)
698-
//
699-
// note that validation may still cause a hard error on this very same constant,
700-
// because any code that existed before validation could not have failed validation
701-
// thus preventing such a hard error from being a backwards compatibility hazard
702-
Some(DefKind::Const) | Some(DefKind::AssocConst) => {
703-
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
693+
tcx.sess.delay_span_bug(
694+
err.span,
695+
&format!("static eval failure did not emit an error: {:#?}", v)
696+
);
697+
v
698+
} else if def_id.is_local() {
699+
// constant defined in this crate, we can figure out a lint level!
700+
match tcx.def_kind(def_id) {
701+
// constants never produce a hard error at the definition site. Anything else is
702+
// a backwards compatibility hazard (and will break old versions of winapi for sure)
703+
//
704+
// note that validation may still cause a hard error on this very same constant,
705+
// because any code that existed before validation could not have failed validation
706+
// thus preventing such a hard error from being a backwards compatibility hazard
707+
Some(DefKind::Const) | Some(DefKind::AssocConst) => {
708+
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
709+
err.report_as_lint(
710+
tcx.at(tcx.def_span(def_id)),
711+
"any use of this value will cause an error",
712+
hir_id,
713+
Some(err.span),
714+
)
715+
},
716+
// promoting runtime code is only allowed to error if it references broken constants
717+
// any other kind of error will be reported to the user as a deny-by-default lint
718+
_ => if let Some(p) = cid.promoted {
719+
let span = tcx.promoted_mir(def_id)[p].span;
720+
if let err_inval!(ReferencedConstant) = err.error {
721+
err.report_as_error(
722+
tcx.at(span),
723+
"evaluation of constant expression failed",
724+
)
725+
} else {
704726
err.report_as_lint(
705-
tcx.at(tcx.def_span(def_id)),
706-
"any use of this value will cause an error",
707-
hir_id,
727+
tcx.at(span),
728+
"reaching this expression at runtime will panic or abort",
729+
tcx.hir().as_local_hir_id(def_id).unwrap(),
708730
Some(err.span),
709731
)
710-
},
711-
// promoting runtime code is only allowed to error if it references broken constants
712-
// any other kind of error will be reported to the user as a deny-by-default lint
713-
_ => if let Some(p) = cid.promoted {
714-
let span = tcx.promoted_mir(def_id)[p].span;
715-
if let err_inval!(ReferencedConstant) = err.error {
716-
err.report_as_error(
717-
tcx.at(span),
718-
"evaluation of constant expression failed",
719-
)
720-
} else {
721-
err.report_as_lint(
722-
tcx.at(span),
723-
"reaching this expression at runtime will panic or abort",
724-
tcx.hir().as_local_hir_id(def_id).unwrap(),
725-
Some(err.span),
726-
)
727-
}
728-
// anything else (array lengths, enum initializers, constant patterns) are reported
729-
// as hard errors
730-
} else {
731-
err.report_as_error(
732+
}
733+
// anything else (array lengths, enum initializers, constant patterns) are reported
734+
// as hard errors
735+
} else {
736+
err.report_as_error(
732737
ecx.tcx,
733-
"evaluation of constant value failed",
734-
)
735-
},
736-
}
737-
} else {
738-
// use of broken constant from other crate
739-
err.report_as_error(ecx.tcx, "could not evaluate constant")
738+
"evaluation of constant value failed",
739+
)
740+
},
740741
}
742+
} else {
743+
// use of broken constant from other crate
744+
err.report_as_error(ecx.tcx, "could not evaluate constant")
745+
}
741746
})
742747
}

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ crate fn eval_nullary_intrinsic<'tcx>(
4545
param_env: ty::ParamEnv<'tcx>,
4646
def_id: DefId,
4747
substs: SubstsRef<'tcx>,
48-
) -> &'tcx ty::Const<'tcx> {
48+
) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
4949
let tp_ty = substs.type_at(0);
5050
let name = &*tcx.item_name(def_id).as_str();
51-
match name {
51+
Ok(match name {
5252
"type_name" => {
5353
let alloc = type_name::alloc_type_name(tcx, tp_ty);
5454
tcx.mk_const(ty::Const {
@@ -64,7 +64,7 @@ crate fn eval_nullary_intrinsic<'tcx>(
6464
"size_of" |
6565
"min_align_of" |
6666
"pref_align_of" => {
67-
let layout = tcx.layout_of(param_env.and(tp_ty)).unwrap();
67+
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
6868
let n = match name {
6969
"pref_align_of" => layout.align.pref.bytes(),
7070
"min_align_of" => layout.align.abi.bytes(),
@@ -79,7 +79,7 @@ crate fn eval_nullary_intrinsic<'tcx>(
7979
param_env.and(tcx.types.u64),
8080
),
8181
other => bug!("`{}` is not a zero arg intrinsic", other),
82-
}
82+
})
8383
}
8484

8585
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {

0 commit comments

Comments
 (0)