diff options
| author | Jana Dönszelmann <jana@donsz.nl> | 2025-06-10 13:00:09 +0200 |
|---|---|---|
| committer | Jana Dönszelmann <jana@donsz.nl> | 2025-06-12 09:42:45 +0200 |
| commit | 28bf61b9b32a2db0a9a7f32d75349b4e0db72201 (patch) | |
| tree | 500de2761dc6e0ce93d1bf56abb3a28bc288a5b3 /compiler/rustc_attr_parsing/src/attributes/mod.rs | |
| parent | fe5c95d4ae33ec9d7831921e448e2daf8264ea42 (diff) | |
| download | rust-28bf61b9b32a2db0a9a7f32d75349b4e0db72201.tar.gz rust-28bf61b9b32a2db0a9a7f32d75349b4e0db72201.zip | |
introduce duplicate attribute diagnostic logic
Diffstat (limited to 'compiler/rustc_attr_parsing/src/attributes/mod.rs')
| -rw-r--r-- | compiler/rustc_attr_parsing/src/attributes/mod.rs | 106 |
1 files changed, 99 insertions, 7 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 7cceca3c24d..7aac4744504 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -22,6 +22,7 @@ use thin_vec::ThinVec; use crate::context::{AcceptContext, FinalizeContext}; use crate::parser::ArgParser; +use crate::session_diagnostics::UnusedMultiple; pub(crate) mod allow_unstable; pub(crate) mod cfg; @@ -83,11 +84,28 @@ pub(crate) trait AttributeParser: Default + 'static { pub(crate) trait SingleAttributeParser: 'static { const PATH: &'static [Symbol]; +<<<<<<< Conflict 1 of 1 ++++++++ Contents of side #1 /// Called when a duplicate attribute is found. +%%%%%%% Changes from base to side #2 ++ const ON_DUPLICATE_STRATEGY: AttributeDuplicates; ++ + /// Caled when a duplicate attribute is found. +>>>>>>> Conflict 1 of 1 ends /// - /// `first_span` is the span of the first occurrence of this attribute. + /// - `unused` is the span of the attribute that was unused or bad because of some + /// duplicate reason (see [`AttributeDuplicates`]) + /// - `used` is the span of the attribute that was used in favor of the unused attribute // FIXME(jdonszelmann): default error - fn on_duplicate(cx: &AcceptContext<'_>, first_span: Span); + fn on_duplicate(cx: &AcceptContext<'_>, used: Span, unused: Span) { + cx.emit_err(UnusedMultiple { + this: used, + other: unused, + name: Symbol::intern( + &Self::PATH.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(".."), + ), + }); + } /// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`] fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind>; @@ -103,12 +121,24 @@ impl<T: SingleAttributeParser> Default for Single<T> { impl<T: SingleAttributeParser> AttributeParser for Single<T> { const ATTRIBUTES: AcceptMapping<Self> = &[(T::PATH, |group: &mut Single<T>, cx, args| { - if let Some((_, s)) = group.1 { - T::on_duplicate(cx, s); - return; - } - if let Some(pa) = T::convert(cx, args) { + match T::ON_DUPLICATE_STRATEGY { + // keep the first and error + AttributeDuplicates::ErrorFollowing => { + if let Some((_, unused)) = group.1 { + T::on_duplicate(cx, cx.attr_span, unused); + return; + } + } + // keep the new one and warn about the previous, + // then replace + AttributeDuplicates::FutureWarnPreceding => { + if let Some((_, used)) = group.1 { + T::on_duplicate(cx, used, cx.attr_span); + } + } + } + group.1 = Some((pa, cx.attr_span)); } })]; @@ -118,6 +148,68 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> { } } +pub(crate) enum OnDuplicate { + /// Give a default warning + Warn, + + /// Duplicates will be a warning, with a note that this will be an error in the future. + WarnButFutureError, + + /// Give a default error + Error, + + /// Ignore duplicates + Ignore, + + /// 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 [`AttributeDuplicates`]) + /// - `used` is the span of the attribute that was used in favor of the unused attribute + Custom(fn(cx: &AcceptContext<'_>, used: Span, unused: Span)), +} + +impl OnDuplicate { + fn exec<P: SingleAttributeParser>(&self, cx: &AcceptContext<'_>, used: Span, unused: Span) { + match self { + OnDuplicate::Warn => { + todo!() + } + OnDuplicate::WarnButFutureError => { + todo!() + } + OnDuplicate::Error => { + cx.emit_err(UnusedMultiple { + this: used, + other: unused, + name: Symbol::intern( + &P::PATH.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(".."), + ), + }); + } + OnDuplicate::Ignore => {} + OnDuplicate::Custom(f) => f(cx, used, unused), + } + } +} + +pub(crate) enum AttributeDuplicates { + /// Duplicates after the first attribute will be an error. + /// + /// 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`? + ErrorFollowing, + + /// Duplicates preceding the last instance of the attribute will be a + /// warning, with a note that this will be an error in the future. + /// + /// This is the same as `FutureWarnFollowing`, except the last attribute is + /// the one that is "used". Ideally these can eventually migrate to + /// `ErrorPreceding`. + FutureWarnPreceding, +} + type ConvertFn<E> = fn(ThinVec<E>) -> AttributeKind; /// Alternative to [`AttributeParser`] that automatically handles state management. |
