Rollup merge of #71824 - ecstatic-morse:const-check-post-drop-elab, r=oli-obk

Check for live drops in constants after drop elaboration

Resolves #66753.

This PR splits the MIR "optimization" pass series in two and introduces a query–`mir_drops_elaborated_and_const_checked`–that holds the result of the `post_borrowck_cleanup` analyses and checks for live drops. This query is invoked in `rustc_interface` for all items requiring const-checking, which means we now do `post_borrowck_cleanup` for items even if they are unused in the crate.

As a result, we are now more precise about when drops are live. This is because drop elaboration can e.g. eliminate drops of a local when all its fields are moved from. This does not mean we are doing value-based analysis on move paths, however; Storing a `Some(CustomDropImpl)` into a field of a local will still set the qualifs for that entire local.

r? @oli-obk
This commit is contained in:
Ralf Jung 2020-06-15 09:57:20 +02:00 committed by GitHub
commit 5c61a8dc34
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 264 additions and 51 deletions

View file

@ -0,0 +1,15 @@
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:10:9
|
LL | let x = Some(Vec::new());
| ^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:41:9
|
LL | let mut tmp = None;
| ^^^^^^^ constants cannot evaluate destructors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0493`.

View file

@ -1,11 +1,14 @@
// revisions: stock precise
#![feature(const_if_match)]
#![feature(const_loop)]
#![cfg_attr(precise, feature(const_precise_live_drops))]
// `x` is *not* always moved into the final value may be dropped inside the initializer.
// `x` is *not* always moved into the final value and may be dropped inside the initializer.
const _: Option<Vec<i32>> = {
let y: Option<Vec<i32>> = None;
let x = Some(Vec::new());
//~^ ERROR destructors cannot be evaluated at compile-time
//[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time
if true {
x
@ -18,7 +21,7 @@ const _: Option<Vec<i32>> = {
// existing analysis.
const _: Vec<i32> = {
let vec_tuple = (Vec::new(),);
//~^ ERROR destructors cannot be evaluated at compile-time
//[stock]~^ ERROR destructors cannot be evaluated at compile-time
vec_tuple.0
};
@ -26,7 +29,7 @@ const _: Vec<i32> = {
// This applies to single-field enum variants as well.
const _: Vec<i32> = {
let x: Result<_, Vec<i32>> = Ok(Vec::new());
//~^ ERROR destructors cannot be evaluated at compile-time
//[stock]~^ ERROR destructors cannot be evaluated at compile-time
match x {
Ok(x) | Err(x) => x,
@ -36,7 +39,7 @@ const _: Vec<i32> = {
const _: Option<Vec<i32>> = {
let mut some = Some(Vec::new());
let mut tmp = None;
//~^ ERROR destructors cannot be evaluated at compile-time
//[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time
let mut i = 0;
while i < 10 {

View file

@ -1,23 +1,23 @@
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/drop-failure.rs:7:9
--> $DIR/drop-fail.rs:10:9
|
LL | let x = Some(Vec::new());
| ^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/drop-failure.rs:20:9
--> $DIR/drop-fail.rs:23:9
|
LL | let vec_tuple = (Vec::new(),);
| ^^^^^^^^^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/drop-failure.rs:28:9
--> $DIR/drop-fail.rs:31:9
|
LL | let x: Result<_, Vec<i32>> = Ok(Vec::new());
| ^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/drop-failure.rs:38:9
--> $DIR/drop-fail.rs:41:9
|
LL | let mut tmp = None;
| ^^^^^^^ constants cannot evaluate destructors

View file

@ -1,7 +1,9 @@
// run-pass
// revisions: stock precise
#![feature(const_if_match)]
#![feature(const_loop)]
#![cfg_attr(precise, feature(const_precise_live_drops))]
// `x` is always moved into the final value and is not dropped inside the initializer.
const _: Option<Vec<i32>> = {

View file

@ -0,0 +1,20 @@
// run-pass
// gate-test-const_precise_live_drops
#![feature(const_if_match)]
#![feature(const_loop)]
#![feature(const_precise_live_drops)]
const _: Vec<i32> = {
let vec_tuple = (Vec::new(),);
vec_tuple.0
};
const _: Vec<i32> = {
let x: Result<_, Vec<i32>> = Ok(Vec::new());
match x {
Ok(x) | Err(x) => x,
}
};
fn main() {}