Skip to content

Commit 821dcc7

Browse files
committed
Use closure parse code
1 parent 1abed7b commit 821dcc7

File tree

20 files changed

+161
-59
lines changed

20 files changed

+161
-59
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,6 +1710,11 @@ pub enum CaptureBy {
17101710
},
17111711
/// `move` keyword was not specified.
17121712
Ref,
1713+
/// `use |x| y + x`.
1714+
Use {
1715+
/// The span of the `use` keyword.
1716+
use_kw: Span,
1717+
},
17131718
}
17141719

17151720
/// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`.

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,6 +1867,9 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
18671867
CaptureBy::Value { move_kw } => {
18681868
vis.visit_span(move_kw);
18691869
}
1870+
CaptureBy::Use { use_kw } => {
1871+
vis.visit_span(use_kw);
1872+
}
18701873
}
18711874
}
18721875

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -251,31 +251,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
251251
body,
252252
fn_decl_span,
253253
fn_arg_span,
254-
}) => match coroutine_kind {
255-
Some(coroutine_kind) => self.lower_expr_coroutine_closure(
256-
binder,
257-
*capture_clause,
258-
e.id,
259-
expr_hir_id,
260-
*coroutine_kind,
261-
fn_decl,
262-
body,
263-
*fn_decl_span,
264-
*fn_arg_span,
265-
),
266-
None => self.lower_expr_closure(
267-
binder,
268-
*capture_clause,
269-
e.id,
270-
expr_hir_id,
271-
*constness,
272-
*movability,
273-
fn_decl,
274-
body,
275-
*fn_decl_span,
276-
*fn_arg_span,
277-
),
278-
},
254+
}) => {
255+
if matches!(capture_clause, hir::CaptureBy::Use { .. })
256+
&& !self.tcx.features().ergonomic_clones()
257+
{
258+
rustc_session::parse::feature_err(
259+
&self.tcx.sess,
260+
sym::ergonomic_clones,
261+
*fn_decl_span,
262+
fluent_generated::ast_lowering_ergonomic_clones,
263+
)
264+
.emit();
265+
}
266+
267+
match coroutine_kind {
268+
Some(coroutine_kind) => self.lower_expr_coroutine_closure(
269+
binder,
270+
*capture_clause,
271+
e.id,
272+
expr_hir_id,
273+
*coroutine_kind,
274+
fn_decl,
275+
body,
276+
*fn_decl_span,
277+
*fn_arg_span,
278+
),
279+
None => self.lower_expr_closure(
280+
binder,
281+
*capture_clause,
282+
e.id,
283+
expr_hir_id,
284+
*constness,
285+
*movability,
286+
fn_decl,
287+
body,
288+
*fn_decl_span,
289+
*fn_arg_span,
290+
),
291+
}
292+
}
279293
ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
280294
let desugaring_kind = match genblock_kind {
281295
GenBlockKind::Async => hir::CoroutineDesugaring::Async,

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,7 @@ impl<'a> State<'a> {
886886
fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
887887
match capture_clause {
888888
ast::CaptureBy::Value { .. } => self.word_space("move"),
889+
ast::CaptureBy::Use { .. } => self.word_space("use"),
889890
ast::CaptureBy::Ref => {}
890891
}
891892
}

compiler/rustc_borrowck/src/borrowck_errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
403403
.expect_closure();
404404
let span = match capture_clause {
405405
rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
406+
rustc_hir::CaptureBy::Use { use_kw } => use_kw.shrink_to_lo(),
406407
rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
407408
};
408409
diag.span_suggestion_verbose(

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,7 @@ impl<'a> State<'a> {
21572157
fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
21582158
match capture_clause {
21592159
hir::CaptureBy::Value { .. } => self.word_space("move"),
2160+
hir::CaptureBy::Use { .. } => self.word_space("use"),
21602161
hir::CaptureBy::Ref => {}
21612162
}
21622163
}

compiler/rustc_hir_typeck/src/upvar.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
666666
origin = updated.1;
667667

668668
let (place, capture_kind) = match capture_clause {
669-
hir::CaptureBy::Value { .. } => adjust_for_move_closure(place, capture_kind),
669+
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. } => {
670+
adjust_for_move_closure(place, capture_kind)
671+
}
670672
hir::CaptureBy::Ref => adjust_for_non_move_closure(place, capture_kind),
671673
};
672674

@@ -1161,7 +1163,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11611163

11621164
let ty = match closure_clause {
11631165
hir::CaptureBy::Value { .. } => ty, // For move closure the capture kind should be by value
1164-
hir::CaptureBy::Ref => {
1166+
hir::CaptureBy::Ref | hir::CaptureBy::Use { .. } => {
11651167
// For non move closure the capture kind is the max capture kind of all captures
11661168
// according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue
11671169
let mut max_capture_info = root_var_min_capture_list.first().unwrap().info;
@@ -1288,7 +1290,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12881290
.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
12891291
return Some(diagnostics_info);
12901292
}
1291-
hir::CaptureBy::Ref => {}
1293+
hir::CaptureBy::Ref | hir::CaptureBy::Use { .. } => {}
12921294
}
12931295

12941296
return None;
@@ -1685,10 +1687,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16851687
//
16861688
// If the data will be moved out of this place, then the place will be truncated
16871689
// at the first Deref in `adjust_for_move_closure` and then moved into the closure.
1688-
hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => {
1690+
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. }
1691+
if !place.deref_tys().any(Ty::is_ref) =>
1692+
{
16891693
ty::UpvarCapture::ByValue
16901694
}
1691-
hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => {
1695+
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. } | hir::CaptureBy::Ref => {
16921696
ty::UpvarCapture::ByRef(BorrowKind::Immutable)
16931697
}
16941698
}

compiler/rustc_parse/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 20
2626
parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
2727
.suggestion = try switching the order
2828
29+
parse_async_use_order_incorrect = the order of `use` and `async` is incorrect
30+
.suggestion = try switching the order
31+
2932
parse_at_dot_dot_in_struct_pattern = `@ ..` is not supported in struct patterns
3033
.suggestion = bind to each field separately or, if you don't need them, just remove `{$ident} @`
3134

compiler/rustc_parse/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,14 @@ pub(crate) struct AsyncMoveOrderIncorrect {
15231523
pub span: Span,
15241524
}
15251525

1526+
#[derive(Diagnostic)]
1527+
#[diag(parse_async_use_order_incorrect)]
1528+
pub(crate) struct AsyncUseOrderIncorrect {
1529+
#[primary_span]
1530+
#[suggestion(style = "verbose", code = "async use", applicability = "maybe-incorrect")]
1531+
pub span: Span,
1532+
}
1533+
15261534
#[derive(Diagnostic)]
15271535
#[diag(parse_double_colon_in_bound)]
15281536
pub(crate) struct DoubleColonInBound {

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,7 @@ impl<'a> Parser<'a> {
14461446
} else if this.check_path() {
14471447
this.parse_expr_path_start()
14481448
} else if this.check_keyword(kw::Move)
1449+
|| this.check_keyword(kw::Use)
14491450
|| this.check_keyword(kw::Static)
14501451
|| this.check_const_closure()
14511452
{
@@ -2449,6 +2450,15 @@ impl<'a> Parser<'a> {
24492450
} else {
24502451
Ok(CaptureBy::Value { move_kw: move_kw_span })
24512452
}
2453+
} else if self.eat_keyword(kw::Use) {
2454+
let use_kw_span = self.prev_token.span;
2455+
// Check for `use async` and recover
2456+
if self.check_keyword(kw::Async) {
2457+
let use_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
2458+
Err(self.dcx().create_err(errors::AsyncUseOrderIncorrect { span: use_async_span }))
2459+
} else {
2460+
Ok(CaptureBy::Use { use_kw: use_kw_span })
2461+
}
24522462
} else {
24532463
Ok(CaptureBy::Ref)
24542464
}

0 commit comments

Comments
 (0)