Skip to content

Use "Innermost" & "Outermost" terminology for AttributeOrder #143659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 10, 2025
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
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) struct OptimizeParser;

impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
const PATH: &[Symbol] = &[sym::optimize];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(List: "size|speed|none");

Expand Down Expand Up @@ -56,7 +56,7 @@ pub(crate) struct ExportNameParser;

impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
const PATH: &[rustc_span::Symbol] = &[sym::export_name];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn get<S: Stage>(

impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
const PATH: &[Symbol] = &[sym::deprecated];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(
Word,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::parser::ArgParser;
pub(crate) struct DummyParser;
impl<S: Stage> SingleAttributeParser<S> for DummyParser {
const PATH: &[Symbol] = &[sym::rustc_dummy];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) struct InlineParser;

impl<S: Stage> SingleAttributeParser<S> for InlineParser {
const PATH: &'static [Symbol] = &[sym::inline];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(Word, List: "always|never");

Expand Down Expand Up @@ -57,7 +57,7 @@ pub(crate) struct RustcForceInlineParser;

impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
const PATH: &'static [Symbol] = &[sym::rustc_force_inline];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(Word, List: "reason", NameValueStr: "reason");

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) struct LinkNameParser;

impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
const PATH: &[Symbol] = &[sym::link_name];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");

Expand All @@ -36,7 +36,7 @@ pub(crate) struct LinkSectionParser;

impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
const PATH: &[Symbol] = &[sym::link_section];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");

Expand Down
39 changes: 13 additions & 26 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,15 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
if let Some(pa) = T::convert(cx, args) {
match T::ATTRIBUTE_ORDER {
// keep the first and report immediately. ignore this attribute
AttributeOrder::KeepFirst => {
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::KeepLast => {
AttributeOrder::KeepOutermost => {
if let Some((_, used)) = group.1 {
T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
}
Expand All @@ -165,9 +165,6 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
}
}

// FIXME(jdonszelmann): logic is implemented but the attribute parsers needing
// them will be merged in another PR
#[allow(unused)]
pub(crate) enum OnDuplicate<S: Stage> {
/// Give a default warning
Warn,
Expand Down Expand Up @@ -213,39 +210,29 @@ impl<S: Stage> OnDuplicate<S> {
}
}
}
//
// FIXME(jdonszelmann): logic is implemented but the attribute parsers needing
// them will be merged in another PR
#[allow(unused)]

pub(crate) enum AttributeOrder {
/// Duplicates after the first attribute will be an error. I.e. only keep the lowest attribute.
/// 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 an error on all the attributes
/// 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")]
/// ```
///
/// This should be used where duplicates would be ignored, but carry extra
/// meaning that could cause confusion. For example, `#[stable(since="1.0")]
/// #[stable(since="2.0")]`, which version should be used for `stable`?
KeepFirst,
KeepInnermost,

/// Duplicates preceding the last instance of the attribute will be a
/// warning, with a note that this will be an error in the future.
/// 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 on all the attributes
/// below the higher one:
/// 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
/// ```
///
/// This is the same as `FutureWarnFollowing`, except the last attribute is
/// the one that is "used". Ideally these can eventually migrate to
/// `ErrorPreceding`.
KeepLast,
KeepOutermost,
}

/// An even simpler version of [`SingleAttributeParser`]:
Expand All @@ -271,7 +258,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> Default for WithoutArgs<T, S> {

impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> {
const PATH: &[Symbol] = T::PATH;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
const TEMPLATE: AttributeTemplate = template!(Word);

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/must_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub(crate) struct MustUseParser;

impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
const PATH: &[Symbol] = &[sym::must_use];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub(crate) struct PathParser;

impl<S: Stage> SingleAttributeParser<S> for PathParser {
const PATH: &[Symbol] = &[sym::path];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "file");

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) struct RustcLayoutScalarValidRangeStart;

impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(List: "start");

Expand All @@ -25,7 +25,7 @@ pub(crate) struct RustcLayoutScalarValidRangeEnd;

impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd {
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(List: "end");

Expand Down Expand Up @@ -62,7 +62,7 @@ pub(crate) struct RustcObjectLifetimeDefaultParser;

impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(Word);

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) struct IgnoreParser;

impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
const PATH: &[Symbol] = &[sym::ignore];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub(crate) struct SkipDuringMethodDispatchParser;

impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;

const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice");
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/transparency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) struct TransparencyParser;
#[allow(rustc::diagnostic_outside_of_impl)]
impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
const PATH: &[Symbol] = &[sym::rustc_macro_transparency];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
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");
});
Expand Down
Loading