diff options
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr_wrapper.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 38 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/generics.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 57 | 
10 files changed, 134 insertions, 85 deletions
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index baaed5ec37b..62c8f9f5dac 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -454,7 +454,7 @@ fn make_token_stream( } // Some types are used a lot. Make sure they don't unintentionally get bigger. -#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))] +#[cfg(target_pointer_width = "64")] mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7038b8bbe47..f256dbf4360 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -29,7 +29,7 @@ use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::AttrTokenTree; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ - AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block, + AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind, }; @@ -51,7 +51,7 @@ use thin_vec::{thin_vec, ThinVec}; pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingAnnotation::NONE, ident, None), + kind: PatKind::Ident(BindingMode::NONE, ident, None), span: ident.span, tokens: None, }); @@ -279,7 +279,7 @@ impl<'a> Parser<'a> { TokenKind::Colon, TokenKind::Comma, TokenKind::Semi, - TokenKind::ModSep, + TokenKind::PathSep, TokenKind::OpenDelim(Delimiter::Brace), TokenKind::OpenDelim(Delimiter::Parenthesis), TokenKind::CloseDelim(Delimiter::Brace), @@ -1169,7 +1169,7 @@ impl<'a> Parser<'a> { return; } - if token::ModSep == self.token.kind && segment.args.is_none() { + if token::PathSep == self.token.kind && segment.args.is_none() { let snapshot = self.create_snapshot_for_diagnostic(); self.bump(); let lo = self.token.span; @@ -1420,7 +1420,7 @@ impl<'a> Parser<'a> { [(token::Lt, 1), (token::Gt, -1), (token::BinOp(token::Shr), -2)]; self.consume_tts(1, &modifiers); - if !&[token::OpenDelim(Delimiter::Parenthesis), token::ModSep] + if !&[token::OpenDelim(Delimiter::Parenthesis), token::PathSep] .contains(&self.token.kind) { // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the @@ -1428,7 +1428,7 @@ impl<'a> Parser<'a> { self.restore_snapshot(snapshot); } } - return if token::ModSep == self.token.kind { + return if token::PathSep == self.token.kind { // We have some certainty that this was a bad turbofish at this point. // `foo< bar >::` if let ExprKind::Binary(o, ..) = inner_op.kind @@ -1784,7 +1784,7 @@ impl<'a> Parser<'a> { } // Do not add `::` to expected tokens. - if self.token == token::ModSep { + if self.token == token::PathSep { if let Some(ty) = base.to_ty() { return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty); } @@ -1799,7 +1799,7 @@ impl<'a> Parser<'a> { ty_span: Span, ty: P<Ty>, ) -> PResult<'a, P<T>> { - self.expect(&token::ModSep)?; + self.expect(&token::PathSep)?; let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None }; self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?; @@ -2787,7 +2787,7 @@ impl<'a> Parser<'a> { } _ => {} }, - PatKind::Ident(BindingAnnotation::NONE, ident, None) => { + PatKind::Ident(BindingMode::NONE, ident, None) => { match &first_pat.kind { PatKind::Ident(_, old_ident, _) => { let path = PatKind::Path( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 00947a4c585..8ed2a6edf1a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -327,7 +327,9 @@ impl<'a> Parser<'a> { this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed) })?; - let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); + self.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span); + let span = lhs_span.to(rhs.span); + lhs = match op { AssocOp::Add | AssocOp::Subtract @@ -426,6 +428,18 @@ impl<'a> Parser<'a> { }); } + fn error_ambiguous_outer_attrs(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) { + if let Some(attr) = lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer) { + self.dcx().emit_err(errors::AmbiguousOuterAttributes { + span: attr.span.to(rhs_span), + sugg: errors::WrapInParentheses::Expression { + left: attr.span.shrink_to_lo(), + right: lhs_span.shrink_to_hi(), + }, + }); + } + } + /// Possibly translate the current token to an associative operator. /// The method does not advance the current token. /// @@ -506,7 +520,8 @@ impl<'a> Parser<'a> { None }; let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span); - let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span); + self.error_ambiguous_outer_attrs(&lhs, lhs.span, rhs_span); + let span = lhs.span.to(rhs_span); let limits = if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; let range = self.mk_range(Some(lhs), rhs, limits); @@ -722,7 +737,8 @@ impl<'a> Parser<'a> { expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind, ) -> PResult<'a, P<Expr>> { let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| { - this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs)) + this.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span); + this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs)) }; // Save the state of the parser before parsing type normally, in case there is a @@ -979,6 +995,12 @@ impl<'a> Parser<'a> { // we are using noexpect here because we don't expect a `.` directly after a `return` // which could be suggested otherwise self.eat_noexpect(&token::Dot) + } else if self.token.kind == TokenKind::RArrow && self.may_recover() { + // Recovery for `expr->suffix`. + self.bump(); + let span = self.prev_token.span; + self.dcx().emit_err(errors::ExprRArrowCall { span }); + true } else { self.eat(&token::Dot) }; @@ -3807,16 +3829,6 @@ impl<'a> Parser<'a> { self.mk_expr(span, ExprKind::Err(guar)) } - /// Create expression span ensuring the span of the parent node - /// is larger than the span of lhs and rhs, including the attributes. - fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span { - lhs.attrs - .iter() - .find(|a| a.style == AttrStyle::Outer) - .map_or(lhs_span, |a| a.span) - .to(rhs_span) - } - fn collect_tokens_for_expr( &mut self, attrs: AttrWrapper, diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index fde16ac957d..93a15c938ec 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -62,7 +62,7 @@ impl<'a> Parser<'a> { let snapshot = self.create_snapshot_for_diagnostic(); match self.parse_ty() { Ok(p) => { - if let TyKind::ImplTrait(_, bounds) = &p.kind { + if let TyKind::ImplTrait(_, bounds, None) = &p.kind { let span = impl_span.to(self.token.span.shrink_to_lo()); let mut err = self.dcx().struct_span_err( span, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index d54eb8dc4c9..848277c4611 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -358,12 +358,12 @@ impl<'a> Parser<'a> { fn is_reuse_path_item(&mut self) -> bool { // no: `reuse ::path` for compatibility reasons with macro invocations self.token.is_keyword(kw::Reuse) - && self.look_ahead(1, |t| t.is_path_start() && t.kind != token::ModSep) + && self.look_ahead(1, |t| t.is_path_start() && t.kind != token::PathSep) } /// Are we sure this could not possibly be a macro invocation? fn isnt_macro_invocation(&mut self) -> bool { - self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep) + self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::PathSep) } /// Recover on encountering a struct or method definition where the user @@ -625,7 +625,7 @@ impl<'a> Parser<'a> { // This notably includes paths passed through `ty` macro fragments (#46438). TyKind::Path(None, path) => path, other => { - if let TyKind::ImplTrait(_, bounds) = other + if let TyKind::ImplTrait(_, bounds, None) = other && let [bound] = bounds.as_slice() { // Suggest removing extra `impl` keyword: @@ -686,6 +686,8 @@ impl<'a> Parser<'a> { (None, self.parse_path(PathStyle::Expr)?) }; + let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None }; + let body = if self.check(&token::OpenDelim(Delimiter::Brace)) { Some(self.parse_block()?) } else { @@ -695,11 +697,9 @@ impl<'a> Parser<'a> { let span = span.to(self.prev_token.span); self.psess.gated_spans.gate(sym::fn_delegation, span); - let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty()); - Ok(( - ident, - ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })), - )) + let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident); + let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body }; + Ok((ident, ItemKind::Delegation(Box::new(deleg)))) } fn parse_item_list<T>( @@ -1020,7 +1020,7 @@ impl<'a> Parser<'a> { { // `use *;` or `use ::*;` or `use {...};` or `use ::{...};` let mod_sep_ctxt = self.token.span.ctxt(); - if self.eat(&token::ModSep) { + if self.eat(&token::PathSep) { prefix .segments .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); @@ -1031,7 +1031,7 @@ impl<'a> Parser<'a> { // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;` prefix = self.parse_path(PathStyle::Mod)?; - if self.eat(&token::ModSep) { + if self.eat(&token::PathSep) { self.parse_use_tree_glob_or_nested()? } else { // Recover from using a colon as path separator. @@ -1063,7 +1063,7 @@ impl<'a> Parser<'a> { /// Parses a `UseTreeKind::Nested(list)`. /// /// ```text - /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] + /// USE_TREE_LIST = ∅ | (USE_TREE `,`)* USE_TREE [`,`] /// ``` fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> { self.parse_delim_comma_seq(Delimiter::Brace, |p| { @@ -1191,7 +1191,11 @@ impl<'a> Parser<'a> { ident_span: ident.span, const_span, }); - ForeignItemKind::Static(ty, Mutability::Not, expr) + ForeignItemKind::Static(Box::new(StaticForeignItem { + ty, + mutability: Mutability::Not, + expr, + })) } _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), }, @@ -1968,11 +1972,8 @@ impl<'a> Parser<'a> { } else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() { let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false, Case::Sensitive) { - let inherited_vis = Visibility { - span: rustc_span::DUMMY_SP, - kind: VisibilityKind::Inherited, - tokens: None, - }; + let inherited_vis = + Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None }; // We use `parse_fn` to get a span for the function let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; match self.parse_fn( @@ -2715,7 +2716,7 @@ impl<'a> Parser<'a> { match ty { Ok(ty) => { let ident = Ident::new(kw::Empty, this.prev_token.span); - let bm = BindingAnnotation::NONE; + let bm = BindingMode::NONE; let pat = this.mk_pat_ident(ty.span, bm, ident); (pat, ty) } @@ -2752,7 +2753,7 @@ impl<'a> Parser<'a> { // Is `self` `n` tokens ahead? let is_isolated_self = |this: &Self, n| { this.is_keyword_ahead(n, &[kw::SelfLower]) - && this.look_ahead(n + 1, |t| t != &token::ModSep) + && this.look_ahead(n + 1, |t| t != &token::PathSep) }; // Is `mut self` `n` tokens ahead? let is_isolated_mut_self = diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 09bc00403f3..7486da33b21 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -109,7 +109,7 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.may_recover() - && $self.look_ahead(1, |t| t == &token::ModSep) + && $self.look_ahead(1, |t| t == &token::PathSep) && let token::Interpolated(nt) = &$self.token.kind && let token::NtTy(ty) = &nt.0 { @@ -162,7 +162,6 @@ pub struct Parser<'a> { /// /// See the comments in the `parse_path_segment` function for more details. unmatched_angle_bracket_count: u16, - max_angle_bracket_count: u16, angle_bracket_nesting: u16, last_unexpected_token_span: Option<Span>, @@ -179,7 +178,7 @@ pub struct Parser<'a> { // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure // it doesn't unintentionally get bigger. -#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))] +#[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(Parser<'_>, 264); /// Stores span information about a closure. @@ -430,7 +429,6 @@ impl<'a> Parser<'a> { num_bump_calls: 0, break_last_token: false, unmatched_angle_bracket_count: 0, - max_angle_bracket_count: 0, angle_bracket_nesting: 0, last_unexpected_token_span: None, subparser_name, @@ -778,7 +776,6 @@ impl<'a> Parser<'a> { if ate { // See doc comment for `unmatched_angle_bracket_count`. self.unmatched_angle_bracket_count += 1; - self.max_angle_bracket_count += 1; debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count); } ate @@ -898,6 +895,7 @@ impl<'a> Parser<'a> { } // Attempt to keep parsing if it was an omitted separator. + self.last_unexpected_token_span = None; match f(self) { Ok(t) => { // Parsed successfully, therefore most probably the code only @@ -1254,8 +1252,6 @@ impl<'a> Parser<'a> { fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> { if pat { self.psess.gated_spans.gate(sym::inline_const_pat, span); - } else { - self.psess.gated_spans.gate(sym::inline_const, span); } self.eat_keyword(kw::Const); let (attrs, blk) = self.parse_inner_attrs_and_block()?; @@ -1532,7 +1528,7 @@ impl<'a> Parser<'a> { /// `::{` or `::*` fn is_import_coupler(&mut self) -> bool { - self.check(&token::ModSep) + self.check(&token::PathSep) && self.look_ahead(1, |t| { *t == token::OpenDelim(Delimiter::Brace) || *t == token::BinOp(token::Star) }) diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 36a00df7b44..73b17353ac9 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -62,7 +62,7 @@ impl<'a> Parser<'a> { _ => false, }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { - token::ModSep | token::Ident(..) => true, + token::PathSep | token::Ident(..) => true, token::Interpolated(nt) => may_be_ident(&nt.0), _ => false, }, @@ -76,7 +76,7 @@ impl<'a> Parser<'a> { token::Literal(_) | // literal token::DotDot | // range pattern (future compat) token::DotDotDot | // range pattern (future compat) - token::ModSep | // path + token::PathSep | // path token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 59e0cd92c4c..78d3d019bf4 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -16,8 +16,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, Token}; use rustc_ast::{ - self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, - PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, + self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField, + PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, }; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, PResult}; @@ -486,7 +486,7 @@ impl<'a> Parser<'a> { } // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); - self.parse_pat_ident(BindingAnnotation(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)? + self.parse_pat_ident(BindingMode(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)? } else if self.eat_keyword(kw::Box) { self.parse_pat_box()? } else if self.check_inline_const(0) { @@ -511,7 +511,7 @@ impl<'a> Parser<'a> { // Parse `ident @ pat` // This can give false positives and parse nullary enums, // they are dealt with later in resolve. - self.parse_pat_ident(BindingAnnotation::NONE, syntax_loc)? + self.parse_pat_ident(BindingMode::NONE, syntax_loc)? } else if self.is_start_of_pat_with_path() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { @@ -766,8 +766,7 @@ impl<'a> Parser<'a> { let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?; // If we don't have `mut $ident (@ pat)?`, error. - if let PatKind::Ident(BindingAnnotation(br @ ByRef::No, m @ Mutability::Not), ..) = - &mut pat.kind + if let PatKind::Ident(BindingMode(br @ ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind { // Don't recurse into the subpattern. // `mut` on the outer binding doesn't affect the inner bindings. @@ -779,8 +778,7 @@ impl<'a> Parser<'a> { self.ban_mut_general_pat(mut_span, &pat, changed_any_binding); } - if matches!(pat.kind, PatKind::Ident(BindingAnnotation(ByRef::Yes(_), Mutability::Mut), ..)) - { + if matches!(pat.kind, PatKind::Ident(BindingMode(ByRef::Yes(_), Mutability::Mut), ..)) { self.psess.gated_spans.gate(sym::mut_ref, pat.span); } Ok(pat.into_inner().kind) @@ -792,7 +790,7 @@ impl<'a> Parser<'a> { struct AddMut(bool); impl MutVisitor for AddMut { fn visit_pat(&mut self, pat: &mut P<Pat>) { - if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = + if let PatKind::Ident(BindingMode(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind { self.0 = true; @@ -1016,7 +1014,7 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| !matches!(t.kind, token::OpenDelim(Delimiter::Parenthesis) // A tuple struct pattern. | token::OpenDelim(Delimiter::Brace) // A struct pattern. | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern. - | token::ModSep // A tuple / struct variant pattern. + | token::PathSep // A tuple / struct variant pattern. | token::Not)) // A macro expanding to a pattern. } @@ -1025,7 +1023,7 @@ impl<'a> Parser<'a> { /// error message when parsing mistakes like `ref foo(a, b)`. fn parse_pat_ident( &mut self, - binding_annotation: BindingAnnotation, + binding_annotation: BindingMode, syntax_loc: Option<PatternLocation>, ) -> PResult<'a, PatKind> { let ident = self.parse_ident_common(false)?; @@ -1163,7 +1161,7 @@ impl<'a> Parser<'a> { None }; - Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub)) + Ok(PatKind::Ident(BindingMode::NONE, Ident::new(kw::Box, box_span), sub)) } else { let pat = self.parse_pat_with_range_pat(false, None, None)?; self.psess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span)); @@ -1344,7 +1342,7 @@ impl<'a> Parser<'a> { if let Some(last) = fields.iter().last() && last.is_shorthand && let PatKind::Ident(binding, ident, None) = last.pat.kind - && binding != BindingAnnotation::NONE + && binding != BindingMode::NONE && self.token == token::Colon // We found `ref mut? ident:`, try to parse a `name,` or `name }`. && let Some(name_span) = self.look_ahead(1, |t| t.is_ident().then(|| t.span)) @@ -1400,7 +1398,7 @@ impl<'a> Parser<'a> { let fieldname = self.parse_field_name()?; hi = self.prev_token.span; - let ann = BindingAnnotation(by_ref, mutability); + let ann = BindingMode(by_ref, mutability); let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname); let subpat = if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat }; @@ -1418,7 +1416,7 @@ impl<'a> Parser<'a> { }) } - pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingAnnotation, ident: Ident) -> P<Pat> { + pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> P<Pat> { self.mk_pat(span, PatKind::Ident(ann, ident, None)) } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 608cdd945ff..b97ec8c613d 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -96,7 +96,7 @@ impl<'a> Parser<'a> { } if !self.recover_colon_before_qpath_proj() { - self.expect(&token::ModSep)?; + self.expect(&token::PathSep)?; } let qself = P(QSelf { ty, path_span, position: path.segments.len() }); @@ -200,7 +200,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let mut segments = ThinVec::new(); let mod_sep_ctxt = self.token.span.ctxt(); - if self.eat(&token::ModSep) { + if self.eat(&token::PathSep) { segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } self.parse_path_segments(&mut segments, style, ty_generics)?; @@ -232,11 +232,11 @@ impl<'a> Parser<'a> { // `PathStyle::Expr` is only provided at the root invocation and never in // `parse_path_segment` to recurse and therefore can be checked to maintain // this invariant. - self.check_trailing_angle_brackets(&segment, &[&token::ModSep]); + self.check_trailing_angle_brackets(&segment, &[&token::PathSep]); } segments.push(segment); - if self.is_import_coupler() || !self.eat(&token::ModSep) { + if self.is_import_coupler() || !self.eat(&token::PathSep) { if style == PathStyle::Expr && self.may_recover() && self.token == token::Colon @@ -291,7 +291,7 @@ impl<'a> Parser<'a> { Ok( if style == PathStyle::Type && check_args_start(self) || style != PathStyle::Mod - && self.check(&token::ModSep) + && self.check(&token::PathSep) && self.look_ahead(1, |t| is_args_start(t)) { // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If @@ -299,11 +299,10 @@ impl<'a> Parser<'a> { // parsing a new path. if style == PathStyle::Expr { self.unmatched_angle_bracket_count = 0; - self.max_angle_bracket_count = 0; } // Generic arguments are found - `<`, `(`, `::<` or `::(`. - self.eat(&token::ModSep); + self.eat(&token::PathSep); let lo = self.token.span; let args = if self.eat_lt() { // `<'a, T, A = U>` @@ -379,7 +378,7 @@ impl<'a> Parser<'a> { let token_before_parsing = self.token.clone(); let mut snapshot = None; if self.may_recover() - && prev_token_before_parsing.kind == token::ModSep + && prev_token_before_parsing.kind == token::PathSep && (style == PathStyle::Expr && self.token.can_begin_expr() || style == PathStyle::Pat && self.token.can_begin_pattern()) { @@ -388,7 +387,7 @@ impl<'a> Parser<'a> { let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) { Ok(output) => output, - Err(mut error) if prev_token_before_parsing.kind == token::ModSep => { + Err(mut error) if prev_token_before_parsing.kind == token::PathSep => { error.span_label( prev_token_before_parsing.span.to(token_before_parsing.span), "while parsing this parenthesized list of type arguments starting here", @@ -470,7 +469,7 @@ impl<'a> Parser<'a> { } } - if let token::ModSep | token::RArrow = self.token.kind { + if let token::PathSep | token::RArrow = self.token.kind { return; } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 1cea32cb90f..7096b201f84 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,4 +1,4 @@ -use super::{Parser, PathStyle, TokenType, Trailing}; +use super::{Parser, PathStyle, SeqSep, TokenType, Trailing}; use crate::errors::{ self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, @@ -14,7 +14,7 @@ use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, - TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID, + PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; @@ -82,7 +82,7 @@ enum AllowCVariadic { /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes /// that `IDENT` is not the ident of a fn trait. fn can_continue_type_after_non_fn_ident(t: &Token) -> bool { - t == &token::ModSep || t == &token::Lt || t == &token::BinOp(token::Shl) + t == &token::PathSep || t == &token::Lt || t == &token::BinOp(token::Shl) } fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool { @@ -316,7 +316,7 @@ impl<'a> Parser<'a> { TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) } (TyKind::TraitObject(bounds, _), kw::Impl) => { - TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) + TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, None) } _ => return Err(err), }; @@ -655,7 +655,6 @@ impl<'a> Parser<'a> { /// Parses an `impl B0 + ... + Bn` type. fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { - // Always parse bounds greedily for better error recovery. if self.token.is_lifetime() { self.look_ahead(1, |t| { if let token::Ident(sym, _) = t.kind { @@ -669,9 +668,53 @@ impl<'a> Parser<'a> { } }) } + + // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of + // lifetimes and ident params (including SelfUpper). These are validated later + // for order, duplication, and whether they actually reference params. + let precise_capturing = if self.eat_keyword(kw::Use) { + let use_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::precise_capturing, use_span); + let args = self.parse_precise_capturing_args()?; + Some(P((args, use_span))) + } else { + None + }; + + // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; + *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); - Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) + + Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing)) + } + + fn parse_precise_capturing_args(&mut self) -> PResult<'a, ThinVec<PreciseCapturingArg>> { + Ok(self + .parse_unspanned_seq( + &TokenKind::Lt, + &TokenKind::Gt, + SeqSep::trailing_allowed(token::Comma), + |self_| { + if self_.check_keyword(kw::SelfUpper) { + self_.bump(); + Ok(PreciseCapturingArg::Arg( + ast::Path::from_ident(self_.prev_token.ident().unwrap().0), + DUMMY_NODE_ID, + )) + } else if self_.check_ident() { + Ok(PreciseCapturingArg::Arg( + ast::Path::from_ident(self_.parse_ident()?), + DUMMY_NODE_ID, + )) + } else if self_.check_lifetime() { + Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime())) + } else { + self_.unexpected_any() + } + }, + )? + .0) } /// Is a `dyn B0 + ... + Bn` type allowed here? @@ -957,7 +1000,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ) } - TyKind::ImplTrait(_, bounds) + TyKind::ImplTrait(_, bounds, None) if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() => { (  | 
