1
Fork 0

Use closure parse code

This commit is contained in:
Santiago Pastorino 2024-11-01 18:37:32 -03:00
parent 05c516446a
commit 81a926cc2a
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF
20 changed files with 137 additions and 68 deletions

View file

@ -1762,6 +1762,11 @@ pub enum CaptureBy {
},
/// `move` keyword was not specified.
Ref,
/// `use |x| y + x`.
Use {
/// The span of the `use` keyword.
use_kw: Span,
},
}
/// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`.

View file

@ -1899,6 +1899,9 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
CaptureBy::Value { move_kw } => {
vis.visit_span(move_kw);
}
CaptureBy::Use { use_kw } => {
vis.visit_span(use_kw);
}
}
}

View file

@ -893,6 +893,7 @@ impl<'a> State<'a> {
fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
match capture_clause {
ast::CaptureBy::Value { .. } => self.word_space("move"),
ast::CaptureBy::Use { .. } => self.word_space("use"),
ast::CaptureBy::Ref => {}
}
}

View file

@ -403,6 +403,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.expect_closure();
let span = match capture_clause {
rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
rustc_hir::CaptureBy::Use { use_kw } => use_kw.shrink_to_lo(),
rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
};
diag.span_suggestion_verbose(

View file

@ -2305,6 +2305,7 @@ impl<'a> State<'a> {
fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
match capture_clause {
hir::CaptureBy::Value { .. } => self.word_space("move"),
hir::CaptureBy::Use { .. } => self.word_space("use"),
hir::CaptureBy::Ref => {}
}
}

View file

@ -670,7 +670,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
origin = updated.1;
let (place, capture_kind) = match capture_clause {
hir::CaptureBy::Value { .. } => adjust_for_move_closure(place, capture_kind),
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. } => {
adjust_for_move_closure(place, capture_kind)
}
hir::CaptureBy::Ref => adjust_for_non_move_closure(place, capture_kind),
};
@ -1165,7 +1167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = match closure_clause {
hir::CaptureBy::Value { .. } => ty, // For move closure the capture kind should be by value
hir::CaptureBy::Ref => {
hir::CaptureBy::Ref | hir::CaptureBy::Use { .. } => {
// For non move closure the capture kind is the max capture kind of all captures
// according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue
let mut max_capture_info = root_var_min_capture_list.first().unwrap().info;
@ -1292,7 +1294,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
return Some(diagnostics_info);
}
hir::CaptureBy::Ref => {}
hir::CaptureBy::Ref | hir::CaptureBy::Use { .. } => {}
}
return None;
@ -1689,10 +1691,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
//
// If the data will be moved out of this place, then the place will be truncated
// at the first Deref in `adjust_for_move_closure` and then moved into the closure.
hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => {
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. }
if !place.deref_tys().any(Ty::is_ref) =>
{
ty::UpvarCapture::ByValue
}
hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => {
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. } | hir::CaptureBy::Ref => {
ty::UpvarCapture::ByRef(BorrowKind::Immutable)
}
}

View file

@ -26,6 +26,9 @@ parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 20
parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
.suggestion = try switching the order
parse_async_use_order_incorrect = the order of `use` and `async` is incorrect
.suggestion = try switching the order
parse_at_dot_dot_in_struct_pattern = `@ ..` is not supported in struct patterns
.suggestion = bind to each field separately or, if you don't need them, just remove `{$ident} @`

View file

@ -1512,6 +1512,14 @@ pub(crate) struct AsyncMoveOrderIncorrect {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_async_use_order_incorrect)]
pub(crate) struct AsyncUseOrderIncorrect {
#[primary_span]
#[suggestion(style = "verbose", code = "async use", applicability = "maybe-incorrect")]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_double_colon_in_bound)]
pub(crate) struct DoubleColonInBound {

View file

@ -1404,6 +1404,7 @@ impl<'a> Parser<'a> {
} else if this.check_path() {
this.parse_expr_path_start()
} else if this.check_keyword(exp!(Move))
|| this.check_keyword(exp!(Use))
|| this.check_keyword(exp!(Static))
|| this.check_const_closure()
{
@ -2395,7 +2396,7 @@ impl<'a> Parser<'a> {
Ok(closure)
}
/// Parses an optional `move` prefix to a closure-like construct.
/// Parses an optional `move` or `use` prefix to a closure-like construct.
fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
if self.eat_keyword(exp!(Move)) {
let move_kw_span = self.prev_token.span;
@ -2408,6 +2409,16 @@ impl<'a> Parser<'a> {
} else {
Ok(CaptureBy::Value { move_kw: move_kw_span })
}
} else if self.eat_keyword(exp!(Use)) {
let use_kw_span = self.prev_token.span;
self.psess.gated_spans.gate(sym::ergonomic_clones, use_kw_span);
// Check for `use async` and recover
if self.check_keyword(exp!(Async)) {
let use_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
Err(self.dcx().create_err(errors::AsyncUseOrderIncorrect { span: use_async_span }))
} else {
Ok(CaptureBy::Use { use_kw: use_kw_span })
}
} else {
Ok(CaptureBy::Ref)
}
@ -3422,7 +3433,7 @@ impl<'a> Parser<'a> {
self.is_keyword_ahead(lookahead, &[kw])
&& ((
// `async move {`
self.is_keyword_ahead(lookahead + 1, &[kw::Move])
self.is_keyword_ahead(lookahead + 1, &[kw::Move, kw::Use])
&& self.look_ahead(lookahead + 2, |t| {
*t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()
})

View file

@ -1290,7 +1290,7 @@ impl<'a> Parser<'a> {
if self.check_keyword(exp!(Static)) {
// Check if this could be a closure.
!self.look_ahead(1, |token| {
if token.is_keyword(kw::Move) {
if token.is_keyword(kw::Move) || token.is_keyword(kw::Use) {
return true;
}
matches!(token.kind, token::Or | token::OrOr)