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

2229: Fix issues with move closures and mutability #80092

Merged
merged 9 commits into from
Feb 1, 2021

Conversation

arora-aman
Copy link
Member

@arora-aman arora-aman commented Dec 16, 2020

This PR fixes two issues when feature capture_disjoint_fields is used.

  1. Can't mutate using a mutable reference
  2. Move closures try to move value out through a reference.

To do so, we

  1. Compute the mutability of the capture and store it as part of the CapturedPlace that is written in TypeckResults
  2. Restrict capture precision. Note this is temporary for now, to allow the feature to be used with move closures and ByValue captures and might change depending on discussions with the lang team.
    • No Derefs are captured for ByValue captures, since that will result in value behind a reference getting moved.
    • No projections are applied to raw pointers since these require unsafe blocks. We capture
      them completely.

r? @nikomatsakis

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 16, 2020
@@ -14,7 +14,6 @@ fn main() {
let mut c = || {
//~^ ERROR: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
z.0.0.0 = format!("X1");
Copy link
Member Author

Choose a reason for hiding this comment

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

I would have expected us to not try read the place z on its own. When the feature isn't enabled we only read z.0.0.0.

Debug logs from the report_mutability_error when the feature is enabled.

DEBUG rustc_mir::borrow_check::diagnostics::mutability_errors report_mutability_error: access_place_desc=Some("z")
....
DEBUG rustc_mir::borrow_check::diagnostics::mutability_errors report_mutability_error: access_place_desc=Some("z.0.0.0")

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 definitely not the error message we want-- we'd like the error to be reported on z.0.0.0, right? I think this may be related to my comment about the used_mut_upvars but I'm not 100% sure.

compiler/rustc_typeck/src/check/upvar.rs Outdated Show resolved Hide resolved
let mut c = || {
//~^ ERROR: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
z.0.0.0 = format!("X1");
//~^ ERROR: cannot assign to `z`, as it is not declared as mutable
Copy link
Member Author

Choose a reason for hiding this comment

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

I hack around this error in a later commit

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

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

First round of comments. I don't quite understand why that error message is showing up on the wrong line in the one case you highlighted.

// b. Is some path starting from a captured place in our parent closure
// c. Is a path starting from a local variable in our parent closure.

// Handle (a)
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 this is maybe missing a case -- if we capture a deref of an &mut. Also, I don't think that (a) is distinct from (b).

}
} else {
this.used_mut.insert(place.local);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

To handle the deref of &mut` case, we could check here if

  • the projection is a deref
  • the type of the place_ref is an &mut

compiler/rustc_mir/src/borrow_check/type_check/mod.rs Outdated Show resolved Hide resolved
// The place isn't mutable once we dereference a immutable reference.
ty::Ref(.., hir::Mutability::Not) => return hir::Mutability::Not,

_ => (),
Copy link
Contributor

Choose a reason for hiding this comment

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

I would add ty::Adt with an assertion that this is a bug, and then make _ => bug!("deref of unexpected pointer type {:?}", pointer_ty.kind()) or something like that

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm assuming you meant Adt(boxed)

compiler/rustc_typeck/src/check/upvar.rs Outdated Show resolved Hide resolved
compiler/rustc_typeck/src/check/upvar.rs Outdated Show resolved Hide resolved
@@ -14,7 +14,6 @@ fn main() {
let mut c = || {
//~^ ERROR: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
z.0.0.0 = format!("X1");
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 definitely not the error message we want-- we'd like the error to be reported on z.0.0.0, right? I think this may be related to my comment about the used_mut_upvars but I'm not 100% sure.

compiler/rustc_typeck/src/check/upvar.rs Show resolved Hide resolved
@arora-aman arora-aman force-pushed the restrict_precision branch 2 times, most recently from dc7edd1 to e6efc89 Compare December 24, 2020 07:02
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-9 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
.................................................................................................... 9000/11208
.................................................................................................... 9100/11208
..................................................................................................i. 9200/11208
.....i.............................................................................................. 9300/11208
.....................................iiiiii..iiiiii.i............................................... 9400/11208
.................................................................................................... 9600/11208
.................................................................................................... 9700/11208
.................................................................................................... 9800/11208
.................................................................................................... 9900/11208
---
i................................................................................................... 11200/11208
........
failures:

---- [ui] ui/closures/2229_closure_analysis/by_value.rs stdout ----

1 error[E0658]: attributes on expressions are experimental
-   --> $DIR/by_value.rs:20:13
+   --> $DIR/by_value.rs:22:13
+   --> $DIR/by_value.rs:22:13
3    |
4 LL |     let c = #[rustc_capture_analysis]

17    = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
18 
18 
19 error: First Pass analysis includes:
-   --> $DIR/by_value.rs:23:5
+   --> $DIR/by_value.rs:25:5
22 LL | /     || {
23 LL | |

29    | |_____^
29    | |_____^
30    |
31 note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
-   --> $DIR/by_value.rs:26:17
+   --> $DIR/by_value.rs:28:17
34 LL |         let p = t.0.0;
35    |                 ^^^^^


36 note: Capturing t[(1, 0)] -> ImmBorrow
-   --> $DIR/by_value.rs:29:29
+   --> $DIR/by_value.rs:31:29
38    |
39 LL |         println!("{} {:?}", t.1, p);

41 
41 
42 error: Min Capture analysis includes:
-   --> $DIR/by_value.rs:23:5
+   --> $DIR/by_value.rs:25:5
45 LL | /     || {
46 LL | |

52    | |_____^
52    | |_____^
53    |
54 note: Min Capture t[(0, 0)] -> ByValue
-   --> $DIR/by_value.rs:26:17
+   --> $DIR/by_value.rs:28:17
57 LL |         let p = t.0.0;
58    |                 ^^^^^


59 note: Min Capture t[(1, 0)] -> ImmBorrow
-   --> $DIR/by_value.rs:29:29
+   --> $DIR/by_value.rs:31:29
61    |
62 LL |         println!("{} {:?}", t.1, p);


The actual stderr differed from the expected stderr.
The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/closures/2229_closure_analysis/by_value/by_value.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args closures/2229_closure_analysis/by_value.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/closures/2229_closure_analysis/by_value.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zemit-future-incompat-report" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/closures/2229_closure_analysis/by_value" "-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/closures/2229_closure_analysis/by_value/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
error[E0658]: attributes on expressions are experimental
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:22:13
   |
LL |     let c = #[rustc_capture_analysis]
   |
   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable

warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:5:12
   |
LL | #![feature(capture_disjoint_fields)]
   |
   = note: `#[warn(incomplete_features)]` on by default
   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information


error: First Pass analysis includes:
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:25:5
LL | /     || {
LL | /     || {
LL | |     //~^ First Pass analysis includes:
LL | |     //~| Min Capture analysis includes:
LL | |         let p = t.0.0;
...  |
LL | |         //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow
LL | |     };
   |
   |
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:28:17
LL |         let p = t.0.0;
   |                 ^^^^^
   |                 ^^^^^
note: Capturing t[(1, 0)] -> ImmBorrow
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:31:29
   |
LL |         println!("{} {:?}", t.1, p);


error: Min Capture analysis includes:
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:25:5
LL | /     || {
LL | /     || {
LL | |     //~^ First Pass analysis includes:
LL | |     //~| Min Capture analysis includes:
LL | |         let p = t.0.0;
...  |
LL | |         //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow
LL | |     };
   |
   |
note: Min Capture t[(0, 0)] -> ByValue
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:28:17
LL |         let p = t.0.0;
   |                 ^^^^^
   |                 ^^^^^
note: Min Capture t[(1, 0)] -> ImmBorrow
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:31:29
   |
LL |         println!("{} {:?}", t.1, p);

error: aborting due to 3 previous errors; 1 warning emitted

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

Some tests failed in compiletest suite=ui mode=ui host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu


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" "--suite" "ui" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-9/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" "9.0.0" "--llvm-components" "aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils aggressiveinstcombine all all-targets amdgpu amdgpuasmparser amdgpucodegen amdgpudesc amdgpudisassembler amdgpuinfo amdgpuutils analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils asmparser asmprinter avr avrasmparser avrcodegen avrdesc avrdisassembler avrinfo binaryformat bitreader bitstreamreader bitwriter bpf bpfasmparser bpfcodegen bpfdesc bpfdisassembler bpfinfo codegen core coroutines coverage debuginfocodeview debuginfodwarf debuginfogsym debuginfomsf debuginfopdb demangle dlltooldriver engine executionengine fuzzmutate globalisel hexagon hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo instcombine instrumentation interpreter ipo irreader jitlink lanai lanaiasmparser lanaicodegen lanaidesc lanaidisassembler lanaiinfo libdriver lineeditor linker lto mc mca mcdisassembler mcjit mcparser mips mipsasmparser mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430 msp430asmparser msp430codegen msp430desc msp430disassembler msp430info native nativecodegen nvptx nvptxcodegen nvptxdesc nvptxinfo objcarcopts object objectyaml option orcjit passes perfjitevents powerpc powerpcasmparser powerpccodegen powerpcdesc powerpcdisassembler powerpcinfo profiledata remarks riscv riscvasmparser riscvcodegen riscvdesc riscvdisassembler riscvinfo riscvutils runtimedyld scalaropts selectiondag sparc sparcasmparser sparccodegen sparcdesc sparcdisassembler sparcinfo support symbolize systemz systemzasmparser systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen target textapi transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler webassemblyinfo windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info x86utils xcore xcorecodegen xcoredesc xcoredisassembler xcoreinfo xray" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"


failed to run: /checkout/obj/build/bootstrap/debug/bootstrap --stage 2 test --exclude src/tools/tidy
Build completed unsuccessfully in 0:17:31

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-9 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
i................................................................................................... 11200/11208
........
failures:

---- [ui] ui/closures/2229_closure_analysis/by_value.rs stdout ----

1 error[E0658]: attributes on expressions are experimental
-   --> $DIR/by_value.rs:20:13
+   --> $DIR/by_value.rs:22:13
+   --> $DIR/by_value.rs:22:13
3    |
4 LL |     let c = #[rustc_capture_analysis]


The actual stderr differed from the expected stderr.
The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/closures/2229_closure_analysis/by_value/by_value.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args closures/2229_closure_analysis/by_value.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/closures/2229_closure_analysis/by_value.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zemit-future-incompat-report" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/closures/2229_closure_analysis/by_value" "-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/closures/2229_closure_analysis/by_value/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
error[E0658]: attributes on expressions are experimental
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:22:13
   |
LL |     let c = #[rustc_capture_analysis]
   |
   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable

warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:5:12
   |
LL | #![feature(capture_disjoint_fields)]
   |
   = note: `#[warn(incomplete_features)]` on by default
   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information


error: First Pass analysis includes:
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:25:5
LL | /     || {
LL | /     || {
LL | |     //~^ First Pass analysis includes:
LL | |     //~| Min Capture analysis includes:
LL | |         let p = t.0.0;
...  |
LL | |         //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow
LL | |     };
   |
   |
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:28:17
LL |         let p = t.0.0;
   |                 ^^^^^
   |                 ^^^^^
note: Capturing t[(1, 0)] -> ImmBorrow
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:31:29
   |
LL |         println!("{} {:?}", t.1, p);


error: Min Capture analysis includes:
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:25:5
LL | /     || {
LL | /     || {
LL | |     //~^ First Pass analysis includes:
LL | |     //~| Min Capture analysis includes:
LL | |         let p = t.0.0;
...  |
LL | |         //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow
LL | |     };
   |
   |
note: Min Capture t[(0, 0)] -> ByValue
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:28:17
LL |         let p = t.0.0;
   |                 ^^^^^
   |                 ^^^^^
note: Min Capture t[(1, 0)] -> ImmBorrow
  --> /checkout/src/test/ui/closures/2229_closure_analysis/by_value.rs:31:29
   |
LL |         println!("{} {:?}", t.1, p);

error: aborting due to 3 previous errors; 1 warning emitted

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

Some tests failed in compiletest suite=ui mode=ui host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu


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" "--suite" "ui" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-9/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" "9.0.0" "--llvm-components" "aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils aggressiveinstcombine all all-targets amdgpu amdgpuasmparser amdgpucodegen amdgpudesc amdgpudisassembler amdgpuinfo amdgpuutils analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils asmparser asmprinter avr avrasmparser avrcodegen avrdesc avrdisassembler avrinfo binaryformat bitreader bitstreamreader bitwriter bpf bpfasmparser bpfcodegen bpfdesc bpfdisassembler bpfinfo codegen core coroutines coverage debuginfocodeview debuginfodwarf debuginfogsym debuginfomsf debuginfopdb demangle dlltooldriver engine executionengine fuzzmutate globalisel hexagon hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo instcombine instrumentation interpreter ipo irreader jitlink lanai lanaiasmparser lanaicodegen lanaidesc lanaidisassembler lanaiinfo libdriver lineeditor linker lto mc mca mcdisassembler mcjit mcparser mips mipsasmparser mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430 msp430asmparser msp430codegen msp430desc msp430disassembler msp430info native nativecodegen nvptx nvptxcodegen nvptxdesc nvptxinfo objcarcopts object objectyaml option orcjit passes perfjitevents powerpc powerpcasmparser powerpccodegen powerpcdesc powerpcdisassembler powerpcinfo profiledata remarks riscv riscvasmparser riscvcodegen riscvdesc riscvdisassembler riscvinfo riscvutils runtimedyld scalaropts selectiondag sparc sparcasmparser sparccodegen sparcdesc sparcdisassembler sparcinfo support symbolize systemz systemzasmparser systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen target textapi transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler webassemblyinfo windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info x86utils xcore xcorecodegen xcoredesc xcoredisassembler xcoreinfo xray" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"


failed to run: /checkout/obj/build/bootstrap/debug/bootstrap --stage 2 test --exclude src/tools/tidy
Build completed unsuccessfully in 0:18:02

// The place isn't mutable once we dereference a immutable reference.
ty::Ref(.., hir::Mutability::Not) => return hir::Mutability::Not,

_ => (),
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm assuming you meant Adt(boxed)

for (i, proj) in place.projections.iter().enumerate() {
if proj.ty.is_unsafe_ptr() {
// Don't apply any projections on top of an unsafe ptr
truncated_length = truncated_length.min(i + 1);
Copy link
Member Author

@arora-aman arora-aman Dec 26, 2020

Choose a reason for hiding this comment

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

I went with this approach here because either we need to do a checked_add or init unsafe_ptr_idx = usize::MAX - 1. compared to the two, this seemed clearer.

let c = || {
//~^ ERROR: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference
**ref_mref_x = y;
//~^ERROR: cannot assign to `ref_mref_x`, as it is not declared as mutable
Copy link
Member Author

Choose a reason for hiding this comment

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

This gets hacked away as well in a later commit.

let c = || {
//~^ ERROR: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference
**mref_ref_x = y;
//~^ERROR: cannot assign to `mref_ref_x`, as it is not declared as mutable
Copy link
Member Author

Choose a reason for hiding this comment

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

This gets hacked away as well in a later commit.

@bors
Copy link
Contributor

bors commented Dec 30, 2020

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

@arora-aman
Copy link
Member Author

Conflicts should be resolved now

@bors
Copy link
Contributor

bors commented Jan 17, 2021

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

#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct CapturedPlace<'tcx> {
/// The `Place` that is captured.
Copy link
Contributor

Choose a reason for hiding this comment

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

I love how you're adding comments here btw 😍

}

impl CapturedPlace<'tcx> {
pub fn get_root_variable(&self) -> hir::HirId {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to see a comment here, something like

/// Returns the hir-id of the root variable for the captured place. e.g., if a.b.c was captured, would return the hir-id for a.

#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct CapturedPlace<'tcx> {
/// The `Place` that is captured.
Copy link
Contributor

Choose a reason for hiding this comment

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

So happy to see added comments 😍

@@ -1374,13 +1358,38 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {

fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
let propagate_closure_used_mut_place = |this: &mut Self, place: Place<'tcx>| {
if !place.projection.is_empty() {
if let Some(field) = this.is_upvar_field_projection(place.as_ref()) {
// We have three possiblities here:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// We have three possiblities here:
// We have three possibilities here:

// We have three possiblities here:
// a. We are modifying something through a mut-ref
// b. We are modifying something that is local to our parent
// c. Current body is a nested clsoure, and we are modifying path starting from
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// c. Current body is a nested clsoure, and we are modifying path starting from
// c. Current body is a nested closure, and we are modifying a path starting from

@nikomatsakis
Copy link
Contributor

@bors delegate+

Left a few nits but this looks good. @arora-aman, you wanted to make a final change as well, right? Feel free to r=nikomatsakis afterwards.

@bors
Copy link
Contributor

bors commented Jan 28, 2021

✌️ @arora-aman can now approve this pull request

- No Derefs in move closure, this will result in value behind a reference getting moved.
- No projections are applied to raw pointers, since these require unsafe blocks. We capture
  them completely.

Motivations for these are recorded here: https://hackmd.io/71qq-IOpTNqzMkPpAI1dVg?view
When `capture_disjoint_fields` is not enabled, checking if the root variable
binding is mutable would suffice.

However with the feature enabled, the captured place might be mutable
because it dereferences a mutable reference.

This PR computes the mutability of each capture after capture analysis
in rustc_typeck. We store this in `ty::CapturedPlace` and then use
`ty::CapturedPlace::mutability` in mir_build and borrow_check.
@arora-aman
Copy link
Member Author

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Jan 29, 2021

📌 Commit 0f4bab2 has been approved by nikomatsakis

@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-review Status: Awaiting review from the assignee but also interested parties. labels Jan 29, 2021
m-ou-se added a commit to m-ou-se/rust that referenced this pull request Jan 30, 2021
…ikomatsakis

2229: Fix issues with move closures and mutability

This PR fixes two issues when feature `capture_disjoint_fields` is used.

1. Can't mutate using a mutable reference
2. Move closures try to move value out through a reference.

To do so, we
1. Compute the mutability of the capture and store it as part of the `CapturedPlace`  that is written in TypeckResults
2. Restrict capture precision. Note this is temporary for now, to allow the feature to be used with move closures and ByValue captures and might change depending on discussions with the lang team.
    - No Derefs are captured for ByValue captures, since that will result in value behind a reference getting moved.
    - No projections are applied to raw pointers since these require unsafe blocks. We capture
    them completely.

r? `@nikomatsakis`
This was referenced Jan 31, 2021
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 31, 2021
…as-schievink

Rollup of 11 pull requests

Successful merges:

 - rust-lang#80092 (2229: Fix issues with move closures and mutability)
 - rust-lang#80404 (Remove const_in_array_repeat)
 - rust-lang#81255 (Don't link with --export-dynamic on wasm32-wasi)
 - rust-lang#81480 (Add suggestion for nested fields)
 - rust-lang#81549 (Misc ip documentation fixes)
 - rust-lang#81566 (Add a test for rust-lang#71202)
 - rust-lang#81568 (Fix an old FIXME in redundant paren lint)
 - rust-lang#81571 (Fix typo in E0759)
 - rust-lang#81572 (Edit multiple error code Markdown files)
 - rust-lang#81589 (Fix small typo in string.rs)
 - rust-lang#81590 (Stabilize int_bits_const)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 7e3a8ec into rust-lang:master Feb 1, 2021
@rustbot rustbot added this to the 1.51.0 milestone Feb 1, 2021
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.

6 participants