2024-12-04 04:55:06 +00:00
|
|
|
use rustc_ast::{self as ast, Attribute, attr, token};
|
2024-02-22 23:20:45 +00:00
|
|
|
use rustc_errors::codes::*;
|
|
|
|
use rustc_errors::{Diag, PResult};
|
2024-12-04 04:55:06 +00:00
|
|
|
use rustc_span::{BytePos, Span};
|
2022-11-23 00:55:16 +00:00
|
|
|
use thin_vec::ThinVec;
|
|
|
|
use tracing::debug;
|
2019-10-11 11:06:36 +00:00
|
|
|
|
2024-08-06 00:17:46 +00:00
|
|
|
use super::{
|
|
|
|
AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle, Trailing,
|
2024-08-06 07:16:40 +00:00
|
|
|
UsePreAttrPos,
|
2024-08-06 00:17:46 +00:00
|
|
|
};
|
2024-12-04 04:55:06 +00:00
|
|
|
use crate::{errors, exp, fluent_generated as fluent, maybe_whole};
|
2024-07-28 22:13:50 +00:00
|
|
|
|
2020-11-26 01:54:08 +00:00
|
|
|
// Public for rustfmt usage
|
2018-03-20 22:58:25 +00:00
|
|
|
#[derive(Debug)]
|
2022-08-31 11:20:59 +00:00
|
|
|
pub enum InnerAttrPolicy {
|
2016-07-06 04:35:12 +00:00
|
|
|
Permitted,
|
2022-08-31 11:20:59 +00:00
|
|
|
Forbidden(Option<InnerAttrForbiddenReason>),
|
2016-07-06 04:35:12 +00:00
|
|
|
}
|
|
|
|
|
2022-08-31 11:20:59 +00:00
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub enum InnerAttrForbiddenReason {
|
|
|
|
InCodeBlock,
|
|
|
|
AfterOuterDocComment { prev_doc_comment_span: Span },
|
|
|
|
AfterOuterAttribute { prev_outer_attr_sp: Span },
|
|
|
|
}
|
2020-03-05 10:42:56 +00:00
|
|
|
|
2021-08-23 10:49:31 +00:00
|
|
|
enum OuterAttributeType {
|
|
|
|
DocComment,
|
|
|
|
DocBlockComment,
|
|
|
|
Attribute,
|
|
|
|
}
|
|
|
|
|
2024-07-10 00:06:49 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
|
|
pub enum AllowLeadingUnsafe {
|
|
|
|
Yes,
|
|
|
|
No,
|
|
|
|
}
|
|
|
|
|
2015-10-24 01:37:21 +00:00
|
|
|
impl<'a> Parser<'a> {
|
2019-09-06 02:56:45 +00:00
|
|
|
/// Parses attributes that appear before an item.
|
2021-01-22 18:28:08 +00:00
|
|
|
pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
|
2022-08-17 02:34:33 +00:00
|
|
|
let mut outer_attrs = ast::AttrVec::new();
|
2016-07-06 04:35:12 +00:00
|
|
|
let mut just_parsed_doc_comment = false;
|
2023-07-31 06:15:54 +00:00
|
|
|
let start_pos = self.num_bump_calls;
|
2012-06-30 10:54:54 +00:00
|
|
|
loop {
|
2024-12-04 04:55:06 +00:00
|
|
|
let attr = if self.check(exp!(Pound)) {
|
2024-10-16 23:14:01 +00:00
|
|
|
let prev_outer_attr_sp = outer_attrs.last().map(|attr: &Attribute| attr.span);
|
2022-03-21 23:36:47 +00:00
|
|
|
|
2020-11-05 17:27:48 +00:00
|
|
|
let inner_error_reason = if just_parsed_doc_comment {
|
2022-08-31 11:20:59 +00:00
|
|
|
Some(InnerAttrForbiddenReason::AfterOuterDocComment {
|
|
|
|
prev_doc_comment_span: prev_outer_attr_sp.unwrap(),
|
|
|
|
})
|
2020-11-05 17:27:48 +00:00
|
|
|
} else {
|
2023-04-15 18:18:30 +00:00
|
|
|
prev_outer_attr_sp.map(|prev_outer_attr_sp| {
|
|
|
|
InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }
|
|
|
|
})
|
2020-11-05 17:27:48 +00:00
|
|
|
};
|
2022-08-31 11:20:59 +00:00
|
|
|
let inner_parse_policy = InnerAttrPolicy::Forbidden(inner_error_reason);
|
2020-11-05 17:27:48 +00:00
|
|
|
just_parsed_doc_comment = false;
|
|
|
|
Some(self.parse_attribute(inner_parse_policy)?)
|
2020-10-22 19:17:40 +00:00
|
|
|
} else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
|
2020-11-05 17:27:48 +00:00
|
|
|
if attr_style != ast::AttrStyle::Outer {
|
2021-08-23 10:49:31 +00:00
|
|
|
let span = self.token.span;
|
2024-01-03 10:50:36 +00:00
|
|
|
let mut err = self
|
|
|
|
.dcx()
|
|
|
|
.struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted);
|
Stop using `String` for error codes.
Error codes are integers, but `String` is used everywhere to represent
them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes,
replacing `String`. It also introduces a constant for every error code,
e.g. `E0123`, and removes the `error_code!` macro. The constants are
imported wherever used with `use rustc_errors::codes::*`.
With the old code, we have three different ways to specify an error code
at a use point:
```
error_code!(E0123) // macro call
struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call
\#[diag(name, code = "E0123")] // string
struct Diag;
```
With the new code, they all use the `E0123` constant.
```
E0123 // constant
struct_span_code_err!(dcx, span, E0123, "msg"); // constant
\#[diag(name, code = E0123)] // constant
struct Diag;
```
The commit also changes the structure of the error code definitions:
- `rustc_error_codes` now just defines a higher-order macro listing the
used error codes and nothing else.
- Because that's now the only thing in the `rustc_error_codes` crate, I
moved it into the `lib.rs` file and removed the `error_codes.rs` file.
- `rustc_errors` uses that macro to define everything, e.g. the error
code constants and the `DIAGNOSTIC_TABLES`. This is in its new
`codes.rs` file.
2024-01-13 23:57:07 +00:00
|
|
|
err.code(E0753);
|
2021-08-23 10:49:31 +00:00
|
|
|
if let Some(replacement_span) = self.annotate_following_item_if_applicable(
|
|
|
|
&mut err,
|
|
|
|
span,
|
|
|
|
match comment_kind {
|
|
|
|
token::CommentKind::Line => OuterAttributeType::DocComment,
|
|
|
|
token::CommentKind::Block => OuterAttributeType::DocBlockComment,
|
|
|
|
},
|
2024-08-01 16:28:57 +00:00
|
|
|
true,
|
2021-08-23 10:49:31 +00:00
|
|
|
) {
|
2022-10-13 09:13:02 +00:00
|
|
|
err.note(fluent::parse_note);
|
2021-08-23 10:49:31 +00:00
|
|
|
err.span_suggestion_verbose(
|
|
|
|
replacement_span,
|
2022-10-13 09:13:02 +00:00
|
|
|
fluent::parse_suggestion,
|
2022-06-13 06:48:40 +00:00
|
|
|
"",
|
2021-08-23 10:49:31 +00:00
|
|
|
rustc_errors::Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
err.emit();
|
2020-11-05 17:27:48 +00:00
|
|
|
}
|
|
|
|
self.bump();
|
|
|
|
just_parsed_doc_comment = true;
|
2021-07-02 16:30:20 +00:00
|
|
|
// Always make an outer attribute - this allows us to recover from a misplaced
|
|
|
|
// inner attribute.
|
|
|
|
Some(attr::mk_doc_comment(
|
2024-03-04 05:31:49 +00:00
|
|
|
&self.psess.attr_id_generator,
|
2021-07-02 16:30:20 +00:00
|
|
|
comment_kind,
|
|
|
|
ast::AttrStyle::Outer,
|
|
|
|
data,
|
|
|
|
self.prev_token.span,
|
|
|
|
))
|
2020-10-22 19:17:40 +00:00
|
|
|
} else {
|
2020-11-05 17:27:48 +00:00
|
|
|
None
|
2020-10-22 19:17:40 +00:00
|
|
|
};
|
|
|
|
|
2020-11-05 17:27:48 +00:00
|
|
|
if let Some(attr) = attr {
|
2022-03-21 23:36:47 +00:00
|
|
|
if attr.style == ast::AttrStyle::Outer {
|
|
|
|
outer_attrs.push(attr);
|
|
|
|
}
|
2020-03-05 10:42:56 +00:00
|
|
|
} else {
|
|
|
|
break;
|
2012-06-30 10:54:54 +00:00
|
|
|
}
|
2012-05-24 20:44:42 +00:00
|
|
|
}
|
2022-08-17 02:34:33 +00:00
|
|
|
Ok(AttrWrapper::new(outer_attrs, start_pos))
|
2012-04-20 03:51:31 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 02:56:45 +00:00
|
|
|
/// Matches `attribute = # ! [ meta_item ]`.
|
2020-11-05 17:27:48 +00:00
|
|
|
/// `inner_parse_policy` prescribes how to handle inner attributes.
|
2020-11-26 01:54:08 +00:00
|
|
|
// Public for rustfmt usage.
|
|
|
|
pub fn parse_attribute(
|
2019-10-08 07:35:34 +00:00
|
|
|
&mut self,
|
2022-08-31 11:20:59 +00:00
|
|
|
inner_parse_policy: InnerAttrPolicy,
|
2019-10-08 07:35:34 +00:00
|
|
|
) -> PResult<'a, ast::Attribute> {
|
2016-07-06 04:35:12 +00:00
|
|
|
debug!(
|
2020-11-05 17:27:48 +00:00
|
|
|
"parse_attribute: inner_parse_policy={:?} self.token={:?}",
|
2016-07-06 04:35:12 +00:00
|
|
|
inner_parse_policy, self.token
|
|
|
|
);
|
2020-03-05 10:42:56 +00:00
|
|
|
let lo = self.token.span;
|
2021-08-23 10:49:31 +00:00
|
|
|
// Attributes can't have attributes of their own [Editor's note: not with that attitude]
|
2021-01-22 18:28:08 +00:00
|
|
|
self.collect_tokens_no_attrs(|this| {
|
2024-12-04 04:55:06 +00:00
|
|
|
assert!(this.eat(exp!(Pound)), "parse_attribute called in non-attribute position");
|
2014-02-25 02:42:40 +00:00
|
|
|
|
2022-09-01 17:29:59 +00:00
|
|
|
let style =
|
2024-12-04 04:55:06 +00:00
|
|
|
if this.eat(exp!(Not)) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
|
2020-11-05 17:27:48 +00:00
|
|
|
|
2024-12-04 04:55:06 +00:00
|
|
|
this.expect(exp!(OpenBracket))?;
|
2024-07-17 03:14:35 +00:00
|
|
|
let item = this.parse_attr_item(ForceCollect::No)?;
|
2024-12-04 04:55:06 +00:00
|
|
|
this.expect(exp!(CloseBracket))?;
|
2022-09-01 17:29:59 +00:00
|
|
|
let attr_sp = lo.to(this.prev_token.span);
|
2020-11-05 17:27:48 +00:00
|
|
|
|
2022-09-01 17:29:59 +00:00
|
|
|
// Emit error if inner attribute is encountered and forbidden.
|
|
|
|
if style == ast::AttrStyle::Inner {
|
2024-08-01 16:28:57 +00:00
|
|
|
this.error_on_forbidden_inner_attr(
|
|
|
|
attr_sp,
|
|
|
|
inner_parse_policy,
|
|
|
|
item.is_valid_for_outer_style(),
|
|
|
|
);
|
2020-11-05 17:27:48 +00:00
|
|
|
}
|
2022-09-01 17:29:59 +00:00
|
|
|
|
2024-03-04 05:31:49 +00:00
|
|
|
Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp))
|
2021-01-13 21:28:57 +00:00
|
|
|
})
|
2020-03-05 10:42:56 +00:00
|
|
|
}
|
2014-02-25 02:42:40 +00:00
|
|
|
|
2021-08-23 10:49:31 +00:00
|
|
|
fn annotate_following_item_if_applicable(
|
|
|
|
&self,
|
2024-02-22 23:20:45 +00:00
|
|
|
err: &mut Diag<'_>,
|
2021-08-23 10:49:31 +00:00
|
|
|
span: Span,
|
|
|
|
attr_type: OuterAttributeType,
|
2024-08-01 16:28:57 +00:00
|
|
|
suggest_to_outer: bool,
|
2021-08-23 10:49:31 +00:00
|
|
|
) -> Option<Span> {
|
2022-03-10 13:11:00 +00:00
|
|
|
let mut snapshot = self.create_snapshot_for_diagnostic();
|
2021-08-23 10:49:31 +00:00
|
|
|
let lo = span.lo()
|
|
|
|
+ BytePos(match attr_type {
|
|
|
|
OuterAttributeType::Attribute => 1,
|
|
|
|
_ => 2,
|
|
|
|
});
|
|
|
|
let hi = lo + BytePos(1);
|
|
|
|
let replacement_span = span.with_lo(lo).with_hi(hi);
|
|
|
|
if let OuterAttributeType::DocBlockComment | OuterAttributeType::DocComment = attr_type {
|
|
|
|
snapshot.bump();
|
|
|
|
}
|
|
|
|
loop {
|
|
|
|
// skip any other attributes, we want the item
|
2024-08-09 07:44:47 +00:00
|
|
|
if snapshot.token == token::Pound {
|
2022-01-26 03:39:14 +00:00
|
|
|
if let Err(err) = snapshot.parse_attribute(InnerAttrPolicy::Permitted) {
|
2021-08-23 10:49:31 +00:00
|
|
|
err.cancel();
|
|
|
|
return Some(replacement_span);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match snapshot.parse_item_common(
|
|
|
|
AttrWrapper::empty(),
|
|
|
|
true,
|
|
|
|
false,
|
2021-12-04 18:05:30 +00:00
|
|
|
FnParseMode { req_name: |_| true, req_body: true },
|
2021-08-23 10:49:31 +00:00
|
|
|
ForceCollect::No,
|
|
|
|
) {
|
|
|
|
Ok(Some(item)) => {
|
2022-08-31 11:20:59 +00:00
|
|
|
// FIXME(#100717)
|
2023-12-23 22:08:41 +00:00
|
|
|
err.arg("item", item.kind.descr());
|
2022-10-13 09:13:02 +00:00
|
|
|
err.span_label(item.span, fluent::parse_label_does_not_annotate_this);
|
2024-08-01 16:28:57 +00:00
|
|
|
if suggest_to_outer {
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
replacement_span,
|
|
|
|
fluent::parse_sugg_change_inner_to_outer,
|
|
|
|
match attr_type {
|
|
|
|
OuterAttributeType::Attribute => "",
|
|
|
|
OuterAttributeType::DocBlockComment => "*",
|
|
|
|
OuterAttributeType::DocComment => "/",
|
|
|
|
},
|
|
|
|
rustc_errors::Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
}
|
2021-08-23 10:49:31 +00:00
|
|
|
return None;
|
|
|
|
}
|
2022-01-26 03:39:14 +00:00
|
|
|
Err(item_err) => {
|
2021-08-23 10:49:31 +00:00
|
|
|
item_err.cancel();
|
|
|
|
}
|
|
|
|
Ok(None) => {}
|
|
|
|
}
|
|
|
|
Some(replacement_span)
|
|
|
|
}
|
|
|
|
|
2024-08-01 16:28:57 +00:00
|
|
|
pub(super) fn error_on_forbidden_inner_attr(
|
|
|
|
&self,
|
|
|
|
attr_sp: Span,
|
|
|
|
policy: InnerAttrPolicy,
|
|
|
|
suggest_to_outer: bool,
|
|
|
|
) {
|
2022-08-31 11:20:59 +00:00
|
|
|
if let InnerAttrPolicy::Forbidden(reason) = policy {
|
|
|
|
let mut diag = match reason.as_ref().copied() {
|
|
|
|
Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => {
|
2024-01-03 05:00:29 +00:00
|
|
|
self.dcx()
|
|
|
|
.struct_span_err(
|
|
|
|
attr_sp,
|
|
|
|
fluent::parse_inner_attr_not_permitted_after_outer_doc_comment,
|
|
|
|
)
|
2024-01-08 22:08:49 +00:00
|
|
|
.with_span_label(attr_sp, fluent::parse_label_attr)
|
|
|
|
.with_span_label(
|
|
|
|
prev_doc_comment_span,
|
|
|
|
fluent::parse_label_prev_doc_comment,
|
|
|
|
)
|
2022-08-31 11:20:59 +00:00
|
|
|
}
|
2024-01-03 05:00:29 +00:00
|
|
|
Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self
|
|
|
|
.dcx()
|
|
|
|
.struct_span_err(
|
2022-08-31 11:20:59 +00:00
|
|
|
attr_sp,
|
2022-11-07 18:47:32 +00:00
|
|
|
fluent::parse_inner_attr_not_permitted_after_outer_attr,
|
2024-01-03 05:00:29 +00:00
|
|
|
)
|
2024-01-08 22:08:49 +00:00
|
|
|
.with_span_label(attr_sp, fluent::parse_label_attr)
|
|
|
|
.with_span_label(prev_outer_attr_sp, fluent::parse_label_prev_attr),
|
2022-08-31 11:20:59 +00:00
|
|
|
Some(InnerAttrForbiddenReason::InCodeBlock) | None => {
|
2023-12-18 10:09:22 +00:00
|
|
|
self.dcx().struct_span_err(attr_sp, fluent::parse_inner_attr_not_permitted)
|
2022-08-31 11:20:59 +00:00
|
|
|
}
|
|
|
|
};
|
2014-02-25 02:42:40 +00:00
|
|
|
|
2022-11-07 18:47:32 +00:00
|
|
|
diag.note(fluent::parse_inner_attr_explanation);
|
2021-08-23 10:49:31 +00:00
|
|
|
if self
|
|
|
|
.annotate_following_item_if_applicable(
|
|
|
|
&mut diag,
|
|
|
|
attr_sp,
|
|
|
|
OuterAttributeType::Attribute,
|
2024-08-01 16:28:57 +00:00
|
|
|
suggest_to_outer,
|
2021-08-23 10:49:31 +00:00
|
|
|
)
|
|
|
|
.is_some()
|
|
|
|
{
|
2022-11-07 18:47:32 +00:00
|
|
|
diag.note(fluent::parse_outer_attr_explanation);
|
2021-08-23 10:49:31 +00:00
|
|
|
};
|
|
|
|
diag.emit();
|
2020-03-05 10:42:56 +00:00
|
|
|
}
|
2012-05-24 20:44:42 +00:00
|
|
|
}
|
2012-04-20 03:51:31 +00:00
|
|
|
|
2019-09-06 02:56:45 +00:00
|
|
|
/// Parses an inner part of an attribute (the path and following tokens).
|
2018-08-12 17:15:59 +00:00
|
|
|
/// The tokens must be either a delimited token stream, or empty token stream,
|
|
|
|
/// or the "legacy" key-value form.
|
2019-09-06 02:56:45 +00:00
|
|
|
/// PATH `(` TOKEN_STREAM `)`
|
|
|
|
/// PATH `[` TOKEN_STREAM `]`
|
|
|
|
/// PATH `{` TOKEN_STREAM `}`
|
|
|
|
/// PATH
|
2019-09-30 21:58:30 +00:00
|
|
|
/// PATH `=` UNSUFFIXED_LIT
|
2018-08-12 17:15:59 +00:00
|
|
|
/// The delimiters or `=` are still put into the resulting token stream.
|
2024-07-17 03:14:35 +00:00
|
|
|
pub fn parse_attr_item(&mut self, force_collect: ForceCollect) -> PResult<'a, ast::AttrItem> {
|
2024-03-19 18:55:44 +00:00
|
|
|
maybe_whole!(self, NtMeta, |attr| attr.into_inner());
|
|
|
|
|
2024-08-06 07:16:40 +00:00
|
|
|
// Attr items don't have attributes.
|
|
|
|
self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| {
|
2024-12-04 04:55:06 +00:00
|
|
|
let is_unsafe = this.eat_keyword(exp!(Unsafe));
|
2024-04-21 04:54:50 +00:00
|
|
|
let unsafety = if is_unsafe {
|
|
|
|
let unsafe_span = this.prev_token.span;
|
2024-12-04 04:55:06 +00:00
|
|
|
this.expect(exp!(OpenParen))?;
|
2024-05-21 13:37:05 +00:00
|
|
|
ast::Safety::Unsafe(unsafe_span)
|
2024-04-21 04:54:50 +00:00
|
|
|
} else {
|
2024-05-21 13:37:05 +00:00
|
|
|
ast::Safety::Default
|
2024-04-21 04:54:50 +00:00
|
|
|
};
|
|
|
|
|
2024-03-19 18:55:44 +00:00
|
|
|
let path = this.parse_path(PathStyle::Mod)?;
|
|
|
|
let args = this.parse_attr_args()?;
|
2024-04-21 04:54:50 +00:00
|
|
|
if is_unsafe {
|
2024-12-04 04:55:06 +00:00
|
|
|
this.expect(exp!(CloseParen))?;
|
2024-04-21 04:54:50 +00:00
|
|
|
}
|
2024-08-06 07:16:40 +00:00
|
|
|
Ok((
|
|
|
|
ast::AttrItem { unsafety, path, args, tokens: None },
|
|
|
|
Trailing::No,
|
|
|
|
UsePreAttrPos::No,
|
|
|
|
))
|
|
|
|
})
|
2017-03-08 23:13:35 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 02:56:45 +00:00
|
|
|
/// Parses attributes that appear after the opening of an item. These should
|
2014-06-09 20:12:30 +00:00
|
|
|
/// be preceded by an exclamation mark, but we accept and warn about one
|
2015-03-13 09:34:51 +00:00
|
|
|
/// terminated by a semicolon.
|
2019-09-06 02:56:45 +00:00
|
|
|
///
|
|
|
|
/// Matches `inner_attrs*`.
|
2024-05-31 03:56:44 +00:00
|
|
|
pub fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
|
2022-08-17 02:34:33 +00:00
|
|
|
let mut attrs = ast::AttrVec::new();
|
2012-06-30 10:54:54 +00:00
|
|
|
loop {
|
2024-07-04 07:50:53 +00:00
|
|
|
let start_pos = self.num_bump_calls;
|
2020-10-22 19:17:40 +00:00
|
|
|
// Only try to parse if it is an inner attribute (has `!`).
|
2024-12-04 04:55:06 +00:00
|
|
|
let attr = if self.check(exp!(Pound)) && self.look_ahead(1, |t| t == &token::Not) {
|
2020-11-05 17:27:48 +00:00
|
|
|
Some(self.parse_attribute(InnerAttrPolicy::Permitted)?)
|
|
|
|
} else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
|
|
|
|
if attr_style == ast::AttrStyle::Inner {
|
|
|
|
self.bump();
|
2022-09-02 08:29:40 +00:00
|
|
|
Some(attr::mk_doc_comment(
|
2024-03-04 05:31:49 +00:00
|
|
|
&self.psess.attr_id_generator,
|
2022-09-02 08:29:40 +00:00
|
|
|
comment_kind,
|
|
|
|
attr_style,
|
|
|
|
data,
|
|
|
|
self.prev_token.span,
|
|
|
|
))
|
2020-03-05 10:42:56 +00:00
|
|
|
} else {
|
2020-11-05 17:27:48 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
if let Some(attr) = attr {
|
2024-07-15 00:37:27 +00:00
|
|
|
// If we are currently capturing tokens (i.e. we are within a call to
|
2024-08-06 07:16:40 +00:00
|
|
|
// `Parser::collect_tokens`) record the token positions of this inner attribute,
|
|
|
|
// for possible later processing in a `LazyAttrTokenStream`.
|
2020-11-28 23:33:17 +00:00
|
|
|
if let Capturing::Yes = self.capture_state.capturing {
|
2024-07-12 05:47:16 +00:00
|
|
|
let end_pos = self.num_bump_calls;
|
2024-07-31 20:44:39 +00:00
|
|
|
let parser_range = ParserRange(start_pos..end_pos);
|
|
|
|
self.capture_state.inner_attr_parser_ranges.insert(attr.id, parser_range);
|
2020-11-28 23:33:17 +00:00
|
|
|
}
|
2020-09-26 23:33:42 +00:00
|
|
|
attrs.push(attr);
|
2020-03-05 10:42:56 +00:00
|
|
|
} else {
|
|
|
|
break;
|
2012-05-24 20:44:42 +00:00
|
|
|
}
|
2012-04-20 03:51:31 +00:00
|
|
|
}
|
2015-10-24 02:02:38 +00:00
|
|
|
Ok(attrs)
|
2012-05-24 20:44:42 +00:00
|
|
|
}
|
|
|
|
|
2022-11-23 04:39:42 +00:00
|
|
|
// Note: must be unsuffixed.
|
|
|
|
pub(crate) fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'a, ast::MetaItemLit> {
|
|
|
|
let lit = self.parse_meta_item_lit()?;
|
2022-10-10 02:40:56 +00:00
|
|
|
debug!("checking if {:?} is unsuffixed", lit);
|
2016-08-20 01:58:14 +00:00
|
|
|
|
2019-09-26 15:56:53 +00:00
|
|
|
if !lit.kind.is_unsuffixed() {
|
2024-05-05 23:25:49 +00:00
|
|
|
self.dcx().emit_err(errors::SuffixedLiteralInAttribute { span: lit.span });
|
2016-08-20 01:58:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(lit)
|
|
|
|
}
|
|
|
|
|
2019-10-08 07:14:07 +00:00
|
|
|
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
|
2024-09-18 15:44:32 +00:00
|
|
|
pub fn parse_cfg_attr(
|
|
|
|
&mut self,
|
2024-10-04 12:59:04 +00:00
|
|
|
) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> {
|
2024-09-18 15:44:32 +00:00
|
|
|
let cfg_predicate = self.parse_meta_item_inner()?;
|
2024-12-04 04:55:06 +00:00
|
|
|
self.expect(exp!(Comma))?;
|
2019-10-08 07:14:07 +00:00
|
|
|
|
|
|
|
// Presumably, the majority of the time there will only be one attr.
|
|
|
|
let mut expanded_attrs = Vec::with_capacity(1);
|
2024-08-09 07:44:47 +00:00
|
|
|
while self.token != token::Eof {
|
2019-12-05 05:45:50 +00:00
|
|
|
let lo = self.token.span;
|
2024-07-17 03:14:35 +00:00
|
|
|
let item = self.parse_attr_item(ForceCollect::Yes)?;
|
2020-02-29 11:56:15 +00:00
|
|
|
expanded_attrs.push((item, lo.to(self.prev_token.span)));
|
2024-12-04 04:55:06 +00:00
|
|
|
if !self.eat(exp!(Comma)) {
|
2019-12-05 13:19:00 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-10-08 07:14:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok((cfg_predicate, expanded_attrs))
|
|
|
|
}
|
|
|
|
|
2019-12-05 13:19:00 +00:00
|
|
|
/// Matches `COMMASEP(meta_item_inner)`.
|
2024-10-04 12:59:04 +00:00
|
|
|
pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> {
|
2019-12-05 13:19:00 +00:00
|
|
|
// Presumably, the majority of the time there will only be one attr.
|
2022-11-23 00:55:16 +00:00
|
|
|
let mut nmis = ThinVec::with_capacity(1);
|
2024-08-09 07:44:47 +00:00
|
|
|
while self.token != token::Eof {
|
2019-12-05 13:19:00 +00:00
|
|
|
nmis.push(self.parse_meta_item_inner()?);
|
2024-12-04 04:55:06 +00:00
|
|
|
if !self.eat(exp!(Comma)) {
|
2019-12-05 13:19:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(nmis)
|
|
|
|
}
|
|
|
|
|
2024-05-05 23:25:49 +00:00
|
|
|
/// Parse a meta item per RFC 1559.
|
|
|
|
///
|
2022-04-15 22:04:34 +00:00
|
|
|
/// ```ebnf
|
2024-05-05 23:25:49 +00:00
|
|
|
/// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ;
|
|
|
|
/// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ;
|
2022-04-15 22:04:34 +00:00
|
|
|
/// ```
|
2024-07-10 00:06:49 +00:00
|
|
|
pub fn parse_meta_item(
|
|
|
|
&mut self,
|
|
|
|
unsafe_allowed: AllowLeadingUnsafe,
|
|
|
|
) -> PResult<'a, ast::MetaItem> {
|
2024-03-19 19:47:59 +00:00
|
|
|
// We can't use `maybe_whole` here because it would bump in the `None`
|
|
|
|
// case, which we don't want.
|
|
|
|
if let token::Interpolated(nt) = &self.token.kind
|
2024-04-22 06:29:27 +00:00
|
|
|
&& let token::NtMeta(attr_item) = &**nt
|
2024-03-19 19:47:59 +00:00
|
|
|
{
|
|
|
|
match attr_item.meta(attr_item.path.span) {
|
2019-08-17 22:10:56 +00:00
|
|
|
Some(meta) => {
|
|
|
|
self.bump();
|
2024-03-15 11:36:21 +00:00
|
|
|
return Ok(meta);
|
2019-08-17 22:10:56 +00:00
|
|
|
}
|
2024-03-15 11:36:21 +00:00
|
|
|
None => self.unexpected()?,
|
2024-03-19 19:47:59 +00:00
|
|
|
}
|
2014-03-26 23:14:07 +00:00
|
|
|
}
|
|
|
|
|
2019-06-07 10:31:13 +00:00
|
|
|
let lo = self.token.span;
|
2024-07-10 00:06:49 +00:00
|
|
|
let is_unsafe = if unsafe_allowed == AllowLeadingUnsafe::Yes {
|
2024-12-04 04:55:06 +00:00
|
|
|
self.eat_keyword(exp!(Unsafe))
|
2024-07-10 00:06:49 +00:00
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
2024-04-21 04:54:50 +00:00
|
|
|
let unsafety = if is_unsafe {
|
|
|
|
let unsafe_span = self.prev_token.span;
|
2024-12-04 04:55:06 +00:00
|
|
|
self.expect(exp!(OpenParen))?;
|
2024-04-21 04:54:50 +00:00
|
|
|
|
2024-05-21 13:37:05 +00:00
|
|
|
ast::Safety::Unsafe(unsafe_span)
|
2024-04-21 04:54:50 +00:00
|
|
|
} else {
|
2024-05-21 13:37:05 +00:00
|
|
|
ast::Safety::Default
|
2024-04-21 04:54:50 +00:00
|
|
|
};
|
|
|
|
|
2019-03-02 16:15:26 +00:00
|
|
|
let path = self.parse_path(PathStyle::Mod)?;
|
2019-09-26 17:04:05 +00:00
|
|
|
let kind = self.parse_meta_item_kind()?;
|
2024-04-21 04:54:50 +00:00
|
|
|
if is_unsafe {
|
2024-12-04 04:55:06 +00:00
|
|
|
self.expect(exp!(CloseParen))?;
|
2024-04-21 04:54:50 +00:00
|
|
|
}
|
2020-02-29 11:56:15 +00:00
|
|
|
let span = lo.to(self.prev_token.span);
|
2024-04-21 04:54:50 +00:00
|
|
|
|
|
|
|
Ok(ast::MetaItem { unsafety, path, kind, span })
|
2017-03-03 09:23:59 +00:00
|
|
|
}
|
|
|
|
|
2022-05-20 23:51:09 +00:00
|
|
|
pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
|
2024-12-04 04:55:06 +00:00
|
|
|
Ok(if self.eat(exp!(Eq)) {
|
2022-11-23 04:39:42 +00:00
|
|
|
ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?)
|
2024-12-04 04:55:06 +00:00
|
|
|
} else if self.check(exp!(OpenParen)) {
|
2019-12-04 09:13:29 +00:00
|
|
|
let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
|
|
|
|
ast::MetaItemKind::List(list)
|
2016-11-15 07:37:10 +00:00
|
|
|
} else {
|
|
|
|
ast::MetaItemKind::Word
|
2017-03-03 09:23:59 +00:00
|
|
|
})
|
2012-04-20 03:51:31 +00:00
|
|
|
}
|
|
|
|
|
2024-05-05 23:25:49 +00:00
|
|
|
/// Parse an inner meta item per RFC 1559.
|
|
|
|
///
|
|
|
|
/// ```ebnf
|
|
|
|
/// MetaItemInner = UNSUFFIXED_LIT | MetaItem ;
|
|
|
|
/// ```
|
2024-10-04 12:59:04 +00:00
|
|
|
pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::MetaItemInner> {
|
2022-11-23 04:39:42 +00:00
|
|
|
match self.parse_unsuffixed_meta_item_lit() {
|
2024-10-04 12:59:04 +00:00
|
|
|
Ok(lit) => return Ok(ast::MetaItemInner::Lit(lit)),
|
2024-05-05 23:25:49 +00:00
|
|
|
Err(err) => err.cancel(), // we provide a better error below
|
2016-08-20 01:58:14 +00:00
|
|
|
}
|
|
|
|
|
2024-07-10 00:06:49 +00:00
|
|
|
match self.parse_meta_item(AllowLeadingUnsafe::No) {
|
2024-10-04 12:59:04 +00:00
|
|
|
Ok(mi) => return Ok(ast::MetaItemInner::MetaItem(mi)),
|
2024-05-05 23:25:49 +00:00
|
|
|
Err(err) => err.cancel(), // we provide a better error below
|
2016-08-20 01:58:14 +00:00
|
|
|
}
|
|
|
|
|
2024-05-05 23:25:49 +00:00
|
|
|
let mut err = errors::InvalidMetaItem {
|
|
|
|
span: self.token.span,
|
|
|
|
token: self.token.clone(),
|
|
|
|
quote_ident_sugg: None,
|
|
|
|
};
|
2023-12-27 02:34:44 +00:00
|
|
|
|
2024-05-05 23:25:49 +00:00
|
|
|
// Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
|
|
|
|
// don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
|
|
|
|
// when macro metavariables are involved.
|
|
|
|
if self.prev_token == token::Eq
|
|
|
|
&& let token::Ident(..) = self.token.kind
|
|
|
|
{
|
2023-12-27 02:34:44 +00:00
|
|
|
let before = self.token.span.shrink_to_lo();
|
2024-05-05 23:25:49 +00:00
|
|
|
while let token::Ident(..) = self.token.kind {
|
2023-12-27 02:34:44 +00:00
|
|
|
self.bump();
|
|
|
|
}
|
2024-05-05 23:25:49 +00:00
|
|
|
err.quote_ident_sugg = Some(errors::InvalidMetaItemQuoteIdentSugg {
|
|
|
|
before,
|
|
|
|
after: self.prev_token.span.shrink_to_hi(),
|
|
|
|
});
|
2023-12-27 02:34:44 +00:00
|
|
|
}
|
|
|
|
|
2024-05-05 23:25:49 +00:00
|
|
|
Err(self.dcx().create_err(err))
|
2016-08-20 01:58:14 +00:00
|
|
|
}
|
2012-04-20 03:51:31 +00:00
|
|
|
}
|