Make more informative error on outer attr after inner
This commit is contained in:
parent
09e3989758
commit
8b3f28cf0f
2 changed files with 37 additions and 17 deletions
|
@ -4,6 +4,7 @@ use crate::parse::{SeqSep, PResult};
|
|||
use crate::parse::token::{self, Nonterminal, DelimToken};
|
||||
use crate::parse::parser::{Parser, TokenType, PathStyle};
|
||||
use crate::tokenstream::{TokenStream, TokenTree};
|
||||
use crate::source_map::Span;
|
||||
|
||||
use log::debug;
|
||||
use smallvec::smallvec;
|
||||
|
@ -11,7 +12,7 @@ use smallvec::smallvec;
|
|||
#[derive(Debug)]
|
||||
enum InnerAttributeParsePolicy<'a> {
|
||||
Permitted,
|
||||
NotPermitted { reason: &'a str },
|
||||
NotPermitted { reason: &'a str, prev_attr_sp: Option<Span> },
|
||||
}
|
||||
|
||||
const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
|
||||
|
@ -42,7 +43,8 @@ impl<'a> Parser<'a> {
|
|||
DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
|
||||
};
|
||||
let inner_parse_policy =
|
||||
InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason };
|
||||
InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason,
|
||||
prev_attr_sp: attrs.last().and_then(|a| Some(a.span)) };
|
||||
let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
|
||||
attrs.push(attr);
|
||||
just_parsed_doc_comment = false;
|
||||
|
@ -77,7 +79,7 @@ impl<'a> Parser<'a> {
|
|||
InnerAttributeParsePolicy::Permitted
|
||||
} else {
|
||||
InnerAttributeParsePolicy::NotPermitted
|
||||
{ reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG }
|
||||
{ reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG, prev_attr_sp: None }
|
||||
};
|
||||
self.parse_attribute_with_inner_parse_policy(inner_parse_policy)
|
||||
}
|
||||
|
@ -98,19 +100,9 @@ impl<'a> Parser<'a> {
|
|||
if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
|
||||
self.expected_tokens.push(TokenType::Token(token::Not));
|
||||
}
|
||||
|
||||
let style = if self.token == token::Not {
|
||||
self.bump();
|
||||
if let InnerAttributeParsePolicy::NotPermitted { reason } = inner_parse_policy
|
||||
{
|
||||
let span = self.token.span;
|
||||
self.diagnostic()
|
||||
.struct_span_err(span, reason)
|
||||
.note("inner attributes, like `#![no_std]`, annotate the item \
|
||||
enclosing them, and are usually found at the beginning of \
|
||||
source files. Outer attributes, like `#[test]`, annotate the \
|
||||
item following them.")
|
||||
.emit()
|
||||
}
|
||||
ast::AttrStyle::Inner
|
||||
} else {
|
||||
ast::AttrStyle::Outer
|
||||
|
@ -121,7 +113,32 @@ impl<'a> Parser<'a> {
|
|||
self.expect(&token::CloseDelim(token::Bracket))?;
|
||||
let hi = self.prev_span;
|
||||
|
||||
(lo.to(hi), path, tokens, style)
|
||||
let attr_sp = lo.to(hi);
|
||||
|
||||
// Emit error if inner attribute is encountered and not permitted
|
||||
if style == ast::AttrStyle::Inner {
|
||||
if let InnerAttributeParsePolicy::NotPermitted { reason, prev_attr_sp }
|
||||
= inner_parse_policy {
|
||||
let mut diagnostic = self
|
||||
.diagnostic()
|
||||
.struct_span_err(attr_sp, reason);
|
||||
|
||||
if let Some(prev_attr_sp) = prev_attr_sp {
|
||||
diagnostic
|
||||
.span_label(attr_sp, "not permitted following an outer attibute")
|
||||
.span_label(prev_attr_sp, "previous outer attribute");
|
||||
}
|
||||
|
||||
diagnostic
|
||||
.note("inner attributes, like `#![no_std]`, annotate the item \
|
||||
enclosing them, and are usually found at the beginning of \
|
||||
source files. Outer attributes, like `#[test]`, annotate the \
|
||||
item following them.")
|
||||
.emit()
|
||||
}
|
||||
}
|
||||
|
||||
(attr_sp, path, tokens, style)
|
||||
}
|
||||
_ => {
|
||||
let token_str = self.this_token_to_string();
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
error: an inner attribute is not permitted following an outer attribute
|
||||
--> $DIR/inner-attr.rs:3:3
|
||||
--> $DIR/inner-attr.rs:3:1
|
||||
|
|
||||
LL | #[feature(lang_items)]
|
||||
| ---------------------- previous outer attribute
|
||||
LL |
|
||||
LL | #![recursion_limit="100"]
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute
|
||||
|
|
||||
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue