mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Port do_not_recommend to new attr parsing
This commit is contained in:
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@
|
||||
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;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
};
|
||||
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 @@ mod late {
|
||||
Single<CrateNameParser>,
|
||||
Single<CustomMirParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<DoNotRecommendParser>,
|
||||
Single<DummyParser>,
|
||||
Single<ExportNameParser>,
|
||||
Single<IgnoreParser>,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -44,6 +44,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
|
||||
DenyExplicitImpl(..) => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DoNotImplementViaObject(..) => No,
|
||||
DoNotRecommend { .. } => Yes,
|
||||
Doc(_) => Yes,
|
||||
DocComment { .. } => Yes,
|
||||
Dummy => No,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3317,3 +3317,7 @@ pub(crate) struct DocTestUnknown {
|
||||
#[diag(lint_attr_crate_level)]
|
||||
#[note]
|
||||
pub(crate) struct AttrCrateLevelOnly;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_incorrect_do_not_recommend_args)]
|
||||
pub(crate) struct DoNotRecommendDoesNotExpectArgs;
|
||||
|
||||
@@ -821,6 +821,7 @@ pub enum AttributeLintKind {
|
||||
},
|
||||
DocTestLiteral,
|
||||
AttrCrateLevelOnly,
|
||||
DoNotRecommendDoesNotExpectArgs,
|
||||
}
|
||||
|
||||
pub type RegisteredTools = FxIndexSet<Ident>;
|
||||
|
||||
@@ -3540,7 +3540,7 @@ pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool {
|
||||
|
||||
/// 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
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
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 @@ pub fn get_all_attrs(self, did: impl Into<DefId>) -> &'tcx [hir::Attribute] {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
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 @@ fn check_attributes(
|
||||
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 @@ fn check_attributes(
|
||||
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 @@ fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 { .. })
|
||||
@@ -592,14 +588,6 @@ fn check_do_not_recommend(
|
||||
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
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
#[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 {
|
||||
|
||||
@@ -434,7 +434,7 @@ fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result
|
||||
} = 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
Reference in New Issue
Block a user