Use closure parse code
This commit is contained in:
parent
05c516446a
commit
81a926cc2a
20 changed files with 137 additions and 68 deletions
|
@ -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 ()|`.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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} @`
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue