1use rustc_ast as ast;
2use rustc_ast::token::{self, MetaVarKind};
3use rustc_ast::tokenstream::{ParserRange, WithTokens};
4use rustc_ast::{Attribute, attr};
5use rustc_errors::codes::*;
6use rustc_errors::{Diag, PResult, msg};
7use rustc_span::{BytePos, Span};
8use thin_vec::ThinVec;
9use tracing::debug;
10
11use super::{
12 AllowConstBlockItems, AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle,
13 Trailing, UsePreAttrPos,
14};
15use crate::parser::FnContext;
16use crate::{diagnostics, exp};
17
18#[derive(#[automatically_derived]
impl ::core::fmt::Debug for InnerAttrPolicy {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Permitted =>
::core::fmt::Formatter::write_str(f, "Permitted"),
Self::Forbidden(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Forbidden", &__self_0),
}
}
}Debug)]
20pub enum InnerAttrPolicy {
21 Permitted,
22 Forbidden(Option<InnerAttrForbiddenReason>),
23}
24
25#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InnerAttrForbiddenReason { }
#[automatically_derived]
impl ::core::clone::Clone for InnerAttrForbiddenReason {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Span>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for InnerAttrForbiddenReason { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for InnerAttrForbiddenReason {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::InCodeBlock =>
::core::fmt::Formatter::write_str(f, "InCodeBlock"),
Self::AfterOuterDocComment { prev_doc_comment_span: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"AfterOuterDocComment", "prev_doc_comment_span", &__self_0),
Self::AfterOuterAttribute { prev_outer_attr_sp: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"AfterOuterAttribute", "prev_outer_attr_sp", &__self_0),
}
}
}Debug)]
26pub enum InnerAttrForbiddenReason {
27 InCodeBlock,
28 AfterOuterDocComment { prev_doc_comment_span: Span },
29 AfterOuterAttribute { prev_outer_attr_sp: Span },
30}
31
32enum OuterAttributeType {
33 DocComment,
34 DocBlockComment,
35 Attribute,
36}
37
38impl<'a> Parser<'a> {
39 pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
41 let mut outer_attrs = ast::AttrVec::new();
42 let mut just_parsed_doc_comment = false;
43 let start_pos = self.num_bump_calls;
44 loop {
45 let attr = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Pound,
token_type: crate::parser::token_type::TokenType::Pound,
}exp!(Pound)) {
46 let prev_outer_attr_sp = outer_attrs.last().map(|attr: &Attribute| attr.span);
47
48 let inner_error_reason = if just_parsed_doc_comment {
49 Some(InnerAttrForbiddenReason::AfterOuterDocComment {
50 prev_doc_comment_span: prev_outer_attr_sp.unwrap(),
51 })
52 } else {
53 prev_outer_attr_sp.map(|prev_outer_attr_sp| {
54 InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }
55 })
56 };
57 let inner_parse_policy = InnerAttrPolicy::Forbidden(inner_error_reason);
58 just_parsed_doc_comment = false;
59 Some(self.parse_attribute(inner_parse_policy)?)
60 } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
61 if attr_style != ast::AttrStyle::Outer {
62 let span = self.token.span;
63 let mut err =
64 self.dcx().struct_span_err(span, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("expected outer doc comment"))msg!("expected outer doc comment"));
65 err.code(E0753);
66 if let Some(replacement_span) = self.annotate_following_item_if_applicable(
67 &mut err,
68 span,
69 match comment_kind {
70 token::CommentKind::Line => OuterAttributeType::DocComment,
71 token::CommentKind::Block => OuterAttributeType::DocBlockComment,
72 },
73 true,
74 ) {
75 err.note(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("inner doc comments like this (starting with `//!` or `/*!`) can only appear before items"))msg!(
76 "inner doc comments like this (starting with `//!` or `/*!`) can only appear before items"
77 ));
78 err.span_suggestion_verbose(
79 replacement_span,
80 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("you might have meant to write a regular comment"))msg!("you might have meant to write a regular comment"),
81 "",
82 rustc_errors::Applicability::MachineApplicable,
83 );
84 }
85 err.emit();
86 }
87 self.bump();
88 just_parsed_doc_comment = true;
89 Some(attr::mk_doc_comment(
92 &self.psess.attr_id_generator,
93 comment_kind,
94 ast::AttrStyle::Outer,
95 data,
96 self.prev_token.span,
97 ))
98 } else {
99 None
100 };
101
102 if let Some(attr) = attr {
103 if attr.style == ast::AttrStyle::Outer {
104 outer_attrs.push(attr);
105 }
106 } else {
107 break;
108 }
109 }
110 Ok(AttrWrapper::new(outer_attrs, start_pos))
111 }
112
113 pub fn parse_attribute(
117 &mut self,
118 inner_parse_policy: InnerAttrPolicy,
119 ) -> PResult<'a, ast::Attribute> {
120 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/4ebd258257737d5b7635c116fa7d281627a7e937/compiler/rustc_parse/src/parser/attr.rs:120",
"rustc_parse::parser::attr", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/4ebd258257737d5b7635c116fa7d281627a7e937/compiler/rustc_parse/src/parser/attr.rs"),
::tracing_core::__macro_support::Option::Some(120u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::attr"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("parse_attribute: inner_parse_policy={0:?} self.token={1:?}",
inner_parse_policy, self.token) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
121 "parse_attribute: inner_parse_policy={:?} self.token={:?}",
122 inner_parse_policy, self.token
123 );
124 let lo = self.token.span;
125 self.collect_tokens_no_attrs(|this| {
127 let pound_hi = this.token.span.hi();
128 if !this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Pound,
token_type: crate::parser::token_type::TokenType::Pound,
}) {
{
::core::panicking::panic_fmt(format_args!("parse_attribute called in non-attribute position"));
}
};assert!(this.eat(exp!(Pound)), "parse_attribute called in non-attribute position");
129
130 let not_lo = this.token.span.lo();
131 let style =
132 if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
133
134 let mut bracket_res = this.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBracket,
token_type: crate::parser::token_type::TokenType::OpenBracket,
}exp!(OpenBracket));
135 if let Err(err) = &mut bracket_res
137 && style == ast::AttrStyle::Inner
138 && pound_hi == not_lo
139 {
140 err.note(
141 "the token sequence `#!` here looks like the start of \
142 a shebang interpreter directive but it is not",
143 );
144 err.help(
145 "if you meant this to be a shebang interpreter directive, \
146 move it to the very start of the file",
147 );
148 }
149 bracket_res?;
150
151 let attr_item = this.parse_attr_item(ForceCollect::No)?;
152 if !attr_item.tokens.is_none() {
::core::panicking::panic("assertion failed: attr_item.tokens.is_none()")
};assert!(attr_item.tokens.is_none());
158
159 this.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBracket,
token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket))?;
160 let attr_sp = lo.to(this.prev_token.span);
161
162 if style == ast::AttrStyle::Inner {
164 this.error_on_forbidden_inner_attr(
165 attr_sp,
166 inner_parse_policy,
167 attr_item.node.is_valid_for_outer_style(),
168 );
169 }
170
171 Ok(attr::mk_attr_from_item(
172 &self.psess.attr_id_generator,
173 attr_item.node,
174 None,
175 style,
176 attr_sp,
177 ))
178 })
179 }
180
181 fn annotate_following_item_if_applicable(
182 &self,
183 err: &mut Diag<'_>,
184 span: Span,
185 attr_type: OuterAttributeType,
186 suggest_to_outer: bool,
187 ) -> Option<Span> {
188 let mut snapshot = self.create_snapshot_for_diagnostic();
189 let lo = span.lo()
190 + BytePos(match attr_type {
191 OuterAttributeType::Attribute => 1,
192 _ => 2,
193 });
194 let hi = lo + BytePos(1);
195 let replacement_span = span.with_lo(lo).with_hi(hi);
196 if let OuterAttributeType::DocBlockComment | OuterAttributeType::DocComment = attr_type {
197 snapshot.bump();
198 }
199 loop {
200 if snapshot.token == token::Pound {
202 if let Err(err) = snapshot.parse_attribute(InnerAttrPolicy::Permitted) {
203 err.cancel();
204 return Some(replacement_span);
205 }
206 } else {
207 break;
208 }
209 }
210 match snapshot.parse_item_common(
211 AttrWrapper::empty(),
212 true,
213 false,
214 FnParseMode {
215 req_name: |_, _| true,
216 context: FnContext::Free,
217 req_body: true,
218 allow_const_params: true,
219 },
220 ForceCollect::No,
221 AllowConstBlockItems::Yes,
222 ) {
223 Ok(Some(item)) => {
224 err.arg("item", item.kind.descr());
225 err.span_label(
226 item.span,
227 match attr_type {
228 OuterAttributeType::Attribute => {
229 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("the inner attribute doesn't annotate this {$item}"))msg!("the inner attribute doesn't annotate this {$item}")
230 }
231 OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => {
232 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("the inner doc comment doesn't annotate this {$item}"))msg!("the inner doc comment doesn't annotate this {$item}")
233 }
234 },
235 );
236 if suggest_to_outer {
237 err.span_suggestion_verbose(
238 replacement_span,
239 match attr_type {
240 OuterAttributeType::Attribute => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("to annotate the {$item}, change the attribute from inner to outer style"))msg!("to annotate the {$item}, change the attribute from inner to outer style"),
241 OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("to annotate the {$item}, change the doc comment from inner to outer style"))msg!("to annotate the {$item}, change the doc comment from inner to outer style"),
242 },
243 match attr_type {
244 OuterAttributeType::Attribute => "",
245 OuterAttributeType::DocBlockComment => "*",
246 OuterAttributeType::DocComment => "/",
247 },
248 rustc_errors::Applicability::MachineApplicable,
249 );
250 }
251 return None;
252 }
253 Err(item_err) => {
254 item_err.cancel();
255 }
256 Ok(None) => {}
257 }
258 Some(replacement_span)
259 }
260
261 pub(super) fn error_on_forbidden_inner_attr(
262 &self,
263 attr_sp: Span,
264 policy: InnerAttrPolicy,
265 suggest_to_outer: bool,
266 ) {
267 if let InnerAttrPolicy::Forbidden(reason) = policy {
268 let mut diag = match reason.as_ref().copied() {
269 Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => {
270 self.dcx()
271 .struct_span_err(
272 attr_sp,
273 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("an inner attribute is not permitted following an outer doc comment"))msg!(
274 "an inner attribute is not permitted following an outer doc comment"
275 ),
276 )
277 .with_span_label(
278 attr_sp,
279 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("not permitted following an outer doc comment"))msg!("not permitted following an outer doc comment"),
280 )
281 .with_span_label(prev_doc_comment_span, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("previous doc comment"))msg!("previous doc comment"))
282 }
283 Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self
284 .dcx()
285 .struct_span_err(
286 attr_sp,
287 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("an inner attribute is not permitted following an outer attribute"))msg!("an inner attribute is not permitted following an outer attribute"),
288 )
289 .with_span_label(attr_sp, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("not permitted following an outer attribute"))msg!("not permitted following an outer attribute"))
290 .with_span_label(prev_outer_attr_sp, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("previous outer attribute"))msg!("previous outer attribute")),
291 Some(InnerAttrForbiddenReason::InCodeBlock) | None => self.dcx().struct_span_err(
292 attr_sp,
293 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("an inner attribute is not permitted in this context"))msg!("an inner attribute is not permitted in this context"),
294 ),
295 };
296
297 diag.note(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files"))msg!("inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files"));
298 if self
299 .annotate_following_item_if_applicable(
300 &mut diag,
301 attr_sp,
302 OuterAttributeType::Attribute,
303 suggest_to_outer,
304 )
305 .is_some()
306 {
307 diag.note(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("outer attributes, like `#[test]`, annotate the item following them"))msg!(
308 "outer attributes, like `#[test]`, annotate the item following them"
309 ));
310 };
311 diag.emit();
312 }
313 }
314
315 pub fn parse_attr_item(
329 &mut self,
330 force_collect: ForceCollect,
331 ) -> PResult<'a, WithTokens<ast::AttrItem>> {
332 if let Some(item) = self.eat_metavar_seq_with_matcher(
333 |mv_kind| #[allow(non_exhaustive_omitted_patterns)] match mv_kind {
MetaVarKind::Meta { .. } => true,
_ => false,
}matches!(mv_kind, MetaVarKind::Meta { .. }),
334 |this| this.parse_attr_item(force_collect),
335 ) {
336 return Ok(item);
337 }
338
339 self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| {
341 let lo = this.token.span;
342 let is_unsafe = this.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe));
343 let unsafety = if is_unsafe {
344 let unsafe_span = this.prev_token.span;
345 this.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))?;
346 ast::Safety::Unsafe(unsafe_span)
347 } else {
348 ast::Safety::Default
349 };
350
351 let path = this.parse_path(PathStyle::Mod)?;
352 let args = this.parse_attr_args()?;
353 if is_unsafe {
354 this.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
355 }
356 let span = lo.to(this.prev_token.span);
357 Ok((
358 WithTokens::new(ast::AttrItem { unsafety, path, args, span }),
359 Trailing::No,
360 UsePreAttrPos::No,
361 ))
362 })
363 }
364
365 pub fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
371 let mut attrs = ast::AttrVec::new();
372 loop {
373 let start_pos = self.num_bump_calls;
374 let attr = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Pound,
token_type: crate::parser::token_type::TokenType::Pound,
}exp!(Pound)) && self.look_ahead(1, |t| t == &token::Bang) {
376 Some(self.parse_attribute(InnerAttrPolicy::Permitted)?)
377 } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
378 if attr_style == ast::AttrStyle::Inner {
379 self.bump();
380 Some(attr::mk_doc_comment(
381 &self.psess.attr_id_generator,
382 comment_kind,
383 attr_style,
384 data,
385 self.prev_token.span,
386 ))
387 } else {
388 None
389 }
390 } else {
391 None
392 };
393 if let Some(attr) = attr {
394 if let Capturing::Yes = self.capture_state.capturing {
398 let end_pos = self.num_bump_calls;
399 let parser_range = ParserRange(start_pos..end_pos);
400 self.capture_state.inner_attr_parser_ranges.insert(attr.id, parser_range);
401 }
402 attrs.push(attr);
403 } else {
404 break;
405 }
406 }
407 Ok(attrs)
408 }
409
410 pub(crate) fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'a, ast::MetaItemLit> {
412 let lit = self.parse_meta_item_lit()?;
413 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/4ebd258257737d5b7635c116fa7d281627a7e937/compiler/rustc_parse/src/parser/attr.rs:413",
"rustc_parse::parser::attr", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/4ebd258257737d5b7635c116fa7d281627a7e937/compiler/rustc_parse/src/parser/attr.rs"),
::tracing_core::__macro_support::Option::Some(413u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::attr"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("checking if {0:?} is unsuffixed",
lit) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("checking if {:?} is unsuffixed", lit);
414
415 if !lit.kind.is_unsuffixed() {
416 self.dcx().emit_err(diagnostics::SuffixedLiteralInAttribute { span: lit.span });
417 }
418
419 Ok(lit)
420 }
421
422 pub fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> {
424 let mut nmis = ThinVec::with_capacity(1);
426 while self.token != token::Eof {
427 nmis.push(self.parse_meta_item_inner()?);
428 if !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)) {
429 break;
430 }
431 }
432 Ok(nmis)
433 }
434
435 pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
442 if let Some(MetaVarKind::Meta { has_meta_form }) = self.token.is_metavar_seq() {
443 return if has_meta_form {
444 let attr_item = self
445 .eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
446 this.parse_attr_item(ForceCollect::No)
447 })
448 .unwrap()
449 .node;
450 Ok(attr_item.meta(attr_item.span).unwrap())
451 } else {
452 self.unexpected_any()
453 };
454 }
455 let lo = self.token.span;
456
457 let path = self.parse_path(PathStyle::Mod)?;
458 let kind = self.parse_meta_item_kind()?;
459 let span = lo.to(self.prev_token.span);
460
461 Ok(ast::MetaItem { unsafety: ast::Safety::Default, path, kind, span })
462 }
463
464 pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
465 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
466 ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?)
467 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
468 let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
469 ast::MetaItemKind::List(list)
470 } else {
471 ast::MetaItemKind::Word
472 })
473 }
474
475 pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::MetaItemInner> {
481 match self.parse_unsuffixed_meta_item_lit() {
482 Ok(lit) => return Ok(ast::MetaItemInner::Lit(lit)),
483 Err(err) => err.cancel(), }
485
486 match self.parse_meta_item() {
487 Ok(mi) => return Ok(ast::MetaItemInner::MetaItem(mi)),
488 Err(err) => err.cancel(), }
490
491 let mut err = diagnostics::InvalidMetaItem {
492 span: self.token.span,
493 descr: super::token_descr(&self.token),
494 quote_ident_sugg: None,
495 };
496
497 if self.prev_token == token::Eq
501 && let token::Ident(..) = self.token.kind
502 {
503 let before = self.token.span.shrink_to_lo();
504 while let token::Ident(..) = self.token.kind {
505 self.bump();
506 }
507 err.quote_ident_sugg = Some(diagnostics::InvalidMetaItemQuoteIdentSugg {
508 before,
509 after: self.prev_token.span.shrink_to_hi(),
510 });
511 }
512
513 Err(self.dcx().create_err(err))
514 }
515
516 pub fn recover_from_outer_attributes(&mut self, target: &str) -> PResult<'a, ()> {
518 if !self.may_recover() || !#[allow(non_exhaustive_omitted_patterns)] match self.token.kind {
token::Pound | token::DocComment(..) => true,
_ => false,
}matches!(self.token.kind, token::Pound | token::DocComment(..)) {
521 return Ok(());
522 }
523
524 let attrs = self.parse_outer_attributes()?;
525 if attrs.is_empty() {
526 return Ok(());
527 }
528
529 let attrs = attrs.take_for_recovery(self.psess);
530 let span = attrs.first().unwrap().span.to(attrs.last().unwrap().span);
531
532 let subject = if attrs.iter().all(|attr| #[allow(non_exhaustive_omitted_patterns)] match attr.kind {
ast::AttrKind::DocComment(..) => true,
_ => false,
}matches!(attr.kind, ast::AttrKind::DocComment(..)))
533 {
534 "doc comments"
535 } else {
536 "attributes"
537 };
538
539 self.dcx()
540 .struct_span_err(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} cannot be applied to {1}",
subject, target))
})format!("{subject} cannot be applied to {target}"))
541 .with_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} are not allowed here",
subject))
})format!("{subject} are not allowed here"))
542 .with_span_suggestion_with_style(
543 span.until(self.token.span),
544 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("remove these {0}", subject))
})format!("remove these {subject}"),
545 String::new(),
546 rustc_errors::Applicability::MachineApplicable,
547 rustc_errors::SuggestionStyle::CompletelyHidden,
548 )
549 .emit();
550
551 Ok(())
552 }
553}