Port do_not_recommend to new attr parsing
This commit is contained in:
parent
db1484bdee
commit
a1e2cea685
17 changed files with 65 additions and 66 deletions
|
|
@ -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 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;
|
||||
|
|
|
|||
|
|
@ -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<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 @@ impl AttributeKind {
|
|||
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 DocTestLiteral;
|
|||
#[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 @@ 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
|
||||
|
|
|
|||
|
|
@ -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<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_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<ItemLike<'_>>,
|
||||
) {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 { }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue