@@ -13,6 +13,7 @@ use rustc_session::parse::{feature_err, ParseSess};
1313use rustc_session:: { RustcVersion , Session } ;
1414use rustc_span:: hygiene:: Transparency ;
1515use rustc_span:: { symbol:: sym, symbol:: Symbol , Span } ;
16+ use std:: fmt:: { self , Display } ;
1617use std:: num:: NonZeroU32 ;
1718
1819use crate :: session_diagnostics:: { self , IncorrectReprFormatGenericCause } ;
@@ -720,17 +721,37 @@ pub fn eval_condition(
720721
721722#[ derive( Copy , Debug , Encodable , Decodable , Clone , HashStable_Generic ) ]
722723pub struct Deprecation {
723- pub since : Option < Symbol > ,
724+ pub since : Option < DeprecatedSince > ,
724725 /// The note to issue a reason.
725726 pub note : Option < Symbol > ,
726727 /// A text snippet used to completely replace any use of the deprecated item in an expression.
727728 ///
728729 /// This is currently unstable.
729730 pub suggestion : Option < Symbol > ,
731+ }
732+
733+ /// Release in which an API is deprecated.
734+ #[ derive( Copy , Debug , Encodable , Decodable , Clone , HashStable_Generic ) ]
735+ pub enum DeprecatedSince {
736+ RustcVersion ( RustcVersion ) ,
737+ /// Deprecated in the future ("to be determined").
738+ Future ,
739+ /// `feature(staged_api)` is off, or it's on but the deprecation version
740+ /// cannot be parsed as a RustcVersion. In the latter case, an error has
741+ /// already been emitted. In the former case, deprecation versions outside
742+ /// the standard library are allowed to be arbitrary strings, for better or
743+ /// worse.
744+ Symbol ( Symbol ) ,
745+ }
730746
731- /// Whether to treat the since attribute as being a Rust version identifier
732- /// (rather than an opaque string).
733- pub is_since_rustc_version : bool ,
747+ impl Display for DeprecatedSince {
748+ fn fmt ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
749+ match self {
750+ DeprecatedSince :: RustcVersion ( since) => Display :: fmt ( since, formatter) ,
751+ DeprecatedSince :: Future => formatter. write_str ( "TBD" ) ,
752+ DeprecatedSince :: Symbol ( since) => Display :: fmt ( since, formatter) ,
753+ }
754+ }
734755}
735756
736757/// Finds the deprecation attribute. `None` if none exists.
@@ -839,22 +860,30 @@ pub fn find_deprecation(
839860 }
840861 }
841862
842- if is_rustc {
843- if since. is_none ( ) {
844- sess. emit_err ( session_diagnostics:: MissingSince { span : attr. span } ) ;
845- continue ;
863+ let since = if let Some ( since) = since {
864+ if since. as_str ( ) == "TBD" {
865+ Some ( DeprecatedSince :: Future )
866+ } else if !is_rustc {
867+ Some ( DeprecatedSince :: Symbol ( since) )
868+ } else if let Some ( version) = parse_version ( since) {
869+ Some ( DeprecatedSince :: RustcVersion ( version) )
870+ } else {
871+ sess. emit_err ( session_diagnostics:: InvalidSince { span : attr. span } ) ;
872+ Some ( DeprecatedSince :: Symbol ( since) )
846873 }
874+ } else if is_rustc {
875+ sess. emit_err ( session_diagnostics:: MissingSince { span : attr. span } ) ;
876+ continue ;
877+ } else {
878+ None
879+ } ;
847880
848- if note. is_none ( ) {
849- sess. emit_err ( session_diagnostics:: MissingNote { span : attr. span } ) ;
850- continue ;
851- }
881+ if is_rustc && note. is_none ( ) {
882+ sess. emit_err ( session_diagnostics:: MissingNote { span : attr. span } ) ;
883+ continue ;
852884 }
853885
854- depr = Some ( (
855- Deprecation { since, note, suggestion, is_since_rustc_version : is_rustc } ,
856- attr. span ,
857- ) ) ;
886+ depr = Some ( ( Deprecation { since, note, suggestion } , attr. span ) ) ;
858887 }
859888
860889 depr
0 commit comments