@@ -22,6 +22,7 @@ use thin_vec::ThinVec;
2222
2323use crate :: context:: { AcceptContext , FinalizeContext } ;
2424use crate :: parser:: ArgParser ;
25+ use crate :: session_diagnostics:: UnusedMultiple ;
2526
2627pub ( crate ) mod allow_unstable;
2728pub ( crate ) mod cfg;
@@ -74,11 +75,28 @@ pub(crate) trait AttributeParser: Default + 'static {
7475pub ( crate ) trait SingleAttributeParser : ' static {
7576 const PATH : & ' static [ Symbol ] ;
7677
78+ <<<<<<< Conflict 1 of 1
79+ +++++++ Contents of side #1
7780 /// Called when a duplicate attribute is found.
81+ %%%%%%% Changes from base to side #2
82+ + const ON_DUPLICATE_STRATEGY : AttributeDuplicates ;
83+ +
84+ /// Caled when a duplicate attribute is found.
85+ >>>>>>> Conflict 1 of 1 ends
7886 ///
79- /// `first_span` is the span of the first occurrence of this attribute.
87+ /// - `unused` is the span of the attribute that was unused or bad because of some
88+ /// duplicate reason (see [`AttributeDuplicates`])
89+ /// - `used` is the span of the attribute that was used in favor of the unused attribute
8090 // FIXME(jdonszelmann): default error
81- fn on_duplicate ( cx : & AcceptContext < ' _ > , first_span : Span ) ;
91+ fn on_duplicate ( cx : & AcceptContext < ' _ > , used : Span , unused : Span ) {
92+ cx. emit_err( UnusedMultiple {
93+ this : used,
94+ other : unused,
95+ name: Symbol :: intern(
96+ & Self :: PATH . into_iter( ) . map( |i| i. to_string( ) ) . collect :: < Vec < _ > > ( ) . join( ".." ) ,
97+ ) ,
98+ } ) ;
99+ }
82100
83101 /// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
84102 fn convert( cx: & AcceptContext < ' _ > , args: & ArgParser < ' _ > ) -> Option < AttributeKind > ;
@@ -94,12 +112,24 @@ impl<T: SingleAttributeParser> Default for Single<T> {
94112
95113impl <T : SingleAttributeParser > AttributeParser for Single < T > {
96114 const ATTRIBUTES : AcceptMapping < Self > = & [ ( T :: PATH , |group : & mut Single < T > , cx, args| {
97- if let Some ( ( _, s) ) = group. 1 {
98- T :: on_duplicate ( cx, s) ;
99- return ;
100- }
101-
102115 if let Some ( pa) = T :: convert ( cx, args) {
116+ match T :: ON_DUPLICATE_STRATEGY {
117+ // keep the first and error
118+ AttributeDuplicates :: ErrorFollowing => {
119+ if let Some ( ( _, unused) ) = group. 1 {
120+ T :: on_duplicate ( cx, cx. attr_span , unused) ;
121+ return ;
122+ }
123+ }
124+ // keep the new one and warn about the previous,
125+ // then replace
126+ AttributeDuplicates :: FutureWarnPreceding => {
127+ if let Some ( ( _, used) ) = group. 1 {
128+ T :: on_duplicate ( cx, used, cx. attr_span ) ;
129+ }
130+ }
131+ }
132+
103133 group. 1 = Some ( ( pa, cx. attr_span ) ) ;
104134 }
105135 } ) ] ;
@@ -109,6 +139,68 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> {
109139 }
110140}
111141
142+ pub ( crate ) enum OnDuplicate {
143+ /// Give a default warning
144+ Warn,
145+
146+ /// Duplicates will be a warning, with a note that this will be an error in the future.
147+ WarnButFutureError,
148+
149+ /// Give a default error
150+ Error,
151+
152+ /// Ignore duplicates
153+ Ignore,
154+
155+ /// Custom function called when a duplicate attribute is found.
156+ ///
157+ /// - `unused` is the span of the attribute that was unused or bad because of some
158+ /// duplicate reason (see [`AttributeDuplicates`])
159+ /// - `used` is the span of the attribute that was used in favor of the unused attribute
160+ Custom( fn ( cx: & AcceptContext < ' _ > , used : Span , unused : Span ) ) ,
161+ }
162+
163+ impl OnDuplicate {
164+ fn exec< P : SingleAttributeParser > ( & self , cx: & AcceptContext < ' _ > , used: Span , unused: Span ) {
165+ match self {
166+ OnDuplicate :: Warn => {
167+ todo ! ( )
168+ }
169+ OnDuplicate :: WarnButFutureError => {
170+ todo ! ( )
171+ }
172+ OnDuplicate :: Error => {
173+ cx. emit_err( UnusedMultiple {
174+ this : used,
175+ other : unused,
176+ name: Symbol :: intern(
177+ & P :: PATH . into_iter( ) . map( |i| i. to_string( ) ) . collect :: < Vec < _ > > ( ) . join( ".." ) ,
178+ ) ,
179+ } ) ;
180+ }
181+ OnDuplicate :: Ignore => { }
182+ OnDuplicate :: Custom ( f) => f( cx, used, unused) ,
183+ }
184+ }
185+ }
186+
187+ pub ( crate ) enum AttributeDuplicates {
188+ /// Duplicates after the first attribute will be an error.
189+ ///
190+ /// This should be used where duplicates would be ignored, but carry extra
191+ /// meaning that could cause confusion. For example, `#[stable(since="1.0")]
192+ /// #[stable(since="2.0")]`, which version should be used for `stable`?
193+ ErrorFollowing,
194+
195+ /// Duplicates preceding the last instance of the attribute will be a
196+ /// warning, with a note that this will be an error in the future.
197+ ///
198+ /// This is the same as `FutureWarnFollowing`, except the last attribute is
199+ /// the one that is "used". Ideally these can eventually migrate to
200+ /// `ErrorPreceding`.
201+ FutureWarnPreceding,
202+ }
203+
112204type ConvertFn <E > = fn ( ThinVec <E >) -> AttributeKind ;
113205
114206/// Alternative to [`AttributeParser`] that automatically handles state management.
0 commit comments