@@ -9,6 +9,7 @@ use rustc_session::parse::{feature_err, ParseSess};
9
9
use rustc_session:: Session ;
10
10
use rustc_span:: hygiene:: Transparency ;
11
11
use rustc_span:: { symbol:: sym, symbol:: Symbol , Span } ;
12
+ use std:: fmt;
12
13
use std:: num:: NonZeroU32 ;
13
14
14
15
pub fn is_builtin_attr ( attr : & Attribute ) -> bool {
@@ -18,7 +19,7 @@ pub fn is_builtin_attr(attr: &Attribute) -> bool {
18
19
enum AttrError {
19
20
MultipleItem ( String ) ,
20
21
UnknownMetaItem ( String , & ' static [ & ' static str ] ) ,
21
- MissingSince ,
22
+ InvalidSince ,
22
23
NonIdentFeature ,
23
24
MissingFeature ,
24
25
MultipleStabilityLevels ,
@@ -37,8 +38,8 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
37
38
. span_label ( span, format ! ( "expected one of {}" , expected. join( ", " ) ) )
38
39
. emit ( ) ;
39
40
}
40
- AttrError :: MissingSince => {
41
- struct_span_err ! ( diag, span, E0542 , "missing 'since'" ) . emit ( ) ;
41
+ AttrError :: InvalidSince => {
42
+ struct_span_err ! ( diag, span, E0542 , "invalid 'since'" ) . emit ( ) ;
42
43
}
43
44
AttrError :: NonIdentFeature => {
44
45
struct_span_err ! ( diag, span, E0546 , "'feature' is not an identifier" ) . emit ( ) ;
@@ -158,7 +159,7 @@ pub struct ConstStability {
158
159
pub enum StabilityLevel {
159
160
// Reason for the current stability level and the relevant rust-lang issue
160
161
Unstable { reason : Option < Symbol > , issue : Option < NonZeroU32 > , is_soft : bool } ,
161
- Stable { since : Symbol } ,
162
+ Stable { since : Version } ,
162
163
}
163
164
164
165
impl StabilityLevel {
@@ -428,7 +429,7 @@ where
428
429
}
429
430
}
430
431
431
- match ( feature, since) {
432
+ match ( feature, since. and_then ( |s| parse_version ( & s . as_str ( ) , false ) ) ) {
432
433
( Some ( feature) , Some ( since) ) => {
433
434
let level = Stable { since } ;
434
435
if sym:: stable == meta_name {
@@ -443,7 +444,7 @@ where
443
444
continue ;
444
445
}
445
446
_ => {
446
- handle_errors ( & sess. parse_sess , attr. span , AttrError :: MissingSince ) ;
447
+ handle_errors ( & sess. parse_sess , attr. span , AttrError :: InvalidSince ) ;
447
448
continue ;
448
449
}
449
450
}
@@ -525,11 +526,18 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
525
526
}
526
527
}
527
528
528
- #[ derive( Clone , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
529
- struct Version {
530
- major : u16 ,
531
- minor : u16 ,
532
- patch : u16 ,
529
+ #[ derive( Encodable , Decodable , Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
530
+ #[ derive( HashStable_Generic ) ]
531
+ pub struct Version {
532
+ major : u8 ,
533
+ minor : u8 ,
534
+ patch : u8 ,
535
+ }
536
+
537
+ impl fmt:: Display for Version {
538
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
539
+ write ! ( f, "{}.{}.{}" , self . major, self . minor, self . patch)
540
+ }
533
541
}
534
542
535
543
fn parse_version ( s : & str , allow_appendix : bool ) -> Option < Version > {
@@ -648,30 +656,56 @@ pub fn eval_condition(
648
656
}
649
657
650
658
#[ derive( Debug , Encodable , Decodable , Clone , HashStable_Generic ) ]
651
- pub struct Deprecation {
652
- pub since : Option < Symbol > ,
653
- /// The note to issue a reason.
654
- pub note : Option < Symbol > ,
655
- /// A text snippet used to completely replace any use of the deprecated item in an expression.
656
- ///
657
- /// This is currently unstable.
658
- pub suggestion : Option < Symbol > ,
659
-
660
- /// Whether to treat the since attribute as being a Rust version identifier
661
- /// (rather than an opaque string).
662
- pub is_since_rustc_version : bool ,
659
+ pub enum DeprKind {
660
+ /// The stable #[deprecated] attribute
661
+ Deprecated {
662
+ /// Opaque, unvalidated string
663
+ since : Option < Symbol > ,
664
+ /// Note displayed alongside deprecation warning
665
+ note : Option < Symbol > ,
666
+ } ,
667
+ /// The compiler-only #[rustc_deprecated] attribute
668
+ RustcDeprecated {
669
+ /// Whether or not the deprecation is currently in effect,
670
+ /// i.e. whether `since` is at least the current Rust version.
671
+ now : bool ,
672
+ /// `None` if `since="TBD"`, otherwise a Rust version triple "X.Y.Z"
673
+ since : Option < Version > ,
674
+ /// Note displayed alongside deprecation warning
675
+ note : Symbol ,
676
+ /// A text snippet used to completely replace any use
677
+ /// of the deprecated item in an expression.
678
+ /// Currently unstable.
679
+ suggestion : Option < Symbol > ,
680
+ } ,
681
+ }
682
+
683
+ impl DeprKind {
684
+ pub fn note ( & self ) -> Option < Symbol > {
685
+ match * self {
686
+ Self :: Deprecated { note, .. } => note,
687
+ Self :: RustcDeprecated { note, .. } => Some ( note) ,
688
+ }
689
+ }
690
+
691
+ pub fn suggestion ( & self ) -> Option < Symbol > {
692
+ match * self {
693
+ Self :: Deprecated { .. } => None ,
694
+ Self :: RustcDeprecated { suggestion, .. } => suggestion,
695
+ }
696
+ }
663
697
}
664
698
665
699
/// Finds the deprecation attribute. `None` if none exists.
666
- pub fn find_deprecation ( sess : & Session , attrs : & [ Attribute ] ) -> Option < ( Deprecation , Span ) > {
700
+ pub fn find_deprecation ( sess : & Session , attrs : & [ Attribute ] ) -> Option < ( DeprKind , Span ) > {
667
701
find_deprecation_generic ( sess, attrs. iter ( ) )
668
702
}
669
703
670
- fn find_deprecation_generic < ' a , I > ( sess : & Session , attrs_iter : I ) -> Option < ( Deprecation , Span ) >
704
+ fn find_deprecation_generic < ' a , I > ( sess : & Session , attrs_iter : I ) -> Option < ( DeprKind , Span ) >
671
705
where
672
706
I : Iterator < Item = & ' a Attribute > ,
673
707
{
674
- let mut depr: Option < ( Deprecation , Span ) > = None ;
708
+ let mut depr: Option < ( DeprKind , Span ) > = None ;
675
709
let diagnostic = & sess. parse_sess . span_diagnostic ;
676
710
677
711
' outer: for attr in attrs_iter {
@@ -786,26 +820,53 @@ where
786
820
}
787
821
}
788
822
789
- if suggestion. is_some ( ) && sess. check_name ( attr, sym:: deprecated) {
790
- unreachable ! ( "only allowed on rustc_deprecated" )
791
- }
823
+ depr = if sess. check_name ( attr, sym:: deprecated) {
824
+ Some ( ( DeprKind :: Deprecated { since, note } , attr. span ) )
825
+ } else {
826
+ let since = match since {
827
+ None => {
828
+ // `since` field must be present
829
+ handle_errors ( & sess. parse_sess , attr. span , AttrError :: InvalidSince ) ;
830
+ continue ;
831
+ }
832
+ Some ( since_sym) => {
833
+ if since_sym == sym:: TBD {
834
+ None // "TBD" is the only non-version allowed for the `since` field
835
+ } else {
836
+ if let Some ( since_ver) = parse_version ( & since_sym. as_str ( ) , false ) {
837
+ Some ( since_ver)
838
+ } else {
839
+ // `since` field must be a valid version
840
+ handle_errors ( & sess. parse_sess , attr. span , AttrError :: InvalidSince ) ;
841
+ continue ;
842
+ }
843
+ }
844
+ }
845
+ } ;
792
846
793
- if sess. check_name ( attr, sym:: rustc_deprecated) {
794
- if since. is_none ( ) {
795
- handle_errors ( & sess. parse_sess , attr. span , AttrError :: MissingSince ) ;
796
- continue ;
797
- }
847
+ let note = match note {
848
+ None => {
849
+ struct_span_err ! ( diagnostic, attr. span, E0543 , "missing 'reason'" ) . emit ( ) ;
850
+ continue ;
851
+ }
852
+ Some ( n) => n,
853
+ } ;
798
854
799
- if note. is_none ( ) {
800
- struct_span_err ! ( diagnostic, attr. span, E0543 , "missing 'reason'" ) . emit ( ) ;
801
- continue ;
802
- }
803
- }
855
+ // Whether the deprecation is currently active
856
+ let now = match since {
857
+ None => false , // "TBD", therefore deprecated_in_future
858
+ Some ( since_ver) => {
859
+ match option_env ! ( "CFG_RELEASE" ) . and_then ( |s| parse_version ( s, true ) ) {
860
+ None => true , // if invalid Rust version, assume deprecation is in effect
861
+ Some ( rust_ver) => rust_ver > since_ver,
862
+ }
863
+ }
864
+ } ;
804
865
805
- sess. mark_attr_used ( & attr) ;
866
+ Some ( ( DeprKind :: RustcDeprecated { now, since, note, suggestion } , attr. span ) )
867
+ } ;
806
868
807
- let is_since_rustc_version = sess. check_name ( attr, sym:: rustc_deprecated) ;
808
- depr = Some ( ( Deprecation { since, note, suggestion, is_since_rustc_version } , attr. span ) ) ;
869
+ sess. mark_attr_used ( & attr) ;
809
870
}
810
871
811
872
depr
0 commit comments