@@ -18,6 +18,7 @@ use std::marker::PhantomData;
1818
1919use rustc_feature:: { AttributeTemplate , template} ;
2020use rustc_hir:: attrs:: AttributeKind ;
21+ use rustc_span:: edition:: Edition ;
2122use rustc_span:: { Span , Symbol } ;
2223use thin_vec:: ThinVec ;
2324
@@ -97,6 +98,7 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
9798 /// If an attribute has this symbol, the `accept` function will be called on it.
9899 const ATTRIBUTES : AcceptMapping < Self , S > ;
99100 const ALLOWED_TARGETS : AllowedTargets ;
101+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
100102
101103 /// The parser has gotten a chance to accept the attributes on an item,
102104 /// here it can produce an attribute.
@@ -127,6 +129,7 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
127129 /// Configures what to do when when the same attribute is
128130 /// applied more than once on the same syntax node.
129131 const ON_DUPLICATE : OnDuplicate < S > ;
132+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
130133
131134 const ALLOWED_TARGETS : AllowedTargets ;
132135
@@ -165,6 +168,7 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
165168 } ,
166169 ) ] ;
167170 const ALLOWED_TARGETS : AllowedTargets = T :: ALLOWED_TARGETS ;
171+ const SAFETY : AttributeSafety = T :: SAFETY ;
168172
169173 fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
170174 Some ( self . 1 ?. 0 )
@@ -217,6 +221,18 @@ impl<S: Stage> OnDuplicate<S> {
217221 }
218222}
219223
224+ #[ derive( Copy , Clone , PartialEq , Debug ) ]
225+ pub enum AttributeSafety {
226+ /// Normal attribute that does not need `#[unsafe(...)]`
227+ Normal ,
228+ /// Unsafe attribute that requires safety obligations to be discharged.
229+ ///
230+ /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition
231+ /// is less than the one stored in `unsafe_since`. This handles attributes that were safe in
232+ /// earlier editions, but become unsafe in later ones.
233+ Unsafe { unsafe_since : Option < Edition > } ,
234+ }
235+
220236/// An even simpler version of [`SingleAttributeParser`]:
221237/// now automatically check that there are no arguments provided to the attribute.
222238///
@@ -226,6 +242,7 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
226242 const PATH : & [ Symbol ] ;
227243 const ON_DUPLICATE : OnDuplicate < S > ;
228244 const ALLOWED_TARGETS : AllowedTargets ;
245+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
229246
230247 /// Create the [`AttributeKind`] given attribute's [`Span`].
231248 const CREATE : fn ( Span ) -> AttributeKind ;
@@ -242,6 +259,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> Default for WithoutArgs<T, S> {
242259impl < T : NoArgsAttributeParser < S > , S : Stage > SingleAttributeParser < S > for WithoutArgs < T , S > {
243260 const PATH : & [ Symbol ] = T :: PATH ;
244261 const ON_DUPLICATE : OnDuplicate < S > = T :: ON_DUPLICATE ;
262+ const SAFETY : AttributeSafety = T :: SAFETY ;
245263 const ALLOWED_TARGETS : AllowedTargets = T :: ALLOWED_TARGETS ;
246264 const TEMPLATE : AttributeTemplate = template ! ( Word ) ;
247265
@@ -271,6 +289,7 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
271289 /// For example, individual representations from `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`,
272290 /// where `x` is a vec of these individual reprs.
273291 const CONVERT : ConvertFn < Self :: Item > ;
292+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
274293
275294 const ALLOWED_TARGETS : AllowedTargets ;
276295
@@ -312,6 +331,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
312331 group. items . extend ( T :: extend ( cx, args) )
313332 } ) ] ;
314333 const ALLOWED_TARGETS : AllowedTargets = T :: ALLOWED_TARGETS ;
334+ const SAFETY : AttributeSafety = T :: SAFETY ;
315335
316336 fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
317337 if let Some ( first_span) = self . first_span {
0 commit comments