diff --git a/Cargo.lock b/Cargo.lock index 8d68be636fa92..ae97971a16070 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4013,7 +4013,6 @@ name = "rustc_expand" version = "0.0.0" dependencies = [ "rustc_ast", - "rustc_ast_passes", "rustc_ast_pretty", "rustc_attr_ir", "rustc_attr_parsing", diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1265bae778601..def0934214ef2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,7 +45,7 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, *}; -use rustc_attr_parsing::{AttributeParser, OmitDoc, Recovery, ShouldEmit}; +use rustc_attr_parsing::{AttributeParser, Recovery, ShouldEmit}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hash::{StableHash, StableHasher}; @@ -1231,7 +1231,6 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs, target_span, target, - OmitDoc::Lower, |s| l.lower(s), |lint_id, span, kind| { self.delayed_lints.push(DelayedLint { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 01d81bab55075..6ed7d6757b8b1 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -46,10 +46,6 @@ macro_rules! gate_multi { }}; } -pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) { - PostExpansionVisitor { sess, features }.visit_attribute(attr) -} - struct PostExpansionVisitor<'a> { sess: &'a Session, @@ -152,33 +148,9 @@ impl<'a> PostExpansionVisitor<'a> { } impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { - fn visit_attribute(&mut self, attr: &ast::Attribute) { - // Check unstable flavors of the `#[doc]` attribute. - if attr.has_name(sym::doc) { - for meta_item_inner in attr.meta_item_list().unwrap_or_default() { - macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) => { - $($(if meta_item_inner.has_name(sym::$name) { - let msg = concat!("`#[doc(", stringify!($name), ")]` is ", $s); - gate!(self, $feature, attr.span, msg); - })*)* - }} - - gate_doc!( - "experimental" { - cfg => doc_cfg - auto_cfg => doc_cfg - masked => doc_masked - notable_trait => doc_notable_trait - } - "meant for internal use only" { - attribute => rustdoc_internals - keyword => rustdoc_internals - fake_variadic => rustdoc_internals - search_unbox => rustdoc_internals - } - ); - } - } + fn visit_attribute(&mut self, attr: &'a ast::Attribute) { + // Checked in attribute parsers, do NOT add checks here + visit::walk_attribute(self, attr) } fn visit_item(&mut self, i: &'a ast::Item) { diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 7b0df693debf5..e315d6abea395 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -5,10 +5,9 @@ use rustc_attr_ir::{ DocInline, HideOrShow, }; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry}; -use rustc_errors::{Applicability, msg}; +use rustc_errors::Applicability; use rustc_feature::AttributeStability; use rustc_lint_defs::builtin::{INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES}; -use rustc_session::diagnostics::feature_err; use rustc_span::{Span, Symbol, edition, sym}; use super::prelude::{ALL_TARGETS, AllowedTargets}; @@ -526,19 +525,15 @@ impl DocParser { } macro_rules! no_args_and_crate_level { ($ident: ident) => {{ - no_args_and_crate_level!($ident, |span| {}); - }}; - ($ident: ident, |$span:ident| $extra_validation:block) => {{ if let Err(span) = args.as_no_args() { expected_no_args(cx, span); return; } - let $span = path.span(); - if !check_attr_crate_level(cx, $span) { + let span = path.span(); + if !check_attr_crate_level(cx, span) { return; } - $extra_validation - self.attribute.$ident = Some($span); + self.attribute.$ident = Some(span); }}; } macro_rules! string_arg_and_crate_level { @@ -569,6 +564,12 @@ impl DocParser { self.attribute.$ident = Some((s, path.span())); }}; } + macro_rules! gated { + ($feature:ident $(,$notes:expr)*) => { + let stability = $crate::unstable!($feature $(, $notes)*); + cx.shared.cx.check_attribute_stability(&cx.attr_path, path.span(), stability); + }; + } match path.word_sym() { Some(sym::alias) => self.parse_alias(cx, path, args), @@ -583,37 +584,60 @@ impl DocParser { } Some(sym::inline) => self.parse_inline(cx, path, args, DocInline::Inline), Some(sym::no_inline) => self.parse_inline(cx, path, args, DocInline::NoInline), - Some(sym::masked) => no_args!(masked), - Some(sym::cfg) => self.parse_cfg(cx, args), - Some(sym::notable_trait) => no_args!(notable_trait), - Some(sym::keyword) => parse_keyword_and_attribute( - cx, - path, - args, - &mut self.attribute.keyword, - sym::keyword, - ), - Some(sym::attribute) => parse_keyword_and_attribute( - cx, - path, - args, - &mut self.attribute.attribute, - sym::attribute, - ), - Some(sym::fake_variadic) => no_args_and_not_crate_level!(fake_variadic), - Some(sym::search_unbox) => no_args_and_not_crate_level!(search_unbox), - Some(sym::rust_logo) => no_args_and_crate_level!(rust_logo, |span| { - if !cx.features().rustdoc_internals() { - feature_err( - cx.sess(), - sym::rustdoc_internals, - span, - msg!("the `#[doc(rust_logo)]` attribute is used for Rust branding"), - ) - .emit(); + Some(sym::masked) => { + gated!(doc_masked); + no_args!(masked) + } + Some(sym::cfg) => { + gated!(doc_cfg); + self.parse_cfg(cx, args) + } + Some(sym::notable_trait) => { + gated!(doc_notable_trait); + no_args!(notable_trait) + } + Some(sym::keyword) => { + gated!(rustdoc_internals); + parse_keyword_and_attribute( + cx, + path, + args, + &mut self.attribute.keyword, + sym::keyword, + ) + } + Some(sym::attribute) => { + gated!(rustdoc_internals); + parse_keyword_and_attribute( + cx, + path, + args, + &mut self.attribute.attribute, + sym::attribute, + ) + } + Some(sym::fake_variadic) => { + gated!(rustdoc_internals); + no_args_and_not_crate_level!(fake_variadic) + } + Some(sym::search_unbox) => { + gated!(rustdoc_internals); + no_args_and_not_crate_level!(search_unbox) + } + Some(sym::rust_logo) => { + // FIXME: Only feature gated at the crate level (!!) + if cx.target == Target::Crate { + gated!( + rustdoc_internals, + "the `#[doc(rust_logo)]` attribute is used for Rust branding" + ); } - }), - Some(sym::auto_cfg) => self.parse_auto_cfg(cx, path, args), + no_args_and_crate_level!(rust_logo) + } + Some(sym::auto_cfg) => { + gated!(doc_cfg); + self.parse_auto_cfg(cx, path, args) + } Some(sym::test) => { let Some(list) = args.as_list() else { cx.emit_lint( diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5783f17028029..7e7fa6ce77a93 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -866,12 +866,6 @@ impl<'p, 'sess: 'p> DerefMut for SharedContext<'p, 'sess> { } } -#[derive(PartialEq, Clone, Copy, Debug)] -pub enum OmitDoc { - Lower, - Skip, -} - #[derive(Copy, Clone, Debug)] pub enum ShouldEmit { /// The operations will emit errors, and lints, and errors are fatal. diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 602fa6f707055..0686613acb250 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -23,7 +23,7 @@ use crate::context::{ use crate::diagnostics::ParsedDescription; use crate::parser::{AllowExprMetavar, ArgParser, PathParser, RefPathParser}; use crate::synthetic::SyntheticAttrState; -use crate::{AttributeTemplate, OmitDoc, ShouldEmit}; +use crate::{AttributeTemplate, ShouldEmit}; pub struct EmitAttribute( pub Box< @@ -161,7 +161,6 @@ impl<'sess> AttributeParser<'sess> { attrs, target_span, target, - OmitDoc::Skip, std::convert::identity, |lint_id, span, kind| { sess.psess.dyn_buffer_lint_sess(lint_id.lint, span, target_node_id, kind.0) @@ -310,14 +309,12 @@ impl<'sess> AttributeParser<'sess> { /// Parse a list of attributes. /// - /// `target_span` is the span of the thing this list of attributes is applied to, - /// and when `omit_doc` is set, doc attributes are filtered out. + /// `target_span` is the span of the thing this list of attributes is applied to. pub fn parse_attribute_list( &mut self, attrs: &[ast::Attribute], target_span: Span, target: Target, - omit_doc: OmitDoc, lower_span: impl Copy + Fn(Span) -> Span, mut emit_lint: impl FnMut(LintId, MultiSpan, EmitAttribute), ) -> Vec { @@ -335,23 +332,26 @@ impl<'sess> AttributeParser<'sess> { } } - // Sometimes, for example for `#![doc = include_str!("readme.md")]`, - // doc still contains a non-literal. You might say, when we're lowering attributes - // that's expanded right? But no, sometimes, when parsing attributes on macros, - // we already use the lowering logic and these are still there. So, when `omit_doc` - // is set we *also* want to ignore these. - let is_doc_attribute = attr.has_name(sym::doc); - if omit_doc == OmitDoc::Skip && is_doc_attribute { + fn is_doc_non_lit_expr(attr: &ast::Attribute) -> bool { + if !attr.has_name(sym::doc) { + return false; + } + let ast::AttrKind::Normal(n) = &attr.kind else { return false }; + let ast::AttrArgs::Eq { expr, .. } = &n.item.args else { return false }; + if matches!(expr.kind, ast::ExprKind::Lit(_)) { + return false; + }; + true + } + + // FIXME accidentally allowed on Stable Rust + if target == Target::MacroCall && is_doc_non_lit_expr(attr) { continue; } let attr_span = lower_span(attr.span); match &attr.kind { ast::AttrKind::DocComment(comment_kind, symbol) => { - if omit_doc == OmitDoc::Skip { - continue; - } - attributes.push(Attribute::Parsed(AttributeKind::DocComment { style: attr.style, kind: DocFragmentKind::Sugared(*comment_kind), @@ -407,7 +407,7 @@ impl<'sess> AttributeParser<'sess> { // bla // blob // a - if is_doc_attribute + if attr.has_name(sym::doc) && let ArgParser::NameValue(nv) = &args // If not a string key/value, it should emit an error, but to make // things simpler, it's handled in `DocParser` because it's simpler to diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 4b386f06a005c..3360791cdbc5f 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -116,7 +116,7 @@ pub use attributes::cfg::{ }; pub use attributes::cfg_select::*; pub use attributes::util::{is_builtin_attr, parse_version}; -pub use context::{OmitDoc, ShouldEmit}; +pub use context::ShouldEmit; pub use diagnostics::ParsedDescription; pub use interface::{AttributeParser, EmitAttribute}; pub use rustc_parse::parser::Recovery; diff --git a/compiler/rustc_attr_parsing/src/stability.rs b/compiler/rustc_attr_parsing/src/stability.rs index b0ab2649c4078..9ae8287812542 100644 --- a/compiler/rustc_attr_parsing/src/stability.rs +++ b/compiler/rustc_attr_parsing/src/stability.rs @@ -53,10 +53,24 @@ impl<'sess> AttributeParser<'sess> { sym::prelude_import => ("the `prelude_import` attribute is for use by rustc only".to_string(), &[]), sym::profiler_runtime => ("the `profiler_runtime` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable".to_string(), &[]), sym::thread_local => ("the `thread_local` attribute is an experimental feature, and does not currently handle destructors".to_string(), &[]), + sym::rustdoc_internals => ("this subset of the `doc` attribute is meant for internal use only".to_string(), &[]), + sym::doc_notable_trait => ("the `doc(notable_trait)` attribute is experimental".to_string(), &[]), + sym::doc_cfg => ("the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental".to_string(), &[]), + sym::doc_masked => ("the `doc(masked)` attribute is experimental".to_string(), &[]), _ => (format!("the `{attr_path}` attribute is an experimental feature"), &[]), }; - let mut diag = feature_err(self.sess, gate_name, attr_path.span, explain); + // For unstable subsets of an attribute, point at that + let err_span = if matches!( + gate_name, + sym::rustdoc_internals | sym::doc_notable_trait | sym::doc_cfg | sym::doc_masked + ) { + attr_span + } else { + attr_path.span + }; + + let mut diag = feature_err(self.sess, gate_name, err_span, explain); // Remove the suggestion for `#![feature(staged_api)]` as these attributes are currently // not usable outside std. If we do ever expose `#[stable]` etc under a different feature diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 80353e4c8dba4..0f216aa9f68df 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -10,7 +10,6 @@ doctest = false [dependencies] # tidy-alphabetical-start rustc_ast = { path = "../rustc_ast" } -rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 3a51b758a427b..d6605c070e76c 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -2212,15 +2212,13 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { attr } - // Detect use of feature-gated or invalid attributes on macro invocations + // Run attributes through the attribute parser // since they will not be detected after macro expansion. fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) { use SyntheticAttr::*; - let features = self.cx.ecfg.features; let mut attrs = attrs.iter().peekable(); let mut span: Option = None; while let Some(attr) = attrs.next() { - rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); validate_attr::check_attr(&self.cx.sess.psess, attr); AttributeParser::parse_limited_all( self.cx.sess, diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index a04f2b5421e37..58a9f4ffef16d 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -3,7 +3,7 @@ use std::mem; use rustc_ast::visit::FnKind; use rustc_ast::*; use rustc_attr_parsing as attr; -use rustc_attr_parsing::{AttributeParser, OmitDoc, ShouldEmit}; +use rustc_attr_parsing::{AttributeParser, ShouldEmit}; use rustc_expand::expand::AstFragment; use rustc_hir as hir; use rustc_hir::Target; @@ -187,7 +187,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { &i.attrs, i.span, Target::MacroDef, - OmitDoc::Skip, std::convert::identity, |_lint_id, _span, _kind| { // FIXME(jdonszelmann): emit lints here properly diff --git a/tests/rustdoc-ui/feature-gate-doc_cfg.stderr b/tests/rustdoc-ui/feature-gate-doc_cfg.stderr index 68a86c1abb777..db2f3b5737549 100644 --- a/tests/rustdoc-ui/feature-gate-doc_cfg.stderr +++ b/tests/rustdoc-ui/feature-gate-doc_cfg.stderr @@ -1,58 +1,58 @@ -error[E0658]: `#[doc(auto_cfg)]` is experimental - --> $DIR/feature-gate-doc_cfg.rs:1:1 +error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental + --> $DIR/feature-gate-doc_cfg.rs:1:8 | LL | #![doc(auto_cfg)] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` 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[E0658]: `#[doc(auto_cfg)]` is experimental - --> $DIR/feature-gate-doc_cfg.rs:2:1 +error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental + --> $DIR/feature-gate-doc_cfg.rs:2:8 | LL | #![doc(auto_cfg(false))] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` 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[E0658]: `#[doc(auto_cfg)]` is experimental - --> $DIR/feature-gate-doc_cfg.rs:3:1 +error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental + --> $DIR/feature-gate-doc_cfg.rs:3:8 | LL | #![doc(auto_cfg(true))] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` 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[E0658]: `#[doc(auto_cfg)]` is experimental - --> $DIR/feature-gate-doc_cfg.rs:4:1 +error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental + --> $DIR/feature-gate-doc_cfg.rs:4:8 | LL | #![doc(auto_cfg(hide(feature = "solecism")))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` 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[E0658]: `#[doc(auto_cfg)]` is experimental - --> $DIR/feature-gate-doc_cfg.rs:5:1 +error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental + --> $DIR/feature-gate-doc_cfg.rs:5:8 | LL | #![doc(auto_cfg(show(feature = "bla")))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` 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[E0658]: `#[doc(cfg)]` is experimental - --> $DIR/feature-gate-doc_cfg.rs:6:1 +error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental + --> $DIR/feature-gate-doc_cfg.rs:6:8 | LL | #![doc(cfg(feature = "solecism"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ | = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` to the crate attributes to enable diff --git a/tests/ui/attributes/attr-on-mac-call.rs b/tests/ui/attributes/attr-on-mac-call.rs index 7b30ec810ff81..618e583d0af5e 100644 --- a/tests/ui/attributes/attr-on-mac-call.rs +++ b/tests/ui/attributes/attr-on-mac-call.rs @@ -110,4 +110,15 @@ fn main() { #[register_tool(xyz)] //~^ ERROR crate-level attribute should be an inner attribute unreachable!(); + #[deprecated = concat!("woah", "dude")] + //~^ ERROR attribute value must be a literal + #[doc = concat!("woah", "dude")] + unreachable!(); + #[doc = { + let a = 1; + let b = 1; + let sum = a + b; + assert_eq!(sum, 2); + }] + unreachable!(); } diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr index 3454998af2922..aa158bee22768 100644 --- a/tests/ui/attributes/attr-on-mac-call.stderr +++ b/tests/ui/attributes/attr-on-mac-call.stderr @@ -38,6 +38,12 @@ note: this attribute does not have an `!`, which means it is applied to this mac LL | unreachable!(); | ^^^^^^^^^^^^^^ +error: attribute value must be a literal + --> $DIR/attr-on-mac-call.rs:113:20 + | +LL | #[deprecated = concat!("woah", "dude")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + warning: the `export_name` attribute cannot be used on macro calls --> $DIR/attr-on-mac-call.rs:8:7 | @@ -341,6 +347,6 @@ LL | #[repr(Rust)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: placing this attribute on a macro invocation does nothing even if the macro expands to what would be a valid target for the attribute -error: aborting due to 4 previous errors; 30 warnings emitted +error: aborting due to 5 previous errors; 30 warnings emitted For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/doc-rust-logo.rs b/tests/ui/feature-gates/doc-rust-logo.rs index e6a58512944bb..08857cc778f5b 100644 --- a/tests/ui/feature-gates/doc-rust-logo.rs +++ b/tests/ui/feature-gates/doc-rust-logo.rs @@ -1,5 +1,7 @@ #![doc(rust_logo)] -//~^ ERROR the `#[doc(rust_logo)]` attribute is used for Rust branding +//~^ ERROR this subset of the `doc` attribute is meant for internal use only //! This is not an official rust crate +#[doc(rust_logo)] +//~^ WARN this attribute can only be applied at the crate level fn main() {} diff --git a/tests/ui/feature-gates/doc-rust-logo.stderr b/tests/ui/feature-gates/doc-rust-logo.stderr index 5c64652667ed8..f31837be284d1 100644 --- a/tests/ui/feature-gates/doc-rust-logo.stderr +++ b/tests/ui/feature-gates/doc-rust-logo.stderr @@ -1,4 +1,4 @@ -error[E0658]: the `#[doc(rust_logo)]` attribute is used for Rust branding +error[E0658]: this subset of the `doc` attribute is meant for internal use only --> $DIR/doc-rust-logo.rs:1:8 | LL | #![doc(rust_logo)] @@ -7,7 +7,17 @@ LL | #![doc(rust_logo)] = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `#[doc(rust_logo)]` attribute is used for Rust branding -error: aborting due to 1 previous error +warning: this attribute can only be applied at the crate level + --> $DIR/doc-rust-logo.rs:5:7 + | +LL | #[doc(rust_logo)] + | ^^^^^^^^^ + | + = note: read for more information + = note: `#[warn(invalid_doc_attributes)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-doc_cfg.stderr b/tests/ui/feature-gates/feature-gate-doc_cfg.stderr index 5315aaeeb3edb..cb2898960472a 100644 --- a/tests/ui/feature-gates/feature-gate-doc_cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-doc_cfg.stderr @@ -1,8 +1,8 @@ -error[E0658]: `#[doc(cfg)]` is experimental - --> $DIR/feature-gate-doc_cfg.rs:1:1 +error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental + --> $DIR/feature-gate-doc_cfg.rs:1:7 | LL | #[doc(cfg(unix))] - | ^^^^^^^^^^^^^^^^^ + | ^^^ | = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-doc_masked.rs b/tests/ui/feature-gates/feature-gate-doc_masked.rs index bde3af6b594c2..a2776cb696c49 100644 --- a/tests/ui/feature-gates/feature-gate-doc_masked.rs +++ b/tests/ui/feature-gates/feature-gate-doc_masked.rs @@ -1,4 +1,8 @@ -#[doc(masked)] //~ ERROR: `#[doc(masked)]` is experimental +#[doc(masked)] //~ ERROR the `doc(masked)` attribute is experimental extern crate std as realstd; -fn main() {} +fn main() { + #[doc(masked)] + //~^ ERROR the `doc(masked)` attribute is experimental [E0658] + println!(); +} diff --git a/tests/ui/feature-gates/feature-gate-doc_masked.stderr b/tests/ui/feature-gates/feature-gate-doc_masked.stderr index 10607a19757cb..8f1b03e50325c 100644 --- a/tests/ui/feature-gates/feature-gate-doc_masked.stderr +++ b/tests/ui/feature-gates/feature-gate-doc_masked.stderr @@ -1,13 +1,23 @@ -error[E0658]: `#[doc(masked)]` is experimental - --> $DIR/feature-gate-doc_masked.rs:1:1 +error[E0658]: the `doc(masked)` attribute is experimental + --> $DIR/feature-gate-doc_masked.rs:5:11 + | +LL | #[doc(masked)] + | ^^^^^^ + | + = note: see issue #44027 for more information + = help: add `#![feature(doc_masked)]` 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[E0658]: the `doc(masked)` attribute is experimental + --> $DIR/feature-gate-doc_masked.rs:1:7 | LL | #[doc(masked)] - | ^^^^^^^^^^^^^^ + | ^^^^^^ | = note: see issue #44027 for more information = help: add `#![feature(doc_masked)]` 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: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-doc_notable_trait.rs b/tests/ui/feature-gates/feature-gate-doc_notable_trait.rs index 7f3392eadadb3..1bc1028b9e0ef 100644 --- a/tests/ui/feature-gates/feature-gate-doc_notable_trait.rs +++ b/tests/ui/feature-gates/feature-gate-doc_notable_trait.rs @@ -1,4 +1,8 @@ -#[doc(notable_trait)] //~ ERROR: `#[doc(notable_trait)]` is experimental +#[doc(notable_trait)] //~ ERROR the `doc(notable_trait)` attribute is experimental trait SomeTrait {} -fn main() {} +fn main() { + #[doc(notable_trait)] + //~^ ERROR the `doc(notable_trait)` attribute is experimental [E0658] + println!(); +} diff --git a/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr b/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr index 1b40b9ac18a8f..632c91b929185 100644 --- a/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr +++ b/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr @@ -1,13 +1,23 @@ -error[E0658]: `#[doc(notable_trait)]` is experimental - --> $DIR/feature-gate-doc_notable_trait.rs:1:1 +error[E0658]: the `doc(notable_trait)` attribute is experimental + --> $DIR/feature-gate-doc_notable_trait.rs:5:11 + | +LL | #[doc(notable_trait)] + | ^^^^^^^^^^^^^ + | + = note: see issue #45040 for more information + = help: add `#![feature(doc_notable_trait)]` 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[E0658]: the `doc(notable_trait)` attribute is experimental + --> $DIR/feature-gate-doc_notable_trait.rs:1:7 | LL | #[doc(notable_trait)] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = note: see issue #45040 for more information = help: add `#![feature(doc_notable_trait)]` 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: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs index 7aa6dcbd5daac..e39221a204ca8 100644 --- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs @@ -1,17 +1,29 @@ -#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword)]` is meant for internal use only +#[doc(keyword = "match")] //~ ERROR: this subset of the `doc` attribute is meant for internal use only /// wonderful const _: () = (); -#[doc(attribute = "repr")] //~ ERROR: `#[doc(attribute)]` is meant for internal use only +#[doc(attribute = "repr")] //~ ERROR this subset of the `doc` attribute is meant for internal use only /// wonderful const _: () = (); trait Mine {} -#[doc(fake_variadic)] //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only +#[doc(fake_variadic)] //~ ERROR this subset of the `doc` attribute is meant for internal use only impl Mine for (T,) {} -#[doc(search_unbox)] //~ ERROR: `#[doc(search_unbox)]` is meant for internal use only +#[doc(search_unbox)] //~ ERROR this subset of the `doc` attribute is meant for internal use only struct Wrap (T); -fn main() {} +fn main() { + #[doc(search_unbox)] + //~^ ERROR this subset of the `doc` attribute is meant for internal use only [E0658] + println!(); + + #[doc(fake_variadic)] + //~^ ERROR this subset of the `doc` attribute is meant for internal use only [E0658] + println!(); + + #[doc(attribute = "repr")] + //~^ ERROR this subset of the `doc` attribute is meant for internal use only [E0658] + println!(); +} diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr index 5a6d4d3b45e0f..ab542eb85bacf 100644 --- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -1,43 +1,73 @@ -error[E0658]: `#[doc(keyword)]` is meant for internal use only - --> $DIR/feature-gate-rustdoc_internals.rs:1:1 +error[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:18:11 + | +LL | #[doc(search_unbox)] + | ^^^^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` 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[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:22:11 + | +LL | #[doc(fake_variadic)] + | ^^^^^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` 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[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:26:11 + | +LL | #[doc(attribute = "repr")] + | ^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` 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[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:1:7 | LL | #[doc(keyword = "match")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ | = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` 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[E0658]: `#[doc(attribute)]` is meant for internal use only - --> $DIR/feature-gate-rustdoc_internals.rs:5:1 +error[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:5:7 | LL | #[doc(attribute = "repr")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` 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[E0658]: `#[doc(fake_variadic)]` is meant for internal use only - --> $DIR/feature-gate-rustdoc_internals.rs:11:1 +error[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:11:7 | LL | #[doc(fake_variadic)] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` 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[E0658]: `#[doc(search_unbox)]` is meant for internal use only - --> $DIR/feature-gate-rustdoc_internals.rs:14:1 +error[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:14:7 | LL | #[doc(search_unbox)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` 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: aborting due to 4 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/unused/unused-doc-comments-for-macros.rs b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs index 0a95b79988894..62c4fe82348cc 100644 --- a/tests/ui/lint/unused/unused-doc-comments-for-macros.rs +++ b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs @@ -16,11 +16,12 @@ fn main() { foo!(); // Even invalid doc attributes should emit the warning. - #[doc = { //~ ERROR: unused doc comment + #[doc = { let a = 1; let b = 1; let sum = a + b; assert_eq!(sum, 2); }] + //~^^^^^^ ERROR: unused doc comment foo!(); }