Skip to content

Commit d4f263a

Browse files
committed
Auto merge of #88467 - sexxi-goose:issue-88431, r=nikomatsakis
2229: Drop any deref in move closure Fixes: #88431 r? `@nikomatsakis`
2 parents 1e37e83 + 793fbc7 commit d4f263a

File tree

6 files changed

+77
-52
lines changed

6 files changed

+77
-52
lines changed

compiler/rustc_typeck/src/check/upvar.rs

+7-18
Original file line numberDiff line numberDiff line change
@@ -1901,31 +1901,20 @@ fn restrict_capture_precision<'tcx>(
19011901
return (place, curr_mode);
19021902
}
19031903

1904-
/// Take ownership if data being accessed is owned by the variable used to access it
1905-
/// (or if closure attempts to move data that it doesn’t own).
1906-
/// Note: When taking ownership, only capture data found on the stack.
1904+
/// Truncate deref of any reference.
19071905
fn adjust_for_move_closure<'tcx>(
19081906
mut place: Place<'tcx>,
19091907
mut kind: ty::UpvarCapture<'tcx>,
19101908
) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
1911-
let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
19121909
let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
19131910

1914-
match kind {
1915-
ty::UpvarCapture::ByRef(..) if contains_deref_of_ref => (place, kind),
1916-
1917-
// If there's any Deref and the data needs to be moved into the closure body,
1918-
// or it's a Deref of a Box, truncate the path to the first deref
1919-
_ => {
1920-
if let Some(idx) = first_deref {
1921-
truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
1922-
}
1923-
1924-
// AMAN: I think we don't need the span inside the ByValue anymore
1925-
// we have more detailed span in CaptureInfo
1926-
(place, ty::UpvarCapture::ByValue(None))
1927-
}
1911+
if let Some(idx) = first_deref {
1912+
truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
19281913
}
1914+
1915+
// AMAN: I think we don't need the span inside the ByValue anymore
1916+
// we have more detailed span in CaptureInfo
1917+
(place, ty::UpvarCapture::ByValue(None))
19291918
}
19301919

19311920
/// Adjust closure capture just that if taking ownership of data, only move data

src/test/ui/closures/2229_closure_analysis/move_closure.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn simple_ref() {
3535
//~| ERROR: Min Capture analysis includes:
3636
*ref_s += 10;
3737
//~^ NOTE: Capturing ref_s[Deref] -> MutBorrow
38-
//~| NOTE: Min Capture ref_s[Deref] -> MutBorrow
38+
//~| NOTE: Min Capture ref_s[] -> ByValue
3939
};
4040
c();
4141
}
@@ -56,7 +56,7 @@ fn struct_contains_ref_to_another_struct_1() {
5656
//~| ERROR: Min Capture analysis includes:
5757
t.0.0 = "new s".into();
5858
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow
59-
//~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> MutBorrow
59+
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
6060
};
6161

6262
c();
@@ -79,7 +79,7 @@ fn struct_contains_ref_to_another_struct_2() {
7979
//~| ERROR: Min Capture analysis includes:
8080
let _t = t.0.0;
8181
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
82-
//~| NOTE: Min Capture t[(0, 0),Deref] -> ImmBorrow
82+
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
8383
};
8484

8585
c();
@@ -175,7 +175,7 @@ fn box_mut_1() {
175175
//~| First Pass analysis includes:
176176
//~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
177177
//~| Min Capture analysis includes:
178-
//~| NOTE: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
178+
//~| NOTE: Min Capture box_p_foo[] -> ByValue
179179
}
180180

181181
// Ensure that even in move closures, if the data is not owned by the root variable
@@ -192,7 +192,7 @@ fn box_mut_2() {
192192
//~| First Pass analysis includes:
193193
//~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow
194194
//~| Min Capture analysis includes:
195-
//~| NOTE: Min Capture p_foo[Deref,Deref,(0, 0)] -> MutBorrow
195+
//~| NOTE: Min Capture p_foo[] -> ByValue
196196
}
197197

198198
// Test that move closures can take ownership of Copy type

src/test/ui/closures/2229_closure_analysis/move_closure.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ LL | |
187187
LL | | };
188188
| |_____^
189189
|
190-
note: Min Capture ref_s[Deref] -> MutBorrow
190+
note: Min Capture ref_s[] -> ByValue
191191
--> $DIR/move_closure.rs:36:9
192192
|
193193
LL | *ref_s += 10;
@@ -223,7 +223,7 @@ LL | |
223223
LL | | };
224224
| |_____^
225225
|
226-
note: Min Capture t[(0, 0),Deref,(0, 0)] -> MutBorrow
226+
note: Min Capture t[(0, 0)] -> ByValue
227227
--> $DIR/move_closure.rs:57:9
228228
|
229229
LL | t.0.0 = "new s".into();
@@ -259,7 +259,7 @@ LL | |
259259
LL | | };
260260
| |_____^
261261
|
262-
note: Min Capture t[(0, 0),Deref] -> ImmBorrow
262+
note: Min Capture t[(0, 0)] -> ByValue
263263
--> $DIR/move_closure.rs:80:18
264264
|
265265
LL | let _t = t.0.0;
@@ -427,7 +427,7 @@ error: Min Capture analysis includes:
427427
LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
428428
| ^^^^^^^^^^^^^^^^^^^^^^^^^
429429
|
430-
note: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
430+
note: Min Capture box_p_foo[] -> ByValue
431431
--> $DIR/move_closure.rs:172:47
432432
|
433433
LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
@@ -451,7 +451,7 @@ error: Min Capture analysis includes:
451451
LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
452452
| ^^^^^^^^^^^^^^^^^^^^^
453453
|
454-
note: Min Capture p_foo[Deref,Deref,(0, 0)] -> MutBorrow
454+
note: Min Capture p_foo[] -> ByValue
455455
--> $DIR/move_closure.rs:189:47
456456
|
457457
LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// edition:2021
2+
// check-pass
3+
4+
use std::collections::HashMap;
5+
use std::future::Future;
6+
use std::pin::Pin;
7+
8+
pub struct GameMode {}
9+
10+
struct GameStateManager<'a> {
11+
gamestate_stack: Vec<Box<dyn GameState<'a> + 'a>>,
12+
}
13+
14+
pub trait GameState<'a> {}
15+
16+
async fn construct_gamestate_replay<'a>(
17+
_gamemode: &GameMode,
18+
_factory: &mut GameStateManager<'a>,
19+
) -> Box<dyn GameState<'a> + 'a> {
20+
unimplemented!()
21+
}
22+
23+
type FutureGameState<'a, 'b> = Pin<Box<dyn Future<Output = Box<dyn GameState<'a> + 'a>> + 'b>>;
24+
25+
struct MenuOption<'a> {
26+
command: Box<dyn for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a>,
27+
}
28+
29+
impl<'a> MenuOption<'a> {
30+
fn new(
31+
_command: impl for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a,
32+
) -> Self {
33+
unimplemented!()
34+
}
35+
}
36+
37+
struct MenuState<'a> {
38+
options: Vec<MenuOption<'a>>,
39+
}
40+
41+
impl<'a> GameState<'a> for MenuState<'a> {}
42+
43+
pub async fn get_replay_menu<'a>(
44+
gamemodes: &'a HashMap<&str, GameMode>,
45+
) -> Box<dyn GameState<'a> + 'a> {
46+
let recordings: Vec<String> = vec![];
47+
let _ = recordings
48+
.into_iter()
49+
.map(|entry| {
50+
MenuOption::new(move |f| {
51+
Box::pin(construct_gamestate_replay(&gamemodes[entry.as_str()], f))
52+
})
53+
})
54+
.collect::<Vec<_>>();
55+
56+
todo!()
57+
}
58+
59+
fn main() {}

src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs

-23
Original file line numberDiff line numberDiff line change
@@ -56,28 +56,6 @@ fn no_ref_nested() {
5656
c();
5757
}
5858

59-
struct A<'a>(&'a mut String, &'a mut String);
60-
// Test that reborrowing works as expected for move closures
61-
// by attempting a disjoint capture through a reference.
62-
fn disjoint_via_ref() {
63-
let mut x = String::new();
64-
let mut y = String::new();
65-
66-
let mut a = A(&mut x, &mut y);
67-
let a = &mut a;
68-
69-
let mut c1 = move || {
70-
a.0.truncate(0);
71-
};
72-
73-
let mut c2 = move || {
74-
a.1.truncate(0);
75-
};
76-
77-
c1();
78-
c2();
79-
}
80-
8159
// Test that even if a path is moved into the closure, the closure is not FnOnce
8260
// if the path is not moved by the closure call.
8361
fn data_moved_but_not_fn_once() {
@@ -109,7 +87,6 @@ fn main() {
10987
no_ref();
11088
no_ref_nested();
11189

112-
disjoint_via_ref();
11390
data_moved_but_not_fn_once();
11491

11592
returned_closure_owns_copy_type_data();

src/test/ui/nll/closure-use-spans.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ LL | let y = &x;
2626
LL | x = 0;
2727
| ^^^^^ assignment to borrowed `x` occurs here
2828
LL | move || *y;
29-
| - borrow later captured here by closure
29+
| -- borrow later captured here by closure
3030

3131
error: aborting due to 3 previous errors
3232

0 commit comments

Comments
 (0)