diff options
| author | bors <bors@rust-lang.org> | 2024-06-24 06:06:16 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-06-24 06:06:16 +0000 |
| commit | b8e1d7ef6fcec31db99ef82d8a913a2a703e8944 (patch) | |
| tree | 475052c1564920a30d5c4612177eafb17e7b72de /compiler/rustc_parse/src | |
| parent | aded2be375993cfb08c8d13be71c046bd048c5d2 (diff) | |
| parent | c660016cc1879d9714d134604856b5914f5d0aa0 (diff) | |
| download | rust-b8e1d7ef6fcec31db99ef82d8a913a2a703e8944.tar.gz rust-b8e1d7ef6fcec31db99ef82d8a913a2a703e8944.zip | |
Auto merge of #3706 - rust-lang:rustup-2024-06-24, r=oli-obk
Automatic Rustup
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/validate_attr.rs | 64 |
3 files changed, 101 insertions, 22 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 46e15734853..8d49887f164 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2997,3 +2997,34 @@ pub(crate) struct DotDotRangeAttribute { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_invalid_attr_unsafe)] +#[note] +pub struct InvalidAttrUnsafe { + #[primary_span] + pub span: Span, + pub name: Path, +} + +#[derive(Diagnostic)] +#[diag(parse_unsafe_attr_outside_unsafe)] +pub struct UnsafeAttrOutsideUnsafe { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + parse_unsafe_attr_outside_unsafe_suggestion, + applicability = "machine-applicable" +)] +pub struct UnsafeAttrOutsideUnsafeSuggestion { + #[suggestion_part(code = "unsafe(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 59f6eff07b3..4a78b427832 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,5 +1,7 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; +use rustc_ast::token::{ + self, Delimiter, Nonterminal::*, NonterminalKind, NtExprKind::*, NtPatKind::*, Token, +}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; @@ -36,14 +38,14 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr2021 { inferred: _ } => { + NonterminalKind::Expr(Expr2021 { .. }) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) // This exception is here for backwards compatibility. && !token.is_keyword(kw::Const) } - NonterminalKind::Expr => { + NonterminalKind::Expr(Expr) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) @@ -74,7 +76,7 @@ impl<'a> Parser<'a> { token::Interpolated(nt) => may_be_ident(nt), _ => false, }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind { + NonterminalKind::Pat(pat_kind) => match &token.kind { // box, ref, mut, and other identifiers (can stricten) token::Ident(..) | token::NtIdent(..) | token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern @@ -89,7 +91,7 @@ impl<'a> Parser<'a> { 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::BinOp(token::Or) => matches!(pat_kind, PatWithOr), token::Interpolated(nt) => may_be_ident(nt), _ => false, }, @@ -135,31 +137,25 @@ impl<'a> Parser<'a> { .create_err(UnexpectedNonterminal::Statement(self.token.span))); } }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { - NtPat(self.collect_tokens_no_attrs(|this| match kind { - NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None), - NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt( + NonterminalKind::Pat(pat_kind) => { + NtPat(self.collect_tokens_no_attrs(|this| match pat_kind { + PatParam { .. } => this.parse_pat_no_top_alt(None, None), + PatWithOr => this.parse_pat_allow_top_alt( None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe, ), - _ => unreachable!(), })?) } - - NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => { - NtExpr(self.parse_expr_force_collect()?) - } + NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) } - NonterminalKind::Ty => { NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?) } - // this could be handled like a token, since it is one NonterminalKind::Ident => { return if let Some((ident, is_raw)) = get_macro_ident(&self.token) { diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 4ca52146039..bcb1131cc19 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -5,21 +5,73 @@ use crate::{errors, parse_in}; use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::MetaItemKind; -use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem}; +use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety}; use rustc_errors::{Applicability, FatalError, PResult}; -use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{ + AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP, +}; use rustc_session::errors::report_lit_error; -use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; +use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::ParseSess; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{sym, BytePos, Span, Symbol}; -pub fn check_attr(psess: &ParseSess, attr: &Attribute) { +pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) { if attr.is_doc_comment() { return; } let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); + let attr_item = attr.get_normal_item(); + + let is_unsafe_attr = attr_info.is_some_and(|attr| attr.safety == AttributeSafety::Unsafe); + + if features.unsafe_attributes { + if is_unsafe_attr { + if let ast::Safety::Default = attr_item.unsafety { + let path_span = attr_item.path.span; + + // If the `attr_item`'s span is not from a macro, then just suggest + // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the + // `unsafe(`, `)` right after and right before the opening and closing + // square bracket respectively. + let diag_span = if attr_item.span().can_be_used_for_suggestions() { + attr_item.span() + } else { + attr.span + .with_lo(attr.span.lo() + BytePos(2)) + .with_hi(attr.span.hi() - BytePos(1)) + }; + + if attr.span.at_least_rust_2024() { + psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { + span: path_span, + suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { + left: diag_span.shrink_to_lo(), + right: diag_span.shrink_to_hi(), + }, + }); + } else { + psess.buffer_lint( + UNSAFE_ATTR_OUTSIDE_UNSAFE, + path_span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::UnsafeAttrOutsideUnsafe { + attribute_name_span: path_span, + sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), + }, + ); + } + } + } else { + if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { + psess.dcx().emit_err(errors::InvalidAttrUnsafe { + span: unsafe_span, + name: attr_item.path.clone(), + }); + } + } + } // Check input tokens for built-in and key-value attributes. match attr_info { @@ -32,7 +84,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { } } } - _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => { + _ if let AttrArgs::Eq(..) = attr_item.args => { // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { Ok(_) => {} |
