Rollup merge of #80734 - abonander:ab/issue-66693, r=oli-obk

check that first arg to `panic!()` in const is `&str`

closes #66693

~~TODO: regression test~~

cc `@RalfJung` for error message wording
This commit is contained in:
Guillaume Gomez 2021-03-02 00:50:04 +01:00 committed by GitHub
commit 865cf0c3b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 114 additions and 6 deletions

View File

@ -377,6 +377,18 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<
}
}
/// 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 {

View File

@ -819,7 +819,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
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();
@ -881,9 +881,17 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
}
// 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;
}

View File

@ -0,0 +1,17 @@
// This is a separate test from `issue-66693.rs` because array lengths are evaluated
// in a separate stage before `const`s and `statics` and so the error below is hit and
// the compiler exits before generating errors for the others.
#![feature(const_panic)]
fn main() {
let _ = [0i32; panic!(2f32)];
//~^ ERROR: argument to `panic!()` in a const context must have type `&str`
// ensure that conforming panics are handled correctly
let _ = [false; panic!()];
//~^ ERROR: evaluation of constant value failed
// typechecking halts before getting to this one
let _ = ['a', panic!("panic in array len")];
}

View File

@ -0,0 +1,19 @@
error: argument to `panic!()` in a const context must have type `&str`
--> $DIR/issue-66693-panic-in-array-len.rs:8:20
|
LL | let _ = [0i32; panic!(2f32)];
| ^^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
--> $DIR/issue-66693-panic-in-array-len.rs:12:21
|
LL | let _ = [false; panic!()];
| ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-66693-panic-in-array-len.rs:12:21
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -0,0 +1,24 @@
// Tests that the compiler does not ICE when const-evaluating a `panic!()` invocation with a
// non-`&str` argument.
#![feature(const_panic)]
const _: () = panic!(1);
//~^ ERROR: argument to `panic!()` in a const context must have type `&str`
static _FOO: () = panic!(true);
//~^ ERROR: argument to `panic!()` in a const context must have type `&str`
const fn _foo() {
panic!(&1); //~ ERROR: argument to `panic!()` in a const context must have type `&str`
}
// ensure that conforming panics don't cause an error
const _: () = panic!();
static _BAR: () = panic!("panic in static");
const fn _bar() {
panic!("panic in const fn");
}
fn main() {}

View File

@ -0,0 +1,26 @@
error: argument to `panic!()` in a const context must have type `&str`
--> $DIR/issue-66693.rs:13:5
|
LL | panic!(&1);
| ^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: argument to `panic!()` in a const context must have type `&str`
--> $DIR/issue-66693.rs:6:15
|
LL | const _: () = panic!(1);
| ^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: argument to `panic!()` in a const context must have type `&str`
--> $DIR/issue-66693.rs:9:19
|
LL | static _FOO: () = panic!(true);
| ^^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors

View File

@ -1,3 +1,5 @@
struct Bug([u8; panic!(1)]); //~ ERROR panicking in constants is unstable
// Note: non-`&str` panic arguments gained a separate error in PR #80734
// which is why this doesn't match the issue
struct Bug([u8; panic!("panic")]); //~ ERROR panicking in constants is unstable
fn main() {}

View File

@ -1,8 +1,8 @@
error[E0658]: panicking in constants is unstable
--> $DIR/issue-76064.rs:1:17
--> $DIR/issue-76064.rs:3:17
|
LL | struct Bug([u8; panic!(1)]);
| ^^^^^^^^^
LL | struct Bug([u8; panic!("panic")]);
| ^^^^^^^^^^^^^^^
|
= note: see issue #51999 <https://github.com/rust-lang/rust/issues/51999> for more information
= help: add `#![feature(const_panic)]` to the crate attributes to enable