about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-31 06:01:52 +0000
committerbors <bors@rust-lang.org>2021-08-31 06:01:52 +0000
commitd4f263a558d065d73e21ef1505ac391caa651f5d (patch)
tree02e42c4c346ba04329c88d59c99530af5c92ee92
parent1e37e83dc05a7c359ebb88188b0a2179a8ec9067 (diff)
parent793fbc73e8c14050d38469c3932b21cd172b8146 (diff)
downloadrust-d4f263a558d065d73e21ef1505ac391caa651f5d.tar.gz
rust-d4f263a558d065d73e21ef1505ac391caa651f5d.zip
Auto merge of #88467 - sexxi-goose:issue-88431, r=nikomatsakis
2229: Drop any deref in move closure

Fixes: #88431

r? `@nikomatsakis`
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs25
-rw-r--r--src/test/ui/closures/2229_closure_analysis/move_closure.rs10
-rw-r--r--src/test/ui/closures/2229_closure_analysis/move_closure.stderr10
-rw-r--r--src/test/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs59
-rw-r--r--src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs23
-rw-r--r--src/test/ui/nll/closure-use-spans.stderr2
6 files changed, 77 insertions, 52 deletions
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index bb8d2ecdcf0..75fd545060c 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -1901,31 +1901,20 @@ fn restrict_capture_precision<'tcx>(
     return (place, curr_mode);
 }
 
-/// Take ownership if data being accessed is owned by the variable used to access it
-/// (or if closure attempts to move data that it doesn’t own).
-/// Note: When taking ownership, only capture data found on the stack.
+/// Truncate deref of any reference.
 fn adjust_for_move_closure<'tcx>(
     mut place: Place<'tcx>,
     mut kind: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
-    let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
     let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
 
-    match kind {
-        ty::UpvarCapture::ByRef(..) if contains_deref_of_ref => (place, kind),
-
-        // If there's any Deref and the data needs to be moved into the closure body,
-        // or it's a Deref of a Box, truncate the path to the first deref
-        _ => {
-            if let Some(idx) = first_deref {
-                truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
-            }
-
-            // AMAN: I think we don't need the span inside the ByValue anymore
-            //       we have more detailed span in CaptureInfo
-            (place, ty::UpvarCapture::ByValue(None))
-        }
+    if let Some(idx) = first_deref {
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
     }
+
+    // AMAN: I think we don't need the span inside the ByValue anymore
+    //       we have more detailed span in CaptureInfo
+    (place, ty::UpvarCapture::ByValue(None))
 }
 
 /// Adjust closure capture just that if taking ownership of data, only move data
diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/move_closure.rs
index 6b49293e6d3..b542fa2430c 100644
--- a/src/test/ui/closures/2229_closure_analysis/move_closure.rs
+++ b/src/test/ui/closures/2229_closure_analysis/move_closure.rs
@@ -35,7 +35,7 @@ fn simple_ref() {
     //~| ERROR: Min Capture analysis includes:
         *ref_s += 10;
         //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow
-        //~| NOTE: Min Capture ref_s[Deref] -> MutBorrow
+        //~| NOTE: Min Capture ref_s[] -> ByValue
     };
     c();
 }
@@ -56,7 +56,7 @@ fn struct_contains_ref_to_another_struct_1() {
     //~| ERROR: Min Capture analysis includes:
         t.0.0 = "new s".into();
         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow
-        //~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> MutBorrow
+        //~| NOTE: Min Capture t[(0, 0)] -> ByValue
     };
 
     c();
@@ -79,7 +79,7 @@ fn struct_contains_ref_to_another_struct_2() {
     //~| ERROR: Min Capture analysis includes:
         let _t = t.0.0;
         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture t[(0, 0),Deref] -> ImmBorrow
+        //~| NOTE: Min Capture t[(0, 0)] -> ByValue
     };
 
     c();
@@ -175,7 +175,7 @@ fn box_mut_1() {
     //~| First Pass analysis includes:
     //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
     //~| Min Capture analysis includes:
-    //~| NOTE: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+    //~| NOTE: Min Capture box_p_foo[] -> ByValue
 }
 
 // Ensure that even in move closures, if the data is not owned by the root variable
@@ -192,7 +192,7 @@ fn box_mut_2() {
     //~| First Pass analysis includes:
     //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow
     //~| Min Capture analysis includes:
-    //~| NOTE: Min Capture p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+    //~| NOTE: Min Capture p_foo[] -> ByValue
 }
 
 // Test that move closures can take ownership of Copy type
diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr
index b99b451a171..fd80e05c689 100644
--- a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr
@@ -187,7 +187,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture ref_s[Deref] -> MutBorrow
+note: Min Capture ref_s[] -> ByValue
   --> $DIR/move_closure.rs:36:9
    |
 LL |         *ref_s += 10;
@@ -223,7 +223,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0),Deref,(0, 0)] -> MutBorrow
+note: Min Capture t[(0, 0)] -> ByValue
   --> $DIR/move_closure.rs:57:9
    |
 LL |         t.0.0 = "new s".into();
@@ -259,7 +259,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0),Deref] -> ImmBorrow
+note: Min Capture t[(0, 0)] -> ByValue
   --> $DIR/move_closure.rs:80:18
    |
 LL |         let _t = t.0.0;
@@ -427,7 +427,7 @@ error: Min Capture analysis includes:
 LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+note: Min Capture box_p_foo[] -> ByValue
   --> $DIR/move_closure.rs:172:47
    |
 LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
@@ -451,7 +451,7 @@ error: Min Capture analysis includes:
 LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
    |                                       ^^^^^^^^^^^^^^^^^^^^^
    |
-note: Min Capture p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+note: Min Capture p_foo[] -> ByValue
   --> $DIR/move_closure.rs:189:47
    |
 LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs
new file mode 100644
index 00000000000..99962053077
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs
@@ -0,0 +1,59 @@
+// edition:2021
+// check-pass
+
+use std::collections::HashMap;
+use std::future::Future;
+use std::pin::Pin;
+
+pub struct GameMode {}
+
+struct GameStateManager<'a> {
+    gamestate_stack: Vec<Box<dyn GameState<'a> + 'a>>,
+}
+
+pub trait GameState<'a> {}
+
+async fn construct_gamestate_replay<'a>(
+    _gamemode: &GameMode,
+    _factory: &mut GameStateManager<'a>,
+) -> Box<dyn GameState<'a> + 'a> {
+    unimplemented!()
+}
+
+type FutureGameState<'a, 'b> = Pin<Box<dyn Future<Output = Box<dyn GameState<'a> + 'a>> + 'b>>;
+
+struct MenuOption<'a> {
+    command: Box<dyn for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a>,
+}
+
+impl<'a> MenuOption<'a> {
+    fn new(
+        _command: impl for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a,
+    ) -> Self {
+        unimplemented!()
+    }
+}
+
+struct MenuState<'a> {
+    options: Vec<MenuOption<'a>>,
+}
+
+impl<'a> GameState<'a> for MenuState<'a> {}
+
+pub async fn get_replay_menu<'a>(
+    gamemodes: &'a HashMap<&str, GameMode>,
+) -> Box<dyn GameState<'a> + 'a> {
+    let recordings: Vec<String> = vec![];
+    let _ = recordings
+        .into_iter()
+        .map(|entry| {
+            MenuOption::new(move |f| {
+                Box::pin(construct_gamestate_replay(&gamemodes[entry.as_str()], f))
+            })
+        })
+        .collect::<Vec<_>>();
+
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
index e1b61e85ec1..f76965bdd3f 100644
--- a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
+++ b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
@@ -56,28 +56,6 @@ fn no_ref_nested() {
     c();
 }
 
-struct A<'a>(&'a mut String,  &'a mut String);
-// Test that reborrowing works as expected for move closures
-// by attempting a disjoint capture through a reference.
-fn disjoint_via_ref() {
-    let mut x = String::new();
-    let mut y = String::new();
-
-    let mut a = A(&mut x, &mut y);
-    let a = &mut a;
-
-    let mut c1 = move || {
-        a.0.truncate(0);
-    };
-
-    let mut c2 = move || {
-        a.1.truncate(0);
-    };
-
-    c1();
-    c2();
-}
-
 // Test that even if a path is moved into the closure, the closure is not FnOnce
 // if the path is not moved by the closure call.
 fn data_moved_but_not_fn_once() {
@@ -109,7 +87,6 @@ fn main() {
     no_ref();
     no_ref_nested();
 
-    disjoint_via_ref();
     data_moved_but_not_fn_once();
 
     returned_closure_owns_copy_type_data();
diff --git a/src/test/ui/nll/closure-use-spans.stderr b/src/test/ui/nll/closure-use-spans.stderr
index 87162904ba6..ad928f1bbc9 100644
--- a/src/test/ui/nll/closure-use-spans.stderr
+++ b/src/test/ui/nll/closure-use-spans.stderr
@@ -26,7 +26,7 @@ LL |     let y = &x;
 LL |     x = 0;
    |     ^^^^^ assignment to borrowed `x` occurs here
 LL |     move || *y;
-   |              - borrow later captured here by closure
+   |             -- borrow later captured here by closure
 
 error: aborting due to 3 previous errors