diff --git a/Cargo.lock b/Cargo.lock index 7d2fca8bb3f48..d58c98978aa76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3275,7 +3275,6 @@ dependencies = [ "rustc_feature", "rustc_fluent_macro", "rustc_macros", - "rustc_parse", "rustc_session", "rustc_span", "rustc_target", @@ -3321,6 +3320,7 @@ dependencies = [ "rustc_hir", "rustc_lexer", "rustc_macros", + "rustc_parse", "rustc_session", "rustc_span", "thin-vec", diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 1940628b44a53..3e04f8b11ec9d 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -15,7 +15,6 @@ rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_macros = { path = "../rustc_macros" } -rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a08dae1115307..5aef6b2af1b7f 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -29,7 +29,6 @@ use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::DiagCtxtHandle; use rustc_feature::Features; -use rustc_parse::validate_attr; use rustc_session::Session; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN, @@ -928,10 +927,6 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara } impl<'a> Visitor<'a> for AstValidator<'a> { - fn visit_attribute(&mut self, attr: &Attribute) { - validate_attr::check_attr(&self.sess.psess, attr, self.lint_node_id); - } - fn visit_ty(&mut self, ty: &'a Ty) { self.visit_ty_common(ty); self.walk_ty(ty) diff --git a/compiler/rustc_attr_data_structures/src/lints.rs b/compiler/rustc_attr_data_structures/src/lints.rs index 60ca4d43ce9bf..179dc22baae01 100644 --- a/compiler/rustc_attr_data_structures/src/lints.rs +++ b/compiler/rustc_attr_data_structures/src/lints.rs @@ -13,4 +13,5 @@ pub enum AttributeLintKind { UnusedDuplicate { this: Span, other: Span, warning: bool }, IllFormedAttributeInput { suggestions: Vec }, EmptyAttribute { first_span: Span }, + UnsafeAttrOutsideUnsafe { attribute_name_span: Span, sugg_spans: (Span, Span) }, } diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index 32029137268ba..e248b242a194f 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -15,6 +15,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } +rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 35ff48cb5f24b..c4593a0590296 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -161,3 +161,12 @@ attr_parsing_unused_multiple = -attr_parsing_previously_accepted = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +attr_parsing_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe + .label = usage of unsafe attribute +attr_parsing_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` + +attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute + .label = this is not an unsafe attribute + .suggestion = remove the `unsafe(...)` + .note = extraneous unsafe is not allowed in attributes diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 59337749c8775..e0d4da13bd411 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -247,7 +247,12 @@ pub(crate) fn parse_stability( let mut feature = None; let mut since = None; - for param in args.list()?.mixed() { + let ArgParser::List(list) = args else { + cx.expected_list(cx.attr_span); + return None; + }; + + for param in list.mixed() { let param_span = param.span(); let Some(param) = param.meta_item() else { cx.emit_err(session_diagnostics::UnsupportedLiteral { @@ -322,7 +327,13 @@ pub(crate) fn parse_unstability( let mut is_soft = false; let mut implied_by = None; let mut old_name = None; - for param in args.list()?.mixed() { + + let ArgParser::List(list) = args else { + cx.expected_list(cx.attr_span); + return None; + }; + + for param in list.mixed() { let Some(param) = param.meta_item() else { cx.emit_err(session_diagnostics::UnsupportedLiteral { span: param.span(), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 4d692d9562c1e..d256985919b02 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -203,10 +203,11 @@ mod private { #[allow(private_interfaces)] pub trait Stage: Sized + 'static + Sealed { type Id: Copy; - const SHOULD_EMIT_LINTS: bool; fn parsers() -> &'static group_type!(Self); + fn should_emit_errors_and_lints(&self) -> bool; + fn emit_err<'sess>( &self, sess: &'sess Session, @@ -218,11 +219,15 @@ pub trait Stage: Sized + 'static + Sealed { #[allow(private_interfaces)] impl Stage for Early { type Id = NodeId; - const SHOULD_EMIT_LINTS: bool = false; fn parsers() -> &'static group_type!(Self) { &early::ATTRIBUTE_PARSERS } + + fn should_emit_errors_and_lints(&self) -> bool { + self.emit_errors.should_emit() + } + fn emit_err<'sess>( &self, sess: &'sess Session, @@ -240,11 +245,15 @@ impl Stage for Early { #[allow(private_interfaces)] impl Stage for Late { type Id = HirId; - const SHOULD_EMIT_LINTS: bool = true; fn parsers() -> &'static group_type!(Self) { &late::ATTRIBUTE_PARSERS } + + fn should_emit_errors_and_lints(&self) -> bool { + true + } + fn emit_err<'sess>( &self, tcx: &'sess Session, @@ -290,7 +299,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { /// must be delayed until after HIR is built. This method will take care of the details of /// that. pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) { - if !S::SHOULD_EMIT_LINTS { + if !self.stage.should_emit_errors_and_lints() { return; } let id = self.target_id; @@ -696,6 +705,22 @@ impl<'sess> AttributeParser<'sess, Early> { }; parse_fn(&mut cx, args) } + + /// Returns whether the attribute is valid + pub fn validate_attribute_early( + sess: &'sess Session, + attr: &ast::Attribute, + target_node_id: NodeId, + ) -> bool { + let parser = Self { + features: None, + tools: Vec::new(), + parse_only: None, + sess, + stage: Early { emit_errors: ShouldEmit::ErrorsAndLints }, + }; + parser.validate_attribute(attr, target_node_id, &mut |_| {}, true) + } } impl<'sess, S: Stage> AttributeParser<'sess, S> { @@ -712,6 +737,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { &self.sess } + pub(crate) fn stage(&self) -> &S { + &self.stage + } + pub(crate) fn features(&self) -> &'sess Features { self.features.expect("features not available at this point in the compiler") } @@ -785,12 +814,14 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { ast::AttrKind::Normal(n) => { attr_paths.push(PathParser::Ast(&n.item.path)); + // Parse attribute using new infra let parser = MetaItemParser::from_attr(n, self.dcx()); let path = parser.path(); let args = parser.args(); let parts = path.segments().map(|i| i.name).collect::>(); if let Some(accepts) = S::parsers().0.get(parts.as_slice()) { + self.validate_attribute(attr, target_id, &mut emit_lint, true); for (template, accept) in accepts { let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { shared: SharedContext { @@ -821,7 +852,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { // // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]), // "attribute {path} wasn't parsed and isn't a know tool attribute", // ); - + self.validate_attribute(attr, target_id, &mut emit_lint, false); attributes.push(Attribute::Unparsed(Box::new(AttrItem { path: AttrPath::from_ast(&n.item.path), args: self.lower_attr_args(&n.item.args, lower_span), diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index dc54cb6b840cf..438295d1c1805 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -89,6 +89,7 @@ pub(crate) mod context; mod lints; pub mod parser; mod session_diagnostics; +mod validate_attr; pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr}; pub use attributes::cfg_old::*; @@ -97,5 +98,8 @@ pub use attributes::util::{ }; pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit}; pub use lints::emit_attribute_lint; +pub use validate_attr::{ + check_attribute_safety, check_builtin_meta_item, emit_fatal_malformed_builtin_attribute, +}; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs index e648ca4fdf808..9cc321f9fad9f 100644 --- a/compiler/rustc_attr_parsing/src/lints.rs +++ b/compiler/rustc_attr_parsing/src/lints.rs @@ -3,6 +3,7 @@ use rustc_errors::{DiagArgValue, LintEmitter}; use rustc_hir::HirId; use crate::session_diagnostics; +use crate::session_diagnostics::{UnsafeAttrOutsideUnsafeLint, UnsafeAttrOutsideUnsafeSuggestion}; pub fn emit_attribute_lint(lint: &AttributeLint, lint_emitter: L) { let AttributeLint { id, span, kind } = lint; @@ -34,5 +35,19 @@ pub fn emit_attribute_lint(lint: &AttributeLint, lint_emi *first_span, session_diagnostics::EmptyAttributeList { attr_span: *first_span }, ), + &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => { + lint_emitter.emit_node_span_lint( + rustc_session::lint::builtin::UNSAFE_ATTR_OUTSIDE_UNSAFE, + *id, + *span, + UnsafeAttrOutsideUnsafeLint { + span: attribute_name_span, + suggestion: UnsafeAttrOutsideUnsafeSuggestion { + left: sugg_spans.0.shrink_to_lo(), + right: sugg_spans.1.shrink_to_hi(), + }, + }, + ) + } } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 9a400e0fe1042..c8530ae240034 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1,6 +1,7 @@ use std::num::IntErrorKind; use rustc_ast as ast; +use rustc_ast::Path; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, @@ -701,3 +702,44 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError { diag } } + +#[derive(Diagnostic)] +#[diag(attr_parsing_unsafe_attr_outside_unsafe)] +pub(crate) struct UnsafeAttrOutsideUnsafe { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + attr_parsing_unsafe_attr_outside_unsafe_suggestion, + applicability = "machine-applicable" +)] +pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { + #[suggestion_part(code = "unsafe(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(attr_parsing_invalid_attr_unsafe)] +#[note] +pub(crate) struct InvalidAttrUnsafe { + #[primary_span] + #[label] + pub span: Span, + pub name: Path, +} + +#[derive(LintDiagnostic)] +#[diag(attr_parsing_unsafe_attr_outside_unsafe)] +pub(crate) struct UnsafeAttrOutsideUnsafeLint { + #[label] + pub span: Span, + #[subdiagnostic] + pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, +} diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs new file mode 100644 index 0000000000000..5598aa7d02bb6 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -0,0 +1,288 @@ +use rustc_ast::{self as ast, MetaItem, MetaItemInner, MetaItemKind, Safety}; +use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind}; +use rustc_errors::Applicability; +use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; +use rustc_parse::validate_attr::parse_meta; +use rustc_session::Session; +use rustc_session::lint::BuiltinLintDiag; +use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; +use rustc_span::fatal_error::FatalError; +use rustc_span::{Span, Symbol, sym}; + +use crate::context::Stage; +use crate::session_diagnostics::{ + InvalidAttrUnsafe, UnsafeAttrOutsideUnsafe, UnsafeAttrOutsideUnsafeSuggestion, +}; +use crate::{AttributeParser, Early}; + +impl<'sess, S: Stage> AttributeParser<'sess, S> { + pub(crate) fn validate_attribute( + &self, + attr: &ast::Attribute, + target_id: S::Id, + emit_lint: &mut impl FnMut(AttributeLint), + skip_template_check: bool, + ) -> bool { + if !self.stage().should_emit_errors_and_lints() { + return true; + } + let ast::AttrKind::Normal(normal) = &attr.kind else { return true }; + + // Trace attributes have already been checked when their respective non-trace attribute is parsed + if attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) { + return true; + } + + // Check attribute for safety + check_attribute_safety::(self.sess(), attr, target_id, emit_lint); + let builtin_attr_info = + attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); + + // All non-builtin attributes (and rustc_dummy) are not checked further unless they're for the form `#[attr = ...]`. + if (builtin_attr_info.is_none() || attr.has_name(sym::rustc_dummy)) + && !matches!(normal.item.args, rustc_ast::AttrArgs::Eq { .. }) + { + return true; + } + + // FIXME This check will be removed in the future (and costs performance :c) + // It checks some general things about the attribute (such that the literals are valid) + // This will be checked by the attribute parser in the future + let meta = match parse_meta(&self.sess().psess, attr) { + Ok(meta) => meta, + Err(err) => { + err.emit(); + return false; + } + }; + + // FIXME when all attributes are parsed, this check can be removed + // this checks the structure of built-in attributes that are not parsed yet + if skip_template_check { + return true; + } + if let Some(BuiltinAttribute { name, template, .. }) = builtin_attr_info { + if !is_attr_template_compatible(&template, &meta.kind) { + emit_malformed_attribute::( + self.sess(), + attr.style, + meta.span, + *name, + *template, + &mut |suggestions| { + emit_lint(AttributeLint { + id: target_id, + span: meta.span, + kind: AttributeLintKind::IllFormedAttributeInput { suggestions }, + }) + }, + ); + return false; + } + } + + true + } +} + +// FIXME this function can be removed when all attributes are parsed +// For now it is still used by a few built-in unparsed attributes +/// Check the safety and template of a given MetaItem +pub fn check_builtin_meta_item( + sess: &Session, + meta: &MetaItem, + style: ast::AttrStyle, + name: Symbol, + template: AttributeTemplate, +) { + if !is_attr_template_compatible(&template, &meta.kind) { + emit_malformed_attribute::( + sess, + style, + meta.span, + name, + template, + &mut |suggestions| { + sess.psess.buffer_lint( + ILL_FORMED_ATTRIBUTE_INPUT, + meta.span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::IllFormedAttributeInput { suggestions }, + ) + }, + ); + } + // This only supports denying unsafety right now - making builtin attributes + // support unsafety will requite us to thread the actual `Attribute` through + // for the nice diagnostics. + if let Safety::Unsafe(unsafe_span) = meta.unsafety { + sess.dcx().emit_err(InvalidAttrUnsafe { span: unsafe_span, name: meta.path.clone() }); + } +} + +// FIXME this function can be removed when all attributes are parsed +// For now it is still used by a few built-in unparsed attributes +pub fn emit_fatal_malformed_builtin_attribute( + sess: &Session, + attr: &rustc_ast::Attribute, + name: Symbol, +) -> ! { + let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template; + emit_malformed_attribute::(sess, attr.style, attr.span, name, template, &mut |_| {}); + // This is fatal, otherwise it will likely cause a cascade of other errors + // (and an error here is expected to be very rare). + FatalError.raise() +} + +fn emit_malformed_attribute( + sess: &Session, + style: ast::AttrStyle, + span: Span, + name: Symbol, + template: AttributeTemplate, + emit_lint: &mut impl FnMut(Vec), +) { + // Some of previously accepted forms were used in practice, + // report them as warnings for now. + let should_warn = |name| matches!(name, sym::doc | sym::link | sym::test | sym::bench); + + let error_msg = format!("malformed `{name}` attribute input"); + let mut suggestions = vec![]; + let inner = if style == ast::AttrStyle::Inner { "!" } else { "" }; + if template.word { + suggestions.push(format!("#{inner}[{name}]")); + } + if let Some(descr) = template.list { + suggestions.push(format!("#{inner}[{name}({descr})]")); + } + suggestions.extend(template.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]"))); + if let Some(descr) = template.name_value_str { + suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); + } + if should_warn(name) { + emit_lint(suggestions); + } else { + suggestions.sort(); + sess.dcx() + .struct_span_err(span, error_msg) + .with_span_suggestions( + span, + if suggestions.len() == 1 { + "must be of the form" + } else { + "the following are the possible correct uses" + }, + suggestions, + Applicability::HasPlaceholders, + ) + .emit(); + } +} + +// FIXME this function can be made private when all attributes are parsed +// For now it is still used by a few built-in unparsed attributes +pub fn check_attribute_safety( + sess: &Session, + attr: &ast::Attribute, + id: S::Id, + emit_lint: &mut impl FnMut(AttributeLint), +) { + let builtin_attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); + + let builtin_attr_safety = builtin_attr_info.map(|x| x.safety); + + let attr_item = attr.get_normal_item(); + match (builtin_attr_safety, attr_item.unsafety) { + // - Unsafe builtin attribute + // - User wrote `#[unsafe(..)]`, which is permitted on any edition + (Some(AttributeSafety::Unsafe { .. }), Safety::Unsafe(..)) => { + // OK + } + + // - Unsafe builtin attribute + // - User did not write `#[unsafe(..)]` + (Some(AttributeSafety::Unsafe { unsafe_since }), Safety::Default) => { + 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 = attr_item.span(); + + // Attributes can be safe in earlier editions, and become unsafe in later ones. + // + // Use the span of the attribute's name to determine the edition: the span of the + // attribute as a whole may be inaccurate if it was emitted by a macro. + // + // See https://github.com/rust-lang/rust/issues/142182. + let emit_error = match unsafe_since { + None => true, + Some(unsafe_since) => path_span.edition() >= unsafe_since, + }; + + if emit_error { + sess.dcx().emit_err(UnsafeAttrOutsideUnsafe { + span: path_span, + suggestion: UnsafeAttrOutsideUnsafeSuggestion { + left: diag_span.shrink_to_lo(), + right: diag_span.shrink_to_hi(), + }, + }); + } else { + emit_lint(AttributeLint { + id, + span: path_span, + kind: AttributeLintKind::UnsafeAttrOutsideUnsafe { + attribute_name_span: path_span, + sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), + }, + }); + } + } + + // - Normal builtin attribute, or any non-builtin attribute + // - All non-builtin attributes are currently considered safe; writing `#[unsafe(..)]` is + // not permitted on non-builtin attributes or normal builtin attributes + (Some(AttributeSafety::Normal) | None, Safety::Unsafe(unsafe_span)) => { + sess.dcx() + .emit_err(InvalidAttrUnsafe { span: unsafe_span, name: attr_item.path.clone() }); + } + + // - Normal builtin attribute + // - No explicit `#[unsafe(..)]` written. + (Some(AttributeSafety::Normal), Safety::Default) => { + // OK + } + + // - Non-builtin attribute + // - No explicit `#[unsafe(..)]` written. + (None, Safety::Default) => { + // OK + } + + ( + Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None, + Safety::Safe(..), + ) => { + sess.psess.dcx().span_delayed_bug( + attr_item.span(), + "`check_attribute_safety` does not expect `Safety::Safe` on attributes", + ); + } + } +} + +/// Checks that the given meta-item is compatible with this `AttributeTemplate`. +fn is_attr_template_compatible(template: &AttributeTemplate, meta: &MetaItemKind) -> bool { + let is_one_allowed_subword = |items: &[MetaItemInner]| match items { + [item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)), + _ => false, + }; + match meta { + MetaItemKind::Word => template.word, + MetaItemKind::List(items) => template.list.is_some() || is_one_allowed_subword(items), + MetaItemKind::NameValue(lit) if lit.kind.is_str() => template.name_value_str.is_some(), + MetaItemKind::NameValue(..) => false, + } +} diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 5f203dd5d1131..519387d518e26 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -1,9 +1,9 @@ //! Implementation of the `#[cfg_accessible(path)]` attribute macro. use rustc_ast as ast; +use rustc_attr_parsing::check_builtin_meta_item; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_feature::AttributeTemplate; -use rustc_parse::validate_attr; use rustc_span::{Span, sym}; use crate::errors; @@ -45,13 +45,12 @@ impl MultiItemModifier for Expander { _is_derive_const: bool, ) -> ExpandResult, Annotatable> { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; - validate_attr::check_builtin_meta_item( - &ecx.sess.psess, + check_builtin_meta_item( + ecx.sess, meta_item, ast::AttrStyle::Outer, sym::cfg_accessible, template, - true, ); let Some(path) = validate_input(ecx, meta_item) else { diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index e259f5b3955be..85cd915d76674 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,10 +1,10 @@ use rustc_ast as ast; use rustc_ast::{GenericParamKind, ItemKind, MetaItemInner, MetaItemKind, StmtKind}; +use rustc_attr_parsing::check_builtin_meta_item; use rustc_expand::base::{ Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier, }; use rustc_feature::AttributeTemplate; -use rustc_parse::validate_attr; use rustc_session::Session; use rustc_span::{ErrorGuaranteed, Ident, Span, sym}; @@ -36,13 +36,12 @@ impl MultiItemModifier for Expander { ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { let template = AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; - validate_attr::check_builtin_meta_item( - &sess.psess, + check_builtin_meta_item( + sess, meta_item, ast::AttrStyle::Outer, sym::derive, template, - true, ); let mut resolutions = match &meta_item.kind { diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 38fec2bff14c8..a4b2fe6c84504 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -1,13 +1,14 @@ use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{self as ast, AttrStyle, Attribute, MetaItem, attr, token}; +use rustc_attr_parsing::check_builtin_meta_item; use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt}; use rustc_expand::expand::AstFragment; use rustc_feature::AttributeTemplate; use rustc_lint_defs::BuiltinLintDiag; use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; -use rustc_parse::{exp, parser, validate_attr}; +use rustc_parse::{exp, parser}; use rustc_session::errors::report_lit_error; use rustc_span::{BytePos, Span, Symbol}; @@ -16,14 +17,7 @@ use crate::errors; pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { // All the built-in macro attributes are "words" at the moment. let template = AttributeTemplate { word: true, ..Default::default() }; - validate_attr::check_builtin_meta_item( - &ecx.sess.psess, - meta_item, - AttrStyle::Outer, - name, - template, - true, - ); + check_builtin_meta_item(ecx.sess, meta_item, AttrStyle::Outer, name, template); } /// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 83a8d601afeae..eac9b3922c16a 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -12,16 +12,15 @@ use rustc_ast::{ }; use rustc_attr_parsing as attr; use rustc_attr_parsing::{ - AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg_attr, + AttributeParser, CFG_TEMPLATE, Early, EvalConfigResult, ShouldEmit, check_attribute_safety, + eval_config_entry, parse_cfg_attr, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_feature::{ - ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, EnabledLibFeature, Features, - REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES, + ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, REMOVED_LANG_FEATURES, + UNSTABLE_LANG_FEATURES, }; use rustc_lint_defs::BuiltinLintDiag; -use rustc_parse::validate_attr; -use rustc_parse::validate_attr::deny_builtin_meta_unsafety; use rustc_session::Session; use rustc_session::parse::feature_err; use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym}; @@ -292,12 +291,7 @@ impl<'a> StripUnconfigured<'a> { /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec { - validate_attr::check_attribute_safety( - &self.sess.psess, - Some(AttributeSafety::Normal), - &cfg_attr, - ast::CRATE_NODE_ID, - ); + check_attribute_safety::(self.sess, &cfg_attr, ast::CRATE_NODE_ID, &mut |_| {}); // A trace attribute left in AST in place of the original `cfg_attr` attribute. // It can later be used by lints or other diagnostics. @@ -415,23 +409,10 @@ impl<'a> StripUnconfigured<'a> { node: NodeId, emit_errors: ShouldEmit, ) -> EvalConfigResult { - // We need to run this to do basic validation of the attribute, such as that lits are valid, etc - // FIXME(jdonszelmann) this should not be necessary in the future - match validate_attr::parse_meta(&self.sess.psess, attr) { - Ok(_) => {} - Err(err) => { - err.emit(); - return EvalConfigResult::True; - } + if !AttributeParser::validate_attribute_early(self.sess, attr, node) { + return EvalConfigResult::True; } - // Unsafety check needs to be done explicitly here because this attribute will be removed before the normal check - deny_builtin_meta_unsafety( - self.sess.dcx(), - attr.get_normal_item().unsafety, - &rustc_ast::Path::from_ident(attr.ident().unwrap()), - ); - let Some(cfg) = AttributeParser::parse_single( self.sess, attr, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 79ec79a2fdf42..cf49ca98f3f39 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -13,7 +13,7 @@ use rustc_ast::{ MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token, }; use rustc_ast_pretty::pprust; -use rustc_attr_parsing::{EvalConfigResult, ShouldEmit}; +use rustc_attr_parsing::{AttributeParser, EvalConfigResult, ShouldEmit}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_errors::PResult; use rustc_feature::Features; @@ -2119,17 +2119,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Detect use of feature-gated or invalid attributes on macro invocations // since they will not be detected after macro expansion. - fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) { + fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall, call_id: NodeId) { let features = self.cx.ecfg.features; let mut attrs = attrs.iter().peekable(); let mut span: Option = None; while let Some(attr) = attrs.next() { + // Attributes on a macro call will not be checked during late parsing since we'll remove them + // We do some basic checks now, but we don't fully parse them rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); - validate_attr::check_attr( - &self.cx.sess.psess, - attr, - self.cx.current_expansion.lint_node_id, - ); + AttributeParser::validate_attribute_early(self.cx.sess, attr, call_id); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); @@ -2228,8 +2226,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } }, None if node.is_mac_call() => { + let mac_node_id = node.node_id(); let (mac, attrs, add_semicolon) = node.take_mac_call(); - self.check_attributes(&attrs, &mac); + self.check_attributes(&attrs, &mac, mac_node_id); let mut res = self.collect_bang(mac, Node::KIND).make_ast::(); Node::post_flat_map_node_collect_bang(&mut res, add_semicolon); res @@ -2315,7 +2314,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { None if node.is_mac_call() => { let n = mem::replace(node, Node::dummy()); let (mac, attrs, _) = n.take_mac_call(); - self.check_attributes(&attrs, &mac); + self.check_attributes(&attrs, &mac, node.node_id()); *node = self.collect_bang(mac, Node::KIND).make_ast::().into() } diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index e925052c60709..cc0877a427ebe 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -3,8 +3,9 @@ use std::path::{self, Path, PathBuf}; use rustc_ast::ptr::P; use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans}; +use rustc_attr_parsing::emit_fatal_malformed_builtin_attribute; use rustc_errors::{Diag, ErrorGuaranteed}; -use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal, validate_attr}; +use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal}; use rustc_session::Session; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, sym}; @@ -190,7 +191,7 @@ pub(crate) fn mod_file_path_from_attr( // Usually bad forms are checked during semantic analysis via // `TyCtxt::check_mod_attrs`), but by the time that runs the macro // is expanded, and it doesn't give an error. - validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, first_path, sym::path); + emit_fatal_malformed_builtin_attribute(sess, first_path, sym::path); }; let path_str = path_sym.as_str(); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index fb6897c7d8958..cff4d5397a186 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -6,6 +6,7 @@ use std::sync::{Arc, LazyLock, OnceLock}; use std::{env, fs, iter}; use rustc_ast as ast; +use rustc_attr_parsing::emit_fatal_malformed_builtin_attribute; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::steal::Steal; @@ -25,9 +26,7 @@ use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepsType; use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; -use rustc_parse::{ - new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr, -}; +use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_resolve::Resolver; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; @@ -1304,7 +1303,7 @@ fn validate_and_find_value_str_builtin_attr( // Validate *all* relevant attributes, not just the first occurrence. for attr in ast::attr::filter_by_name(krate_attrs, name) { let Some(value) = attr.value_str() else { - validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, attr, name) + emit_fatal_malformed_builtin_attribute(sess, attr, name) }; // Choose the first occurrence as our result. result.get_or_insert((value, attr.span)); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0ca4fcc66ca55..7caab067ae7e3 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -5,12 +5,12 @@ use std::sync::{Arc, OnceLock}; use std::{env, thread}; use rustc_ast as ast; +use rustc_attr_parsing::emit_fatal_malformed_builtin_attribute; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::sync; use rustc_metadata::{DylibError, load_symbol_from_dylib}; use rustc_middle::ty::CurrentGcx; -use rustc_parse::validate_attr; use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple}; use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer}; use rustc_session::output::{CRATE_TYPES, categorize_crate_type}; @@ -477,11 +477,7 @@ pub(crate) fn check_attr_crate_type( // caught during semantic analysis via `TyCtxt::check_mod_attrs`, // but by the time that runs the macro is expanded, and it doesn't // give an error. - validate_attr::emit_fatal_malformed_builtin_attribute( - &sess.psess, - a, - sym::crate_type, - ); + emit_fatal_malformed_builtin_attribute(sess, a, sym::crate_type); } } } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 1a1cfc9fa6f1b..af4de248a837a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -963,10 +963,6 @@ lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::` -lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe - .label = usage of unsafe attribute -lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` - lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´ lint_untranslatable_diag = diagnostics should be created using translatable messages diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index f0fbf5bc81e9b..ee056e9bff4fc 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -357,16 +357,6 @@ pub fn decorate_builtin_lint( BuiltinLintDiag::UnusedQualifications { removal_span } => { lints::UnusedQualifications { removal_span }.decorate_lint(diag); } - BuiltinLintDiag::UnsafeAttrOutsideUnsafe { - attribute_name_span, - sugg_spans: (left, right), - } => { - lints::UnsafeAttrOutsideUnsafe { - span: attribute_name_span, - suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }, - } - .decorate_lint(diag); - } BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index fd8d0f832aa47..6d0372b787fde 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3134,27 +3134,6 @@ pub(crate) struct RedundantImportVisibility { pub max_vis: String, } -#[derive(LintDiagnostic)] -#[diag(lint_unsafe_attr_outside_unsafe)] -pub(crate) struct UnsafeAttrOutsideUnsafe { - #[label] - pub span: Span, - #[subdiagnostic] - pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - lint_unsafe_attr_outside_unsafe_suggestion, - applicability = "machine-applicable" -)] -pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { - #[suggestion_part(code = "unsafe(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, -} - #[derive(LintDiagnostic)] #[diag(lint_out_of_scope_macro_calls)] #[help] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index fe068d96b7424..7b950001c8b96 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -748,10 +748,6 @@ pub enum BuiltinLintDiag { /// The span of the unnecessarily-qualified path to remove. removal_span: Span, }, - UnsafeAttrOutsideUnsafe { - attribute_name_span: Span, - sugg_spans: (Span, Span), - }, AssociatedConstElidedLifetime { elided: bool, span: Span, diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 859118a4adee5..c52506935013f 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -425,11 +425,6 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item} .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style -parse_invalid_attr_unsafe = `{$name}` is not an unsafe attribute - .label = this is not an unsafe attribute - .suggestion = remove the `unsafe(...)` - .note = extraneous unsafe is not allowed in attributes - parse_invalid_block_macro_segment = cannot use a `block` macro fragment here .label = the `block` fragment is within this context .suggestion = wrap this in another block @@ -977,11 +972,6 @@ parse_unmatched_angle_brackets = {$num_extra_brackets -> *[other] remove extra angle brackets } -parse_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe - .label = usage of unsafe attribute -parse_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` - - parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped .label = {parse_unskipped_whitespace} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4aaaba01faeb3..484e0010d102c 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3460,38 +3460,6 @@ pub(crate) struct DotDotRangeAttribute { pub span: Span, } -#[derive(Diagnostic)] -#[diag(parse_invalid_attr_unsafe)] -#[note] -pub(crate) struct InvalidAttrUnsafe { - #[primary_span] - #[label] - pub span: Span, - pub name: Path, -} - -#[derive(Diagnostic)] -#[diag(parse_unsafe_attr_outside_unsafe)] -pub(crate) 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(crate) struct UnsafeAttrOutsideUnsafeSuggestion { - #[suggestion_part(code = "unsafe(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, -} - #[derive(Diagnostic)] #[diag(parse_binder_before_modifiers)] pub(crate) struct BinderBeforeModifiers { diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index a476f0db37e0d..055ab0e4f74ca 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -2,60 +2,13 @@ use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; -use rustc_ast::{ - self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, NodeId, - Path, Safety, -}; -use rustc_errors::{Applicability, DiagCtxtHandle, FatalError, PResult}; -use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; +use rustc_ast::{self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemKind}; +use rustc_errors::PResult; use rustc_session::errors::report_lit_error; -use rustc_session::lint::BuiltinLintDiag; -use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE}; use rustc_session::parse::ParseSess; -use rustc_span::{Span, Symbol, sym}; use crate::{errors, parse_in}; -pub fn check_attr(psess: &ParseSess, attr: &Attribute, id: NodeId) { - if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) - { - return; - } - - let builtin_attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); - - let builtin_attr_safety = builtin_attr_info.map(|x| x.safety); - check_attribute_safety(psess, builtin_attr_safety, attr, id); - - // Check input tokens for built-in and key-value attributes. - match builtin_attr_info { - // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { - match parse_meta(psess, attr) { - // Don't check safety again, we just did that - Ok(meta) => { - check_builtin_meta_item(psess, &meta, attr.style, *name, *template, false) - } - Err(err) => { - err.emit(); - } - } - } - _ => { - let attr_item = attr.get_normal_item(); - if let AttrArgs::Eq { .. } = attr_item.args { - // All key-value attributes are restricted to meta-item syntax. - match parse_meta(psess, attr) { - Ok(_) => {} - Err(err) => { - err.emit(); - } - } - } - } - } -} - pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> { let item = attr.get_normal_item(); Ok(MetaItem { @@ -139,255 +92,3 @@ pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close }, }); } - -/// 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: &[MetaItemInner]| match items { - [item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)), - _ => false, - }; - match meta { - MetaItemKind::Word => template.word, - MetaItemKind::List(items) => template.list.is_some() || is_one_allowed_subword(items), - MetaItemKind::NameValue(lit) if lit.kind.is_str() => template.name_value_str.is_some(), - MetaItemKind::NameValue(..) => false, - } -} - -pub fn check_attribute_safety( - psess: &ParseSess, - builtin_attr_safety: Option, - attr: &Attribute, - id: NodeId, -) { - let attr_item = attr.get_normal_item(); - match (builtin_attr_safety, attr_item.unsafety) { - // - Unsafe builtin attribute - // - User wrote `#[unsafe(..)]`, which is permitted on any edition - (Some(AttributeSafety::Unsafe { .. }), Safety::Unsafe(..)) => { - // OK - } - - // - Unsafe builtin attribute - // - User did not write `#[unsafe(..)]` - (Some(AttributeSafety::Unsafe { unsafe_since }), Safety::Default) => { - 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 = attr_item.span(); - - // Attributes can be safe in earlier editions, and become unsafe in later ones. - // - // Use the span of the attribute's name to determine the edition: the span of the - // attribute as a whole may be inaccurate if it was emitted by a macro. - // - // See https://github.com/rust-lang/rust/issues/142182. - let emit_error = match unsafe_since { - None => true, - Some(unsafe_since) => path_span.edition() >= unsafe_since, - }; - - if emit_error { - 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, - id, - BuiltinLintDiag::UnsafeAttrOutsideUnsafe { - attribute_name_span: path_span, - sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), - }, - ); - } - } - - // - Normal builtin attribute, or any non-builtin attribute - // - All non-builtin attributes are currently considered safe; writing `#[unsafe(..)]` is - // not permitted on non-builtin attributes or normal builtin attributes - (Some(AttributeSafety::Normal) | None, Safety::Unsafe(unsafe_span)) => { - psess.dcx().emit_err(errors::InvalidAttrUnsafe { - span: unsafe_span, - name: attr_item.path.clone(), - }); - } - - // - Normal builtin attribute - // - No explicit `#[unsafe(..)]` written. - (Some(AttributeSafety::Normal), Safety::Default) => { - // OK - } - - // - Non-builtin attribute - // - No explicit `#[unsafe(..)]` written. - (None, Safety::Default) => { - // OK - } - - ( - Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None, - Safety::Safe(..), - ) => { - psess.dcx().span_delayed_bug( - attr_item.span(), - "`check_attribute_safety` does not expect `Safety::Safe` on attributes", - ); - } - } -} - -// Called by `check_builtin_meta_item` and code that manually denies -// `unsafe(...)` in `cfg` -pub fn deny_builtin_meta_unsafety(diag: DiagCtxtHandle<'_>, unsafety: Safety, name: &Path) { - // This only supports denying unsafety right now - making builtin attributes - // support unsafety will requite us to thread the actual `Attribute` through - // for the nice diagnostics. - if let Safety::Unsafe(unsafe_span) = unsafety { - diag.emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: name.clone() }); - } -} - -pub fn check_builtin_meta_item( - psess: &ParseSess, - meta: &MetaItem, - style: ast::AttrStyle, - name: Symbol, - template: AttributeTemplate, - deny_unsafety: bool, -) { - if !is_attr_template_compatible(&template, &meta.kind) { - // attrs with new parsers are locally validated so excluded here - if matches!( - name, - sym::inline - | sym::export_stable - | sym::ffi_const - | sym::ffi_pure - | sym::rustc_std_internal_symbol - | sym::may_dangle - | sym::rustc_as_ptr - | sym::rustc_pub_transparent - | sym::rustc_const_stable_indirect - | sym::rustc_force_inline - | sym::rustc_confusables - | sym::rustc_skip_during_method_dispatch - | sym::rustc_pass_by_value - | sym::rustc_deny_explicit_impl - | sym::rustc_do_not_implement_via_object - | sym::rustc_coinductive - | sym::const_trait - | sym::rustc_specialization_trait - | sym::rustc_unsafe_specialization_marker - | sym::rustc_allow_incoherent_impl - | sym::rustc_coherence_is_core - | sym::marker - | sym::fundamental - | sym::rustc_paren_sugar - | sym::type_const - | sym::repr - | sym::align - | sym::deprecated - | sym::optimize - | sym::pointee - | sym::cold - | sym::target_feature - | sym::rustc_allow_const_fn_unstable - | sym::naked - | sym::no_mangle - | sym::non_exhaustive - | sym::omit_gdb_pretty_printer_section - | sym::path - | sym::ignore - | sym::must_use - | sym::track_caller - | sym::link_name - | sym::link_ordinal - | sym::export_name - | sym::rustc_macro_transparency - | sym::link_section - | sym::rustc_layout_scalar_valid_range_start - | sym::rustc_layout_scalar_valid_range_end - | sym::no_implicit_prelude - | sym::automatically_derived - | sym::coverage - ) { - return; - } - emit_malformed_attribute(psess, style, meta.span, name, template); - } - - if deny_unsafety { - deny_builtin_meta_unsafety(psess.dcx(), meta.unsafety, &meta.path); - } -} - -fn emit_malformed_attribute( - psess: &ParseSess, - style: ast::AttrStyle, - span: Span, - name: Symbol, - template: AttributeTemplate, -) { - // Some of previously accepted forms were used in practice, - // report them as warnings for now. - let should_warn = |name| matches!(name, sym::doc | sym::link | sym::test | sym::bench); - - let error_msg = format!("malformed `{name}` attribute input"); - let mut suggestions = vec![]; - let inner = if style == ast::AttrStyle::Inner { "!" } else { "" }; - if template.word { - suggestions.push(format!("#{inner}[{name}]")); - } - if let Some(descr) = template.list { - suggestions.push(format!("#{inner}[{name}({descr})]")); - } - suggestions.extend(template.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]"))); - if let Some(descr) = template.name_value_str { - suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); - } - if should_warn(name) { - psess.buffer_lint( - ILL_FORMED_ATTRIBUTE_INPUT, - span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::IllFormedAttributeInput { suggestions: suggestions.clone() }, - ); - } else { - suggestions.sort(); - psess - .dcx() - .struct_span_err(span, error_msg) - .with_span_suggestions( - span, - if suggestions.len() == 1 { - "must be of the form" - } else { - "the following are the possible correct uses" - }, - suggestions, - Applicability::HasPlaceholders, - ) - .emit(); - } -} - -pub fn emit_fatal_malformed_builtin_attribute( - psess: &ParseSess, - attr: &Attribute, - name: Symbol, -) -> ! { - let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template; - emit_malformed_attribute(psess, attr.style, attr.span, name, template); - // This is fatal, otherwise it will likely cause a cascade of other errors - // (and an error here is expected to be very rare). - FatalError.raise() -} diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 016a1813babd7..f8846a0ec74c6 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -278,7 +278,7 @@ pub fn no_mangle() {} #[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail5")] #[rustc_clean(cfg = "cfail6")] -#[no_mangle] +#[unsafe(no_mangle)] pub fn no_mangle() {} // Linkage --------------------------------------------------------------------- diff --git a/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs index 044c3d2b86c13..b55580c086444 100644 --- a/tests/incremental/hashes/inherent_impls.rs +++ b/tests/incremental/hashes/inherent_impls.rs @@ -660,7 +660,7 @@ impl Foo { //-------------------------- //-------------------------- //-------------------------- - //---------- + //------------------ pub fn add_no_mangle_to_method(&self) { } } @@ -674,7 +674,7 @@ impl Foo { #[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] - #[no_mangle] + #[unsafe(no_mangle)] pub fn add_no_mangle_to_method(&self) { } } diff --git a/tests/incremental/hashes/statics.rs b/tests/incremental/hashes/statics.rs index 9ea21d84ba154..ba247be06387f 100644 --- a/tests/incremental/hashes/statics.rs +++ b/tests/incremental/hashes/statics.rs @@ -65,7 +65,7 @@ static STATIC_NO_MANGLE: u8 = 0; #[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] -#[no_mangle] +#[unsafe(no_mangle)] static STATIC_NO_MANGLE: u8 = 0; diff --git a/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs index a89b5b3e78298..55f50dbe98d8f 100644 --- a/tests/incremental/hashes/trait_impls.rs +++ b/tests/incremental/hashes/trait_impls.rs @@ -568,7 +568,7 @@ impl AddNoMangleToMethod for Foo { // ------------------------- // ------------------------- // ------------------------- - // --------- + // ----------------- fn add_no_mangle_to_method(&self) { } } @@ -582,7 +582,7 @@ impl AddNoMangleToMethod for Foo { #[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] - #[no_mangle] + #[unsafe(no_mangle)] fn add_no_mangle_to_method(&self) { } } diff --git a/tests/ui/attributes/issue-90873.stderr b/tests/ui/attributes/issue-90873.stderr index 444497538e8dc..afe36156f0e3a 100644 --- a/tests/ui/attributes/issue-90873.stderr +++ b/tests/ui/attributes/issue-90873.stderr @@ -1,15 +1,3 @@ -error: attribute value must be a literal - --> $DIR/issue-90873.rs:1:6 - | -LL | #![u=||{static d=||1;}] - | ^^^^^^^^^^^^^^^^^ - -error: attribute value must be a literal - --> $DIR/issue-90873.rs:6:6 - | -LL | #![a={impl std::ops::Neg for i8 {}}] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: cannot find attribute `u` in this scope --> $DIR/issue-90873.rs:1:4 | @@ -22,6 +10,18 @@ error: cannot find attribute `a` in this scope LL | #![a={impl std::ops::Neg for i8 {}}] | ^ +error: attribute value must be a literal + --> $DIR/issue-90873.rs:1:6 + | +LL | #![u=||{static d=||1;}] + | ^^^^^^^^^^^^^^^^^ + +error: attribute value must be a literal + --> $DIR/issue-90873.rs:6:6 + | +LL | #![a={impl std::ops::Neg for i8 {}}] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0601]: `main` function not found in crate `issue_90873` --> $DIR/issue-90873.rs:6:37 | diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 0d0c338d30269..f214d689b0732 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -25,171 +25,6 @@ error[E0463]: can't find crate for `wloop` LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate -error: malformed `windows_subsystem` attribute input - --> $DIR/malformed-attrs.rs:29:1 - | -LL | #![windows_subsystem] - | ^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![windows_subsystem = "windows|console"]` - -error: malformed `crate_name` attribute input - --> $DIR/malformed-attrs.rs:74:1 - | -LL | #[crate_name] - | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` - -error: malformed `no_sanitize` attribute input - --> $DIR/malformed-attrs.rs:92:1 - | -LL | #[no_sanitize] - | ^^^^^^^^^^^^^^ help: must be of the form: `#[no_sanitize(address, kcfi, memory, thread)]` - -error: malformed `proc_macro` attribute input - --> $DIR/malformed-attrs.rs:99:1 - | -LL | #[proc_macro = 18] - | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` - -error: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:106:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` - -error: malformed `patchable_function_entry` attribute input - --> $DIR/malformed-attrs.rs:108:1 - | -LL | #[patchable_function_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` - -error: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:111:5 - | -LL | #[coroutine = 63] || {} - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[coroutine]` - -error: malformed `proc_macro_attribute` attribute input - --> $DIR/malformed-attrs.rs:116:1 - | -LL | #[proc_macro_attribute = 19] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` - -error: malformed `proc_macro_derive` attribute input - --> $DIR/malformed-attrs.rs:123:1 - | -LL | #[proc_macro_derive] - | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` - -error: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:132:1 - | -LL | #[must_not_suspend()] - | ^^^^^^^^^^^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL - #[must_not_suspend()] -LL + #[must_not_suspend = "reason"] - | -LL - #[must_not_suspend()] -LL + #[must_not_suspend] - | - -error: malformed `cfi_encoding` attribute input - --> $DIR/malformed-attrs.rs:134:1 - | -LL | #[cfi_encoding] - | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` - -error: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:173:5 - | -LL | #[linkage] - | ^^^^^^^^^^ help: must be of the form: `#[linkage = "external|internal|..."]` - -error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:178:1 - | -LL | #[allow] - | ^^^^^^^^ help: must be of the form: `#[allow(lint1, lint2, ..., /*opt*/ reason = "...")]` - -error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:180:1 - | -LL | #[expect] - | ^^^^^^^^^ help: must be of the form: `#[expect(lint1, lint2, ..., /*opt*/ reason = "...")]` - -error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:182:1 - | -LL | #[warn] - | ^^^^^^^ help: must be of the form: `#[warn(lint1, lint2, ..., /*opt*/ reason = "...")]` - -error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:184:1 - | -LL | #[deny] - | ^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]` - -error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:186:1 - | -LL | #[forbid] - | ^^^^^^^^^ help: must be of the form: `#[forbid(lint1, lint2, ..., /*opt*/ reason = "...")]` - -error: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:188:1 - | -LL | #[debugger_visualizer] - | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]` - -error: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:203:1 - | -LL | #[thread_local()] - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]` - -error: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:207:1 - | -LL | #[no_link()] - | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` - -error: malformed `macro_use` attribute input - --> $DIR/malformed-attrs.rs:209:1 - | -LL | #[macro_use = 1] - | ^^^^^^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL - #[macro_use = 1] -LL + #[macro_use(name1, name2, ...)] - | -LL - #[macro_use = 1] -LL + #[macro_use] - | - -error: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:214:1 - | -LL | #[macro_export = 18] - | ^^^^^^^^^^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL - #[macro_export = 18] -LL + #[macro_export(local_inner_macros)] - | -LL - #[macro_export = 18] -LL + #[macro_export] - | - -error: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:216:1 - | -LL | #[allow_internal_unsafe = 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[allow_internal_unsafe]` - error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/malformed-attrs.rs:99:1 | @@ -217,34 +52,6 @@ LL | #[allow_internal_unsafe = 1] = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:43:1 - | -LL | #[doc] - | ^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 - = note: `#[deny(ill_formed_attribute_input)]` on by default - -error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:76:1 - | -LL | #[doc] - | ^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 - -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-attrs.rs:83:1 - | -LL | #[link] - | ^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 - error: invalid argument --> $DIR/malformed-attrs.rs:188:1 | @@ -264,6 +71,12 @@ LL | #![omit_gdb_pretty_printer_section = 1] | | didn't expect any arguments here | help: must be of the form: `#[omit_gdb_pretty_printer_section]` +error: malformed `windows_subsystem` attribute input + --> $DIR/malformed-attrs.rs:29:1 + | +LL | #![windows_subsystem] + | ^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![windows_subsystem = "windows|console"]` + error[E0539]: malformed `export_name` attribute input --> $DIR/malformed-attrs.rs:32:1 | @@ -417,6 +230,12 @@ LL - #[used()] LL + #[used] | +error: malformed `crate_name` attribute input + --> $DIR/malformed-attrs.rs:74:1 + | +LL | #[crate_name] + | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` + error[E0539]: malformed `target_feature` attribute input --> $DIR/malformed-attrs.rs:79:1 | @@ -460,6 +279,12 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: malformed `no_sanitize` attribute input + --> $DIR/malformed-attrs.rs:92:1 + | +LL | #[no_sanitize] + | ^^^^^^^^^^^^^^ help: must be of the form: `#[no_sanitize(address, kcfi, memory, thread)]` + error[E0565]: malformed `no_implicit_prelude` attribute input --> $DIR/malformed-attrs.rs:97:1 | @@ -469,6 +294,36 @@ LL | #[no_implicit_prelude = 23] | | didn't expect any arguments here | help: must be of the form: `#[no_implicit_prelude]` +error: malformed `proc_macro` attribute input + --> $DIR/malformed-attrs.rs:99:1 + | +LL | #[proc_macro = 18] + | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` + +error: malformed `instruction_set` attribute input + --> $DIR/malformed-attrs.rs:106:1 + | +LL | #[instruction_set] + | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` + +error: malformed `patchable_function_entry` attribute input + --> $DIR/malformed-attrs.rs:108:1 + | +LL | #[patchable_function_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` + +error: malformed `coroutine` attribute input + --> $DIR/malformed-attrs.rs:111:5 + | +LL | #[coroutine = 63] || {} + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[coroutine]` + +error: malformed `proc_macro_attribute` attribute input + --> $DIR/malformed-attrs.rs:116:1 + | +LL | #[proc_macro_attribute = 19] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` + error[E0539]: malformed `must_use` attribute input --> $DIR/malformed-attrs.rs:119:1 | @@ -486,6 +341,12 @@ LL - #[must_use = 1] LL + #[must_use] | +error: malformed `proc_macro_derive` attribute input + --> $DIR/malformed-attrs.rs:123:1 + | +LL | #[proc_macro_derive] + | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input --> $DIR/malformed-attrs.rs:128:1 | @@ -504,6 +365,27 @@ LL | #[rustc_layout_scalar_valid_range_end] | expected this to be a list | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` +error: malformed `must_not_suspend` attribute input + --> $DIR/malformed-attrs.rs:132:1 + | +LL | #[must_not_suspend()] + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL - #[must_not_suspend()] +LL + #[must_not_suspend = "reason"] + | +LL - #[must_not_suspend()] +LL + #[must_not_suspend] + | + +error: malformed `cfi_encoding` attribute input + --> $DIR/malformed-attrs.rs:134:1 + | +LL | #[cfi_encoding] + | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` + error[E0565]: malformed `marker` attribute input --> $DIR/malformed-attrs.rs:155:1 | @@ -549,6 +431,48 @@ LL | #[unsafe(ffi_const = 1)] | | didn't expect any arguments here | help: must be of the form: `#[ffi_const]` +error: malformed `linkage` attribute input + --> $DIR/malformed-attrs.rs:173:5 + | +LL | #[linkage] + | ^^^^^^^^^^ help: must be of the form: `#[linkage = "external|internal|..."]` + +error: malformed `allow` attribute input + --> $DIR/malformed-attrs.rs:178:1 + | +LL | #[allow] + | ^^^^^^^^ help: must be of the form: `#[allow(lint1, lint2, ..., /*opt*/ reason = "...")]` + +error: malformed `expect` attribute input + --> $DIR/malformed-attrs.rs:180:1 + | +LL | #[expect] + | ^^^^^^^^^ help: must be of the form: `#[expect(lint1, lint2, ..., /*opt*/ reason = "...")]` + +error: malformed `warn` attribute input + --> $DIR/malformed-attrs.rs:182:1 + | +LL | #[warn] + | ^^^^^^^ help: must be of the form: `#[warn(lint1, lint2, ..., /*opt*/ reason = "...")]` + +error: malformed `deny` attribute input + --> $DIR/malformed-attrs.rs:184:1 + | +LL | #[deny] + | ^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]` + +error: malformed `forbid` attribute input + --> $DIR/malformed-attrs.rs:186:1 + | +LL | #[forbid] + | ^^^^^^^^^ help: must be of the form: `#[forbid(lint1, lint2, ..., /*opt*/ reason = "...")]` + +error: malformed `debugger_visualizer` attribute input + --> $DIR/malformed-attrs.rs:188:1 + | +LL | #[debugger_visualizer] + | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]` + error[E0565]: malformed `automatically_derived` attribute input --> $DIR/malformed-attrs.rs:191:1 | @@ -567,6 +491,54 @@ LL | #[non_exhaustive = 1] | | didn't expect any arguments here | help: must be of the form: `#[non_exhaustive]` +error: malformed `thread_local` attribute input + --> $DIR/malformed-attrs.rs:203:1 + | +LL | #[thread_local()] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]` + +error: malformed `no_link` attribute input + --> $DIR/malformed-attrs.rs:207:1 + | +LL | #[no_link()] + | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` + +error: malformed `macro_use` attribute input + --> $DIR/malformed-attrs.rs:209:1 + | +LL | #[macro_use = 1] + | ^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL - #[macro_use = 1] +LL + #[macro_use(name1, name2, ...)] + | +LL - #[macro_use = 1] +LL + #[macro_use] + | + +error: malformed `macro_export` attribute input + --> $DIR/malformed-attrs.rs:214:1 + | +LL | #[macro_export = 18] + | ^^^^^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL - #[macro_export = 18] +LL + #[macro_export(local_inner_macros)] + | +LL - #[macro_export = 18] +LL + #[macro_export] + | + +error: malformed `allow_internal_unsafe` attribute input + --> $DIR/malformed-attrs.rs:216:1 + | +LL | #[allow_internal_unsafe = 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[allow_internal_unsafe]` + error[E0565]: malformed `type_const` attribute input --> $DIR/malformed-attrs.rs:143:5 | @@ -624,6 +596,16 @@ LL | #[diagnostic::on_unimplemented = 1] | = help: only `message`, `note` and `label` are allowed as options +error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` + --> $DIR/malformed-attrs.rs:43:1 + | +LL | #[doc] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + = note: `#[deny(ill_formed_attribute_input)]` on by default + error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` --> $DIR/malformed-attrs.rs:53:1 | @@ -633,6 +615,24 @@ LL | #[inline = 5] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 +error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` + --> $DIR/malformed-attrs.rs:76:1 + | +LL | #[doc] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` + --> $DIR/malformed-attrs.rs:83:1 + | +LL | #[link] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` --> $DIR/malformed-attrs.rs:94:1 | diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index af3625b1f3b9e..cc584bd3a0bb2 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -1,17 +1,3 @@ -error: expected unsuffixed literal, found `-` - --> $DIR/malformed-fn-align.rs:24:9 - | -LL | #[align(-1)] - | ^ - -error: suffixed literals are not allowed in attributes - --> $DIR/malformed-fn-align.rs:30:9 - | -LL | #[align(4usize)] - | ^^^^^^ - | - = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) - error[E0539]: malformed `align` attribute input --> $DIR/malformed-fn-align.rs:5:5 | @@ -51,12 +37,26 @@ error[E0589]: invalid alignment value: not a power of two LL | #[align(0)] | ^ +error: expected unsuffixed literal, found `-` + --> $DIR/malformed-fn-align.rs:24:9 + | +LL | #[align(-1)] + | ^ + error[E0589]: invalid alignment value: not a power of two --> $DIR/malformed-fn-align.rs:27:9 | LL | #[align(3)] | ^ +error: suffixed literals are not allowed in attributes + --> $DIR/malformed-fn-align.rs:30:9 + | +LL | #[align(4usize)] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + error[E0589]: invalid alignment value: not an unsuffixed integer --> $DIR/malformed-fn-align.rs:30:9 | diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr index 0825cf794083d..8ab945e0f182e 100644 --- a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr @@ -9,6 +9,12 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(r#unsafe(no_mangle))] | ++ +error: cannot find attribute `r#unsafe` in this scope + --> $DIR/double-unsafe-attributes.rs:1:10 + | +LL | #[unsafe(unsafe(no_mangle))] + | ^^^^^^ + error: `r#unsafe` is not an unsafe attribute --> $DIR/double-unsafe-attributes.rs:1:3 | @@ -17,11 +23,5 @@ LL | #[unsafe(unsafe(no_mangle))] | = note: extraneous unsafe is not allowed in attributes -error: cannot find attribute `r#unsafe` in this scope - --> $DIR/double-unsafe-attributes.rs:1:10 - | -LL | #[unsafe(unsafe(no_mangle))] - | ^^^^^^ - error: aborting due to 3 previous errors diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 25b83a26e1700..f0a0cd959251c 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -12,6 +12,46 @@ LL | #[unsafe(allow(unsafe(dead_code)))] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:1:1 + | +LL | #[unsafe(proc_macro)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:7:1 + | +LL | #[unsafe(proc_macro_derive(Foo))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:12:1 + | +LL | #[proc_macro_derive(unsafe(Foo))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:17:1 + | +LL | #[unsafe(proc_macro_attribute)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:26:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:26:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: `proc_macro` is not an unsafe attribute --> $DIR/proc-unsafe-attributes.rs:1:3 | @@ -74,46 +114,6 @@ help: escape `unsafe` to use it as an identifier LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ -error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:1:1 - | -LL | #[unsafe(proc_macro)] - | ^^^^^^^^^^^^^^^^^^^^^ - -error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:7:1 - | -LL | #[unsafe(proc_macro_derive(Foo))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:12:1 - | -LL | #[proc_macro_derive(unsafe(Foo))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:17:1 - | -LL | #[unsafe(proc_macro_attribute)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:26:16 - | -LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:26:16 - | -LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0452]: malformed lint attribute input --> $DIR/proc-unsafe-attributes.rs:26:16 | diff --git a/tests/ui/attributes/unsafe/unsafe-on-macro.rs b/tests/ui/attributes/unsafe/unsafe-on-macro.rs new file mode 100644 index 0000000000000..b1e5befce0d88 --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-on-macro.rs @@ -0,0 +1,11 @@ +#![feature(rustc_attrs)] + +macro_rules! bar { + () => {}; +} + +#[unsafe(rustc_dummy)] +//~^ ERROR `rustc_dummy` is not an unsafe attribute +bar!(); + +fn main() {} diff --git a/tests/ui/attributes/unsafe/unsafe-on-macro.stderr b/tests/ui/attributes/unsafe/unsafe-on-macro.stderr new file mode 100644 index 0000000000000..ccebae11ec851 --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-on-macro.stderr @@ -0,0 +1,10 @@ +error: `rustc_dummy` is not an unsafe attribute + --> $DIR/unsafe-on-macro.rs:7:3 + | +LL | #[unsafe(rustc_dummy)] + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes + +error: aborting due to 1 previous error + diff --git a/tests/ui/attributes/unused-item-in-attr.stderr b/tests/ui/attributes/unused-item-in-attr.stderr index 84130965d31cf..1d4437647d3cc 100644 --- a/tests/ui/attributes/unused-item-in-attr.stderr +++ b/tests/ui/attributes/unused-item-in-attr.stderr @@ -1,14 +1,14 @@ -error: attribute value must be a literal - --> $DIR/unused-item-in-attr.rs:1:7 - | -LL | #[w = { extern crate alloc; }] - | ^^^^^^^^^^^^^^^^^^^^^^^ - error: cannot find attribute `w` in this scope --> $DIR/unused-item-in-attr.rs:1:3 | LL | #[w = { extern crate alloc; }] | ^ +error: attribute value must be a literal + --> $DIR/unused-item-in-attr.rs:1:7 + | +LL | #[w = { extern crate alloc; }] + | ^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 2 previous errors diff --git a/tests/ui/consts/issue-90878-2.stderr b/tests/ui/consts/issue-90878-2.stderr index 0b332840042ef..f5991ef9bcf7b 100644 --- a/tests/ui/consts/issue-90878-2.stderr +++ b/tests/ui/consts/issue-90878-2.stderr @@ -1,14 +1,14 @@ -error: attribute value must be a literal - --> $DIR/issue-90878-2.rs:1:7 - | -LL | #![l=|x|[b;x ]] - | ^^^^^^^^^ - error: cannot find attribute `l` in this scope --> $DIR/issue-90878-2.rs:1:5 | LL | #![l=|x|[b;x ]] | ^ +error: attribute value must be a literal + --> $DIR/issue-90878-2.rs:1:7 + | +LL | #![l=|x|[b;x ]] + | ^^^^^^^^^ + error: aborting due to 2 previous errors diff --git a/tests/ui/coverage-attr/bad-syntax.stderr b/tests/ui/coverage-attr/bad-syntax.stderr index 927f61da08db8..ecf3ed83bca7b 100644 --- a/tests/ui/coverage-attr/bad-syntax.stderr +++ b/tests/ui/coverage-attr/bad-syntax.stderr @@ -1,15 +1,3 @@ -error: expected identifier, found `,` - --> $DIR/bad-syntax.rs:44:12 - | -LL | #[coverage(,off)] - | ^ expected identifier - | -help: remove this comma - | -LL - #[coverage(,off)] -LL + #[coverage(off)] - | - error: multiple `coverage` attributes --> $DIR/bad-syntax.rs:9:1 | @@ -162,6 +150,18 @@ LL - #[coverage(off, bogus)] LL + #[coverage(on)] | +error: expected identifier, found `,` + --> $DIR/bad-syntax.rs:44:12 + | +LL | #[coverage(,off)] + | ^ expected identifier + | +help: remove this comma + | +LL - #[coverage(,off)] +LL + #[coverage(off)] + | + error: aborting due to 11 previous errors Some errors have detailed explanations: E0539, E0805. diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr index 0bdcc293b6524..a535ecd0980a4 100644 --- a/tests/ui/lint/lint-malformed.stderr +++ b/tests/ui/lint/lint-malformed.stderr @@ -12,12 +12,6 @@ LL | #![allow(bar = "baz")] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: malformed `deny` attribute input - --> $DIR/lint-malformed.rs:1:1 - | -LL | #![deny = "foo"] - | ^^^^^^^^^^^^^^^^ help: must be of the form: `#![deny(lint1, lint2, ..., /*opt*/ reason = "...")]` - error[E0452]: malformed lint attribute input --> $DIR/lint-malformed.rs:2:10 | @@ -34,6 +28,12 @@ LL | #![allow(bar = "baz")] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: malformed `deny` attribute input + --> $DIR/lint-malformed.rs:1:1 + | +LL | #![deny = "foo"] + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#![deny(lint1, lint2, ..., /*opt*/ reason = "...")]` + error[E0452]: malformed lint attribute input --> $DIR/lint-malformed.rs:2:10 | diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 8c22919a1c2f1..95984798b37e5 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -8,38 +8,38 @@ LL | #[doc] = note: for more information, see issue #57571 = note: `#[deny(ill_formed_attribute_input)]` on by default -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-regressions.rs:7:1 +error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` + --> $DIR/malformed-regressions.rs:3:1 | -LL | #[link] - | ^^^^^^^ +LL | #[ignore()] + | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-regressions.rs:9:1 +error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` + --> $DIR/malformed-regressions.rs:5:1 | -LL | #[link = ""] - | ^^^^^^^^^^^^ +LL | #[inline = ""] + | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-regressions.rs:3:1 +error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` + --> $DIR/malformed-regressions.rs:7:1 | -LL | #[ignore()] - | ^^^^^^^^^^^ +LL | #[link] + | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` - --> $DIR/malformed-regressions.rs:5:1 +error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` + --> $DIR/malformed-regressions.rs:9:1 | -LL | #[inline = ""] - | ^^^^^^^^^^^^^^ +LL | #[link = ""] + | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr index 7876d75c5a427..6d994301cfdfe 100644 --- a/tests/ui/parser/bad-lit-suffixes.stderr +++ b/tests/ui/parser/bad-lit-suffixes.stderr @@ -10,32 +10,6 @@ error: suffixes on string literals are invalid LL | "C"suffix | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on string literals are invalid - --> $DIR/bad-lit-suffixes.rs:30:17 - | -LL | #[rustc_dummy = "string"suffix] - | ^^^^^^^^^^^^^^ invalid suffix `suffix` - -error: suffixes on string literals are invalid - --> $DIR/bad-lit-suffixes.rs:34:14 - | -LL | #[must_use = "string"suffix] - | ^^^^^^^^^^^^^^ invalid suffix `suffix` - -error: suffixes on string literals are invalid - --> $DIR/bad-lit-suffixes.rs:39:15 - | -LL | #[link(name = "string"suffix)] - | ^^^^^^^^^^^^^^ invalid suffix `suffix` - -error: invalid suffix `suffix` for number literal - --> $DIR/bad-lit-suffixes.rs:43:41 - | -LL | #[rustc_layout_scalar_valid_range_start(0suffix)] - | ^^^^^^^ invalid suffix `suffix` - | - = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) - warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/bad-lit-suffixes.rs:3:1 | @@ -150,6 +124,18 @@ LL | 1.0e10suffix; | = help: valid suffixes are `f32` and `f64` +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:30:17 + | +LL | #[rustc_dummy = "string"suffix] + | ^^^^^^^^^^^^^^ invalid suffix `suffix` + +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:34:14 + | +LL | #[must_use = "string"suffix] + | ^^^^^^^^^^^^^^ invalid suffix `suffix` + error[E0539]: malformed `must_use` attribute input --> $DIR/bad-lit-suffixes.rs:34:1 | @@ -167,6 +153,20 @@ LL - #[must_use = "string"suffix] LL + #[must_use] | +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:39:15 + | +LL | #[link(name = "string"suffix)] + | ^^^^^^^^^^^^^^ invalid suffix `suffix` + +error: invalid suffix `suffix` for number literal + --> $DIR/bad-lit-suffixes.rs:43:41 + | +LL | #[rustc_layout_scalar_valid_range_start(0suffix)] + | ^^^^^^^ invalid suffix `suffix` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + error[E0805]: malformed `rustc_layout_scalar_valid_range_start` attribute input --> $DIR/bad-lit-suffixes.rs:43:1 | diff --git a/tests/ui/proc-macro/attribute.stderr b/tests/ui/proc-macro/attribute.stderr index 3269aaf7f917e..e6d8c4b932810 100644 --- a/tests/ui/proc-macro/attribute.stderr +++ b/tests/ui/proc-macro/attribute.stderr @@ -1,15 +1,3 @@ -error: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:9:1 - | -LL | #[proc_macro_derive] - | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` - -error: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:12:1 - | -LL | #[proc_macro_derive = ""] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` - error: attribute must have either one or two arguments --> $DIR/attribute.rs:15:1 | @@ -100,5 +88,17 @@ error: `self` cannot be a name of derive helper attribute LL | #[proc_macro_derive(d17, attributes(self))] | ^^^^ +error: malformed `proc_macro_derive` attribute input + --> $DIR/attribute.rs:9:1 + | +LL | #[proc_macro_derive] + | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + +error: malformed `proc_macro_derive` attribute input + --> $DIR/attribute.rs:12:1 + | +LL | #[proc_macro_derive = ""] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + error: aborting due to 17 previous errors diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr index 8ead943ffe3a1..f656aeaa16c7f 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr +++ b/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr @@ -1,26 +1,38 @@ -error: malformed `unstable` attribute input +error[E0539]: malformed `unstable` attribute input --> $DIR/stability-attribute-sanity-4.rs:8:5 | LL | #[unstable] - | ^^^^^^^^^^^ help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]` + | ^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]` -error: malformed `unstable` attribute input +error[E0539]: malformed `unstable` attribute input --> $DIR/stability-attribute-sanity-4.rs:11:5 | LL | #[unstable = "b"] - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]` + | ^^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]` -error: malformed `stable` attribute input +error[E0539]: malformed `stable` attribute input --> $DIR/stability-attribute-sanity-4.rs:14:5 | LL | #[stable] - | ^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]` + | ^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[stable(feature = "name", since = "version")]` -error: malformed `stable` attribute input +error[E0539]: malformed `stable` attribute input --> $DIR/stability-attribute-sanity-4.rs:17:5 | LL | #[stable = "a"] - | ^^^^^^^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]` + | ^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[stable(feature = "name", since = "version")]` error[E0542]: missing 'since' --> $DIR/stability-attribute-sanity-4.rs:21:5 @@ -42,5 +54,5 @@ LL | #[deprecated = "a"] error: aborting due to 7 previous errors -Some errors have detailed explanations: E0542, E0543. -For more information about an error, try `rustc --explain E0542`. +Some errors have detailed explanations: E0539, E0542, E0543. +For more information about an error, try `rustc --explain E0539`.