@@ -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;
@@ -74,11 +75,28 @@ pub(crate) trait AttributeParser: Default + 'static {
74
75
pub ( crate ) trait SingleAttributeParser : ' static {
75
76
const PATH : & ' static [ Symbol ] ;
76
77
78
+ <<<<<<< Conflict 1 of 1
79
+ +++++++ Contents of side #1
77
80
/// 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
78
86
///
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
80
90
// 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
+ }
82
100
83
101
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
84
102
fn convert( cx: & AcceptContext < ' _ > , args: & ArgParser < ' _ > ) -> Option < AttributeKind > ;
@@ -94,12 +112,24 @@ impl<T: SingleAttributeParser> Default for Single<T> {
94
112
95
113
impl <T : SingleAttributeParser > AttributeParser for Single < T > {
96
114
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
-
102
115
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
+
103
133
group. 1 = Some ( ( pa, cx. attr_span ) ) ;
104
134
}
105
135
} ) ] ;
@@ -109,6 +139,68 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> {
109
139
}
110
140
}
111
141
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
+
112
204
type ConvertFn <E > = fn ( ThinVec <E >) -> AttributeKind ;
113
205
114
206
/// Alternative to [`AttributeParser`] that automatically handles state management.
0 commit comments