@@ -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;
@@ -83,11 +84,28 @@ pub(crate) trait AttributeParser: Default + 'static {
8384pub ( crate ) trait SingleAttributeParser : ' static {
8485 const PATH : & ' static [ Symbol ] ;
8586
87+ <<<<<<< Conflict 1 of 1
88+ +++++++ Contents of side #1
8689 /// Called when a duplicate attribute is found.
90+ %%%%%%% Changes from base to side #2
91+ + const ON_DUPLICATE_STRATEGY : AttributeDuplicates ;
92+ +
93+ /// Caled when a duplicate attribute is found.
94+ >>>>>>> Conflict 1 of 1 ends
8795 ///
88- /// `first_span` is the span of the first occurrence of this attribute.
96+ /// - `unused` is the span of the attribute that was unused or bad because of some
97+ /// duplicate reason (see [`AttributeDuplicates`])
98+ /// - `used` is the span of the attribute that was used in favor of the unused attribute
8999 // FIXME(jdonszelmann): default error
90- fn on_duplicate ( cx : & AcceptContext < ' _ > , first_span : Span ) ;
100+ fn on_duplicate ( cx : & AcceptContext < ' _ > , used : Span , unused : Span ) {
101+ cx. emit_err( UnusedMultiple {
102+ this : used,
103+ other : unused,
104+ name: Symbol :: intern(
105+ & Self :: PATH . into_iter( ) . map( |i| i. to_string( ) ) . collect :: < Vec < _ > > ( ) . join( ".." ) ,
106+ ) ,
107+ } ) ;
108+ }
91109
92110 /// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
93111 fn convert( cx: & AcceptContext < ' _ > , args: & ArgParser < ' _ > ) -> Option < AttributeKind > ;
@@ -103,12 +121,24 @@ impl<T: SingleAttributeParser> Default for Single<T> {
103121
104122impl <T : SingleAttributeParser > AttributeParser for Single < T > {
105123 const ATTRIBUTES : AcceptMapping < Self > = & [ ( T :: PATH , |group : & mut Single < T > , cx, args| {
106- if let Some ( ( _, s) ) = group. 1 {
107- T :: on_duplicate ( cx, s) ;
108- return ;
109- }
110-
111124 if let Some ( pa) = T :: convert ( cx, args) {
125+ match T :: ON_DUPLICATE_STRATEGY {
126+ // keep the first and error
127+ AttributeDuplicates :: ErrorFollowing => {
128+ if let Some ( ( _, unused) ) = group. 1 {
129+ T :: on_duplicate ( cx, cx. attr_span , unused) ;
130+ return ;
131+ }
132+ }
133+ // keep the new one and warn about the previous,
134+ // then replace
135+ AttributeDuplicates :: FutureWarnPreceding => {
136+ if let Some ( ( _, used) ) = group. 1 {
137+ T :: on_duplicate ( cx, used, cx. attr_span ) ;
138+ }
139+ }
140+ }
141+
112142 group. 1 = Some ( ( pa, cx. attr_span ) ) ;
113143 }
114144 } ) ] ;
@@ -118,6 +148,68 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> {
118148 }
119149}
120150
151+ pub ( crate ) enum OnDuplicate {
152+ /// Give a default warning
153+ Warn,
154+
155+ /// Duplicates will be a warning, with a note that this will be an error in the future.
156+ WarnButFutureError,
157+
158+ /// Give a default error
159+ Error,
160+
161+ /// Ignore duplicates
162+ Ignore,
163+
164+ /// Custom function called when a duplicate attribute is found.
165+ ///
166+ /// - `unused` is the span of the attribute that was unused or bad because of some
167+ /// duplicate reason (see [`AttributeDuplicates`])
168+ /// - `used` is the span of the attribute that was used in favor of the unused attribute
169+ Custom( fn ( cx: & AcceptContext < ' _ > , used : Span , unused : Span ) ) ,
170+ }
171+
172+ impl OnDuplicate {
173+ fn exec< P : SingleAttributeParser > ( & self , cx: & AcceptContext < ' _ > , used: Span , unused: Span ) {
174+ match self {
175+ OnDuplicate :: Warn => {
176+ todo ! ( )
177+ }
178+ OnDuplicate :: WarnButFutureError => {
179+ todo ! ( )
180+ }
181+ OnDuplicate :: Error => {
182+ cx. emit_err( UnusedMultiple {
183+ this : used,
184+ other : unused,
185+ name: Symbol :: intern(
186+ & P :: PATH . into_iter( ) . map( |i| i. to_string( ) ) . collect :: < Vec < _ > > ( ) . join( ".." ) ,
187+ ) ,
188+ } ) ;
189+ }
190+ OnDuplicate :: Ignore => { }
191+ OnDuplicate :: Custom ( f) => f( cx, used, unused) ,
192+ }
193+ }
194+ }
195+
196+ pub ( crate ) enum AttributeDuplicates {
197+ /// Duplicates after the first attribute will be an error.
198+ ///
199+ /// This should be used where duplicates would be ignored, but carry extra
200+ /// meaning that could cause confusion. For example, `#[stable(since="1.0")]
201+ /// #[stable(since="2.0")]`, which version should be used for `stable`?
202+ ErrorFollowing,
203+
204+ /// Duplicates preceding the last instance of the attribute will be a
205+ /// warning, with a note that this will be an error in the future.
206+ ///
207+ /// This is the same as `FutureWarnFollowing`, except the last attribute is
208+ /// the one that is "used". Ideally these can eventually migrate to
209+ /// `ErrorPreceding`.
210+ FutureWarnPreceding,
211+ }
212+
121213type ConvertFn <E > = fn ( ThinVec <E >) -> AttributeKind ;
122214
123215/// Alternative to [`AttributeParser`] that automatically handles state management.
0 commit comments