diff options
Diffstat (limited to 'compiler/rustc_const_eval/src')
3 files changed, 21 insertions, 2 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 8a90686b900..ae20f6f97b2 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -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); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index d5682f702ba..0e5a896a8f1 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -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; } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index a5cb0f4e14b..d1fd3ceaa58 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -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() |
