Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for live drops in constants after drop elaboration #71824

Merged
merged 8 commits into from
Jun 15, 2020

Conversation

ecstatic-morse
Copy link
Contributor

@ecstatic-morse ecstatic-morse commented May 3, 2020

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

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-8 of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
========================== Starting Command Output ===========================
[command]/bin/bash --noprofile --norc /home/vsts/work/_temp/073f0068-586b-4b26-9711-764668e66c20.sh

##[section]Finishing: Disable git automatic line ending conversion
##[section]Starting: Checkout rust-lang/rust@refs/pull/71824/merge to s
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
---
##[command]git remote add origin https://github.com/rust-lang/rust
##[command]git config gc.auto 0
##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
##[command]git config --get-all http.proxy
##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/71824/merge:refs/remotes/pull/71824/merge
---
 ---> cb2676f08729
Step 5/8 : ENV RUST_CONFIGURE_ARGS       --build=x86_64-unknown-linux-gnu       --llvm-root=/usr/lib/llvm-8       --enable-llvm-link-shared       --set rust.thin-lto-import-instr-limit=10
 ---> Using cache
 ---> df25ce111862
Step 6/8 : ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy &&            python2.7 ../x.py test src/test/mir-opt --pass=build                                   --target=armv5te-unknown-linux-gnueabi &&            python2.7 ../x.py test src/tools/tidy
 ---> 599b9ac96b27
Step 7/8 : ENV NO_DEBUG_ASSERTIONS=1
 ---> Using cache
 ---> 091087e35a36
---
   Compiling rustc_feature v0.0.0 (/checkout/src/librustc_feature)
   Compiling fmt_macros v0.0.0 (/checkout/src/libfmt_macros)
   Compiling rustc_ast_pretty v0.0.0 (/checkout/src/librustc_ast_pretty)
   Compiling rustc_hir v0.0.0 (/checkout/src/librustc_hir)
   Compiling rustc_query_system v0.0.0 (/checkout/src/librustc_query_system)
   Compiling rustc_hir_pretty v0.0.0 (/checkout/src/librustc_hir_pretty)
   Compiling rustc_attr v0.0.0 (/checkout/src/librustc_attr)
   Compiling rustc_parse v0.0.0 (/checkout/src/librustc_parse)
   Compiling rustc_ast_lowering v0.0.0 (/checkout/src/librustc_ast_lowering)
---
   Compiling rustc_feature v0.0.0 (/checkout/src/librustc_feature)
   Compiling fmt_macros v0.0.0 (/checkout/src/libfmt_macros)
   Compiling rustc_ast_pretty v0.0.0 (/checkout/src/librustc_ast_pretty)
   Compiling rustc_hir v0.0.0 (/checkout/src/librustc_hir)
   Compiling rustc_query_system v0.0.0 (/checkout/src/librustc_query_system)
   Compiling rustc_hir_pretty v0.0.0 (/checkout/src/librustc_hir_pretty)
   Compiling rustc_attr v0.0.0 (/checkout/src/librustc_attr)
   Compiling rustc_parse v0.0.0 (/checkout/src/librustc_parse)
   Compiling rustc_ast_lowering v0.0.0 (/checkout/src/librustc_ast_lowering)
---
.................i.................................................................................. 1800/9971
.................................................................................................... 1900/9971
.................................i.................................................................. 2000/9971
.................................................................................................... 2100/9971
.......................iiiii........................................................................ 2200/9971
.................................................................................................... 2400/9971
.................................................................................................... 2500/9971
.................................................................................................... 2600/9971
.................................................................................................... 2700/9971
---
.......i...............i............................................................................ 5100/9971
.................................................................................................... 5200/9971
.....................................................i.............................................. 5300/9971
............................................i....................................................... 5400/9971
..............................................ii.ii........i...i.................................... 5500/9971
.............................................................................................i...... 5700/9971
.................................................................................................... 5800/9971
............................ii.....................................i................................ 5900/9971
.................................................................................................... 6000/9971
.................................................................................................... 6000/9971
.................................................................................................... 6100/9971
..............................................................ii...i..ii...........i................ 6200/9971
.................................................................................................... 6400/9971
.................................................................................................... 6500/9971
.................................................................................................... 6500/9971
..............................................................................................i..ii. 6600/9971
.................................................................................................... 6800/9971
...............................................................................................i.... 6900/9971
.................................................................................................... 7000/9971
.................................................................................................... 7100/9971
---
.................................................................................................... 7900/9971
.................................................................................................... 8000/9971
.................................................................................................... 8100/9971
.....i.............................................................................................. 8200/9971
...........................................................iiiiii.iiiii.i........................... 8300/9971
............i........................................F.............................................. 8500/9971
.................................................................................................... 8600/9971
..................F................................................................................. 8700/9971
.................................................................................................... 8800/9971
---

- error[E0493]: destructors cannot be evaluated at compile-time
-   --> $DIR/check-static-values-constraints.rs:65:43
-    |
- LL |                                           ..SafeStruct{field1: SafeEnum::Variant3(WithDtor),
- LL | |
- LL | |
- LL | |                                                      field2: SafeEnum::Variant1}};
-    | |________________________________________________________________________________^ statics cannot evaluate destructors
10 error[E0010]: allocations are not allowed in statics
11   --> $DIR/check-static-values-constraints.rs:79:33
12    |


106 LL |     let y = { static x: Box<isize> = box 3; x };
108 
- error: aborting due to 17 previous errors
+ error[E0493]: destructors cannot be evaluated at compile-time
+   --> $DIR/check-static-values-constraints.rs:61:81
+   --> $DIR/check-static-values-constraints.rs:61:81
+    |
+ LL | ...                   field2: SafeEnum::Variant1}};
+    |                                                  ^ statics cannot evaluate destructors
+ error[E0493]: destructors cannot be evaluated at compile-time
+   --> $DIR/check-static-values-constraints.rs:67:81
+    |
+    |
+ LL | ...                   field2: SafeEnum::Variant1}};
+    |                                                  ^ statics cannot evaluate destructors
+ error: aborting due to 18 previous errors
110 
111 Some errors have detailed explanations: E0010, E0015, E0019, E0493, E0507.
112 For more information about an error, try `rustc --explain E0010`.
112 For more information about an error, try `rustc --explain E0010`.


The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/check-static-values-constraints/check-static-values-constraints.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args check-static-values-constraints.rs`
error: 1 errors occurred comparing output.
status: exit code: 1
status: exit code: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/check-static-values-constraints.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/check-static-values-constraints" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/check-static-values-constraints/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
error[E0010]: allocations are not allowed in statics
  --> /checkout/src/test/ui/check-static-values-constraints.rs:79:33
   |
LL | static STATIC11: Box<MyOwned> = box MyOwned;
   |                                 ^^^^^^^^^^^ allocation not allowed in statics
error[E0019]: static contains unimplemented expression type
  --> /checkout/src/test/ui/check-static-values-constraints.rs:79:37
   |
   |
LL | static STATIC11: Box<MyOwned> = box MyOwned;

error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
  --> /checkout/src/test/ui/check-static-values-constraints.rs:90:32
   |
   |
LL |     field2: SafeEnum::Variant4("str".to_string())

error[E0010]: allocations are not allowed in statics
  --> /checkout/src/test/ui/check-static-values-constraints.rs:95:5
   |
   |
LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
   |     ^^^^^^^^^^^ allocation not allowed in statics
error[E0019]: static contains unimplemented expression type
  --> /checkout/src/test/ui/check-static-values-constraints.rs:95:9
   |
   |
LL |     box MyOwned, //~ ERROR allocations are not allowed in statics

error[E0010]: allocations are not allowed in statics
  --> /checkout/src/test/ui/check-static-values-constraints.rs:97:5
   |
   |
LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
   |     ^^^^^^^^^^^ allocation not allowed in statics
error[E0019]: static contains unimplemented expression type
  --> /checkout/src/test/ui/check-static-values-constraints.rs:97:9
   |
   |
LL |     box MyOwned, //~ ERROR allocations are not allowed in statics

error[E0010]: allocations are not allowed in statics
  --> /checkout/src/test/ui/check-static-values-constraints.rs:102:6
   |
   |
LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
   |      ^^^^^^^^^^^ allocation not allowed in statics
error[E0019]: static contains unimplemented expression type
  --> /checkout/src/test/ui/check-static-values-constraints.rs:102:10
   |
   |
LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics

error[E0010]: allocations are not allowed in statics
  --> /checkout/src/test/ui/check-static-values-constraints.rs:104:6
   |
   |
LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
   |      ^^^^^^^^^^^ allocation not allowed in statics
error[E0019]: static contains unimplemented expression type
  --> /checkout/src/test/ui/check-static-values-constraints.rs:104:10
   |
   |
LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics

error[E0010]: allocations are not allowed in statics
  --> /checkout/src/test/ui/check-static-values-constraints.rs:111:5
   |
---

error[E0507]: cannot move out of static item `x`
  --> /checkout/src/test/ui/check-static-values-constraints.rs:116:45
   |
LL |     let y = { static x: Box<isize> = box 3; x };
   |                                             |
   |                                             |
   |                                             move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
   |                                             help: consider borrowing here: `&x`
error[E0010]: allocations are not allowed in statics
  --> /checkout/src/test/ui/check-static-values-constraints.rs:116:38
   |
   |
LL |     let y = { static x: Box<isize> = box 3; x };
   |                                      ^^^^^ allocation not allowed in statics
error[E0019]: static contains unimplemented expression type
  --> /checkout/src/test/ui/check-static-values-constraints.rs:116:42
   |
   |
LL |     let y = { static x: Box<isize> = box 3; x };

error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/check-static-values-constraints.rs:61:81
   |
   |
LL | ...                   field2: SafeEnum::Variant1}};
   |                                                  ^ statics cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/check-static-values-constraints.rs:67:81
   |
   |
LL | ...                   field2: SafeEnum::Variant1}};
   |                                                  ^ statics cannot evaluate destructors
error: aborting due to 18 previous errors

Some errors have detailed explanations: E0010, E0015, E0019, E0493, E0507.
For more information about an error, try `rustc --explain E0010`.
---
1 error[E0493]: destructors cannot be evaluated at compile-time
-   --> $DIR/E0493.rs:17:17
+   --> $DIR/E0493.rs:17:48
3    |
4 LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1;
+    |                                                ^ constants cannot evaluate destructors
6 
7 error: aborting due to previous error
8 
8 


The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/span/E0493/E0493.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args span/E0493.rs`
error: 1 errors occurred comparing output.
status: exit code: 1
status: exit code: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/span/E0493.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/span/E0493" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/span/E0493/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/span/E0493.rs:17:48
   |
LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1;
   |                                                ^ constants cannot evaluate destructors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0493`.

---

- error[E0493]: destructors cannot be evaluated at compile-time
-   --> $DIR/static-drop-scope.rs:9:60
-    |
- LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
-    |                                                            ^^^^^^^^ statics cannot evaluate destructors
7 error[E0716]: temporary value dropped while borrowed
8   --> $DIR/static-drop-scope.rs:9:60
9    |


14    |                                                      |     creates a temporary which is freed while still in use
15    |                                                      using this value as a static requires that borrow lasts for `'static`
16 
- error[E0493]: destructors cannot be evaluated at compile-time
-   --> $DIR/static-drop-scope.rs:13:59
-    |
- LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
- 
23 error[E0716]: temporary value dropped while borrowed
24   --> $DIR/static-drop-scope.rs:13:59
25    |
---
+ 
+ error[E0493]: destructors cannot be evaluated at compile-time
+   --> $DIR/static-drop-scope.rs:9:60
+    |
+ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
+    |                                                            ^^^^^^^^ statics cannot evaluate destructors
+ error[E0493]: destructors cannot be evaluated at compile-time
+   --> $DIR/static-drop-scope.rs:13:59
+    |
+    |
+ LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
32 
33 error[E0493]: destructors cannot be evaluated at compile-time
34   --> $DIR/static-drop-scope.rs:17:28



The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/static/static-drop-scope/static-drop-scope.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args static/static-drop-scope.rs`
error: 1 errors occurred comparing output.
status: exit code: 1
status: exit code: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/static/static-drop-scope.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/static/static-drop-scope" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/static/static-drop-scope/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
error[E0716]: temporary value dropped while borrowed
  --> /checkout/src/test/ui/static/static-drop-scope.rs:9:60
   |
LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
   |                                                      |     |       |
   |                                                      |     |       temporary value is freed at the end of this statement
   |                                                      |     creates a temporary which is freed while still in use
   |                                                      using this value as a static requires that borrow lasts for `'static`
   |                                                      using this value as a static requires that borrow lasts for `'static`

error[E0716]: temporary value dropped while borrowed
  --> /checkout/src/test/ui/static/static-drop-scope.rs:13:59
   |
LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
   |                                                     |     |       |
   |                                                     |     |       temporary value is freed at the end of this statement
   |                                                     |     creates a temporary which is freed while still in use
   |                                                     using this value as a constant requires that borrow lasts for `'static`
   |                                                     using this value as a constant requires that borrow lasts for `'static`

error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:9:60
   |
LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
   |                                                            ^^^^^^^^ statics cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:13:59
   |
   |
LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);

error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:17:28
   |
   |
LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1;
   |                            ^^^^^^^^^^^^^ statics cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:20:27
   |
   |
LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1;

error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:23:24
   |
   |
LL | const fn const_drop<T>(_: T) {}
   |                        ^ constant functions cannot evaluate destructors

error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:27:5
   |
LL |     (x, ()).1

error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:31:34
   |
   |
LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;

error[E0493]: destructors cannot be evaluated at compile-time
  --> /checkout/src/test/ui/static/static-drop-scope.rs:36:43
   |
   |
LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;

error: aborting due to 10 previous errors

Some errors have detailed explanations: E0493, E0716.
---
thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:348:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-8/bin/FileCheck" "--nodejs" "/usr/bin/node" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "8.0.0" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"


failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test --exclude src/tools/tidy
Build completed unsuccessfully in 0:58:14
Build completed unsuccessfully in 0:58:14
== clock drift check ==
  local time: Sun May  3 05:26:39 UTC 2020
  network time: Sun, 03 May 2020 05:26:39 GMT
== end clock drift check ==

##[error]Bash exited with code '1'.
##[section]Finishing: Run build
##[section]Starting: Checkout rust-lang/rust@refs/pull/71824/merge to s
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
Author       : Microsoft
Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
==============================================================================
Cleaning any cached credential from repository: rust-lang/rust (GitHub)
##[section]Finishing: Checkout rust-lang/rust@refs/pull/71824/merge to s
Cleaning up task key
Start cleaning up orphan processes.
Terminate orphan process: pid (4437) (python)
##[section]Finishing: Finalize Job

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @rust-lang/infra. (Feature Requests)

@ecstatic-morse
Copy link
Contributor Author

ecstatic-morse commented May 3, 2020

Here's an interesting case:

// Test variadic constructor for structs. The base struct should be examined
// as well as every field present in the constructor.
// This example shouldn't fail because all the fields are safe.
static STATIC8: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
..SafeStruct{field1: SafeEnum::Variant1,
field2: SafeEnum::Variant1}};

MIR before const-checking

// MIR for `STATIC8` after SimplifyCfg-initial

static STATIC8: SafeStruct = {
    let mut _0: SafeStruct;              // return place in scope 0 at src/test/ui/check-static-values-constraints.rs:59:17: 59:27
    let mut _1: SafeEnum;                // in scope 0 at src/test/ui/check-static-values-constraints.rs:59:49: 59:67
    let mut _2: SafeStruct;              // in scope 0 at src/test/ui/check-static-values-constraints.rs:60:43: 61:81
    let mut _3: SafeEnum;                // in scope 0 at src/test/ui/check-static-values-constraints.rs:60:62: 60:80
    let mut _4: SafeEnum;                // in scope 0 at src/test/ui/check-static-values-constraints.rs:61:62: 61:80

    bb0: {
        StorageLive(_1);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:59:49: 59:67
        _1 = SafeEnum::Variant1;         // scope 0 at src/test/ui/check-static-values-constraints.rs:59:49: 59:67
        StorageLive(_2);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:60:43: 61:81
        StorageLive(_3);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:60:62: 60:80
        _3 = SafeEnum::Variant1;         // scope 0 at src/test/ui/check-static-values-constraints.rs:60:62: 60:80
        StorageLive(_4);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:61:62: 61:80
        _4 = SafeEnum::Variant1;         // scope 0 at src/test/ui/check-static-values-constraints.rs:61:62: 61:80
        _2 = SafeStruct { field1: move _3, field2: move _4 }; // scope 0 at src/test/ui/check-static-values-constraints.rs:60:43: 61:81
        _0 = SafeStruct { field1: move _1, field2: move (_2.1: SafeEnum) }; // scope 0 at src/test/ui/check-static-values-constraints.rs:59:30: 61:82
        drop(_2) -> [return: bb2, unwind: bb1]; // scope 0 at src/test/ui/check-static-values-constraints.rs:61:81: 61:82
    }

    bb1 (cleanup): {
        resume;                          // scope 0 at src/test/ui/check-static-values-constraints.rs:59:1: 61:83
    }

    bb2: {
        StorageDead(_2);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:61:81: 61:82
        return;                          // scope 0 at src/test/ui/check-static-values-constraints.rs:59:1: 61:83
    }
}

After drop elaboration:

// MIR for `STATIC8` after SimplifyCfg-elaborate-drops

static STATIC8: SafeStruct = {
    let mut _0: SafeStruct;              // return place in scope 0 at src/test/ui/check-static-values-constraints.rs:59:17: 59:27
    let mut _1: SafeEnum;                // in scope 0 at src/test/ui/check-static-values-constraints.rs:59:49: 59:67
    let mut _2: SafeStruct;              // in scope 0 at src/test/ui/check-static-values-constraints.rs:60:43: 61:81
    let mut _3: SafeEnum;                // in scope 0 at src/test/ui/check-static-values-constraints.rs:60:62: 60:80
    let mut _4: SafeEnum;                // in scope 0 at src/test/ui/check-static-values-constraints.rs:61:62: 61:80

    bb0: {
        StorageLive(_1);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:59:49: 59:67
        _1 = SafeEnum::Variant1;         // scope 0 at src/test/ui/check-static-values-constraints.rs:59:49: 59:67
        StorageLive(_2);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:60:43: 61:81
        StorageLive(_3);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:60:62: 60:80
        _3 = SafeEnum::Variant1;         // scope 0 at src/test/ui/check-static-values-constraints.rs:60:62: 60:80
        StorageLive(_4);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:61:62: 61:80
        _4 = SafeEnum::Variant1;         // scope 0 at src/test/ui/check-static-values-constraints.rs:61:62: 61:80
        _2 = SafeStruct { field1: move _3, field2: move _4 }; // scope 0 at src/test/ui/check-static-values-constraints.rs:60:43: 61:81
        _0 = SafeStruct { field1: move _1, field2: move (_2.1: SafeEnum) }; // scope 0 at src/test/ui/check-static-values-constraints.rs:59:30: 61:82
        drop((_2.0: SafeEnum)) -> [return: bb2, unwind: bb1]; // scope 0 at src/test/ui/check-static-values-constraints.rs:61:81: 61:82
    }

    bb1 (cleanup): {
        resume;                          // scope 0 at src/test/ui/check-static-values-constraints.rs:59:1: 61:83
    }

    bb2: {
        StorageDead(_2);                 // scope 0 at src/test/ui/check-static-values-constraints.rs:61:81: 61:82
        return;                          // scope 0 at src/test/ui/check-static-values-constraints.rs:59:1: 61:83
    }
}

After drop elaboration, we drop only a single field of SafeStruct, which we don't realize is composed only of the non-Drop variants of SafeEnums because value-based qualification is only used for whole locals. The solution is to still look at the qualifs of the base local when dropping a projection of that local, or alternatively start using move paths as the domain for the qualif dataflow analysis instead of locals.

@ecstatic-morse ecstatic-morse force-pushed the const-check-post-drop-elab branch 2 times, most recently from 45d454f to bfc4fb8 Compare May 3, 2020 19:42
@bors

This comment has been minimized.

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 4, 2020
@ecstatic-morse ecstatic-morse marked this pull request as ready for review May 4, 2020 16:43
@ecstatic-morse ecstatic-morse changed the title [WIP] Check for live drops in constants after drop elaboration Check for live drops in constants after drop elaboration May 4, 2020
@ecstatic-morse ecstatic-morse force-pushed the const-check-post-drop-elab branch from bfc4fb8 to 101d012 Compare May 4, 2020 16:50
@ecstatic-morse
Copy link
Contributor Author

ecstatic-morse commented May 4, 2020

Okay, this is ready for review I suppose. I think we may want to put this behind a feature gate or at least wait until the next full beta cycle to merge. It also could use some new tests of the interaction between the value-based analysis on locals in CheckLiveDrops and the type-based analysis on move paths done during drop elaboration. Eventually I think we want to remember qualifs for individual move paths, but I don't think we need to wait.

r? @oli-obk

@@ -600,7 +581,8 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
};

if needs_drop {
self.check_op_spanned(ops::LiveDrop, err_span);
// self.check_op_spanned(ops::LiveDrop, err_span);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so... in order to do the feature gating you suggested, all we need is to change this to be run if the feature gate is not active and the better logic you implemented will run, too, but since it won't cause more errors, it basically works as redundancy?

Copy link
Contributor Author

@ecstatic-morse ecstatic-morse May 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so yes. I'm pretty sure the spans will be the same. Should we still force mir_drops_elaborated_and_const_checked even if the feature gate is not enabled?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running it helps ensure it's equivalent to the old logic, where the old logic doesn't error, but may regress perf to do so. I think it'd be nice to run both, but if you see it's annoying in tests, only force it if the feature gate is enabled.

Copy link
Contributor Author

@ecstatic-morse ecstatic-morse May 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I'm second guessing whether we actually want to put these changes behind a feature flag.

The post_drop_elaboration part is pretty trivial; the only thing I'm worried about implementing wrong is the query forcing part, but that's not too hard. We really just need to decide whether it's okay for a const-checking pass to depend on drop elaboration. A feature gate just allows us to delay that discussion; it doesn't help resolve it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason we should have some feature gate is that this does allow stable const fn to do more afaict (well, at least if we consider if/match stable 😆 ) and we should have a test for that, so please add one in case it's not there already.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nikomatsakis, do you want me to nominate this for lang-team or compiler-team discussion? Specifically the part about depending on drop elaboration to determine whether code compiles?

}
}

mir::TerminatorKind::DropAndReplace { .. } => {
unreachable!("`DropAndReplace` should be removed by drop elaboration")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use span_bug instead of unreachable where possible

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request May 8, 2020
…r=oli-obk

Use a single enum for the kind of a const context

This adds a `ConstContext` enum to the `rustc_hir` crate and method that can be called via `tcx.hir()` to get the `ConstContext` for a given body owner. This arose from discussion in rust-lang#71824.

r? @oli-obk
@nikomatsakis
Copy link
Contributor

@ecstatic-morse

So, I have some reservations about this approach. In borrowck, at least, we do our own computation for which drops are live, precisely so that drop elaboration remains a kind of "optimization" and doesn't define our overall semantics. I am unsure whether that's an important invariant to maintain, but I think it's noteworthy that we are giving it up.

I think maybe what I'm missing is some content -- ideally in the rustc-dev-guide -- documenting the phases of the pipeline and which sort of safety checks we do and when.

@ecstatic-morse
Copy link
Contributor Author

ecstatic-morse commented May 13, 2020

As I understand the status quo, borrow-checking, the unconditional recursion lint, and const-checking/promotion are the only semantic checks done to the MIR prior to drop elaboration. We force the generator state transform (which doesn't emit any lints or errors) and const propagation (which does, although I think this is considered a bug, see #70923) to run after drop elaboration even when optimizations are disabled. In other words, I think you are right that this PR represents a significant change.

One alternative is to reimplement parts of drop elaboration inside the const-checker, obviously this is bad for code duplication, but would put less pressure on those who refactor the drop elaboration pass to preserve existing optimizations. However, it seems wasteful to do all the analysis required to perform drop elaboration for const-checking, then throw it away and re-run it a few optimization passes later.

Here's the list of passes that run after borrow/const-checking and promotion:

fn run_optimization_passes<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
def_id: LocalDefId,
promoted: Option<Promoted>,
) {
let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
// Remove all things only needed by analysis
&no_landing_pads::NoLandingPads::new(tcx),
&simplify_branches::SimplifyBranches::new("initial"),
&remove_noop_landing_pads::RemoveNoopLandingPads,
&cleanup_post_borrowck::CleanupNonCodegenStatements,
&simplify::SimplifyCfg::new("early-opt"),
// These next passes must be executed together
&add_call_guards::CriticalCallEdges,
&elaborate_drops::ElaborateDrops,
&no_landing_pads::NoLandingPads::new(tcx),
// AddMovesForPackedDrops needs to run after drop
// elaboration.
&add_moves_for_packed_drops::AddMovesForPackedDrops,
// `AddRetag` needs to run after `ElaborateDrops`. Otherwise it should run fairly late,
// but before optimizations begin.
&add_retag::AddRetag,
&simplify::SimplifyCfg::new("elaborate-drops"),
// No lifetime analysis based on borrowing can be done from here on out.
];
let optimizations: &[&dyn MirPass<'tcx>] = &[
&unreachable_prop::UnreachablePropagation,
&uninhabited_enum_branching::UninhabitedEnumBranching,
&simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
&inline::Inline,
// Lowering generator control-flow and variables has to happen before we do anything else
// to them. We do this inside the "optimizations" block so that it can benefit from
// optimizations that run before, that might be harder to do on the state machine than MIR
// with async primitives.
&generator::StateTransform,
&instcombine::InstCombine,
&const_prop::ConstProp,
&simplify_branches::SimplifyBranches::new("after-const-prop"),
// Run deaggregation here because:
// 1. Some codegen backends require it
// 2. It creates additional possibilities for some MIR optimizations to trigger
// FIXME(#70073): Why is this done here and not in `post_borrowck_cleanup`?
&deaggregator::Deaggregator,
&copy_prop::CopyPropagation,
&simplify_branches::SimplifyBranches::new("after-copy-prop"),
&remove_noop_landing_pads::RemoveNoopLandingPads,
&simplify::SimplifyCfg::new("after-remove-noop-landing-pads"),
&simplify_try::SimplifyArmIdentity,
&simplify_try::SimplifyBranchSame,
&simplify::SimplifyCfg::new("final"),
&simplify::SimplifyLocals,
];
let no_optimizations: &[&dyn MirPass<'tcx>] = &[
// Even if we don't do optimizations, we still have to lower generators for codegen.
&generator::StateTransform,
// FIXME(#70073): This pass is responsible for both optimization as well as some lints.
&const_prop::ConstProp,
// Even if we don't do optimizations, still run deaggregation because some backends assume
// that deaggregation always occurs.
&deaggregator::Deaggregator,
];

I don't feel qualified to document the split between "MIR for analysis" and "MIR for optimization". For example, I only found out in this PR that DropAndReplace exists solely for analysis, and is removed prior to optimization. However, if there was already some discussion about the difference between the two, I would be happy to summarize it for the guide.

@joelpalmer joelpalmer added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 21, 2020
@nikomatsakis
Copy link
Contributor

@ecstatic-morse So, currently, the borrow checker includes a certain amount of duplicated reasoning as well -- in particular, it tracks which values "may be" initialized (as well as those that "must be") at each point, and we can use that to determine when a Drop is known to be a no-op. I'd have to review the logic there to say precisely what we do and do not handle. It sounds like this may be the same information that you need access to, however, which makes me wonder if const qualification could take advantage of it.

@ecstatic-morse
Copy link
Contributor Author

ecstatic-morse commented May 22, 2020

If I were to implement this without relying on drop elaboration, I would need only the MaybeInitializedPlaces analysis. I don't think this would be too hard for me, although it would be more work than the current approach. The borrow checker uses several others–MaybeUninitializedPlaces to detect reads from places that are moved from or never assigned and EverInitializedPlaces to detect mutation of immutable variables–but I think you are correct that it is doing something very similar to drop elaboration.

I suppose the "live drop" aspect of const-checking just seems more tied to drop elaboration than the borrow checking does. The first two are doing very similar things, whereas drop elaboration is sort of a small subset of what the borrow checker is doing. This is why it felt natural for one to depend on the other.

In your opinion, how likely is the potential backwards compatibility hazard of relying on drop elaboration to materialize? My thinking is that it's highly unlikely that we will make drop elaboration less precise without changing the underlying dataflow analysis. Both const-checking and drop elaboration will rely on MaybeInitializedPlaces even if they are separated.

@nikomatsakis
Copy link
Contributor

@ecstatic-morse

how likely is the potential backwards compatibility hazard of relying on drop elaboration to materialize

Yeah, that's a good question. It doesn't seem very likely for things to diverge, and I feel like drop-elaboration is kind of an "obvious" optimization that doesn't involve any particular heuristics. It just kind of works "as well as it obviously can" and that's the end of it.

I think I'm ok with landing it in this form, but I also would like us to sort of document better the "phase transition" point where we move from "static analysis" to "optimizable, go wild". I've always had "drop elaboration" in my head as that transition point, but it seems like after this PR lands, the point has moved somewhat forward, to after this check.

Is there a clear query transition? I guess I can skim the diff. I think I'd be happiest if we documented it in the rustc-dev-guide ultimately.

@ecstatic-morse
Copy link
Contributor Author

MIR passes are currently divided into "post-borrowck cleanup" and "optimization passes". This runs immediately after "post-borrowck cleanup".

@bors
Copy link
Contributor

bors commented May 30, 2020

☔ The latest upstream changes (presumably #72778) made this pull request unmergeable. Please resolve the merge conflicts.

@ecstatic-morse
Copy link
Contributor Author

ecstatic-morse commented Jun 1, 2020

@rust-lang/lang, do we want to put these changes behind a feature gate? @oli-obk thinks we should. My opinion is that this isn't really a "feature" but a refinement to const-checking, and it's kind of non-obvious what the user would be opting in to with the feature gate, since drop elaboration is an implementation detail. A relevant precedent is #![feature(nll)], but that was much larger and more fundamental than this change would be.

This is also somewhat relevant to the stabilization of #![feature(const_if_match)]. Nothing in this PR is specifically related to branching in constants. For instance, it makes the example below compile as well. However, I expect users will commonly want to move out of Option::<T>::Some within a match, which won't work without this PR if T: !Copy

const _: Vec<i32> = {
    let vec_tuple = (Vec::new(),);
    vec_tuple.0
};

@ecstatic-morse ecstatic-morse force-pushed the const-check-post-drop-elab branch from 7fad28d to 2dcf7db Compare June 13, 2020 18:05
@ecstatic-morse
Copy link
Contributor Author

@bors r=oli-obk rollup

@bors
Copy link
Contributor

bors commented Jun 13, 2020

📌 Commit 2dcf7db has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 13, 2020
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jun 13, 2020
…p-elab, r=oli-obk

Check for live drops in constants after drop elaboration

Resolves rust-lang#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
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jun 14, 2020
…p-elab, r=oli-obk

Check for live drops in constants after drop elaboration

Resolves rust-lang#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
RalfJung added a commit to RalfJung/rust that referenced this pull request Jun 15, 2020
…p-elab, r=oli-obk

Check for live drops in constants after drop elaboration

Resolves rust-lang#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 was referenced Jun 15, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 15, 2020
Rollup of 10 pull requests

Successful merges:

 - rust-lang#71824 (Check for live drops in constants after drop elaboration)
 - rust-lang#72389 (Explain move errors that occur due to method calls involving `self`)
 - rust-lang#72556 (Fix trait alias inherent impl resolution)
 - rust-lang#72584 (Stabilize vec::Drain::as_slice)
 - rust-lang#72598 (Display information about captured variable in `FnMut` error)
 - rust-lang#73336 (Group `Pattern::strip_*` method together)
 - rust-lang#73341 (_match.rs: fix module doc comment)
 - rust-lang#73342 (Fix iterator copied() documentation example code)
 - rust-lang#73351 (Update E0446.md)
 - rust-lang#73353 (structural_match: non-structural-match ty closures)

Failed merges:

r? @ghost
@bors bors merged commit 5c61a8d into rust-lang:master Jun 15, 2020
@ecstatic-morse ecstatic-morse deleted the const-check-post-drop-elab branch August 29, 2020 20:25
mir::TerminatorKind::Drop { location: dropped_place, .. } => {
let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
return;
Copy link
Member

@RalfJung RalfJung Mar 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oli-obk Is this even reachable? I'd think we don't keep Drop terminators around after drop elaboration for types that do not need dropping...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed not reachable.

return;
}

if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this looks like it second-guessing drop elaboration which already determined that this drop is indeed necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is reachable. I'm not sure yet why, but I am guessing the reason is that needs_drop is its own analysis, while drop elaboration relies on MaybeInitializedPlaces and MaybeUninitializedPlaces to make a decision. We could probably rewrite drop elaboration in terms of the NeedsDrop qualif, which would (afaict) allow post_drop_elaboration to not do any checks except for looking for Drop terminators.

Of course such a change would insta-stabilize the feature gate from this PR without any reasonable way to avoid said stabilization. So I'm tempted to stabilize the feature but leave a FIXME on this function to merge its qualif checks into elaborate_drops

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternative would be to ignore qualifs here, and just follow what drop elaboration does.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do keep following the qualifs to get an edge in precision over drop elaboration (maybe we have to, for backwards compat), we should add a test case for a program where the qualifs are more precise than drop elaboration is (i.e. a program that would get rejected if we just always called check_live_drop), and reference that testcase from the code here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

struct A;
impl Drop for A {
fn drop(&mut self) {}
}
const FOO: Option<A> = None;
const BAR: () = (FOO, ()).1;

Is this what you're looking for? We do have to keep this for back-compat, see #57734

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot to post that here: the follow-up to this discussion is at #83351.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you already found an equivalent one.


// `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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we unconditionally error on drops, this line will cause an error (meaning: this is the test case you're looking for)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I interpret the error annotations correctly, this errors (in the next line) even with precise analysis? Doesn't seem terribly useful then to not error here.^^

Isn't there an example where we need this to actually accept more code?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'll split up the feature gate into two, so we can actually play with examples on the playground.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want this exposed to the user; doesn't just commenting out those lines make some tests fail (in more ways than just moving around the location of the error message)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found examples in the test suite: #83351

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 2, 2021
…rops-take-2, r=oli-obk

Move `#![feature(const_precise_live_drops)]` checks earlier in the pipeline

Should mitigate the issues found during MCP on rust-lang#73255.

Once this is done, we should clean up the queries a bit, since I think `mir_drops_elaborated_and_const_checked` can be merged back into `mir_promoted`.

Fixes rust-lang#90770.

cc `@rust-lang/wg-const-eval`
r? `@nikomatsakis` (since they reviewed rust-lang#71824)
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 2, 2021
…rops-take-2, r=oli-obk

Move `#![feature(const_precise_live_drops)]` checks earlier in the pipeline

Should mitigate the issues found during MCP on rust-lang#73255.

Once this is done, we should clean up the queries a bit, since I think `mir_drops_elaborated_and_const_checked` can be merged back into `mir_promoted`.

Fixes rust-lang#90770.

cc ``@rust-lang/wg-const-eval``
r? ``@nikomatsakis`` (since they reviewed rust-lang#71824)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't implement a const Option::unwrap because of "destructors cannot be evaluated at compile-time" error.
8 participants