diff --git a/compiler/rustc_attr_parsing/src/attributes/do_not_recommend.rs b/compiler/rustc_attr_parsing/src/attributes/do_not_recommend.rs new file mode 100644 index 0000000000000..4a89cf6515ce0 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/do_not_recommend.rs @@ -0,0 +1,31 @@ +use rustc_feature::{AttributeTemplate, template}; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::lints::AttributeLintKind; +use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; +use crate::target_checking::{ALL_TARGETS, AllowedTargets}; + +pub(crate) struct DoNotRecommendParser; +impl SingleAttributeParser for DoNotRecommendParser { + const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Checked in check_attr. + const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let attr_span = cx.attr_span; + if !matches!(args, ArgParser::NoArgs) { + cx.emit_lint( + MALFORMED_DIAGNOSTIC_ATTRIBUTES, + AttributeLintKind::DoNotRecommendDoesNotExpectArgs, + attr_span, + ); + } + Some(AttributeKind::DoNotRecommend { attr_span }) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index e02d71a261581..3da27f077a613 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -39,6 +39,7 @@ pub(crate) mod confusables; pub(crate) mod crate_level; pub(crate) mod debugger; pub(crate) mod deprecation; +pub(crate) mod do_not_recommend; pub(crate) mod doc; pub(crate) mod dummy; pub(crate) mod inline; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 6b1b1d484283f..a207af57ccca0 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -34,6 +34,7 @@ use crate::attributes::crate_level::{ }; use crate::attributes::debugger::DebuggerViualizerParser; use crate::attributes::deprecation::DeprecationParser; +use crate::attributes::do_not_recommend::DoNotRecommendParser; use crate::attributes::doc::DocParser; use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; @@ -197,6 +198,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 68265649d1823..63c82ccbc7df5 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -113,8 +113,12 @@ impl ArgParser { Some(match value { AttrArgs::Empty => Self::NoArgs, AttrArgs::Delimited(args) => { - // The arguments of rustc_dummy are not validated if the arguments are delimited - if parts == &[sym::rustc_dummy] { + // The arguments of rustc_dummy and diagnostic::do_not_recommend are not validated + // if the arguments are delimited. + // See https://doc.rust-lang.org/reference/attributes/diagnostics.html#r-attributes.diagnostic.namespace.unknown-invalid-syntax + if parts == &[sym::rustc_dummy] + || parts == &[sym::diagnostic, sym::do_not_recommend] + { return Some(ArgParser::List(MetaItemListParser { sub_parsers: ThinVec::new(), span: args.dspan.entire(), diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 8d18d335b355b..16bee3d532972 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -731,6 +731,9 @@ pub enum AttributeKind { /// Represents `#[rustc_do_not_implement_via_object]`. DoNotImplementViaObject(Span), + /// Represents `#[diagnostic::do_not_recommend]`. + DoNotRecommend { attr_span: Span }, + /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html). /// Represents all other uses of the [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html) /// attribute. diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 33655f4f00635..7cdcdc3a5e948 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -44,6 +44,7 @@ impl AttributeKind { DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, DoNotImplementViaObject(..) => No, + DoNotRecommend { .. } => Yes, Doc(_) => Yes, DocComment { .. } => Yes, Dummy => No, diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 9b0b1abc91df6..f5b882494863a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -480,6 +480,9 @@ lint_improper_ctypes_unsafe_binder = unsafe binders are incompatible with foreig lint_improper_gpu_kernel_arg = passing type `{$ty}` to a function with "gpu-kernel" ABI may have unexpected behavior .help = use primitive types and raw pointers to get reliable behavior +lint_incorrect_do_not_recommend_args = + `#[diagnostic::do_not_recommend]` does not expect any arguments + lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a pointer without provenance .note = this is dangerous because dereferencing the resulting pointer is undefined behavior .note_exposed_provenance = exposed provenance semantics can be used to create a pointer based on some previously exposed provenance diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 5745f0d4eddec..037a31c162d2b 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -419,5 +419,9 @@ pub fn decorate_attribute_lint( &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.decorate_lint(diag), &AttributeLintKind::AttrCrateLevelOnly => lints::AttrCrateLevelOnly.decorate_lint(diag), + + &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => { + lints::DoNotRecommendDoesNotExpectArgs.decorate_lint(diag) + } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 33e9375ec71bd..c85e4ffe91fcf 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3317,3 +3317,7 @@ pub(crate) struct DocTestLiteral; #[diag(lint_attr_crate_level)] #[note] pub(crate) struct AttrCrateLevelOnly; + +#[derive(LintDiagnostic)] +#[diag(lint_incorrect_do_not_recommend_args)] +pub(crate) struct DoNotRecommendDoesNotExpectArgs; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c8713b23633f7..4d0c44f167602 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -821,6 +821,7 @@ pub enum AttributeLintKind { }, DocTestLiteral, AttrCrateLevelOnly, + DoNotRecommendDoesNotExpectArgs, } pub type RegisteredTools = FxIndexSet; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a3eec72214c06..e9fa3f14358e8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3540,7 +3540,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]` pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { - self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some() + find_attr!(self.get_all_attrs(def_id), AttributeKind::DoNotRecommend { .. }) } pub fn is_trivial_const

(self, def_id: P) -> bool diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e2a94b607de10..8eee114ead02e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -51,7 +51,7 @@ use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; pub use rustc_session::lint::RegisteredTools; use rustc_span::hygiene::MacroKind; -use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol}; pub use rustc_type_ir::data_structures::{DelayedMap, DelayedSet}; pub use rustc_type_ir::fast_reject::DeepRejectCtxt; #[allow( @@ -1819,37 +1819,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// Get an attribute from the diagnostic attribute namespace - /// - /// This function requests an attribute with the following structure: - /// - /// `#[diagnostic::$attr]` - /// - /// This function performs feature checking, so if an attribute is returned - /// it can be used by the consumer - pub fn get_diagnostic_attr( - self, - did: impl Into, - attr: Symbol, - ) -> Option<&'tcx hir::Attribute> { - let did: DefId = did.into(); - if did.as_local().is_some() { - // it's a crate local item, we need to check feature flags - if rustc_feature::is_stable_diagnostic_attribute(attr, self.features()) { - self.get_attrs_by_path(did, &[sym::diagnostic, sym::do_not_recommend]).next() - } else { - None - } - } else { - // we filter out unstable diagnostic attributes before - // encoding attributes - debug_assert!(rustc_feature::encode_cross_crate(attr)); - self.attrs_for_def(did) - .iter() - .find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr)) - } - } - pub fn get_attrs_by_path( self, did: DefId, diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 11e4b8b20222d..51c439b4243c1 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -246,9 +246,6 @@ passes_implied_feature_not_exist = passes_incorrect_crate_type = lang items are not allowed in stable dylibs -passes_incorrect_do_not_recommend_args = - `#[diagnostic::do_not_recommend]` does not expect any arguments - passes_incorrect_do_not_recommend_location = `#[diagnostic::do_not_recommend]` can only be placed on trait implementations diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8f80822a81ab1..3402b9744b3c2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -43,8 +43,8 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; use rustc_session::lint; use rustc_session::lint::builtin::{ - CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES, - MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, + CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, + UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; use rustc_span::edition::Edition; @@ -223,6 +223,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::RustcMustImplementOneOf { attr_span, fn_names }) => { self.check_rustc_must_implement_one_of(*attr_span, fn_names, hir_id,target) }, + Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)}, Attribute::Parsed( AttributeKind::EiiDeclaration { .. } | AttributeKind::EiiForeignItem @@ -313,9 +314,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { - [sym::diagnostic, sym::do_not_recommend, ..] => { - self.check_do_not_recommend(attr.span(), hir_id, target, attr, item) - } [sym::diagnostic, sym::on_unimplemented, ..] => { self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target) } @@ -568,14 +566,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl and that it has no - /// arguments. + /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl fn check_do_not_recommend( &self, attr_span: Span, hir_id: HirId, target: Target, - attr: &Attribute, item: Option>, ) { if !matches!(target, Target::Impl { .. }) @@ -592,14 +588,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { errors::IncorrectDoNotRecommendLocation, ); } - if !attr.is_word() { - self.tcx.emit_node_span_lint( - MALFORMED_DIAGNOSTIC_ATTRIBUTES, - hir_id, - attr_span, - errors::DoNotRecommendDoesNotExpectArgs, - ); - } } /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1f3f0d7f8884f..bf9b615546d89 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -20,10 +20,6 @@ use crate::lang_items::Duplicate; #[diag(passes_incorrect_do_not_recommend_location)] pub(crate) struct IncorrectDoNotRecommendLocation; -#[derive(LintDiagnostic)] -#[diag(passes_incorrect_do_not_recommend_args)] -pub(crate) struct DoNotRecommendDoesNotExpectArgs; - #[derive(Diagnostic)] #[diag(passes_autodiff_attr)] pub(crate) struct AutoDiffAttr { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index eef8b870a5b85..77834320dbc6b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -434,7 +434,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } = candidate.kind() && tcx.do_not_recommend_impl(impl_def_id) { - trace!("#[do_not_recommend] -> exit"); + trace!("#[diagnostic::do_not_recommend] -> exit"); return ControlFlow::Break(self.obligation.clone()); } diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index fc644668735ed..04f51f54b2cd0 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -729,14 +729,6 @@ help: use `#[rustc_align(...)]` instead LL | #[repr] | ^^^^^^^ -warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:155:1 - | -LL | #[diagnostic::do_not_recommend()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default - warning: missing options for `on_unimplemented` attribute --> $DIR/malformed-attrs.rs:144:1 | @@ -744,6 +736,7 @@ LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: at least one of the `message`, `note` and `label` options are expected + = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: malformed `on_unimplemented` attribute --> $DIR/malformed-attrs.rs:146:1 @@ -823,6 +816,12 @@ LL | #[no_implicit_prelude = 23] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[no_implicit_prelude]` can be applied to crates and modules +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/malformed-attrs.rs:155:1 + | +LL | #[diagnostic::do_not_recommend()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + warning: `#[automatically_derived]` attribute cannot be used on modules --> $DIR/malformed-attrs.rs:196:1 | diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr index 2af24130a1e58..43205bd395fcd 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:11:1 + --> $DIR/does_not_acccept_args.rs:12:1 | LL | #[diagnostic::do_not_recommend(not_accepted)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,16 +7,22 @@ LL | #[diagnostic::do_not_recommend(not_accepted)] = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:15:1 + --> $DIR/does_not_acccept_args.rs:16:1 | LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:19:1 + --> $DIR/does_not_acccept_args.rs:20:1 | LL | #[diagnostic::do_not_recommend(not_accepted(42))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 3 warnings emitted +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:24:1 + | +LL | #[diagnostic::do_not_recommend(x = y + z)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr index 2af24130a1e58..43205bd395fcd 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:11:1 + --> $DIR/does_not_acccept_args.rs:12:1 | LL | #[diagnostic::do_not_recommend(not_accepted)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,16 +7,22 @@ LL | #[diagnostic::do_not_recommend(not_accepted)] = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:15:1 + --> $DIR/does_not_acccept_args.rs:16:1 | LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/does_not_acccept_args.rs:19:1 + --> $DIR/does_not_acccept_args.rs:20:1 | LL | #[diagnostic::do_not_recommend(not_accepted(42))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 3 warnings emitted +warning: `#[diagnostic::do_not_recommend]` does not expect any arguments + --> $DIR/does_not_acccept_args.rs:24:1 + | +LL | #[diagnostic::do_not_recommend(x = y + z)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs index 5c21c045e10aa..918bf5a0113ea 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs @@ -7,6 +7,7 @@ trait Foo {} trait Bar {} trait Baz {} +trait Boo {} #[diagnostic::do_not_recommend(not_accepted)] //~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments @@ -20,4 +21,8 @@ impl Bar for T where T: Send {} //~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments impl Baz for T where T: Send {} +#[diagnostic::do_not_recommend(x = y + z)] +//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments +impl Boo for T where T: Send {} + fn main() {} diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout index 4822cf4700b94..f74637fa7efe6 100644 --- a/tests/ui/unpretty/diagnostic-attr.stdout +++ b/tests/ui/unpretty/diagnostic-attr.stdout @@ -11,5 +11,5 @@ use ::std::prelude::rust_2015::*; "My Label", note = "Note 1", note = "Note 2")] trait ImportantTrait { } -#[diagnostic::do_not_recommend] +#[attr = DoNotRecommend] impl ImportantTrait for T where T: Clone { }