Remove ATTRIBUTE_ORDER

This commit is contained in:
Jonathan Brouwer
2026-02-24 09:08:12 +01:00
parent bbe8536158
commit 34ef9a6146
29 changed files with 63 additions and 170 deletions
@@ -9,7 +9,7 @@
use thin_vec::ThinVec;
use crate::attributes::prelude::Allow;
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::attributes::{OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::{ArgParser, MetaItemOrLitParser};
use crate::target_checking::AllowedTargets;
@@ -18,7 +18,6 @@
impl<S: Stage> SingleAttributeParser<S> for RustcAutodiffParser {
const PATH: &[Symbol] = &[sym::rustc_autodiff];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
@@ -8,7 +8,6 @@ impl<S: Stage> SingleAttributeParser<S> for CfiEncodingParser {
Allow(Target::Enum),
Allow(Target::Union),
]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "encoding");
@@ -12,7 +12,6 @@
impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
const PATH: &[Symbol] = &[sym::optimize];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
@@ -68,7 +67,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
const PATH: &[Symbol] = &[sym::coverage];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
@@ -119,7 +117,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
const PATH: &[rustc_span::Symbol] = &[sym::export_name];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Static),
@@ -157,7 +154,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for RustcObjcClassParser {
const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_class];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
@@ -189,7 +185,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for RustcObjcSelectorParser {
const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_selector];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
@@ -595,7 +590,6 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
r#"realtime = "nonblocking|blocking|caller""#,
]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
@@ -724,7 +718,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEiiForeignItemParser {
impl<S: Stage> SingleAttributeParser<S> for PatchableFunctionEntryParser {
const PATH: &[Symbol] = &[sym::patchable_function_entry];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]);
@@ -10,7 +10,6 @@
impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
const PATH: &[Symbol] = &[sym::crate_name];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -84,7 +83,6 @@ fn extend(
impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
const PATH: &[Symbol] = &[sym::recursion_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -107,7 +105,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
const PATH: &[Symbol] = &[sym::move_size_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -130,7 +127,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
const PATH: &[Symbol] = &[sym::type_length_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -153,7 +149,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -213,7 +208,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
impl<S: Stage> SingleAttributeParser<S> for WindowsSubsystemParser {
const PATH: &[Symbol] = &[sym::windows_subsystem];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute");
@@ -34,7 +34,6 @@ fn get<S: Stage>(
pub(crate) struct DeprecatedParser;
impl<S: Stage> SingleAttributeParser<S> for DeprecatedParser {
const PATH: &[Symbol] = &[sym::deprecated];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Fn),
@@ -4,7 +4,7 @@
use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::attributes::{OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
@@ -12,7 +12,6 @@
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 */);
@@ -2,7 +2,7 @@
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::attributes::{OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
@@ -10,7 +10,6 @@
pub(crate) struct RustcDummyParser;
impl<S: Stage> SingleAttributeParser<S> for RustcDummyParser {
const PATH: &[Symbol] = &[sym::rustc_dummy];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really
@@ -11,7 +11,6 @@
impl<S: Stage> SingleAttributeParser<S> for InlineParser {
const PATH: &[Symbol] = &[sym::inline];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
@@ -68,7 +67,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
const PATH: &[Symbol] = &[sym::rustc_force_inline];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
@@ -16,7 +16,6 @@ impl<S: Stage> SingleAttributeParser<S> for InstructionSetParser {
]);
const TEMPLATE: AttributeTemplate = template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute");
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32];
@@ -22,7 +22,6 @@
impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
const PATH: &[Symbol] = &[sym::link_name];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::ForeignFn),
@@ -466,7 +465,6 @@ fn parse_link_import_name_type<S: Stage>(
impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
const PATH: &[Symbol] = &[sym::link_section];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Static),
@@ -541,7 +539,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcStdInternalSymbolParser {
impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
const PATH: &[Symbol] = &[sym::link_ordinal];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::ForeignFn),
@@ -583,8 +580,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
const PATH: &[Symbol] = &[sym::linkage];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
@@ -130,7 +130,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
const PATH: &[Symbol] = &[sym::macro_export];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const TEMPLATE: AttributeTemplate = template!(Word, List: &["local_inner_macros"]);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
@@ -168,7 +167,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for CollapseDebugInfoParser {
const PATH: &[Symbol] = &[sym::collapse_debuginfo];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(
List: &["no", "external", "yes"],
@@ -124,14 +124,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
/// If you need the parser to accept more than one path, use [`AttributeParser`] instead
const PATH: &[Symbol];
/// Configures the precedence of attributes with the same `PATH` on a syntax node.
const ATTRIBUTE_ORDER: AttributeOrder;
/// Configures what to do when when the same attribute is
/// applied more than once on the same syntax node.
///
/// [`ATTRIBUTE_ORDER`](Self::ATTRIBUTE_ORDER) specified which one is assumed to be correct,
/// and this specified whether to, for example, warn or error on the other one.
const ON_DUPLICATE: OnDuplicate<S>;
const ALLOWED_TARGETS: AllowedTargets;
@@ -162,21 +156,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
<T as SingleAttributeParser<S>>::TEMPLATE,
|group: &mut Single<T, S>, cx, args| {
if let Some(pa) = T::convert(cx, args) {
match T::ATTRIBUTE_ORDER {
// keep the first and report immediately. ignore this attribute
AttributeOrder::KeepInnermost => {
if let Some((_, unused)) = group.1 {
T::ON_DUPLICATE.exec::<T>(cx, cx.attr_span, unused);
return;
}
}
// keep the new one and warn about the previous,
// then replace
AttributeOrder::KeepOutermost => {
if let Some((_, used)) = group.1 {
T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
}
}
if let Some((_, used)) = group.1 {
T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
}
group.1 = Some((pa, cx.attr_span));
@@ -206,7 +187,7 @@ pub(crate) enum OnDuplicate<S: Stage> {
/// Custom function called when a duplicate attribute is found.
///
/// - `unused` is the span of the attribute that was unused or bad because of some
/// duplicate reason (see [`AttributeOrder`])
/// duplicate reason
/// - `used` is the span of the attribute that was used in favor of the unused attribute
Custom(fn(cx: &AcceptContext<'_, '_, S>, used: Span, unused: Span)),
}
@@ -223,8 +204,8 @@ fn exec<P: SingleAttributeParser<S>>(
OnDuplicate::WarnButFutureError => cx.warn_unused_duplicate_future_error(used, unused),
OnDuplicate::Error => {
cx.emit_err(UnusedMultiple {
this: used,
other: unused,
this: unused,
other: used,
name: Symbol::intern(
&P::PATH.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(".."),
),
@@ -236,30 +217,6 @@ fn exec<P: SingleAttributeParser<S>>(
}
}
pub(crate) enum AttributeOrder {
/// Duplicates after the innermost instance of the attribute will be an error/warning.
/// Only keep the lowest attribute.
///
/// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
/// further above the lowest one:
/// ```
/// #[stable(since="1.0")] //~ WARNING duplicated attribute
/// #[stable(since="2.0")]
/// ```
KeepInnermost,
/// Duplicates before the outermost instance of the attribute will be an error/warning.
/// Only keep the highest attribute.
///
/// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
/// below the highest one:
/// ```
/// #[path="foo.rs"]
/// #[path="bar.rs"] //~ WARNING duplicated attribute
/// ```
KeepOutermost,
}
/// An even simpler version of [`SingleAttributeParser`]:
/// now automatically check that there are no arguments provided to the attribute.
///
@@ -284,7 +241,6 @@ fn default() -> Self {
impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> {
const PATH: &[Symbol] = T::PATH;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
const TEMPLATE: AttributeTemplate = template!(Word);
@@ -4,7 +4,6 @@
impl<S: Stage> SingleAttributeParser<S> for MustNotSuspendParser {
const PATH: &[rustc_span::Symbol] = &[sym::must_not_suspend];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Struct),
@@ -4,7 +4,6 @@
impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
const PATH: &[Symbol] = &[sym::must_use];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Fn),
@@ -4,7 +4,6 @@
impl<S: Stage> SingleAttributeParser<S> for PathParser {
const PATH: &[Symbol] = &[sym::path];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Error(Target::Crate)]);
@@ -12,8 +12,8 @@
#[doc(hidden)]
pub(super) use crate::attributes::{
AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, NoArgsAttributeParser,
OnDuplicate, SingleAttributeParser,
};
// contexts
#[doc(hidden)]
@@ -25,7 +25,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
pub(crate) struct ProcMacroDeriveParser;
impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
const PATH: &[Symbol] = &[sym::proc_macro_derive];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
const TEMPLATE: AttributeTemplate = template!(
@@ -46,7 +45,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
pub(crate) struct RustcBuiltinMacroParser;
impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser {
const PATH: &[Symbol] = &[sym::rustc_builtin_macro];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
const TEMPLATE: AttributeTemplate =
@@ -5,7 +5,7 @@
use rustc_hir::attrs::{AttributeKind, MirDialect, MirPhase};
use rustc_span::{Span, Symbol, sym};
use super::{AttributeOrder, OnDuplicate};
use super::OnDuplicate;
use crate::attributes::SingleAttributeParser;
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
@@ -18,8 +18,6 @@
impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
const PATH: &[rustc_span::Symbol] = &[sym::custom_mir];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
@@ -28,7 +28,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcAllocatorZeroedVariantParser {
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function");
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(name) = args.name_value().and_then(NameValueParser::value_as_str) else {
cx.expected_name_value(cx.attr_span, None);
@@ -31,7 +31,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcMustImplementOneOfParser {
const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
@@ -105,7 +104,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitAutorefsParser {
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStartParser {
const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
const TEMPLATE: AttributeTemplate = template!(List: &["start"]);
@@ -120,7 +118,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEndParser {
const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
const TEMPLATE: AttributeTemplate = template!(List: &["end"]);
@@ -135,7 +132,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
const TEMPLATE: AttributeTemplate = template!(List: &["N"]);
@@ -193,7 +189,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcInheritOverflowChecksParser {
impl<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {
const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]);
const TEMPLATE: AttributeTemplate = template!(Word);
@@ -373,7 +368,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcDeprecatedSafe2024Parser {
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const TEMPLATE: AttributeTemplate = template!(List: &[r#"audit_that = "...""#]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
@@ -441,7 +435,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcNeverTypeOptionsParser {
const PATH: &[Symbol] = &[sym::rustc_never_type_options];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const TEMPLATE: AttributeTemplate = template!(List: &[
r#"fallback = "unit", "never", "no""#,
r#"diverging_block_default = "unit", "never""#,
@@ -592,7 +585,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcLintUntrackedQueryInformationPa
impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser {
const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
@@ -610,7 +602,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
const PATH: &[Symbol] = &[sym::rustc_scalable_vector];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]);
@@ -636,7 +627,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for LangParser {
const PATH: &[Symbol] = &[sym::lang];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes`
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
@@ -981,8 +971,6 @@ fn extend(
impl<S: Stage> SingleAttributeParser<S> for RustcIfThisChangedParser {
const PATH: &[Symbol] = &[sym::rustc_if_this_changed];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
@@ -1147,7 +1135,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEffectiveVisibilityParser {
impl<S: Stage> SingleAttributeParser<S> for RustcDiagnosticItemParser {
const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Trait),
@@ -1220,7 +1207,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcSymbolNameParser {
Allow(Target::Impl { of_trait: false }),
]);
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const TEMPLATE: AttributeTemplate = template!(Word);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
@@ -1245,7 +1231,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcDefPathParser {
Allow(Target::Impl { of_trait: false }),
]);
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const TEMPLATE: AttributeTemplate = template!(Word);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
@@ -1275,7 +1260,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcStrictCoherenceParser {
impl<S: Stage> SingleAttributeParser<S> for RustcReservationImplParser {
const PATH: &[Symbol] = &[sym::rustc_reservation_impl];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]);
@@ -1311,7 +1295,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for PreludeImportParser {
impl<S: Stage> SingleAttributeParser<S> for RustcDocPrimitiveParser {
const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name");
@@ -7,7 +7,6 @@
impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
const PATH: &[Symbol] = &[sym::ignore];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]);
@@ -41,7 +40,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
const PATH: &[Symbol] = &[sym::should_panic];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]);
@@ -98,7 +96,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for ReexportTestHarnessMainParser {
const PATH: &[Symbol] = &[sym::reexport_test_harness_main];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
@@ -126,7 +123,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcAbiParser {
const PATH: &[Symbol] = &[sym::rustc_abi];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::debug, sym::assert_eq]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::TyAlias),
Allow(Target::Fn),
@@ -197,7 +193,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEvaluateWhereClausesParser {
impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser {
const PATH: &[Symbol] = &[sym::test_runner];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate = template!(List: &["path"]);
@@ -226,7 +221,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
impl<S: Stage> SingleAttributeParser<S> for RustcTestMarkerParser {
const PATH: &[Symbol] = &[sym::rustc_test_marker];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Const),
@@ -1,9 +1,7 @@
use std::mem;
use super::prelude::*;
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::attributes::{NoArgsAttributeParser, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::Policy::{Allow, Warn};
@@ -12,7 +10,6 @@
pub(crate) struct RustcSkipDuringMethodDispatchParser;
impl<S: Stage> SingleAttributeParser<S> for RustcSkipDuringMethodDispatchParser {
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
@@ -6,7 +6,6 @@
impl<S: Stage> SingleAttributeParser<S> for RustcMacroTransparencyParser {
const PATH: &[Symbol] = &[sym::rustc_macro_transparency];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| {
cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes");
});
+3 -3
View File
@@ -6,12 +6,12 @@
// Tests the error messages produced (or not produced) by various unusual
// uses of the `#[coverage(..)]` attribute.
#[coverage(off)] //~ ERROR multiple `coverage` attributes
#[coverage(off)]
#[coverage(off)] //~ ERROR multiple `coverage` attributes
fn multiple_consistent() {}
#[coverage(off)] //~ ERROR multiple `coverage` attributes
#[coverage(on)]
#[coverage(off)]
#[coverage(on)] //~ ERROR multiple `coverage` attributes
fn multiple_inconsistent() {}
#[coverage] //~ ERROR malformed `coverage` attribute input
+9 -9
View File
@@ -1,26 +1,26 @@
error: multiple `coverage` attributes
--> $DIR/bad-syntax.rs:9:1
--> $DIR/bad-syntax.rs:10:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/bad-syntax.rs:10:1
--> $DIR/bad-syntax.rs:9:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
error: multiple `coverage` attributes
--> $DIR/bad-syntax.rs:13:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/bad-syntax.rs:14:1
|
LL | #[coverage(on)]
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/bad-syntax.rs:13:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
error[E0539]: malformed `coverage` attribute input
--> $DIR/bad-syntax.rs:17:1
@@ -61,7 +61,7 @@ macro_rules! foo {
fn t1() {}
#[must_use]
#[must_use = "some message"] //~ ERROR unused attribute
#[must_use = "some message"] //~ ERROR unused attribute
//~^ WARN this was previously accepted
// No warnings for #[repr], would require more logic.
#[repr(C)]
@@ -89,15 +89,15 @@ pub fn xyz() {}
#[link(name = "rust_test_helpers", kind = "static")]
#[link(name = "rust_test_helpers", kind = "static")]
extern "C" {
#[link_name = "this_does_not_exist"] //~ ERROR unused attribute
#[link_name = "this_does_not_exist"]
#[link_name = "rust_dbg_extern_identity_u32"] //~ ERROR unused attribute
//~^ WARN this was previously accepted
#[link_name = "rust_dbg_extern_identity_u32"]
pub fn name_in_rust(v: u32) -> u32;
}
#[export_name = "exported_symbol_name"] //~ ERROR unused attribute
#[export_name = "exported_symbol_name"]
#[export_name = "exported_symbol_name2"] //~ ERROR unused attribute
//~^ WARN this was previously accepted
#[export_name = "exported_symbol_name2"]
pub fn export_test() {}
#[no_mangle]
@@ -109,9 +109,9 @@ pub fn no_mangle_test() {}
static FOO: u32 = 0;
#[link_section = ".text"]
#[link_section = ".bss"]
//~^ ERROR unused attribute
//~| WARN this was previously accepted
#[link_section = ".bss"]
pub extern "C" fn example() {}
fn main() {}
@@ -165,29 +165,29 @@ LL | #[track_caller]
| ^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:93:5
|
LL | #[link_name = "rust_dbg_extern_identity_u32"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:92:5
|
LL | #[link_name = "this_does_not_exist"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:94:5
|
LL | #[link_name = "rust_dbg_extern_identity_u32"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:99:1
|
LL | #[export_name = "exported_symbol_name2"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:98:1
|
LL | #[export_name = "exported_symbol_name"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:100:1
|
LL | #[export_name = "exported_symbol_name2"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
@@ -215,16 +215,16 @@ LL | #[used]
| ^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:112:1
|
LL | #[link_section = ".bss"]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:111:1
|
LL | #[link_section = ".text"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:114:1
|
LL | #[link_section = ".bss"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: unused attribute
+3 -3
View File
@@ -4,12 +4,12 @@
#[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input
fn main() {}
#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
#[sanitize(address = "off")]
#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
fn multiple_consistent() {}
#[sanitize(address = "on")] //~ ERROR multiple `sanitize` attributes
#[sanitize(address = "off")]
#[sanitize(address = "on")]
#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
fn multiple_inconsistent() {}
#[sanitize(address = "bogus")] //~ ERROR malformed `sanitize` attribute input
@@ -7,28 +7,28 @@ LL | #[sanitize(brontosaurus = "off")]
| valid arguments are "address", "kernel_address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime"
error: multiple `sanitize` attributes
--> $DIR/invalid-sanitize.rs:7:1
--> $DIR/invalid-sanitize.rs:8:1
|
LL | #[sanitize(address = "off")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-sanitize.rs:8:1
--> $DIR/invalid-sanitize.rs:7:1
|
LL | #[sanitize(address = "off")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: multiple `sanitize` attributes
--> $DIR/invalid-sanitize.rs:11:1
|
LL | #[sanitize(address = "on")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-sanitize.rs:12:1
|
LL | #[sanitize(address = "off")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/invalid-sanitize.rs:11:1
|
LL | #[sanitize(address = "on")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0539]: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:15:1