@@ -4,7 +4,7 @@ use crate::parse_in;
4
4
5
5
use rustc_ast:: tokenstream:: { DelimSpan , TokenTree } ;
6
6
use rustc_ast:: { self as ast, Attribute , MacArgs , MacDelimiter , MetaItem , MetaItemKind } ;
7
- use rustc_errors:: { Applicability , PResult } ;
7
+ use rustc_errors:: { Applicability , FatalError , PResult } ;
8
8
use rustc_feature:: { AttributeTemplate , BUILTIN_ATTRIBUTE_MAP } ;
9
9
use rustc_session:: lint:: builtin:: ILL_FORMED_ATTRIBUTE_INPUT ;
10
10
use rustc_session:: parse:: ParseSess ;
@@ -91,73 +91,86 @@ pub fn check_builtin_attribute(
91
91
// Some special attributes like `cfg` must be checked
92
92
// before the generic check, so we skip them here.
93
93
let should_skip = |name| name == sym:: cfg;
94
- // Some of previously accepted forms were used in practice,
95
- // report them as warnings for now.
96
- let should_warn = |name| {
97
- name == sym:: doc
98
- || name == sym:: ignore
99
- || name == sym:: inline
100
- || name == sym:: link
101
- || name == sym:: test
102
- || name == sym:: bench
103
- } ;
104
94
105
95
match parse_meta ( sess, attr) {
106
96
Ok ( meta) => {
107
97
if !should_skip ( name) && !is_attr_template_compatible ( & template, & meta. kind ) {
108
- let error_msg = format ! ( "malformed `{}` attribute input" , name) ;
109
- let mut msg = "attribute must be of the form " . to_owned ( ) ;
110
- let mut suggestions = vec ! [ ] ;
111
- let mut first = true ;
112
- if template. word {
113
- first = false ;
114
- let code = format ! ( "#[{}]" , name) ;
115
- msg. push_str ( & format ! ( "`{}`" , & code) ) ;
116
- suggestions. push ( code) ;
117
- }
118
- if let Some ( descr) = template. list {
119
- if !first {
120
- msg. push_str ( " or " ) ;
121
- }
122
- first = false ;
123
- let code = format ! ( "#[{}({})]" , name, descr) ;
124
- msg. push_str ( & format ! ( "`{}`" , & code) ) ;
125
- suggestions. push ( code) ;
126
- }
127
- if let Some ( descr) = template. name_value_str {
128
- if !first {
129
- msg. push_str ( " or " ) ;
130
- }
131
- let code = format ! ( "#[{} = \" {}\" ]" , name, descr) ;
132
- msg. push_str ( & format ! ( "`{}`" , & code) ) ;
133
- suggestions. push ( code) ;
134
- }
135
- if should_warn ( name) {
136
- sess. buffer_lint (
137
- & ILL_FORMED_ATTRIBUTE_INPUT ,
138
- meta. span ,
139
- ast:: CRATE_NODE_ID ,
140
- & msg,
141
- ) ;
142
- } else {
143
- sess. span_diagnostic
144
- . struct_span_err ( meta. span , & error_msg)
145
- . span_suggestions (
146
- meta. span ,
147
- if suggestions. len ( ) == 1 {
148
- "must be of the form"
149
- } else {
150
- "the following are the possible correct uses"
151
- } ,
152
- suggestions. into_iter ( ) ,
153
- Applicability :: HasPlaceholders ,
154
- )
155
- . emit ( ) ;
156
- }
98
+ emit_malformed_attribute ( sess, attr, name, template) ;
157
99
}
158
100
}
159
101
Err ( mut err) => {
160
102
err. emit ( ) ;
161
103
}
162
104
}
163
105
}
106
+
107
+ fn emit_malformed_attribute (
108
+ sess : & ParseSess ,
109
+ attr : & Attribute ,
110
+ name : Symbol ,
111
+ template : AttributeTemplate ,
112
+ ) {
113
+ // Some of previously accepted forms were used in practice,
114
+ // report them as warnings for now.
115
+ let should_warn = |name| {
116
+ matches ! ( name, sym:: doc | sym:: ignore | sym:: inline | sym:: link | sym:: test | sym:: bench)
117
+ } ;
118
+
119
+ let error_msg = format ! ( "malformed `{}` attribute input" , name) ;
120
+ let mut msg = "attribute must be of the form " . to_owned ( ) ;
121
+ let mut suggestions = vec ! [ ] ;
122
+ let mut first = true ;
123
+ let inner = if attr. style == ast:: AttrStyle :: Inner { "!" } else { "" } ;
124
+ if template. word {
125
+ first = false ;
126
+ let code = format ! ( "#{}[{}]" , inner, name) ;
127
+ msg. push_str ( & format ! ( "`{}`" , & code) ) ;
128
+ suggestions. push ( code) ;
129
+ }
130
+ if let Some ( descr) = template. list {
131
+ if !first {
132
+ msg. push_str ( " or " ) ;
133
+ }
134
+ first = false ;
135
+ let code = format ! ( "#{}[{}({})]" , inner, name, descr) ;
136
+ msg. push_str ( & format ! ( "`{}`" , & code) ) ;
137
+ suggestions. push ( code) ;
138
+ }
139
+ if let Some ( descr) = template. name_value_str {
140
+ if !first {
141
+ msg. push_str ( " or " ) ;
142
+ }
143
+ let code = format ! ( "#{}[{} = \" {}\" ]" , inner, name, descr) ;
144
+ msg. push_str ( & format ! ( "`{}`" , & code) ) ;
145
+ suggestions. push ( code) ;
146
+ }
147
+ if should_warn ( name) {
148
+ sess. buffer_lint ( & ILL_FORMED_ATTRIBUTE_INPUT , attr. span , ast:: CRATE_NODE_ID , & msg) ;
149
+ } else {
150
+ sess. span_diagnostic
151
+ . struct_span_err ( attr. span , & error_msg)
152
+ . span_suggestions (
153
+ attr. span ,
154
+ if suggestions. len ( ) == 1 {
155
+ "must be of the form"
156
+ } else {
157
+ "the following are the possible correct uses"
158
+ } ,
159
+ suggestions. into_iter ( ) ,
160
+ Applicability :: HasPlaceholders ,
161
+ )
162
+ . emit ( ) ;
163
+ }
164
+ }
165
+
166
+ pub fn emit_fatal_malformed_builtin_attribute (
167
+ sess : & ParseSess ,
168
+ attr : & Attribute ,
169
+ name : Symbol ,
170
+ ) -> ! {
171
+ let template = BUILTIN_ATTRIBUTE_MAP . get ( & name) . expect ( "builtin attr defined" ) . 2 ;
172
+ emit_malformed_attribute ( sess, attr, name, template) ;
173
+ // This is fatal, otherwise it will likely cause a cascade of other errors
174
+ // (and an error here is expected to be very rare).
175
+ FatalError . raise ( )
176
+ }
0 commit comments