Rollup merge of #57734 - oli-obk:fixes_and_cleanups, r=pnkfelix

Fix evaluating trivial drop glue in constants

```rust
struct A;
impl Drop for A {
    fn drop(&mut self) {}
}

const FOO: Option<A> = None;

const BAR: () = (FOO, ()).1;
```

was erroring with

```
error: any use of this value will cause an error
 --> src/lib.rs:9:1
  |
9 | const BAR: () = (FOO, ()).1;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^-^
  |                           |
  |                           calling non-const function `std::ptr::real_drop_in_place::<(std::option::Option<A>, ())> - shim(Some((std::option::Option<A>, ())))`
  |
  = note: #[deny(const_err)] on by default

error: aborting due to previous error
```

before this PR. According to godbolt this last compiled successfully in 1.27
This commit is contained in:
Mazdak Farrokhzad 2019-01-25 16:59:27 +01:00 committed by GitHub
commit 141fa859b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 30 deletions

View file

@ -2937,16 +2937,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}
/// Given the DefId of an item, returns its MIR, borrowed immutably.
/// Returns None if there is no MIR for the DefId
pub fn maybe_optimized_mir(self, did: DefId) -> Option<&'gcx Mir<'gcx>> {
if self.is_mir_available(did) {
Some(self.optimized_mir(did))
} else {
None
}
}
/// Get the attributes of a definition.
pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
if let Some(id) = self.hir().as_local_node_id(did) {

View file

@ -340,19 +340,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
ret: Option<mir::BasicBlock>,
) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
debug!("eval_fn_call: {:?}", instance);
// Execution might have wandered off into other crates, so we cannot to a stability-
// sensitive check here. But we can at least rule out functions that are not const
// at all.
if !ecx.tcx.is_const_fn_raw(instance.def_id()) {
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn! We certainly do *not* want to actually call the fn
// though, so be sure we return here.
return if ecx.hook_fn(instance, args, dest)? {
ecx.goto_block(ret)?; // fully evaluated and done
Ok(None)
} else {
err!(MachineError(format!("calling non-const function `{}`", instance)))
};
// Only check non-glue functions
if let ty::InstanceDef::Item(def_id) = instance.def {
// Execution might have wandered off into other crates, so we cannot to a stability-
// sensitive check here. But we can at least rule out functions that are not const
// at all.
if !ecx.tcx.is_const_fn_raw(def_id) {
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn! We certainly do *not* want to actually call the fn
// though, so be sure we return here.
return if ecx.hook_fn(instance, args, dest)? {
ecx.goto_block(ret)?; // fully evaluated and done
Ok(None)
} else {
err!(MachineError(format!("calling non-const function `{}`", instance)))
};
}
}
// This is a const fn. Call it.
Ok(Some(match ecx.load_mir(instance.def) {

View file

@ -273,11 +273,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
}
trace!("load mir {:?}", instance);
match instance {
ty::InstanceDef::Item(def_id) => {
self.tcx.maybe_optimized_mir(def_id).ok_or_else(||
EvalErrorKind::NoMirFor(self.tcx.item_path_str(def_id)).into()
)
}
ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
Ok(self.tcx.optimized_mir(did))
} else {
err!(NoMirFor(self.tcx.item_path_str(def_id)))
},
_ => Ok(self.tcx.instance_mir(instance)),
}
}

View file

@ -0,0 +1,13 @@
// compile-pass
#![allow(dead_code)]
struct A;
impl Drop for A {
fn drop(&mut self) {}
}
const FOO: Option<A> = None;
const BAR: () = (FOO, ()).1;
fn main() {}

View file

@ -54,7 +54,19 @@ error[E0493]: destructors cannot be evaluated at compile-time
LL | (x, ()).1
| ^^^^^^^ constant functions cannot evaluate destructors
error: aborting due to 8 previous errors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:31:34
|
LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
| ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:36:43
|
LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
| ^^^^^^^^^^^ constants cannot evaluate destructors
error: aborting due to 10 previous errors
Some errors occurred: E0493, E0716.
For more information about an error, try `rustc --explain E0493`.

View file

@ -28,4 +28,12 @@ const fn const_drop2<T>(x: T) {
//~^ ERROR destructors cannot be evaluated at compile-time
}
const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
//~^ ERROR destructors cannot be evaluated at compile-time
const HELPER: Option<WithDtor> = Some(WithDtor);
const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
//~^ ERROR destructors cannot be evaluated at compile-time
fn main () {}

View file

@ -54,7 +54,19 @@ error[E0493]: destructors cannot be evaluated at compile-time
LL | (x, ()).1
| ^^^^^^^ constant functions cannot evaluate destructors
error: aborting due to 8 previous errors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:31:34
|
LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
| ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:36:43
|
LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
| ^^^^^^^^^^^ constants cannot evaluate destructors
error: aborting due to 10 previous errors
Some errors occurred: E0493, E0597.
For more information about an error, try `rustc --explain E0493`.