diff options
| author | Matthew Kelly <matthew.kelly2@gmail.com> | 2022-09-26 19:59:52 -0400 |
|---|---|---|
| committer | Matthew Kelly <matthew.kelly2@gmail.com> | 2022-09-26 19:59:52 -0400 |
| commit | 24aab524cbafec7ff8c7cd54ba4f6fb18216c623 (patch) | |
| tree | b0fd92c686ed3fe2b3a5a010c0dc32a6a54d3ea1 /compiler/rustc_parse/src/parser | |
| parent | eda2a401457ba645a32bdc5b9e7e90214e3e4e24 (diff) | |
| parent | 8b705839cd656d202e920efa8769cbe43a5ee269 (diff) | |
| download | rust-24aab524cbafec7ff8c7cd54ba4f6fb18216c623.tar.gz rust-24aab524cbafec7ff8c7cd54ba4f6fb18216c623.zip | |
Merge remote-tracking branch 'origin/master' into mpk/add-long-error-message-for-E0311
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr_wrapper.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 173 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 81 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 51 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 13 |
10 files changed, 321 insertions, 173 deletions
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 72ab96b5ca6..5fd69b15ecc 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -7,8 +7,6 @@ use rustc_errors::{error_code, Diagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use std::convert::TryInto; -use tracing::debug; - // Public for rustfmt usage #[derive(Debug)] pub enum InnerAttrPolicy<'a> { @@ -89,6 +87,7 @@ impl<'a> Parser<'a> { // Always make an outer attribute - this allows us to recover from a misplaced // inner attribute. Some(attr::mk_doc_comment( + &self.sess.attr_id_generator, comment_kind, ast::AttrStyle::Outer, data, @@ -140,7 +139,13 @@ impl<'a> Parser<'a> { this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy); } - Ok(attr::mk_attr_from_item(item, None, style, attr_sp)) + Ok(attr::mk_attr_from_item( + &self.sess.attr_id_generator, + item, + None, + style, + attr_sp, + )) } else { let token_str = pprust::token_to_string(&this.token); let msg = &format!("expected `#`, found `{token_str}`"); @@ -293,7 +298,13 @@ impl<'a> Parser<'a> { } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { if attr_style == ast::AttrStyle::Inner { self.bump(); - Some(attr::mk_doc_comment(comment_kind, attr_style, data, self.prev_token.span)) + Some(attr::mk_doc_comment( + &self.sess.attr_id_generator, + comment_kind, + attr_style, + data, + self.prev_token.span, + )) } else { None } @@ -303,9 +314,9 @@ impl<'a> Parser<'a> { if let Some(attr) = attr { let end_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); // If we are currently capturing tokens, mark the location of this inner attribute. - // If capturing ends up creating a `LazyTokenStream`, we will include + // If capturing ends up creating a `LazyAttrTokenStream`, we will include // this replace range with it, removing the inner attribute from the final - // `AttrAnnotatedTokenStream`. Inner attributes are stored in the parsed AST note. + // `AttrTokenStream`. Inner attributes are stored in the parsed AST note. // During macro expansion, they are selectively inserted back into the // token stream (the first inner attribute is removed each time we invoke the // corresponding macro). diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index b564f4ad92c..86c386b94c8 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -1,7 +1,7 @@ use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken}; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttributesData, CreateTokenStream}; -use rustc_ast::tokenstream::{AttrAnnotatedTokenTree, DelimSpan, LazyTokenStream, Spacing}; +use rustc_ast::tokenstream::{AttrTokenStream, AttributesData, ToAttrTokenStream}; +use rustc_ast::tokenstream::{AttrTokenTree, DelimSpan, LazyAttrTokenStream, Spacing}; use rustc_ast::{self as ast}; use rustc_ast::{AttrVec, Attribute, HasAttrs, HasTokens}; use rustc_errors::PResult; @@ -52,7 +52,7 @@ impl AttrWrapper { // Prepend `self.attrs` to `attrs`. // FIXME: require passing an NT to prevent misuse of this method pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) { - let mut self_attrs = self.attrs.clone(); + let mut self_attrs = self.attrs; std::mem::swap(attrs, &mut self_attrs); attrs.extend(self_attrs); } @@ -88,7 +88,7 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool { // This also makes `Parser` very cheap to clone, since // there is no intermediate collection buffer to clone. #[derive(Clone)] -struct LazyTokenStreamImpl { +struct LazyAttrTokenStreamImpl { start_token: (Token, Spacing), cursor_snapshot: TokenCursor, num_calls: usize, @@ -97,10 +97,10 @@ struct LazyTokenStreamImpl { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(LazyTokenStreamImpl, 144); +rustc_data_structures::static_assert_size!(LazyAttrTokenStreamImpl, 144); -impl CreateTokenStream for LazyTokenStreamImpl { - fn create_token_stream(&self) -> AttrAnnotatedTokenStream { +impl ToAttrTokenStream for LazyAttrTokenStreamImpl { + fn to_attr_token_stream(&self) -> AttrTokenStream { // The token produced by the final call to `{,inlined_}next` was not // actually consumed by the callback. The combination of chaining the // initial token and using `take` produces the desired result - we @@ -179,7 +179,7 @@ impl CreateTokenStream for LazyTokenStreamImpl { impl<'a> Parser<'a> { /// Records all tokens consumed by the provided callback, /// including the current token. These tokens are collected - /// into a `LazyTokenStream`, and returned along with the result + /// into a `LazyAttrTokenStream`, and returned along with the result /// of the callback. /// /// Note: If your callback consumes an opening delimiter @@ -297,8 +297,8 @@ impl<'a> Parser<'a> { // If we 'broke' the last token (e.g. breaking a '>>' token to two '>' tokens), // then extend the range of captured tokens to include it, since the parser - // was not actually bumped past it. When the `LazyTokenStream` gets converted - // into an `AttrAnnotatedTokenStream`, we will create the proper token. + // was not actually bumped past it. When the `LazyAttrTokenStream` gets converted + // into an `AttrTokenStream`, we will create the proper token. if self.token_cursor.break_last_token { assert_eq!( trailing, @@ -316,8 +316,8 @@ impl<'a> Parser<'a> { Box::new([]) } else { // Grab any replace ranges that occur *inside* the current AST node. - // We will perform the actual replacement when we convert the `LazyTokenStream` - // to an `AttrAnnotatedTokenStream` + // We will perform the actual replacement when we convert the `LazyAttrTokenStream` + // to an `AttrTokenStream`. let start_calls: u32 = cursor_snapshot_next_calls.try_into().unwrap(); self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] .iter() @@ -329,7 +329,7 @@ impl<'a> Parser<'a> { .collect() }; - let tokens = LazyTokenStream::new(LazyTokenStreamImpl { + let tokens = LazyAttrTokenStream::new(LazyAttrTokenStreamImpl { start_token, num_calls, cursor_snapshot, @@ -355,7 +355,7 @@ impl<'a> Parser<'a> { && matches!(self.capture_state.capturing, Capturing::Yes) && has_cfg_or_cfg_attr(final_attrs) { - let attr_data = AttributesData { attrs: final_attrs.to_vec().into(), tokens }; + let attr_data = AttributesData { attrs: final_attrs.iter().cloned().collect(), tokens }; // Replace the entire AST node that we just parsed, including attributes, // with a `FlatToken::AttrTarget`. If this AST node is inside an item @@ -392,12 +392,12 @@ impl<'a> Parser<'a> { fn make_token_stream( mut iter: impl Iterator<Item = (FlatToken, Spacing)>, break_last_token: bool, -) -> AttrAnnotatedTokenStream { +) -> AttrTokenStream { #[derive(Debug)] struct FrameData { // This is `None` for the first frame, `Some` for all others. open_delim_sp: Option<(Delimiter, Span)>, - inner: Vec<(AttrAnnotatedTokenTree, Spacing)>, + inner: Vec<AttrTokenTree>, } let mut stack = vec![FrameData { open_delim_sp: None, inner: vec![] }]; let mut token_and_spacing = iter.next(); @@ -418,48 +418,46 @@ fn make_token_stream( open_delim, span ); let dspan = DelimSpan::from_pair(open_sp, span); - let stream = AttrAnnotatedTokenStream::new(frame_data.inner); - let delimited = AttrAnnotatedTokenTree::Delimited(dspan, delim, stream); + let stream = AttrTokenStream::new(frame_data.inner); + let delimited = AttrTokenTree::Delimited(dspan, delim, stream); stack .last_mut() .unwrap_or_else(|| { panic!("Bottom token frame is missing for token: {:?}", token) }) .inner - .push((delimited, Spacing::Alone)); + .push(delimited); } FlatToken::Token(token) => stack .last_mut() .expect("Bottom token frame is missing!") .inner - .push((AttrAnnotatedTokenTree::Token(token), spacing)), + .push(AttrTokenTree::Token(token, spacing)), FlatToken::AttrTarget(data) => stack .last_mut() .expect("Bottom token frame is missing!") .inner - .push((AttrAnnotatedTokenTree::Attributes(data), spacing)), + .push(AttrTokenTree::Attributes(data)), FlatToken::Empty => {} } token_and_spacing = iter.next(); } let mut final_buf = stack.pop().expect("Missing final buf!"); if break_last_token { - let (last_token, spacing) = final_buf.inner.pop().unwrap(); - if let AttrAnnotatedTokenTree::Token(last_token) = last_token { + let last_token = final_buf.inner.pop().unwrap(); + if let AttrTokenTree::Token(last_token, spacing) = last_token { let unglued_first = last_token.kind.break_two_token_op().unwrap().0; // An 'unglued' token is always two ASCII characters let mut first_span = last_token.span.shrink_to_lo(); first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1)); - final_buf.inner.push(( - AttrAnnotatedTokenTree::Token(Token::new(unglued_first, first_span)), - spacing, - )); + final_buf + .inner + .push(AttrTokenTree::Token(Token::new(unglued_first, first_span), spacing)); } else { panic!("Unexpected last token {:?}", last_token) } } - assert!(stack.is_empty(), "Stack should be empty: final_buf={:?} stack={:?}", final_buf, stack); - AttrAnnotatedTokenStream::new(final_buf.inner) + AttrTokenStream::new(final_buf.inner) } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f0ea1dfe297..ccdffb8ce07 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -10,9 +10,9 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind}; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ - AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block, - BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param, Pat, - PatKind, Path, PathSegment, QSelf, Ty, TyKind, + AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block, + BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind, + Path, PathSegment, QSelf, Ty, TyKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -20,7 +20,7 @@ use rustc_errors::{ fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; -use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; @@ -29,7 +29,6 @@ use std::ops::{Deref, DerefMut}; use std::mem::take; use crate::parser; -use tracing::{debug, trace}; const TURBOFISH_SUGGESTION_STR: &str = "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"; @@ -38,7 +37,7 @@ const TURBOFISH_SUGGESTION_STR: &str = pub(super) fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None), + kind: PatKind::Ident(BindingAnnotation::NONE, ident, None), span: ident.span, tokens: None, }); @@ -243,7 +242,7 @@ impl MultiSugg { } } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::maybe_report_ambiguous_plus)] struct AmbiguousPlus { pub sum_ty: String, @@ -252,7 +251,7 @@ struct AmbiguousPlus { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::maybe_recover_from_bad_type_plus, code = "E0178")] struct BadTypePlus { pub ty: String, @@ -262,7 +261,7 @@ struct BadTypePlus { pub sub: BadTypePlusSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum BadTypePlusSub { #[suggestion( parser::add_paren, @@ -286,35 +285,35 @@ pub enum BadTypePlusSub { }, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::maybe_recover_from_bad_qpath_stage_2)] struct BadQPathStage2 { #[primary_span] - #[suggestion(applicability = "maybe-incorrect")] + #[suggestion(code = "", applicability = "maybe-incorrect")] span: Span, ty: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::incorrect_semicolon)] struct IncorrectSemicolon<'a> { #[primary_span] - #[suggestion_short(applicability = "machine-applicable")] + #[suggestion_short(code = "", applicability = "machine-applicable")] span: Span, #[help] opt_help: Option<()>, name: &'a str, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::incorrect_use_of_await)] struct IncorrectUseOfAwait { #[primary_span] - #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")] + #[suggestion(parser::parentheses_suggestion, code = "", applicability = "machine-applicable")] span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::incorrect_use_of_await)] struct IncorrectAwait { #[primary_span] @@ -325,16 +324,16 @@ struct IncorrectAwait { question_mark: &'static str, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::in_in_typo)] struct InInTypo { #[primary_span] span: Span, - #[suggestion(applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] sugg_span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_variable_declaration)] pub struct InvalidVariableDeclaration { #[primary_span] @@ -343,7 +342,7 @@ pub struct InvalidVariableDeclaration { pub sub: InvalidVariableDeclarationSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum InvalidVariableDeclarationSub { #[suggestion( parser::switch_mut_let_order, @@ -363,7 +362,7 @@ pub enum InvalidVariableDeclarationSub { UseLetNotVar(#[primary_span] Span), } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_comparison_operator)] pub(crate) struct InvalidComparisonOperator { #[primary_span] @@ -373,7 +372,7 @@ pub(crate) struct InvalidComparisonOperator { pub sub: InvalidComparisonOperatorSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub(crate) enum InvalidComparisonOperatorSub { #[suggestion_short( parser::use_instead, @@ -390,7 +389,7 @@ pub(crate) enum InvalidComparisonOperatorSub { Spaceship(#[primary_span] Span), } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_logical_operator)] #[note] pub(crate) struct InvalidLogicalOperator { @@ -401,7 +400,7 @@ pub(crate) struct InvalidLogicalOperator { pub sub: InvalidLogicalOperatorSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub(crate) enum InvalidLogicalOperatorSub { #[suggestion_short( parser::use_amp_amp_for_conjunction, @@ -417,7 +416,7 @@ pub(crate) enum InvalidLogicalOperatorSub { Disjunction(#[primary_span] Span), } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::tilde_is_not_unary_operator)] pub(crate) struct TildeAsUnaryOperator( #[primary_span] @@ -425,17 +424,41 @@ pub(crate) struct TildeAsUnaryOperator( pub Span, ); -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::unexpected_token_after_not)] pub(crate) struct NotAsNegationOperator { #[primary_span] pub negated: Span, pub negated_desc: String, - #[suggestion_short(applicability = "machine-applicable", code = "!")] - pub not: Span, + #[subdiagnostic] + pub sub: NotAsNegationOperatorSub, +} + +#[derive(Subdiagnostic)] +pub enum NotAsNegationOperatorSub { + #[suggestion_short( + parser::unexpected_token_after_not_default, + applicability = "machine-applicable", + code = "!" + )] + SuggestNotDefault(#[primary_span] Span), + + #[suggestion_short( + parser::unexpected_token_after_not_bitwise, + applicability = "machine-applicable", + code = "!" + )] + SuggestNotBitwise(#[primary_span] Span), + + #[suggestion_short( + parser::unexpected_token_after_not_logical, + applicability = "machine-applicable", + code = "!" + )] + SuggestNotLogical(#[primary_span] Span), } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::malformed_loop_label)] pub(crate) struct MalformedLoopLabel { #[primary_span] @@ -444,7 +467,7 @@ pub(crate) struct MalformedLoopLabel { pub correct_label: Ident, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::lifetime_in_borrow_expression)] pub(crate) struct LifetimeInBorrowExpression { #[primary_span] @@ -454,15 +477,15 @@ pub(crate) struct LifetimeInBorrowExpression { pub lifetime_span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::field_expression_with_generic)] pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span); -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::macro_invocation_with_qualified_path)] pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span); -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::unexpected_token_after_label)] pub(crate) struct UnexpectedTokenAfterLabel( #[primary_span] @@ -470,7 +493,7 @@ pub(crate) struct UnexpectedTokenAfterLabel( pub Span, ); -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::require_colon_after_labeled_expression)] #[note] pub(crate) struct RequireColonAfterLabeledExpression { @@ -482,7 +505,7 @@ pub(crate) struct RequireColonAfterLabeledExpression { pub label_end: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::do_catch_syntax_removed)] #[note] pub(crate) struct DoCatchSyntaxRemoved { @@ -491,7 +514,7 @@ pub(crate) struct DoCatchSyntaxRemoved { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::float_literal_requires_integer_part)] pub(crate) struct FloatLiteralRequiresIntegerPart { #[primary_span] @@ -500,7 +523,7 @@ pub(crate) struct FloatLiteralRequiresIntegerPart { pub correct: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_int_literal_width)] #[help] pub(crate) struct InvalidIntLiteralWidth { @@ -509,7 +532,7 @@ pub(crate) struct InvalidIntLiteralWidth { pub width: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_num_literal_base_prefix)] #[note] pub(crate) struct InvalidNumLiteralBasePrefix { @@ -519,7 +542,7 @@ pub(crate) struct InvalidNumLiteralBasePrefix { pub fixed: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_num_literal_suffix)] #[help] pub(crate) struct InvalidNumLiteralSuffix { @@ -529,7 +552,7 @@ pub(crate) struct InvalidNumLiteralSuffix { pub suffix: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_float_literal_width)] #[help] pub(crate) struct InvalidFloatLiteralWidth { @@ -538,7 +561,7 @@ pub(crate) struct InvalidFloatLiteralWidth { pub width: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_float_literal_suffix)] #[help] pub(crate) struct InvalidFloatLiteralSuffix { @@ -548,14 +571,14 @@ pub(crate) struct InvalidFloatLiteralSuffix { pub suffix: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::int_literal_too_large)] pub(crate) struct IntLiteralTooLarge { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::missing_semicolon_before_array)] pub(crate) struct MissingSemicolonBeforeArray { #[primary_span] @@ -564,7 +587,7 @@ pub(crate) struct MissingSemicolonBeforeArray { pub semicolon: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::invalid_block_macro_segment)] pub(crate) struct InvalidBlockMacroSegment { #[primary_span] @@ -573,7 +596,7 @@ pub(crate) struct InvalidBlockMacroSegment { pub context: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::if_expression_missing_then_block)] pub(crate) struct IfExpressionMissingThenBlock { #[primary_span] @@ -582,7 +605,7 @@ pub(crate) struct IfExpressionMissingThenBlock { pub sub: IfExpressionMissingThenBlockSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub(crate) enum IfExpressionMissingThenBlockSub { #[help(parser::condition_possibly_unfinished)] UnfinishedCondition(#[primary_span] Span), @@ -590,7 +613,7 @@ pub(crate) enum IfExpressionMissingThenBlockSub { AddThenBlock(#[primary_span] Span), } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::if_expression_missing_condition)] pub(crate) struct IfExpressionMissingCondition { #[primary_span] @@ -600,14 +623,14 @@ pub(crate) struct IfExpressionMissingCondition { pub block_span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::expected_expression_found_let)] pub(crate) struct ExpectedExpressionFoundLet { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::expected_else_block)] pub(crate) struct ExpectedElseBlock { #[primary_span] @@ -619,7 +642,7 @@ pub(crate) struct ExpectedElseBlock { pub condition_start: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::outer_attribute_not_allowed_on_if_else)] pub(crate) struct OuterAttributeNotAllowedOnIfElse { #[primary_span] @@ -636,7 +659,7 @@ pub(crate) struct OuterAttributeNotAllowedOnIfElse { pub attributes: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::missing_in_in_for_loop)] pub(crate) struct MissingInInForLoop { #[primary_span] @@ -645,7 +668,7 @@ pub(crate) struct MissingInInForLoop { pub sub: MissingInInForLoopSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub(crate) enum MissingInInForLoopSub { // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect #[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")] @@ -654,7 +677,7 @@ pub(crate) enum MissingInInForLoopSub { AddIn(#[primary_span] Span), } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::missing_comma_after_match_arm)] pub(crate) struct MissingCommaAfterMatchArm { #[primary_span] @@ -662,7 +685,7 @@ pub(crate) struct MissingCommaAfterMatchArm { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::catch_after_try)] #[help] pub(crate) struct CatchAfterTry { @@ -670,7 +693,7 @@ pub(crate) struct CatchAfterTry { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::comma_after_base_struct)] #[note] pub(crate) struct CommaAfterBaseStruct { @@ -680,7 +703,7 @@ pub(crate) struct CommaAfterBaseStruct { pub comma: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::eq_field_init)] pub(crate) struct EqFieldInit { #[primary_span] @@ -689,7 +712,7 @@ pub(crate) struct EqFieldInit { pub eq: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::dotdotdot)] pub(crate) struct DotDotDot { #[primary_span] @@ -698,7 +721,7 @@ pub(crate) struct DotDotDot { pub span: Span, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(parser::left_arrow_operator)] pub(crate) struct LeftArrowOperator { #[primary_span] @@ -706,6 +729,30 @@ pub(crate) struct LeftArrowOperator { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parser::remove_let)] +pub(crate) struct RemoveLet { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::use_eq_instead)] +pub(crate) struct UseEqInstead { + #[primary_span] + #[suggestion_short(applicability = "machine-applicable", code = "=")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::use_empty_block_not_semi)] +pub(crate) struct UseEmptyBlockNotSemi { + #[primary_span] + #[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")] + pub span: Span, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. @@ -950,6 +997,14 @@ impl<'a> Parser<'a> { } } + if self.token.kind == TokenKind::EqEq + && self.prev_token.is_ident() + && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq))) + { + // Likely typo: `=` → `==` in let expr or enum item + return Err(self.sess.create_err(UseEqInstead { span: self.token.span })); + } + let expect = tokens_to_string(&expected); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { @@ -2962,7 +3017,7 @@ impl<'a> Parser<'a> { } _ => {} }, - PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => { + PatKind::Ident(BindingAnnotation::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 c8541609514..ae77961b7bc 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -6,8 +6,9 @@ use super::diagnostics::{ InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub, LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, - NotAsNegationOperator, OuterAttributeNotAllowedOnIfElse, RequireColonAfterLabeledExpression, - SnapshotParser, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, + NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, + RequireColonAfterLabeledExpression, SnapshotParser, TildeAsUnaryOperator, + UnexpectedTokenAfterLabel, }; use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; @@ -35,10 +36,10 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{ClosureBinder, StmtKind}; use rustc_ast_pretty::pprust; +use rustc_errors::IntoDiagnostic; use rustc_errors::{Applicability, Diagnostic, PResult}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::BuiltinLintDiagnostics; -use rustc_session::SessionDiagnostic; use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos}; @@ -660,12 +661,23 @@ impl<'a> Parser<'a> { fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { // Emit the error... let negated_token = self.look_ahead(1, |t| t.clone()); + + let sub_diag = if negated_token.is_numeric_lit() { + NotAsNegationOperatorSub::SuggestNotBitwise + } else if negated_token.is_bool_lit() { + NotAsNegationOperatorSub::SuggestNotLogical + } else { + NotAsNegationOperatorSub::SuggestNotDefault + }; + self.sess.emit_err(NotAsNegationOperator { negated: negated_token.span, negated_desc: super::token_descr(&negated_token), // Span the `not` plus trailing whitespace to avoid // trailing whitespace after the `!` in our suggestion - not: self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)), + sub: sub_diag( + self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)), + ), }); // ...and recover! @@ -944,13 +956,18 @@ impl<'a> Parser<'a> { // Stitch the list of outer attributes onto the return value. // A little bit ugly, but the best way given the current code // structure - self.parse_dot_or_call_expr_with_(e0, lo).map(|expr| { - expr.map(|mut expr| { - attrs.extend(expr.attrs); - expr.attrs = attrs; - expr + let res = self.parse_dot_or_call_expr_with_(e0, lo); + if attrs.is_empty() { + res + } else { + res.map(|expr| { + expr.map(|mut expr| { + attrs.extend(expr.attrs); + expr.attrs = attrs; + expr + }) }) - }) + } } fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { @@ -1578,7 +1595,7 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); - // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to supress future errors about `break 'label`. + // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`. let stmt = self.mk_stmt(span, StmtKind::Expr(expr)); let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span); self.mk_expr(span, ExprKind::Block(blk, label)) @@ -1972,6 +1989,9 @@ impl<'a> Parser<'a> { open_delim_span: Span, ) -> PResult<'a, ()> { if self.token.kind == token::Comma { + if !self.sess.source_map().is_multiline(prev_span.until(self.token.span)) { + return Ok(()); + } let mut snapshot = self.create_snapshot_for_diagnostic(); snapshot.bump(); match snapshot.parse_seq_to_before_end( @@ -1992,7 +2012,7 @@ impl<'a> Parser<'a> { return Err(MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), - }.into_diagnostic(self.sess)); + }.into_diagnostic(&self.sess.span_diagnostic)); } Ok(_) => (), Err(err) => err.cancel(), @@ -2578,7 +2598,7 @@ impl<'a> Parser<'a> { } pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { - // Used to check the `let_chains` and `if_let_guard` features mostly by scaning + // Used to check the `let_chains` and `if_let_guard` features mostly by scanning // `&&` tokens. fn check_let_expr(expr: &Expr) -> (bool, bool) { match expr.kind { @@ -2740,7 +2760,8 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> { let (attrs, body) = self.parse_inner_attrs_and_block()?; if self.eat_keyword(kw::Catch) { - Err(CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.sess)) + Err(CatchAfterTry { span: self.prev_token.span } + .into_diagnostic(&self.sess.span_diagnostic)) } else { let span = span_lo.to(body.span); self.sess.gated_spans.gate(sym::try_blocks, span); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index b743162a7e4..34f25bd0716 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,4 +1,4 @@ -use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; +use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error, UseEmptyBlockNotSemi}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; @@ -8,7 +8,7 @@ use rustc_ast::token::{self, Delimiter, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID}; use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; -use rustc_ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; +use rustc_ast::{BindingAnnotation, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, VariantData}; use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; use rustc_ast::{MacArgs, MacCall, MacDelimiter}; @@ -22,7 +22,6 @@ use rustc_span::DUMMY_SP; use std::convert::TryFrom; use std::mem; -use tracing::debug; impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. @@ -665,6 +664,14 @@ impl<'a> Parser<'a> { mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>, ) -> PResult<'a, Vec<T>> { let open_brace_span = self.token.span; + + // Recover `impl Ty;` instead of `impl Ty {}` + if self.token == TokenKind::Semi { + self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span }); + self.bump(); + return Ok(vec![]); + } + self.expect(&token::OpenDelim(Delimiter::Brace))?; attrs.extend(self.parse_inner_attributes()?); @@ -699,11 +706,22 @@ impl<'a> Parser<'a> { let semicolon_span = self.token.span; // We have to bail or we'll potentially never make progress. let non_item_span = self.token.span; - self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); + let is_let = self.token.is_keyword(kw::Let); + let mut err = self.struct_span_err(non_item_span, "non-item in item list"); - err.span_label(open_brace_span, "item list starts here") - .span_label(non_item_span, "non-item starts here") - .span_label(self.prev_token.span, "item list ends here"); + self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); + if is_let { + err.span_suggestion( + non_item_span, + "consider using `const` instead of `let` for associated const", + "const", + Applicability::MachineApplicable, + ); + } else { + err.span_label(open_brace_span, "item list starts here") + .span_label(non_item_span, "non-item starts here") + .span_label(self.prev_token.span, "item list ends here"); + } if is_unnecessary_semicolon { err.span_suggestion( semicolon_span, @@ -1295,12 +1313,19 @@ impl<'a> Parser<'a> { let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; - let (variants, _) = self - .parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()) - .map_err(|e| { - self.recover_stmt(); - e - })?; + // Possibly recover `enum Foo;` instead of `enum Foo {}` + let (variants, _) = if self.token == TokenKind::Semi { + self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span }); + self.bump(); + (vec![], false) + } else { + self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err( + |e| { + self.recover_stmt(); + e + }, + )? + }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; Ok((id, ItemKind::Enum(enum_definition, generics))) @@ -1527,6 +1552,17 @@ impl<'a> Parser<'a> { if self.token == token::Comma { seen_comma = true; } + if self.eat(&token::Semi) { + let sp = self.prev_token.span; + let mut err = self.struct_span_err(sp, format!("{adt_ty} fields are separated by `,`")); + err.span_suggestion_short( + sp, + "replace `;` with `,`", + ",", + Applicability::MachineApplicable, + ); + return Err(err); + } match self.token.kind { token::Comma => { self.bump(); @@ -1694,6 +1730,7 @@ impl<'a> Parser<'a> { fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { + let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false) { let inherited_vis = Visibility { span: rustc_span::DUMMY_SP, @@ -1714,6 +1751,22 @@ impl<'a> Parser<'a> { err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks"); err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); err + } else if self.eat_keyword(kw::Struct) { + match self.parse_item_struct() { + Ok((ident, _)) => { + let mut err = self.struct_span_err( + lo.with_hi(ident.span.hi()), + &format!("structs are not allowed in {adt_ty} definitions"), + ); + err.help("consider creating a new `struct` definition instead of nesting"); + err + } + Err(err) => { + err.cancel(); + self.restore_snapshot(snapshot); + self.expected_ident_found() + } + } } else { self.expected_ident_found() }; @@ -2323,7 +2376,7 @@ impl<'a> Parser<'a> { match ty { Ok(ty) => { let ident = Ident::new(kw::Empty, this.prev_token.span); - let bm = BindingMode::ByValue(Mutability::Not); + let bm = BindingAnnotation::NONE; let pat = this.mk_pat_ident(ty.span, bm, ident); (pat, ty) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index f6516d3bd45..4cb198561e0 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -37,7 +37,6 @@ use rustc_errors::{ use rustc_session::parse::ParseSess; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use tracing::debug; use std::ops::Range; use std::{cmp, mem, slice}; @@ -171,7 +170,7 @@ pub struct ClosureSpans { /// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]` /// In this case, we use a `ReplaceRange` to replace the entire inner AST node /// with `FlatToken::AttrTarget`, allowing us to perform eager cfg-expansion -/// on an `AttrAnnotatedTokenStream` +/// on an `AttrTokenStream`. /// /// 2. When we parse an inner attribute while collecting tokens. We /// remove inner attributes from the token stream entirely, and @@ -184,7 +183,7 @@ pub type ReplaceRange = (Range<u32>, Vec<(FlatToken, Spacing)>); /// Controls how we capture tokens. Capturing can be expensive, /// so we try to avoid performing capturing in cases where -/// we will never need an `AttrAnnotatedTokenStream` +/// we will never need an `AttrTokenStream`. #[derive(Copy, Clone)] pub enum Capturing { /// We aren't performing any capturing - this is the default mode. @@ -238,7 +237,7 @@ struct TokenCursor { // the trailing `>>` token. The `break_last_token` // field is used to track this token - it gets // appended to the captured stream when - // we evaluate a `LazyTokenStream` + // we evaluate a `LazyAttrTokenStream`. break_last_token: bool, } @@ -281,7 +280,7 @@ impl TokenCursor { if delim != Delimiter::Invisible { return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone); } - // No open delimeter to return; continue on to the next iteration. + // No open delimiter to return; continue on to the next iteration. } }; } else if let Some(frame) = self.stack.pop() { @@ -1465,11 +1464,11 @@ pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, sess: &Pa } } -/// A helper struct used when building an `AttrAnnotatedTokenStream` from -/// a `LazyTokenStream`. Both delimiter and non-delimited tokens +/// A helper struct used when building an `AttrTokenStream` from +/// a `LazyAttrTokenStream`. Both delimiter and non-delimited tokens /// are stored as `FlatToken::Token`. A vector of `FlatToken`s -/// is then 'parsed' to build up an `AttrAnnotatedTokenStream` with nested -/// `AttrAnnotatedTokenTree::Delimited` tokens +/// is then 'parsed' to build up an `AttrTokenStream` with nested +/// `AttrTokenTree::Delimited` tokens. #[derive(Debug, Clone)] pub enum FlatToken { /// A token - this holds both delimiter (e.g. '{' and '}') @@ -1477,11 +1476,11 @@ pub enum FlatToken { Token(Token), /// Holds the `AttributesData` for an AST node. The /// `AttributesData` is inserted directly into the - /// constructed `AttrAnnotatedTokenStream` as - /// an `AttrAnnotatedTokenTree::Attributes` + /// constructed `AttrTokenStream` as + /// an `AttrTokenTree::Attributes`. AttrTarget(AttributesData), /// A special 'empty' token that is ignored during the conversion - /// to an `AttrAnnotatedTokenStream`. This is used to simplify the + /// to an `AttrTokenStream`. This is used to simplify the /// handling of replace ranges. Empty, } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index e215b6872bf..103dd801257 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -66,18 +66,18 @@ impl<'a> Parser<'a> { }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { match token.kind { - token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) - token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern - token::OpenDelim(Delimiter::Bracket) | // slice pattern - token::BinOp(token::And) | // reference - token::BinOp(token::Minus) | // negative literal - token::AndAnd | // double reference - token::Literal(..) | // literal - token::DotDot | // range pattern (future compat) - token::DotDotDot | // range pattern (future compat) - token::ModSep | // path - token::Lt | // path (UFCS constant) - token::BinOp(token::Shl) => true, // path (double UFCS) + token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) + token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern + token::OpenDelim(Delimiter::Bracket) | // slice pattern + token::BinOp(token::And) | // reference + token::BinOp(token::Minus) | // negative literal + token::AndAnd | // double reference + token::Literal(..) | // literal + token::DotDot | // range pattern (future compat) + token::DotDotDot | // range pattern (future compat) + token::ModSep | // path + token::Lt | // path (UFCS constant) + token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr {..}), token::Interpolated(ref nt) => may_be_ident(nt), diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 8b3200d45fc..120a3c267f1 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,11 +1,12 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken}; +use crate::parser::diagnostics::RemoveLet; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::{ - self as ast, AttrVec, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatKind, - Path, QSelf, RangeEnd, RangeSyntax, + self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, + PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, }; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; @@ -320,7 +321,13 @@ impl<'a> Parser<'a> { maybe_recover_from_interpolated_ty_qpath!(self, true); maybe_whole!(self, NtPat, |x| x); - let lo = self.token.span; + let mut lo = self.token.span; + + if self.token.is_keyword(kw::Let) && self.look_ahead(1, |tok| tok.can_begin_pattern()) { + self.bump(); + self.sess.emit_err(RemoveLet { span: lo }); + lo = self.token.span; + } let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd { self.parse_pat_deref(expected)? @@ -353,7 +360,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Ref) { // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); - self.parse_pat_ident(BindingMode::ByRef(mutbl))? + self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl))? } else if self.eat_keyword(kw::Box) { self.parse_pat_box()? } else if self.check_inline_const(0) { @@ -369,7 +376,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(BindingMode::ByValue(Mutability::Not))? + self.parse_pat_ident(BindingAnnotation::NONE)? } else if self.is_start_of_pat_with_path() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { @@ -578,7 +585,8 @@ impl<'a> Parser<'a> { let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?; // If we don't have `mut $ident (@ pat)?`, error. - if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind { + if let PatKind::Ident(BindingAnnotation(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. *m = Mutability::Mut; @@ -604,7 +612,7 @@ impl<'a> Parser<'a> { ) .emit(); - self.parse_pat_ident(BindingMode::ByRef(Mutability::Mut)) + self.parse_pat_ident(BindingAnnotation::REF_MUT) } /// Turn all by-value immutable bindings in a pattern into mutable bindings. @@ -613,7 +621,8 @@ impl<'a> Parser<'a> { struct AddMut(bool); impl MutVisitor for AddMut { fn visit_pat(&mut self, pat: &mut P<Pat>) { - if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind + if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = + &mut pat.kind { self.0 = true; *m = Mutability::Mut; @@ -838,7 +847,7 @@ impl<'a> Parser<'a> { /// Parses `ident` or `ident @ pat`. /// Used by the copy foo and ref foo patterns to give a good /// error message when parsing mistakes like `ref foo(a, b)`. - fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> { + fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> { let ident = self.parse_ident()?; let sub = if self.eat(&token::At) { Some(self.parse_pat_no_top_alt(Some("binding pattern"))?) @@ -856,7 +865,7 @@ impl<'a> Parser<'a> { .struct_span_err(self.prev_token.span, "expected identifier, found enum pattern")); } - Ok(PatKind::Ident(binding_mode, ident, sub)) + Ok(PatKind::Ident(binding_annotation, ident, sub)) } /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`). @@ -936,11 +945,7 @@ impl<'a> Parser<'a> { None }; - Ok(PatKind::Ident( - BindingMode::ByValue(Mutability::Not), - Ident::new(kw::Box, box_span), - sub, - )) + Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub)) } else { let pat = self.parse_pat_with_range_pat(false, None)?; self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span)); @@ -1117,14 +1122,12 @@ impl<'a> Parser<'a> { let fieldname = self.parse_field_name()?; hi = self.prev_token.span; - let bind_type = match (is_ref, is_mut) { - (true, true) => BindingMode::ByRef(Mutability::Mut), - (true, false) => BindingMode::ByRef(Mutability::Not), - (false, true) => BindingMode::ByValue(Mutability::Mut), - (false, false) => BindingMode::ByValue(Mutability::Not), + let mutability = match is_mut { + false => Mutability::Not, + true => Mutability::Mut, }; - - let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname); + let ann = BindingAnnotation(ByRef::from(is_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 }; (subpat, fieldname, true) @@ -1141,8 +1144,8 @@ impl<'a> Parser<'a> { }) } - pub(super) fn mk_pat_ident(&self, span: Span, bm: BindingMode, ident: Ident) -> P<Pat> { - self.mk_pat(span, PatKind::Ident(bm, ident, None)) + pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingAnnotation, ident: Ident) -> P<Pat> { + self.mk_pat(span, PatKind::Ident(ann, ident, None)) } pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index fc7fb866f11..fdc1af27f82 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -13,7 +13,6 @@ use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym, Ident}; use std::mem; -use tracing::debug; /// Specifies how to parse a path. #[derive(Copy, Clone, PartialEq)] diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 4a2cf74905b..b47f0c09783 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -567,7 +567,8 @@ impl<'a> Parser<'a> { self.check_keyword(kw::Dyn) && (!self.token.uninterpolated_span().rust_2015() || self.look_ahead(1, |t| { - t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t) + (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star)) + && !can_continue_type_after_non_fn_ident(t) })) } @@ -576,10 +577,18 @@ impl<'a> Parser<'a> { /// Note that this does *not* parse bare trait objects. fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { self.bump(); // `dyn` + + // parse dyn* types + let syntax = if self.eat(&TokenKind::BinOp(token::Star)) { + TraitObjectSyntax::DynStar + } else { + TraitObjectSyntax::Dyn + }; + // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds(None)?; *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); - Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)) + Ok(TyKind::TraitObject(bounds, syntax)) } /// Parses a type starting with a path. |
