diff options
| author | Laurențiu Nicola <lnicola@dend.ro> | 2024-10-08 14:25:39 +0300 |
|---|---|---|
| committer | Laurențiu Nicola <lnicola@dend.ro> | 2024-10-08 14:25:39 +0300 |
| commit | 4316afffd9390bdac1d3bd5e5398c65d6e9bb150 (patch) | |
| tree | 9d5b39941405bec4b7c4571606df8b88850325e9 /compiler/rustc_parse/src | |
| parent | 537fb8d1bb2405b118898c663bc076815a1762c7 (diff) | |
| parent | cf24c73141a77db730f4b7fda69dcd7e8b113b51 (diff) | |
| download | rust-4316afffd9390bdac1d3bd5e5398c65d6e9bb150.tar.gz rust-4316afffd9390bdac1d3bd5e5398c65d6e9bb150.zip | |
Merge from rust-lang/rust
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lib.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 54 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/validate_attr.rs | 6 |
5 files changed, 74 insertions, 24 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 20bcefd4fe1..dade3912751 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2572,6 +2572,25 @@ pub(crate) struct EnumPatternInsteadOfIdentifier { } #[derive(Diagnostic)] +#[diag(parse_at_dot_dot_in_struct_pattern)] +pub(crate) struct AtDotDotInStructPattern { + #[primary_span] + pub span: Span, + #[suggestion(code = "", style = "verbose", applicability = "machine-applicable")] + pub remove: Span, + pub ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(parse_at_in_struct_pattern)] +#[note] +#[help] +pub(crate) struct AtInStructPattern { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(parse_dot_dot_dot_for_remaining_fields)] pub(crate) struct DotDotDotForRemainingFields { #[primary_span] @@ -2589,6 +2608,7 @@ pub(crate) struct ExpectedCommaAfterPatternField { #[derive(Diagnostic)] #[diag(parse_unexpected_expr_in_pat)] +#[note] pub(crate) struct UnexpectedExpressionInPattern { /// The unexpected expr's span. #[primary_span] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f7a8b8780ed..2792050a0b3 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -18,7 +18,7 @@ use std::path::Path; use rustc_ast as ast; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrItem, Attribute, MetaItem, token}; +use rustc_ast::{AttrItem, Attribute, MetaItemInner, token}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, FatalError, PResult}; @@ -160,7 +160,7 @@ pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> Tok pub fn parse_cfg_attr( cfg_attr: &Attribute, psess: &ParseSess, -) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> { +) -> Option<(MetaItemInner, Vec<(AttrItem, Span)>)> { const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>"; diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index c65cf3f40f6..b6fa2099588 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -356,8 +356,10 @@ impl<'a> Parser<'a> { } /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. - pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> { - let cfg_predicate = self.parse_meta_item(AllowLeadingUnsafe::No)?; + pub fn parse_cfg_attr( + &mut self, + ) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> { + let cfg_predicate = self.parse_meta_item_inner()?; self.expect(&token::Comma)?; // Presumably, the majority of the time there will only be one attr. @@ -375,7 +377,7 @@ impl<'a> Parser<'a> { } /// Matches `COMMASEP(meta_item_inner)`. - pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::NestedMetaItem>> { + pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> { // Presumably, the majority of the time there will only be one attr. let mut nmis = ThinVec::with_capacity(1); while self.token != token::Eof { @@ -452,14 +454,14 @@ impl<'a> Parser<'a> { /// ```ebnf /// MetaItemInner = UNSUFFIXED_LIT | MetaItem ; /// ``` - fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> { + pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::MetaItemInner> { match self.parse_unsuffixed_meta_item_lit() { - Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)), + Ok(lit) => return Ok(ast::MetaItemInner::Lit(lit)), Err(err) => err.cancel(), // we provide a better error below } match self.parse_meta_item(AllowLeadingUnsafe::No) { - Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)), + Ok(mi) => return Ok(ast::MetaItemInner::MetaItem(mi)), Err(err) => err.cancel(), // we provide a better error below } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index bd2ffaa0a89..7f114013320 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -17,15 +17,16 @@ use thin_vec::{ThinVec, thin_vec}; use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing, UsePreAttrPos}; use crate::errors::{ - self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, - DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, - ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax, - InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, - ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, - SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, - TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg, - UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, - UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, + self, AmbiguousRangePattern, AtDotDotInStructPattern, AtInStructPattern, + DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern, + EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, ExpectedCommaAfterPatternField, + GenericArgsInPatRequireTurbofishSyntax, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, + InclusiveRangeNoEnd, InvalidMutInPattern, ParenRangeSuggestion, PatternOnWrongSideOfAt, + RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, + TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, UnexpectedExpressionInPattern, + UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, + UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, + UnexpectedVertVertInPattern, WrapInParens, }; use crate::parser::expr::{DestructuredFloat, could_be_unclosed_char_literal}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; @@ -1433,7 +1434,7 @@ impl<'a> Parser<'a> { /// Parses the fields of a struct-like pattern. fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, PatFieldsRest)> { - let mut fields = ThinVec::new(); + let mut fields: ThinVec<PatField> = ThinVec::new(); let mut etc = PatFieldsRest::None; let mut ate_comma = true; let mut delayed_err: Option<Diag<'a>> = None; @@ -1454,12 +1455,22 @@ impl<'a> Parser<'a> { // check that a comma comes after every field if !ate_comma { - let mut err = - self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span }); + let err = if self.token == token::At { + let prev_field = fields + .last() + .expect("Unreachable on first iteration, not empty otherwise") + .ident; + self.report_misplaced_at_in_struct_pat(prev_field) + } else { + let mut err = self + .dcx() + .create_err(ExpectedCommaAfterPatternField { span: self.token.span }); + self.recover_misplaced_pattern_modifiers(&fields, &mut err); + err + }; if let Some(delayed) = delayed_err { delayed.emit(); } - self.recover_misplaced_pattern_modifiers(&fields, &mut err); return Err(err); } ate_comma = false; @@ -1594,6 +1605,23 @@ impl<'a> Parser<'a> { Ok((fields, etc)) } + #[deny(rustc::untranslatable_diagnostic)] + fn report_misplaced_at_in_struct_pat(&self, prev_field: Ident) -> Diag<'a> { + debug_assert_eq!(self.token, token::At); + let span = prev_field.span.to(self.token.span); + if let Some(dot_dot_span) = + self.look_ahead(1, |t| if t == &token::DotDot { Some(t.span) } else { None }) + { + self.dcx().create_err(AtDotDotInStructPattern { + span: span.to(dot_dot_span), + remove: span.until(dot_dot_span), + ident: prev_field, + }) + } else { + self.dcx().create_err(AtInStructPattern { span: span }) + } + } + /// If the user writes `S { ref field: name }` instead of `S { field: ref name }`, we suggest /// the correct code. fn recover_misplaced_pattern_modifiers(&self, fields: &ThinVec<PatField>, err: &mut Diag<'a>) { diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index b15d1edf79c..f3174e7dea2 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -3,8 +3,8 @@ use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::{ - self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemKind, - NestedMetaItem, Safety, + self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, + Safety, }; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; @@ -143,7 +143,7 @@ pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim /// Checks that the given meta-item is compatible with this `AttributeTemplate`. fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool { - let is_one_allowed_subword = |items: &[NestedMetaItem]| match items { + let is_one_allowed_subword = |items: &[MetaItemInner]| match items { [item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)), _ => false, }; |
