@@ -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
@@ -98,6 +99,7 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
9899 /// If an attribute has this symbol, the `accept` function will be called on it.
99100 const ATTRIBUTES : AcceptMapping < Self , S > ;
100101 const ALLOWED_TARGETS : AllowedTargets ;
102+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
101103
102104 /// The parser has gotten a chance to accept the attributes on an item,
103105 /// here it can produce an attribute.
@@ -128,6 +130,7 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
128130 /// Configures what to do when when the same attribute is
129131 /// applied more than once on the same syntax node.
130132 const ON_DUPLICATE : OnDuplicate < S > ;
133+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
131134
132135 const ALLOWED_TARGETS : AllowedTargets ;
133136
@@ -166,6 +169,7 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
166169 } ,
167170 ) ] ;
168171 const ALLOWED_TARGETS : AllowedTargets = T :: ALLOWED_TARGETS ;
172+ const SAFETY : AttributeSafety = T :: SAFETY ;
169173
170174 fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
171175 Some ( self . 1 ?. 0 )
@@ -218,6 +222,18 @@ impl<S: Stage> OnDuplicate<S> {
218222 }
219223}
220224
225+ #[ derive( Copy , Clone , PartialEq , Debug ) ]
226+ pub enum AttributeSafety {
227+ /// Normal attribute that does not need `#[unsafe(...)]`
228+ Normal ,
229+ /// Unsafe attribute that requires safety obligations to be discharged.
230+ ///
231+ /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition
232+ /// is less than the one stored in `unsafe_since`. This handles attributes that were safe in
233+ /// earlier editions, but become unsafe in later ones.
234+ Unsafe { unsafe_since : Option < Edition > } ,
235+ }
236+
221237/// An even simpler version of [`SingleAttributeParser`]:
222238/// now automatically check that there are no arguments provided to the attribute.
223239///
@@ -227,6 +243,7 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
227243 const PATH : & [ Symbol ] ;
228244 const ON_DUPLICATE : OnDuplicate < S > ;
229245 const ALLOWED_TARGETS : AllowedTargets ;
246+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
230247
231248 /// Create the [`AttributeKind`] given attribute's [`Span`].
232249 const CREATE : fn ( Span ) -> AttributeKind ;
@@ -243,6 +260,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> Default for WithoutArgs<T, S> {
243260impl < T : NoArgsAttributeParser < S > , S : Stage > SingleAttributeParser < S > for WithoutArgs < T , S > {
244261 const PATH : & [ Symbol ] = T :: PATH ;
245262 const ON_DUPLICATE : OnDuplicate < S > = T :: ON_DUPLICATE ;
263+ const SAFETY : AttributeSafety = T :: SAFETY ;
246264 const ALLOWED_TARGETS : AllowedTargets = T :: ALLOWED_TARGETS ;
247265 const TEMPLATE : AttributeTemplate = template ! ( Word ) ;
248266
@@ -272,6 +290,7 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
272290 /// For example, individual representations from `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`,
273291 /// where `x` is a vec of these individual reprs.
274292 const CONVERT : ConvertFn < Self :: Item > ;
293+ const SAFETY : AttributeSafety = AttributeSafety :: Normal ;
275294
276295 const ALLOWED_TARGETS : AllowedTargets ;
277296
@@ -313,6 +332,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
313332 group. items . extend ( T :: extend ( cx, args) )
314333 } ) ] ;
315334 const ALLOWED_TARGETS : AllowedTargets = T :: ALLOWED_TARGETS ;
335+ const SAFETY : AttributeSafety = T :: SAFETY ;
316336
317337 fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
318338 if let Some ( first_span) = self . first_span {
0 commit comments