11use rustc_attr_data_structures:: { AttributeKind , DeprecatedSince , Deprecation } ;
2+ use rustc_feature:: { AttributeTemplate , template} ;
23use rustc_span:: { Span , Symbol , sym} ;
34
45use super :: util:: parse_version;
56use super :: { AttributeOrder , OnDuplicate , SingleAttributeParser } ;
67use crate :: context:: { AcceptContext , Stage } ;
78use crate :: parser:: ArgParser ;
89use crate :: session_diagnostics;
9- use crate :: session_diagnostics:: UnsupportedLiteralReason ;
1010
1111pub ( crate ) struct DeprecationParser ;
1212
@@ -18,25 +18,18 @@ fn get<S: Stage>(
1818 item : & Option < Symbol > ,
1919) -> Option < Symbol > {
2020 if item. is_some ( ) {
21- cx. emit_err ( session_diagnostics :: MultipleItem { span : param_span, item : name. to_string ( ) } ) ;
21+ cx. duplicate_key ( param_span, name) ;
2222 return None ;
2323 }
2424 if let Some ( v) = arg. name_value ( ) {
2525 if let Some ( value_str) = v. value_as_str ( ) {
2626 Some ( value_str)
2727 } else {
28- let lit = v. value_as_lit ( ) ;
29- cx. emit_err ( session_diagnostics:: UnsupportedLiteral {
30- span : v. value_span ,
31- reason : UnsupportedLiteralReason :: DeprecatedString ,
32- is_bytestr : lit. kind . is_bytestr ( ) ,
33- start_point_span : cx. sess ( ) . source_map ( ) . start_point ( lit. span ) ,
34- } ) ;
28+ cx. expected_string_literal ( v. value_span , Some ( & v. value_as_lit ( ) ) ) ;
3529 None
3630 }
3731 } else {
38- // FIXME(jdonszelmann): suggestion?
39- cx. emit_err ( session_diagnostics:: IncorrectMetaItem { span : param_span, suggestion : None } ) ;
32+ cx. expected_name_value ( param_span, Some ( name) ) ;
4033 None
4134 }
4235}
@@ -45,6 +38,11 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
4538 const PATH : & [ Symbol ] = & [ sym:: deprecated] ;
4639 const ATTRIBUTE_ORDER : AttributeOrder = AttributeOrder :: KeepFirst ;
4740 const ON_DUPLICATE : OnDuplicate < S > = OnDuplicate :: Error ;
41+ const TEMPLATE : AttributeTemplate = template ! (
42+ Word ,
43+ List : r#"/*opt*/ since = "version", /*opt*/ note = "reason""# ,
44+ NameValueStr : "reason"
45+ ) ;
4846
4947 fn convert ( cx : & mut AcceptContext < ' _ , ' _ , S > , args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
5048 let features = cx. features ( ) ;
@@ -55,57 +53,60 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
5553
5654 let is_rustc = features. staged_api ( ) ;
5755
58- if let Some ( value) = args. name_value ( )
59- && let Some ( value_str) = value. value_as_str ( )
60- {
61- note = Some ( value_str)
62- } else if let Some ( list) = args. list ( ) {
63- for param in list. mixed ( ) {
64- let param_span = param. span ( ) ;
65- let Some ( param) = param. meta_item ( ) else {
66- cx. emit_err ( session_diagnostics:: UnsupportedLiteral {
67- span : param_span,
68- reason : UnsupportedLiteralReason :: DeprecatedKvPair ,
69- is_bytestr : false ,
70- start_point_span : cx. sess ( ) . source_map ( ) . start_point ( param_span) ,
71- } ) ;
72- return None ;
73- } ;
56+ match args {
57+ ArgParser :: NoArgs => {
58+ // ok
59+ }
60+ ArgParser :: List ( list) => {
61+ for param in list. mixed ( ) {
62+ let Some ( param) = param. meta_item ( ) else {
63+ cx. unexpected_literal ( param. span ( ) ) ;
64+ return None ;
65+ } ;
7466
75- let ident_name = param. path ( ) . word_sym ( ) ;
67+ let ident_name = param. path ( ) . word_sym ( ) ;
7668
77- match ident_name {
78- Some ( name @ sym:: since) => {
79- since = Some ( get ( cx, name, param_span, param. args ( ) , & since) ?) ;
80- }
81- Some ( name @ sym:: note) => {
82- note = Some ( get ( cx, name, param_span, param. args ( ) , & note) ?) ;
83- }
84- Some ( name @ sym:: suggestion) => {
85- if !features. deprecated_suggestion ( ) {
86- cx. emit_err ( session_diagnostics:: DeprecatedItemSuggestion {
87- span : param_span,
88- is_nightly : cx. sess ( ) . is_nightly_build ( ) ,
89- details : ( ) ,
90- } ) ;
69+ match ident_name {
70+ Some ( name @ sym:: since) => {
71+ since = Some ( get ( cx, name, param. span ( ) , param. args ( ) , & since) ?) ;
72+ }
73+ Some ( name @ sym:: note) => {
74+ note = Some ( get ( cx, name, param. span ( ) , param. args ( ) , & note) ?) ;
9175 }
76+ Some ( name @ sym:: suggestion) => {
77+ if !features. deprecated_suggestion ( ) {
78+ cx. emit_err ( session_diagnostics:: DeprecatedItemSuggestion {
79+ span : param. span ( ) ,
80+ is_nightly : cx. sess ( ) . is_nightly_build ( ) ,
81+ details : ( ) ,
82+ } ) ;
83+ }
9284
93- suggestion = Some ( get ( cx, name, param_span, param. args ( ) , & suggestion) ?) ;
94- }
95- _ => {
96- cx. emit_err ( session_diagnostics:: UnknownMetaItem {
97- span : param_span,
98- item : param. path ( ) . to_string ( ) ,
99- expected : if features. deprecated_suggestion ( ) {
100- & [ "since" , "note" , "suggestion" ]
101- } else {
102- & [ "since" , "note" ]
103- } ,
104- } ) ;
105- return None ;
85+ suggestion =
86+ Some ( get ( cx, name, param. span ( ) , param. args ( ) , & suggestion) ?) ;
87+ }
88+ _ => {
89+ cx. unknown_key (
90+ param. span ( ) ,
91+ param. path ( ) . to_string ( ) ,
92+ if features. deprecated_suggestion ( ) {
93+ & [ "since" , "note" , "suggestion" ]
94+ } else {
95+ & [ "since" , "note" ]
96+ } ,
97+ ) ;
98+ return None ;
99+ }
106100 }
107101 }
108102 }
103+ ArgParser :: NameValue ( v) => {
104+ let Some ( value) = v. value_as_str ( ) else {
105+ cx. expected_string_literal ( v. value_span , Some ( v. value_as_lit ( ) ) ) ;
106+ return None ;
107+ } ;
108+ note = Some ( value) ;
109+ }
109110 }
110111
111112 let since = if let Some ( since) = since {
0 commit comments