Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/do_not_recommend.rs
Original file line number Diff line number Diff line change
@@ -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<S: Stage> SingleAttributeParser<S> for DoNotRecommendParser {
const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = 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<AttributeKind> {
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 })
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -197,6 +198,7 @@ attribute_parsers!(
Single<CrateNameParser>,
Single<CustomMirParser>,
Single<DeprecationParser>,
Single<DoNotRecommendParser>,
Single<DummyParser>,
Single<ExportNameParser>,
Single<IgnoreParser>,
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_attr_parsing/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ impl AttributeKind {
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,
DoNotImplementViaObject(..) => No,
DoNotRecommend { .. } => Yes,
Doc(_) => Yes,
DocComment { .. } => Yes,
Dummy => No,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_lint/src/early/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
1 change: 1 addition & 0 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ pub enum AttributeLintKind {
},
DocTestLiteral,
AttrCrateLevelOnly,
DoNotRecommendDoesNotExpectArgs,
}

pub type RegisteredTools = FxIndexSet<Ident>;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<P>(self, def_id: P) -> bool
Expand Down
33 changes: 1 addition & 32 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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<DefId>,
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,
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
20 changes: 4 additions & 16 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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<ItemLike<'_>>,
) {
if !matches!(target, Target::Impl { .. })
Expand All @@ -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
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down
15 changes: 7 additions & 8 deletions tests/ui/attributes/malformed-attrs.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -729,21 +729,14 @@ 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
|
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
Expand Down Expand Up @@ -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
|
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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

Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -20,4 +21,8 @@ impl<T> Bar for T where T: Send {}
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
impl<T> Baz for T where T: Send {}

#[diagnostic::do_not_recommend(x = y + z)]
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
impl<T> Boo for T where T: Send {}

fn main() {}
2 changes: 1 addition & 1 deletion tests/ui/unpretty/diagnostic-attr.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ use ::std::prelude::rust_2015::*;
"My Label", note = "Note 1", note = "Note 2")]
trait ImportantTrait<A> { }

#[diagnostic::do_not_recommend]
#[attr = DoNotRecommend]
impl <T> ImportantTrait<T> for T where T: Clone { }
Loading