1
Fork 0

Allow panic!("{}", computed_str) in const fn.

This commit is contained in:
Gary Guo 2021-09-14 19:14:37 +01:00
parent c3c0f80d60
commit 11c0e58c74
14 changed files with 135 additions and 46 deletions

View file

@ -36,12 +36,17 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
let def_id = instance.def_id();
if Some(def_id) == self.tcx.lang_items().panic_fn()
|| Some(def_id) == self.tcx.lang_items().panic_str()
|| Some(def_id) == self.tcx.lang_items().panic_display()
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
{
// &str
// &str or &&str
assert!(args.len() == 1);
let msg_place = self.deref_operand(&args[0])?;
let mut msg_place = self.deref_operand(&args[0])?;
while msg_place.layout.ty.is_ref() {
msg_place = self.deref_operand(&msg_place.into())?;
}
let msg = Symbol::intern(self.read_str(&msg_place)?);
let span = self.find_closest_untracked_caller_location();
let (file, line, col) = self.location_triple_for_span(span);

View file

@ -888,6 +888,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
if is_lang_panic_fn(tcx, callee) {
self.check_op(ops::Panic);
// `begin_panic` and `panic_display` are generic functions that accept
// types other than str. Check to enforce that only str can be used in
// const-eval.
// const-eval of the `begin_panic` fn assumes the argument is `&str`
if Some(callee) == tcx.lang_items().begin_panic_fn() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
@ -896,6 +900,15 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
}
}
// const-eval of the `panic_display` fn assumes the argument is `&&str`
if Some(callee) == tcx.lang_items().panic_display() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
{}
_ => self.check_op(ops::PanicNonStr),
}
}
return;
}

View file

@ -79,6 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
// Keep in sync with what that function handles!
Some(def_id) == tcx.lang_items().panic_fn()
|| Some(def_id) == tcx.lang_items().panic_str()
|| Some(def_id) == tcx.lang_items().panic_display()
|| Some(def_id) == tcx.lang_items().begin_panic_fn()
|| Some(def_id) == tcx.lang_items().panic_fmt()
|| Some(def_id) == tcx.lang_items().begin_panic_fmt()