Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 81a926c

Browse files
committed
Use closure parse code
1 parent 05c5164 commit 81a926c

File tree

20 files changed

+133
-64
lines changed

20 files changed

+133
-64
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,11 @@ pub enum CaptureBy {
17621762
},
17631763
/// `move` keyword was not specified.
17641764
Ref,
1765+
/// `use |x| y + x`.
1766+
Use {
1767+
/// The span of the `use` keyword.
1768+
use_kw: Span,
1769+
},
17651770
}
17661771

17671772
/// 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
@@ -1899,6 +1899,9 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
18991899
CaptureBy::Value { move_kw } => {
19001900
vis.visit_span(move_kw);
19011901
}
1902+
CaptureBy::Use { use_kw } => {
1903+
vis.visit_span(use_kw);
1904+
}
19021905
}
19031906
}
19041907

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,7 @@ impl<'a> State<'a> {
893893
fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
894894
match capture_clause {
895895
ast::CaptureBy::Value { .. } => self.word_space("move"),
896+
ast::CaptureBy::Use { .. } => self.word_space("use"),
896897
ast::CaptureBy::Ref => {}
897898
}
898899
}

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
@@ -2305,6 +2305,7 @@ impl<'a> State<'a> {
23052305
fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
23062306
match capture_clause {
23072307
hir::CaptureBy::Value { .. } => self.word_space("move"),
2308+
hir::CaptureBy::Use { .. } => self.word_space("use"),
23082309
hir::CaptureBy::Ref => {}
23092310
}
23102311
}

compiler/rustc_hir_typeck/src/upvar.rs

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

672672
let (place, capture_kind) = match capture_clause {
673-
hir::CaptureBy::Value { .. } => adjust_for_move_closure(place, capture_kind),
673+
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. } => {
674+
adjust_for_move_closure(place, capture_kind)
675+
}
674676
hir::CaptureBy::Ref => adjust_for_non_move_closure(place, capture_kind),
675677
};
676678

@@ -1165,7 +1167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11651167

11661168
let ty = match closure_clause {
11671169
hir::CaptureBy::Value { .. } => ty, // For move closure the capture kind should be by value
1168-
hir::CaptureBy::Ref => {
1170+
hir::CaptureBy::Ref | hir::CaptureBy::Use { .. } => {
11691171
// For non move closure the capture kind is the max capture kind of all captures
11701172
// according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue
11711173
let mut max_capture_info = root_var_min_capture_list.first().unwrap().info;
@@ -1292,7 +1294,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12921294
.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
12931295
return Some(diagnostics_info);
12941296
}
1295-
hir::CaptureBy::Ref => {}
1297+
hir::CaptureBy::Ref | hir::CaptureBy::Use { .. } => {}
12961298
}
12971299

12981300
return None;
@@ -1689,10 +1691,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16891691
//
16901692
// If the data will be moved out of this place, then the place will be truncated
16911693
// at the first Deref in `adjust_for_move_closure` and then moved into the closure.
1692-
hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => {
1694+
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. }
1695+
if !place.deref_tys().any(Ty::is_ref) =>
1696+
{
16931697
ty::UpvarCapture::ByValue
16941698
}
1695-
hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => {
1699+
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. } | hir::CaptureBy::Ref => {
16961700
ty::UpvarCapture::ByRef(BorrowKind::Immutable)
16971701
}
16981702
}

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
@@ -1512,6 +1512,14 @@ pub(crate) struct AsyncMoveOrderIncorrect {
15121512
pub span: Span,
15131513
}
15141514

1515+
#[derive(Diagnostic)]
1516+
#[diag(parse_async_use_order_incorrect)]
1517+
pub(crate) struct AsyncUseOrderIncorrect {
1518+
#[primary_span]
1519+
#[suggestion(style = "verbose", code = "async use", applicability = "maybe-incorrect")]
1520+
pub span: Span,
1521+
}
1522+
15151523
#[derive(Diagnostic)]
15161524
#[diag(parse_double_colon_in_bound)]
15171525
pub(crate) struct DoubleColonInBound {

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,7 @@ impl<'a> Parser<'a> {
14041404
} else if this.check_path() {
14051405
this.parse_expr_path_start()
14061406
} else if this.check_keyword(exp!(Move))
1407+
|| this.check_keyword(exp!(Use))
14071408
|| this.check_keyword(exp!(Static))
14081409
|| this.check_const_closure()
14091410
{
@@ -2395,7 +2396,7 @@ impl<'a> Parser<'a> {
23952396
Ok(closure)
23962397
}
23972398

2398-
/// Parses an optional `move` prefix to a closure-like construct.
2399+
/// Parses an optional `move` or `use` prefix to a closure-like construct.
23992400
fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
24002401
if self.eat_keyword(exp!(Move)) {
24012402
let move_kw_span = self.prev_token.span;
@@ -2408,6 +2409,16 @@ impl<'a> Parser<'a> {
24082409
} else {
24092410
Ok(CaptureBy::Value { move_kw: move_kw_span })
24102411
}
2412+
} else if self.eat_keyword(exp!(Use)) {
2413+
let use_kw_span = self.prev_token.span;
2414+
self.psess.gated_spans.gate(sym::ergonomic_clones, use_kw_span);
2415+
// Check for `use async` and recover
2416+
if self.check_keyword(exp!(Async)) {
2417+
let use_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
2418+
Err(self.dcx().create_err(errors::AsyncUseOrderIncorrect { span: use_async_span }))
2419+
} else {
2420+
Ok(CaptureBy::Use { use_kw: use_kw_span })
2421+
}
24112422
} else {
24122423
Ok(CaptureBy::Ref)
24132424
}
@@ -3422,7 +3433,7 @@ impl<'a> Parser<'a> {
34223433
self.is_keyword_ahead(lookahead, &[kw])
34233434
&& ((
34243435
// `async move {`
3425-
self.is_keyword_ahead(lookahead + 1, &[kw::Move])
3436+
self.is_keyword_ahead(lookahead + 1, &[kw::Move, kw::Use])
34263437
&& self.look_ahead(lookahead + 2, |t| {
34273438
*t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()
34283439
})

compiler/rustc_parse/src/parser/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1290,7 +1290,7 @@ impl<'a> Parser<'a> {
12901290
if self.check_keyword(exp!(Static)) {
12911291
// Check if this could be a closure.
12921292
!self.look_ahead(1, |token| {
1293-
if token.is_keyword(kw::Move) {
1293+
if token.is_keyword(kw::Move) || token.is_keyword(kw::Use) {
12941294
return true;
12951295
}
12961296
matches!(token.kind, token::Or | token::OrOr)

0 commit comments

Comments
 (0)