rust-lang / miri

An interpreter for Rust's mid-level intermediate representation
Apache License 2.0
4.45k stars 340 forks source link

Detect erroneous constants post-monomorphization #1382

Closed RalfJung closed 4 years ago

RalfJung commented 4 years ago

Codegen recently gained a loop to make sure that all constants required by the MIR actually error. Miri does not have anything like that yet, but we probably need that for soundness.

RalfJung commented 4 years ago

Here is a testcase that currently ICEs:

#![feature(const_panic)]
#![feature(never_type)]
#![warn(const_err)]
struct PrintName<T>(T);
impl<T> PrintName<T> {
    const VOID: ! = panic!();
}

fn no_codegen<T>() {
    let _ = PrintName::<T>::VOID;
}
fn main() {
    no_codegen::<i32>();
}
RalfJung commented 4 years ago

Even more interestingly, the same code is considered UB by Miri with -Zmir-opt-level=3:

error: Undefined Behavior: entering unreachable code
  --> const_err.rs:11:13
   |
11 |     let _ = PrintName::<T>::VOID;
   |             ^^^^^^^^^^^^^^^^^^^^ entering unreachable code
   |
   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
oli-obk commented 4 years ago

opt level 3 has some broken optimization in it, but I don't think that's the problem here. Why is it false UB? It's UB to run into a value of ! type, which we do here if we don't evaluate the constant.

RalfJung commented 4 years ago

It's UB in a safe program, so either it's false UB or Rust is unsound.

But there is no actual UB here (and normal codegen shows a compile-time error as it should), thus it is false UB.

oli-obk commented 4 years ago

oh :facepalm: yea makes sense