@@ -124,13 +124,11 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
124124///
125125/// - `#[stable]`
126126/// - `#[unstable]`
127- /// - `#[rustc_deprecated]`
128127#[ derive( RustcEncodable , RustcDecodable , Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
129128#[ derive( HashStable_Generic ) ]
130129pub struct Stability {
131130 pub level : StabilityLevel ,
132131 pub feature : Symbol ,
133- pub rustc_depr : Option < RustcDeprecation > ,
134132}
135133
136134/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
@@ -163,15 +161,6 @@ impl StabilityLevel {
163161 }
164162}
165163
166- #[ derive( RustcEncodable , RustcDecodable , PartialEq , PartialOrd , Copy , Clone , Debug , Eq , Hash ) ]
167- #[ derive( HashStable_Generic ) ]
168- pub struct RustcDeprecation {
169- pub since : Symbol ,
170- pub reason : Symbol ,
171- /// A text snippet used to completely replace any use of the deprecated item in an expression.
172- pub suggestion : Option < Symbol > ,
173- }
174-
175164/// Checks if `attrs` contains an attribute like `#![feature(feature_name)]`.
176165/// This will not perform any "sanity checks" on the form of the attributes.
177166pub fn contains_feature_attr ( attrs : & [ Attribute ] , feature_name : Symbol ) -> bool {
@@ -205,15 +194,13 @@ where
205194 use StabilityLevel :: * ;
206195
207196 let mut stab: Option < Stability > = None ;
208- let mut rustc_depr: Option < RustcDeprecation > = None ;
209197 let mut const_stab: Option < ConstStability > = None ;
210198 let mut promotable = false ;
211199 let mut allow_const_fn_ptr = false ;
212200 let diagnostic = & sess. span_diagnostic ;
213201
214202 ' outer: for attr in attrs_iter {
215203 if ![
216- sym:: rustc_deprecated,
217204 sym:: rustc_const_unstable,
218205 sym:: rustc_const_stable,
219206 sym:: unstable,
@@ -258,76 +245,8 @@ where
258245 }
259246 } ;
260247
261- macro_rules! get_meta {
262- ( $( $name: ident) ,+) => {
263- $(
264- let mut $name = None ;
265- ) +
266- for meta in metas {
267- if let Some ( mi) = meta. meta_item( ) {
268- match mi. name_or_empty( ) {
269- $(
270- sym:: $name => if !get( mi, & mut $name) { continue ' outer } ,
271- ) +
272- _ => {
273- let expected = & [ $( stringify!( $name) ) ,+ ] ;
274- handle_errors(
275- sess,
276- mi. span,
277- AttrError :: UnknownMetaItem (
278- pprust:: path_to_string( & mi. path) ,
279- expected,
280- ) ,
281- ) ;
282- continue ' outer
283- }
284- }
285- } else {
286- handle_errors(
287- sess,
288- meta. span( ) ,
289- AttrError :: UnsupportedLiteral (
290- "unsupported literal" ,
291- false ,
292- ) ,
293- ) ;
294- continue ' outer
295- }
296- }
297- }
298- }
299-
300248 let meta_name = meta. name_or_empty ( ) ;
301249 match meta_name {
302- sym:: rustc_deprecated => {
303- if rustc_depr. is_some ( ) {
304- struct_span_err ! (
305- diagnostic,
306- item_sp,
307- E0540 ,
308- "multiple rustc_deprecated attributes"
309- )
310- . emit ( ) ;
311- continue ' outer;
312- }
313-
314- get_meta ! ( since, reason, suggestion) ;
315-
316- match ( since, reason) {
317- ( Some ( since) , Some ( reason) ) => {
318- rustc_depr = Some ( RustcDeprecation { since, reason, suggestion } )
319- }
320- ( None , _) => {
321- handle_errors ( sess, attr. span , AttrError :: MissingSince ) ;
322- continue ;
323- }
324- _ => {
325- struct_span_err ! ( diagnostic, attr. span, E0543 , "missing 'reason'" )
326- . emit ( ) ;
327- continue ;
328- }
329- }
330- }
331250 sym:: rustc_const_unstable | sym:: unstable => {
332251 if meta_name == sym:: unstable && stab. is_some ( ) {
333252 handle_errors ( sess, attr. span , AttrError :: MultipleStabilityLevels ) ;
@@ -429,7 +348,7 @@ where
429348 ( Some ( feature) , reason, Some ( _) ) => {
430349 let level = Unstable { reason, issue : issue_num, is_soft } ;
431350 if sym:: unstable == meta_name {
432- stab = Some ( Stability { level, feature, rustc_depr : None } ) ;
351+ stab = Some ( Stability { level, feature } ) ;
433352 } else {
434353 const_stab = Some ( ConstStability {
435354 level,
@@ -501,7 +420,7 @@ where
501420 ( Some ( feature) , Some ( since) ) => {
502421 let level = Stable { since } ;
503422 if sym:: stable == meta_name {
504- stab = Some ( Stability { level, feature, rustc_depr : None } ) ;
423+ stab = Some ( Stability { level, feature } ) ;
505424 } else {
506425 const_stab = Some ( ConstStability {
507426 level,
@@ -526,22 +445,6 @@ where
526445 }
527446 }
528447
529- // Merge the deprecation info into the stability info
530- if let Some ( rustc_depr) = rustc_depr {
531- if let Some ( ref mut stab) = stab {
532- stab. rustc_depr = Some ( rustc_depr) ;
533- } else {
534- struct_span_err ! (
535- diagnostic,
536- item_sp,
537- E0549 ,
538- "rustc_deprecated attribute must be paired with \
539- either stable or unstable attribute"
540- )
541- . emit ( ) ;
542- }
543- }
544-
545448 // Merge the const-unstable info into the stability info
546449 if promotable || allow_const_fn_ptr {
547450 if let Some ( ref mut stab) = const_stab {
@@ -714,7 +617,16 @@ pub fn eval_condition(
714617#[ derive( RustcEncodable , RustcDecodable , Clone , HashStable_Generic ) ]
715618pub struct Deprecation {
716619 pub since : Option < Symbol > ,
620+ /// The note to issue a reason.
717621 pub note : Option < Symbol > ,
622+ /// A text snippet used to completely replace any use of the deprecated item in an expression.
623+ ///
624+ /// This is currently unstable.
625+ pub suggestion : Option < Symbol > ,
626+
627+ /// Whether to treat the since attribute as being a Rust version identifier
628+ /// (rather than an opaque string).
629+ pub is_since_rustc_version : bool ,
718630}
719631
720632/// Finds the deprecation attribute. `None` if none exists.
@@ -738,7 +650,7 @@ where
738650 let diagnostic = & sess. span_diagnostic ;
739651
740652 ' outer: for attr in attrs_iter {
741- if !attr. check_name ( sym:: deprecated) {
653+ if !( attr. check_name ( sym:: deprecated) || attr . check_name ( sym :: rustc_deprecated ) ) {
742654 continue ;
743655 }
744656
@@ -751,11 +663,12 @@ where
751663 Some ( meta) => meta,
752664 None => continue ,
753665 } ;
754- depr = match & meta. kind {
755- MetaItemKind :: Word => Some ( Deprecation { since : None , note : None } ) ,
756- MetaItemKind :: NameValue ( ..) => {
757- meta. value_str ( ) . map ( |note| Deprecation { since : None , note : Some ( note) } )
758- }
666+ let mut since = None ;
667+ let mut note = None ;
668+ let mut suggestion = None ;
669+ match & meta. kind {
670+ MetaItemKind :: Word => { }
671+ MetaItemKind :: NameValue ( ..) => note = meta. value_str ( ) ,
759672 MetaItemKind :: List ( list) => {
760673 let get = |meta : & MetaItem , item : & mut Option < Symbol > | {
761674 if item. is_some ( ) {
@@ -789,8 +702,6 @@ where
789702 }
790703 } ;
791704
792- let mut since = None ;
793- let mut note = None ;
794705 for meta in list {
795706 match meta {
796707 NestedMetaItem :: MetaItem ( mi) => match mi. name_or_empty ( ) {
@@ -799,18 +710,32 @@ where
799710 continue ' outer;
800711 }
801712 }
802- sym:: note => {
713+ sym:: note if attr. check_name ( sym:: deprecated) => {
714+ if !get ( mi, & mut note) {
715+ continue ' outer;
716+ }
717+ }
718+ sym:: reason if attr. check_name ( sym:: rustc_deprecated) => {
803719 if !get ( mi, & mut note) {
804720 continue ' outer;
805721 }
806722 }
723+ sym:: suggestion if attr. check_name ( sym:: rustc_deprecated) => {
724+ if !get ( mi, & mut suggestion) {
725+ continue ' outer;
726+ }
727+ }
807728 _ => {
808729 handle_errors (
809730 sess,
810731 meta. span ( ) ,
811732 AttrError :: UnknownMetaItem (
812733 pprust:: path_to_string ( & mi. path ) ,
813- & [ "since" , "note" ] ,
734+ if attr. check_name ( sym:: deprecated) {
735+ & [ "since" , "note" ]
736+ } else {
737+ & [ "since" , "reason" , "suggestion" ]
738+ } ,
814739 ) ,
815740 ) ;
816741 continue ' outer;
@@ -829,10 +754,29 @@ where
829754 }
830755 }
831756 }
757+ }
758+ }
759+
760+ if suggestion. is_some ( ) && attr. check_name ( sym:: deprecated) {
761+ unreachable ! ( "only allowed on rustc_deprecated" )
762+ }
832763
833- Some ( Deprecation { since, note } )
764+ if attr. check_name ( sym:: rustc_deprecated) {
765+ if since. is_none ( ) {
766+ handle_errors ( sess, attr. span , AttrError :: MissingSince ) ;
767+ continue ;
834768 }
835- } ;
769+
770+ if note. is_none ( ) {
771+ struct_span_err ! ( diagnostic, attr. span, E0543 , "missing 'reason'" ) . emit ( ) ;
772+ continue ;
773+ }
774+ }
775+
776+ mark_used ( & attr) ;
777+
778+ let is_since_rustc_version = attr. check_name ( sym:: rustc_deprecated) ;
779+ depr = Some ( Deprecation { since, note, suggestion, is_since_rustc_version } ) ;
836780 }
837781
838782 depr
0 commit comments