summary refs log tree commit diff
path: root/compiler/rustc_mir/src/transform
diff options
context:
space:
mode:
authorAustin Bonander <austin@launchbadge.com>2021-01-05 13:54:28 -0800
committerAustin Bonander <austin@launchbadge.com>2021-03-01 08:32:15 -0800
commit5a33f531cd87988e95a8e811d71b653a7ff9ffca (patch)
treebce9a1aa9f8927c8ef4b716018277c8300191842 /compiler/rustc_mir/src/transform
parentda305a2b00530aa34dea4e48389204c26fa35dbb (diff)
downloadrust-5a33f531cd87988e95a8e811d71b653a7ff9ffca.tar.gz
rust-5a33f531cd87988e95a8e811d71b653a7ff9ffca.zip
check that first arg to `panic!()` in const is `&str`
Diffstat (limited to 'compiler/rustc_mir/src/transform')
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs12
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs12
2 files changed, 22 insertions, 2 deletions
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index 9e90a7519cf..134b6d6fe07 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -360,6 +360,18 @@ impl NonConstOp for Panic {
     }
 }
 
+/// A call to a `panic()` lang item where the first argument is _not_ a `&str`.
+#[derive(Debug)]
+pub struct PanicNonStr;
+impl NonConstOp for PanicNonStr {
+    fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+        ccx.tcx.sess.struct_span_err(
+            span,
+            "argument to `panic!()` in a const context must have type `&str`",
+        )
+    }
+}
+
 #[derive(Debug)]
 pub struct RawPtrComparison;
 impl NonConstOp for RawPtrComparison {
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index d1c07d1051d..fea5dd3554f 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -796,7 +796,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
         self.super_terminator(terminator, location);
 
         match &terminator.kind {
-            TerminatorKind::Call { func, .. } => {
+            TerminatorKind::Call { func, args, .. } => {
                 let ConstCx { tcx, body, param_env, .. } = *self.ccx;
                 let caller = self.def_id().to_def_id();
 
@@ -857,9 +857,17 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 }
 
                 // At this point, we are calling a function, `callee`, whose `DefId` is known...
-
                 if is_lang_panic_fn(tcx, callee) {
                     self.check_op(ops::Panic);
+
+                    // 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() {
+                            ty::Ref(_, ty, _) if ty.is_str() => (),
+                            _ => self.check_op(ops::PanicNonStr),
+                        }
+                    }
+
                     return;
                 }