1
Fork 0

Move #[do_not_recommend] to the #[diagnostic] namespace

This commit moves the `#[do_not_recommend]` attribute to the
`#[diagnostic]` namespace. It still requires
`#![feature(do_not_recommend)]` to work.
This commit is contained in:
Georg Semmler 2024-05-10 14:12:30 +02:00
parent e8ada6ab25
commit 2cff3e90bc
No known key found for this signature in database
GPG key ID: A87BCEE5205CE489
22 changed files with 228 additions and 209 deletions

View file

@ -13,6 +13,7 @@ use crate::util::literal::escape_string_symbol;
use rustc_index::bit_set::GrowableBitSet; use rustc_index::bit_set::GrowableBitSet;
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span; use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
use std::iter; use std::iter;
use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::atomic::{AtomicU32, Ordering};
use thin_vec::{thin_vec, ThinVec}; use thin_vec::{thin_vec, ThinVec};
@ -87,10 +88,20 @@ impl Attribute {
AttrKind::DocComment(..) => None, AttrKind::DocComment(..) => None,
} }
} }
pub fn name_or_empty(&self) -> Symbol { pub fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name self.ident().unwrap_or_else(Ident::empty).name
} }
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
match &self.kind {
AttrKind::Normal(normal) => {
normal.item.path.segments.iter().map(|s| s.ident.name).collect()
}
AttrKind::DocComment(..) => smallvec![sym::doc],
}
}
#[inline] #[inline]
pub fn has_name(&self, name: Symbol) -> bool { pub fn has_name(&self, name: Symbol) -> bool {
match &self.kind { match &self.kind {

View file

@ -515,12 +515,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
EncodeCrossCrate::Yes, experimental!(deprecated_safe), EncodeCrossCrate::Yes, experimental!(deprecated_safe),
), ),
// RFC 2397
gated!(
do_not_recommend, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::Yes, experimental!(do_not_recommend)
),
// `#[cfi_encoding = ""]` // `#[cfi_encoding = ""]`
gated!( gated!(
cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding, cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding,

View file

@ -1805,6 +1805,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.get_attrs(did, attr).next().is_some() self.get_attrs(did, attr).next().is_some()
} }
/// Determines whether an item is annotated with a multi-segement attribute
pub fn has_attrs_with_path(self, did: impl Into<DefId>, attrs: &[Symbol]) -> bool {
self.get_attrs_by_path(did.into(), attrs).next().is_some()
}
/// Returns `true` if this is an `auto trait`. /// Returns `true` if this is an `auto trait`.
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
self.trait_def(trait_def_id).has_auto_impl self.trait_def(trait_def_id).has_auto_impl

View file

@ -341,7 +341,7 @@ passes_implied_feature_not_exist =
feature `{$implied_by}` implying `{$feature}` does not exist feature `{$implied_by}` implying `{$feature}` does not exist
passes_incorrect_do_not_recommend_location = passes_incorrect_do_not_recommend_location =
`#[do_not_recommend]` can only be placed on trait implementations `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
passes_incorrect_meta_item = expected a quoted string literal passes_incorrect_meta_item = expected a quoted string literal
passes_incorrect_meta_item_suggestion = consider surrounding this with quotes passes_incorrect_meta_item_suggestion = consider surrounding this with quotes

View file

@ -116,92 +116,96 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let mut seen = FxHashMap::default(); let mut seen = FxHashMap::default();
let attrs = self.tcx.hir().attrs(hir_id); let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs { for attr in attrs {
if attr.path_matches(&[sym::diagnostic, sym::on_unimplemented]) { match attr.path().as_slice() {
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target); [sym::diagnostic, sym::do_not_recommend] => {
self.check_do_not_recommend(attr.span, hir_id, target)
} }
match attr.name_or_empty() { [sym::diagnostic, sym::on_unimplemented] => {
sym::do_not_recommend => self.check_do_not_recommend(attr.span, target), self.check_diagnostic_on_unimplemented(attr.span, hir_id, target)
sym::inline => self.check_inline(hir_id, attr, span, target), }
sym::coverage => self.check_coverage(hir_id, attr, span, target), [sym::inline] => self.check_inline(hir_id, attr, span, target),
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), [sym::coverage] => self.check_coverage(hir_id, attr, span, target),
sym::marker => self.check_marker(hir_id, attr, span, target), [sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target),
sym::target_feature => self.check_target_feature(hir_id, attr, span, target, attrs), [sym::marker] => self.check_marker(hir_id, attr, span, target),
sym::thread_local => self.check_thread_local(attr, span, target), [sym::target_feature] => {
sym::track_caller => { self.check_target_feature(hir_id, attr, span, target, attrs)
}
[sym::thread_local] => self.check_thread_local(attr, span, target),
[sym::track_caller] => {
self.check_track_caller(hir_id, attr.span, attrs, span, target) self.check_track_caller(hir_id, attr.span, attrs, span, target)
} }
sym::doc => self.check_doc_attrs( [sym::doc] => self.check_doc_attrs(
attr, attr,
hir_id, hir_id,
target, target,
&mut specified_inline, &mut specified_inline,
&mut doc_aliases, &mut doc_aliases,
), ),
sym::no_link => self.check_no_link(hir_id, attr, span, target), [sym::no_link] => self.check_no_link(hir_id, attr, span, target),
sym::export_name => self.check_export_name(hir_id, attr, span, target), [sym::export_name] => self.check_export_name(hir_id, attr, span, target),
sym::rustc_layout_scalar_valid_range_start [sym::rustc_layout_scalar_valid_range_start]
| sym::rustc_layout_scalar_valid_range_end => { | [sym::rustc_layout_scalar_valid_range_end] => {
self.check_rustc_layout_scalar_valid_range(attr, span, target) self.check_rustc_layout_scalar_valid_range(attr, span, target)
} }
sym::allow_internal_unstable => { [sym::allow_internal_unstable] => {
self.check_allow_internal_unstable(hir_id, attr, span, target, attrs) self.check_allow_internal_unstable(hir_id, attr, span, target, attrs)
} }
sym::debugger_visualizer => self.check_debugger_visualizer(attr, target), [sym::debugger_visualizer] => self.check_debugger_visualizer(attr, target),
sym::rustc_allow_const_fn_unstable => { [sym::rustc_allow_const_fn_unstable] => {
self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target) self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target)
} }
sym::rustc_std_internal_symbol => { [sym::rustc_std_internal_symbol] => {
self.check_rustc_std_internal_symbol(attr, span, target) self.check_rustc_std_internal_symbol(attr, span, target)
} }
sym::naked => self.check_naked(hir_id, attr, span, target), [sym::naked] => self.check_naked(hir_id, attr, span, target),
sym::rustc_never_returns_null_ptr => { [sym::rustc_never_returns_null_ptr] => {
self.check_applied_to_fn_or_method(hir_id, attr, span, target) self.check_applied_to_fn_or_method(hir_id, attr, span, target)
} }
sym::rustc_legacy_const_generics => { [sym::rustc_legacy_const_generics] => {
self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
} }
sym::rustc_lint_query_instability => { [sym::rustc_lint_query_instability] => {
self.check_rustc_lint_query_instability(hir_id, attr, span, target) self.check_rustc_lint_query_instability(hir_id, attr, span, target)
} }
sym::rustc_lint_diagnostics => { [sym::rustc_lint_diagnostics] => {
self.check_rustc_lint_diagnostics(hir_id, attr, span, target) self.check_rustc_lint_diagnostics(hir_id, attr, span, target)
} }
sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(attr, span, target), [sym::rustc_lint_opt_ty] => self.check_rustc_lint_opt_ty(attr, span, target),
sym::rustc_lint_opt_deny_field_access => { [sym::rustc_lint_opt_deny_field_access] => {
self.check_rustc_lint_opt_deny_field_access(attr, span, target) self.check_rustc_lint_opt_deny_field_access(attr, span, target)
} }
sym::rustc_clean [sym::rustc_clean]
| sym::rustc_dirty | [sym::rustc_dirty]
| sym::rustc_if_this_changed | [sym::rustc_if_this_changed]
| sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(attr), | [sym::rustc_then_this_would_need] => self.check_rustc_dirty_clean(attr),
sym::rustc_coinductive [sym::rustc_coinductive]
| sym::rustc_must_implement_one_of | [sym::rustc_must_implement_one_of]
| sym::rustc_deny_explicit_impl | [sym::rustc_deny_explicit_impl]
| sym::const_trait => self.check_must_be_applied_to_trait(attr, span, target), | [sym::const_trait] => self.check_must_be_applied_to_trait(attr, span, target),
sym::cmse_nonsecure_entry => { [sym::cmse_nonsecure_entry] => {
self.check_cmse_nonsecure_entry(hir_id, attr, span, target) self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
} }
sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target), [sym::collapse_debuginfo] => self.check_collapse_debuginfo(attr, span, target),
sym::must_not_suspend => self.check_must_not_suspend(attr, span, target), [sym::must_not_suspend] => self.check_must_not_suspend(attr, span, target),
sym::must_use => self.check_must_use(hir_id, attr, target), [sym::must_use] => self.check_must_use(hir_id, attr, target),
sym::rustc_pass_by_value => self.check_pass_by_value(attr, span, target), [sym::rustc_pass_by_value] => self.check_pass_by_value(attr, span, target),
sym::rustc_allow_incoherent_impl => { [sym::rustc_allow_incoherent_impl] => {
self.check_allow_incoherent_impl(attr, span, target) self.check_allow_incoherent_impl(attr, span, target)
} }
sym::rustc_has_incoherent_inherent_impls => { [sym::rustc_has_incoherent_inherent_impls] => {
self.check_has_incoherent_inherent_impls(attr, span, target) self.check_has_incoherent_inherent_impls(attr, span, target)
} }
sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target), [sym::ffi_pure] => self.check_ffi_pure(attr.span, attrs, target),
sym::ffi_const => self.check_ffi_const(attr.span, target), [sym::ffi_const] => self.check_ffi_const(attr.span, target),
sym::rustc_const_unstable [sym::rustc_const_unstable]
| sym::rustc_const_stable | [sym::rustc_const_stable]
| sym::unstable | [sym::unstable]
| sym::stable | [sym::stable]
| sym::rustc_allowed_through_unstable_modules | [sym::rustc_allowed_through_unstable_modules]
| sym::rustc_promotable => self.check_stability_promotable(attr, target), | [sym::rustc_promotable] => self.check_stability_promotable(attr, target),
sym::link_ordinal => self.check_link_ordinal(attr, span, target), [sym::link_ordinal] => self.check_link_ordinal(attr, span, target),
sym::rustc_confusables => self.check_confusables(attr, target), [sym::rustc_confusables] => self.check_confusables(attr, target),
sym::rustc_safe_intrinsic => { [sym::rustc_safe_intrinsic] => {
self.check_rustc_safe_intrinsic(hir_id, attr, span, target) self.check_rustc_safe_intrinsic(hir_id, attr, span, target)
} }
_ => true, _ => true,
@ -293,18 +297,26 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
); );
} }
/// Checks if `#[do_not_recommend]` is applied on a trait impl. /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl.
fn check_do_not_recommend(&self, attr_span: Span, target: Target) -> bool { fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) -> bool {
if let Target::Impl = target { if !matches!(target, Target::Impl) {
true self.tcx.emit_node_span_lint(
} else { UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
self.dcx().emit_err(errors::IncorrectDoNotRecommendLocation { span: attr_span }); hir_id,
false attr_span,
errors::IncorrectDoNotRecommendLocation,
);
} }
true
} }
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) { fn check_diagnostic_on_unimplemented(
&self,
attr_span: Span,
hir_id: HirId,
target: Target,
) -> bool {
if !matches!(target, Target::Trait) { if !matches!(target, Target::Trait) {
self.tcx.emit_node_span_lint( self.tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
@ -313,6 +325,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
DiagnosticOnUnimplementedOnlyForTraits, DiagnosticOnUnimplementedOnlyForTraits,
); );
} }
true
} }
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.

View file

@ -17,12 +17,9 @@ use rustc_span::{Span, Symbol, DUMMY_SP};
use crate::check_attr::ProcMacroKind; use crate::check_attr::ProcMacroKind;
use crate::lang_items::Duplicate; use crate::lang_items::Duplicate;
#[derive(Diagnostic)] #[derive(LintDiagnostic)]
#[diag(passes_incorrect_do_not_recommend_location)] #[diag(passes_incorrect_do_not_recommend_location)]
pub struct IncorrectDoNotRecommendLocation { pub struct IncorrectDoNotRecommendLocation;
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(passes_outer_crate_level_attr)] #[diag(passes_outer_crate_level_attr)]

View file

@ -567,7 +567,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool) if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
&& let [namespace, attribute, ..] = &*path.segments && let [namespace, attribute, ..] = &*path.segments
&& namespace.ident.name == sym::diagnostic && namespace.ident.name == sym::diagnostic
&& attribute.ident.name != sym::on_unimplemented && !(attribute.ident.name == sym::on_unimplemented
|| (attribute.ident.name == sym::do_not_recommend
&& self.tcx.features().do_not_recommend))
{ {
let distance = let distance =
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);

View file

@ -380,7 +380,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
source: CandidateSource::Impl(impl_def_id), source: CandidateSource::Impl(impl_def_id),
result: _, result: _,
} = candidate.kind() } = candidate.kind()
&& goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend) && goal
.infcx()
.tcx
.has_attrs_with_path(impl_def_id, &[sym::diagnostic, sym::do_not_recommend])
{ {
return ControlFlow::Break(self.obligation.clone()); return ControlFlow::Break(self.obligation.clone());
} }

View file

@ -1012,7 +1012,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let mut base_cause = obligation.cause.code().clone(); let mut base_cause = obligation.cause.code().clone();
loop { loop {
if let ObligationCauseCode::ImplDerived(ref c) = base_cause { if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
if self.tcx.has_attr(c.impl_or_alias_def_id, sym::do_not_recommend) { if self.tcx.has_attrs_with_path(
c.impl_or_alias_def_id,
&[sym::diagnostic, sym::do_not_recommend],
) {
let code = (*c.derived.parent_code).clone(); let code = (*c.derived.parent_code).clone();
obligation.cause.map_code(|_| code); obligation.cause.map_code(|_| code);
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx); obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);

View file

@ -26,7 +26,7 @@ impl<T> Expression for Bound<T> {
type SqlType = T; type SqlType = T;
} }
#[do_not_recommend] #[diagnostic::do_not_recommend]
impl<T, ST> AsExpression<ST> for T impl<T, ST> AsExpression<ST> for T
where where
T: Expression<SqlType = ST>, T: Expression<SqlType = ST>,

View file

@ -1,17 +1,13 @@
#![feature(do_not_recommend)] #![feature(do_not_recommend)]
pub trait Foo { pub trait Foo {}
}
impl Foo for i32 { impl Foo for i32 {}
}
pub trait Bar { pub trait Bar {}
}
#[do_not_recommend] #[diagnostic::do_not_recommend]
impl<T: Foo> Bar for T { impl<T: Foo> Bar for T {}
}
fn stuff<T: Bar>(_: T) {} fn stuff<T: Bar>(_: T) {}

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `u8: Bar` is not satisfied error[E0277]: the trait bound `u8: Bar` is not satisfied
--> $DIR/feature-gate-do_not_recommend.rs:19:11 --> $DIR/feature-gate-do_not_recommend.rs:15:11
| |
LL | stuff(1u8); LL | stuff(1u8);
| ^^^ the trait `Bar` is not implemented for `u8` | ^^^ the trait `Bar` is not implemented for `u8`
| |
note: required by a bound in `stuff` note: required by a bound in `stuff`
--> $DIR/feature-gate-do_not_recommend.rs:16:13 --> $DIR/feature-gate-do_not_recommend.rs:12:13
| |
LL | fn stuff<T: Bar>(_: T) {} LL | fn stuff<T: Bar>(_: T) {}
| ^^^ required by this bound in `stuff` | ^^^ required by this bound in `stuff`

View file

@ -0,0 +1,39 @@
//@ check-pass
#![feature(do_not_recommend)]
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
const CONST: () = ();
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
static STATIC: () = ();
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
type Type = ();
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
enum Enum {}
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
extern "C" {}
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
fn fun() {}
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
struct Struct {}
#[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
trait Trait {}
#[diagnostic::do_not_recommend]
impl Trait for i32 {}
fn main() {}

View file

@ -0,0 +1,52 @@
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:4:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:8:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:12:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:16:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:20:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:24:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:28:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:32:1
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: 8 warnings emitted

View file

@ -6,7 +6,7 @@
trait Foo {} trait Foo {}
#[do_not_recommend] #[diagnostic::do_not_recommend]
impl<T> Foo for T where T: Send {} impl<T> Foo for T where T: Send {}
fn needs_foo<T: Foo>() {} fn needs_foo<T: Foo>() {}

View file

@ -8,7 +8,7 @@ trait Root {}
trait DontRecommend {} trait DontRecommend {}
trait Other {} trait Other {}
#[do_not_recommend] #[diagnostic::do_not_recommend]
impl<T> Root for T where T: DontRecommend {} impl<T> Root for T where T: DontRecommend {}
impl<T> DontRecommend for T where T: Other {} impl<T> DontRecommend for T where T: Other {}

View file

@ -0,0 +1,8 @@
#![deny(unknown_or_malformed_diagnostic_attributes)]
trait Foo {}
#[diagnostic::do_not_recommend]
//~^ ERROR unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes]
impl Foo for i32 {}
fn main() {}

View file

@ -0,0 +1,14 @@
error: unknown diagnostic attribute
--> $DIR/unstable-feature.rs:4:15
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/unstable-feature.rs:1:9
|
LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -1,45 +0,0 @@
#![feature(do_not_recommend)]
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
const CONST: () = ();
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
static Static: () = ();
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
type Type = ();
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
enum Enum {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
extern {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
fn fun() {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
struct Struct {
}
#[do_not_recommend]
//~^ `#[do_not_recommend]` can only be placed
trait Trait {
}
#[do_not_recommend]
impl Trait for i32 {
}
fn main() {
}

View file

@ -1,50 +0,0 @@
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:3:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:7:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:11:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:15:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:20:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:25:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:30:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: `#[do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:35:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors

View file

@ -1,10 +0,0 @@
trait Foo {
}
#[do_not_recommend]
//~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature
impl Foo for i32 {
}
fn main() {
}

View file

@ -1,13 +0,0 @@
error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature
--> $DIR/unstable-feature.rs:4:1
|
LL | #[do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #51992 <https://github.com/rust-lang/rust/issues/51992> for more information
= help: add `#![feature(do_not_recommend)]` 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
For more information about this error, try `rustc --explain E0658`.