@@ -22,6 +22,7 @@ use thin_vec::ThinVec;
22
22
23
23
use crate :: context:: { AcceptContext , FinalizeContext } ;
24
24
use crate :: parser:: ArgParser ;
25
+ use crate :: session_diagnostics:: UnusedMultiple ;
25
26
26
27
pub ( crate ) mod allow_unstable;
27
28
pub ( crate ) mod cfg;
@@ -83,11 +84,28 @@ pub(crate) trait AttributeParser: Default + 'static {
83
84
pub ( crate ) trait SingleAttributeParser : ' static {
84
85
const PATH : & ' static [ Symbol ] ;
85
86
87
+ <<<<<<< Conflict 1 of 1
88
+ +++++++ Contents of side #1
86
89
/// 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
87
95
///
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
89
99
// 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
+ }
91
109
92
110
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
93
111
fn convert( cx: & AcceptContext < ' _ > , args: & ArgParser < ' _ > ) -> Option < AttributeKind > ;
@@ -103,12 +121,24 @@ impl<T: SingleAttributeParser> Default for Single<T> {
103
121
104
122
impl <T : SingleAttributeParser > AttributeParser for Single < T > {
105
123
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
-
111
124
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
+
112
142
group. 1 = Some ( ( pa, cx. attr_span ) ) ;
113
143
}
114
144
} ) ] ;
@@ -118,6 +148,68 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> {
118
148
}
119
149
}
120
150
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
+
121
213
type ConvertFn <E > = fn ( ThinVec <E >) -> AttributeKind ;
122
214
123
215
/// Alternative to [`AttributeParser`] that automatically handles state management.
0 commit comments