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
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
use rustc_feature::AttributeStability;
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_session::lint::builtin::{
MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES,
};
use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::{Symbol, sym};

use crate::attributes::prelude::Allow;
use crate::attributes::{OnDuplicate, SingleAttributeParser};
use crate::context::AcceptContext;
use crate::diagnostics::IncorrectDoNotRecommendLocation;
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
use crate::target_checking::AllowedTargets;
use crate::{AttributeTemplate, template};

pub(crate) struct DoNotRecommendParser;
impl SingleAttributeParser for DoNotRecommendParser {
const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
// "Allowed" on any target, noop on all but trait impls
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Impl { of_trait: true })]);
const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */);
const STABILITY: AttributeStability = AttributeStability::Stable;

Expand All @@ -32,16 +31,6 @@ impl SingleAttributeParser for DoNotRecommendParser {
);
}

if !matches!(cx.target, Target::Impl { of_trait: true }) {
let target_span = cx.target_span;
cx.emit_lint(
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
IncorrectDoNotRecommendLocation { target_span },
attr_span,
);
return None;
}

Some(AttributeKind::DoNotRecommend)
}
}
20 changes: 5 additions & 15 deletions compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use rustc_feature::AttributeStability;
use rustc_hir::attrs::diagnostic::Directive;
use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;

use crate::attributes::diagnostic::*;
use crate::attributes::prelude::*;
use crate::diagnostics::DiagnosticOnConstOnlyForTraitImpls;
#[derive(Default)]
pub(crate) struct OnConstParser {
span: Option<Span>,
Expand All @@ -26,18 +24,6 @@ impl AttributeParser for OnConstParser {
let span = cx.attr_span;
this.span = Some(span);

// FIXME(mejrs) no constness field on `Target`,
// so non-constness is still checked in check_attr.rs
if !matches!(cx.target, Target::Impl { of_trait: true }) {
let target_span = cx.target_span;
cx.emit_lint(
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
DiagnosticOnConstOnlyForTraitImpls { target_span },
span,
);
return;
}

let mode = Mode::DiagnosticOnConst;

let Some(items) = parse_list(cx, args, mode) else { return };
Expand All @@ -51,7 +37,11 @@ impl AttributeParser for OnConstParser {

// "Allowed" on all targets; noop on anything but non-const trait impls;
// this linted on in parser.
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
// FIXME(mejrs) no constness field on `Target`,
// so non-constness is still checked in check_attr.rs
Allow(Target::Impl { of_trait: true }),
]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(span) = self.span {
Expand Down
16 changes: 6 additions & 10 deletions compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use rustc_feature::AttributeStability;
use rustc_hir::attrs::AttributeKind;
use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::sym;

use crate::attributes::diagnostic::*;
use crate::attributes::prelude::*;
use crate::context::AcceptContext;
use crate::diagnostics::DiagnosticOnMoveOnlyForAdt;
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
use crate::target_checking::AllowedTargets;
use crate::template;

#[derive(Default)]
Expand All @@ -28,11 +26,6 @@ impl OnMoveParser {
let span = cx.attr_span;
self.span = Some(span);

if !matches!(cx.target, Target::Enum | Target::Struct | Target::Union) {
cx.emit_lint(MISPLACED_DIAGNOSTIC_ATTRIBUTES, DiagnosticOnMoveOnlyForAdt, span);
return;
}

let Some(items) = parse_list(cx, args, mode) else { return };

if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
Expand All @@ -50,8 +43,11 @@ impl AttributeParser for OnMoveParser {
},
)];

// "Allowed" for all targets but noop if used on not-adt.
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Enum),
Allow(Target::Struct),
Allow(Target::Union),
]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(_span) = self.span {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use rustc_hir::attrs::AttributeKind;
use rustc_lint_defs::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::sym;

use crate::attributes::AttributeStability;
use crate::attributes::diagnostic::*;
use crate::attributes::prelude::*;
use crate::context::AcceptContext;
use crate::diagnostics::DiagnosticOnTypeErrorOnlyForAdt;
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
use crate::target_checking::AllowedTargets;
use crate::template;

#[derive(Default)]
Expand All @@ -26,11 +24,6 @@ impl OnTypeErrorParser {
let span = cx.attr_span;
self.span = Some(span);

if !matches!(cx.target, Target::Enum | Target::Struct | Target::Union) {
cx.emit_lint(MISPLACED_DIAGNOSTIC_ATTRIBUTES, DiagnosticOnTypeErrorOnlyForAdt, span);
return;
}

let Some(items) = parse_list(cx, args, mode) else { return };

if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
Expand All @@ -49,7 +42,11 @@ impl AttributeParser for OnTypeErrorParser {
},
)];

const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Enum),
Allow(Target::Struct),
Allow(Target::Union),
]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(span) = self.span {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use rustc_feature::AttributeStability;
use rustc_hir::attrs::diagnostic::Directive;
use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;

use crate::attributes::diagnostic::*;
use crate::attributes::prelude::*;
use crate::diagnostics::DiagnosticOnUnimplementedOnlyForTraits;

#[derive(Default)]
pub(crate) struct OnUnimplementedParser {
Expand All @@ -17,15 +15,6 @@ impl OnUnimplementedParser {
let span = cx.attr_span;
self.span = Some(span);

if !matches!(cx.target, Target::Trait) {
cx.emit_lint(
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
DiagnosticOnUnimplementedOnlyForTraits,
span,
);
return;
}

let Some(items) = parse_list(cx, args, mode) else { return };

if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
Expand Down Expand Up @@ -56,8 +45,8 @@ impl AttributeParser for OnUnimplementedParser {
},
),
];
//FIXME attribute is not parsed for non-traits but diagnostics are issued in `check_attr.rs`
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Trait)]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(_span) = self.span {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use rustc_feature::AttributeStability;
use rustc_hir::attrs::diagnostic::Directive;
use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;

use crate::ShouldEmit;
use crate::attributes::diagnostic::*;
use crate::attributes::prelude::*;
use crate::diagnostics::DiagnosticOnUnknownInvalidTarget;

#[derive(Default)]
pub(crate) struct OnUnknownParser {
Expand All @@ -25,20 +22,6 @@ impl OnUnknownParser {
let span = cx.attr_span;
self.span = Some(span);

// At early parsing we get passed `Target::Crate` regardless of the item we're on.
// Therefore, only do target checking if we can emit.
let early = matches!(cx.should_emit, ShouldEmit::Nothing);

if !early && !matches!(cx.target, Target::Use | Target::Mod | Target::Crate) {
let target_span = cx.target_span;
cx.emit_lint(
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
DiagnosticOnUnknownInvalidTarget { target_span },
span,
);
return;
}

let Some(items) = parse_list(cx, args, mode) else { return };

if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
Expand All @@ -57,7 +40,11 @@ impl AttributeParser for OnUnknownParser {
},
)];
// "Allowed" for all targets, but noop for all but use statements.
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Use),
Allow(Target::Mod),
Allow(Target::Crate),
]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(_span) = self.span {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use rustc_feature::AttributeStability;
use rustc_hir::attrs::diagnostic::Directive;
use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;

use crate::attributes::diagnostic::*;
use crate::attributes::prelude::*;
use crate::diagnostics::DiagnosticOnUnmatchedArgsOnlyForMacros;

#[derive(Default)]
pub(crate) struct OnUnmatchedArgsParser {
Expand All @@ -25,15 +23,6 @@ impl AttributeParser for OnUnmatchedArgsParser {
let span = cx.attr_span;
this.span = Some(span);

if !matches!(cx.target, Target::MacroDef) {
cx.emit_lint(
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
DiagnosticOnUnmatchedArgsOnlyForMacros,
span,
);
return;
}

let mode = Mode::DiagnosticOnUnmatchedArgs;
let Some(items) = parse_list(cx, args, mode) else { return };

Expand All @@ -44,7 +33,8 @@ impl AttributeParser for OnUnmatchedArgsParser {
},
)];

const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowListWarnRest(&[Allow(Target::MacroDef)]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(_span) = self.span {
Expand Down
39 changes: 0 additions & 39 deletions compiler/rustc_attr_parsing/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,45 +279,6 @@ pub(crate) struct UnknownCrateTypesSuggestion {
pub snippet: Symbol,
}

#[derive(Diagnostic)]
#[diag("`#[diagnostic::on_const]` can only be applied to non-const trait implementations")]
pub(crate) struct DiagnosticOnConstOnlyForTraitImpls {
#[label("not a trait implementation")]
pub target_span: Span,
}

#[derive(Diagnostic)]
#[diag("`#[diagnostic::on_move]` can only be applied to enums, structs or unions")]
pub(crate) struct DiagnosticOnMoveOnlyForAdt;

#[derive(Diagnostic)]
#[diag("`#[diagnostic::on_unimplemented]` can only be applied to trait definitions")]
pub(crate) struct DiagnosticOnUnimplementedOnlyForTraits;

#[derive(Diagnostic)]
#[diag(
"`#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations"
)]
pub(crate) struct DiagnosticOnUnknownInvalidTarget {
#[label("not an import or module")]
pub target_span: Span,
}

#[derive(Diagnostic)]
#[diag("`#[diagnostic::on_unmatched_args]` can only be applied to macro definitions")]
pub(crate) struct DiagnosticOnUnmatchedArgsOnlyForMacros;

#[derive(Diagnostic)]
#[diag("`#[diagnostic::on_type_error]` can only be applied to enums, structs or unions")]
pub(crate) struct DiagnosticOnTypeErrorOnlyForAdt;

#[derive(Diagnostic)]
#[diag("`#[diagnostic::do_not_recommend]` can only be placed on trait implementations")]
pub(crate) struct IncorrectDoNotRecommendLocation {
#[label("not a trait implementation")]
pub target_span: Span,
}

#[derive(Diagnostic)]
#[diag("malformed `doc` attribute input")]
#[warning(
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_attr_parsing/src/target_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ impl<'sess> AttributeParser<'sess> {

let allowed_targets = allowed_targets.allowed_targets();
let (applied, only) = allowed_targets_applied(allowed_targets, cx.target, cx.features);
let is_diagnostic_attr = cx.attr_path.segments[0] == sym::diagnostic;

let diag = InvalidTarget {
span: cx.attr_span.clone(),
Expand All @@ -138,7 +139,7 @@ impl<'sess> AttributeParser<'sess> {
applied: DiagArgValue::StrListSepByAnd(applied.into_iter().map(Cow::Owned).collect()),
attribute_args,
help: Self::target_checking_help(attribute_args, cx),
previously_accepted: matches!(result, AllowedResult::Warn),
previously_accepted: matches!(result, AllowedResult::Warn) && !is_diagnostic_attr,
on_macro_call: matches!(cx.target, Target::MacroCall),
};

Expand All @@ -156,6 +157,8 @@ impl<'sess> AttributeParser<'sess> {
.contains(&cx.target)
{
rustc_session::lint::builtin::USELESS_DEPRECATED
} else if is_diagnostic_attr {
rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES
} else {
rustc_session::lint::builtin::UNUSED_ATTRIBUTES
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if trait_pred.polarity() != ty::PredicatePolarity::Positive {
return CustomDiagnostic::default();
}
// This is needed as `on_unimplemented` is currently not allowed on trait aliases,
// but the "not allowed" is a warning, and this check ensures the attribute has no effect
if self.tcx.is_trait_alias(trait_pred.def_id()) {
return CustomDiagnostic::default();
}
let (filter_options, format_args) =
self.on_unimplemented_components(trait_pred, obligation, long_ty_path);
if let Some(command) = find_attr!(self.tcx, trait_pred.def_id(), OnUnimplemented {directive, ..} => directive.as_deref()).flatten() {
Expand Down
Loading
Loading