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::token::{self, Nonterminal, DelimToken};
|
||||||
use crate::parse::parser::{Parser, TokenType, PathStyle};
|
use crate::parse::parser::{Parser, TokenType, PathStyle};
|
||||||
use crate::tokenstream::{TokenStream, TokenTree};
|
use crate::tokenstream::{TokenStream, TokenTree};
|
||||||
|
use crate::source_map::Span;
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
@ -11,7 +12,7 @@ use smallvec::smallvec;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum InnerAttributeParsePolicy<'a> {
|
enum InnerAttributeParsePolicy<'a> {
|
||||||
Permitted,
|
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 \
|
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
|
DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
|
||||||
};
|
};
|
||||||
let inner_parse_policy =
|
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)?;
|
let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
|
||||||
attrs.push(attr);
|
attrs.push(attr);
|
||||||
just_parsed_doc_comment = false;
|
just_parsed_doc_comment = false;
|
||||||
|
@ -77,7 +79,7 @@ impl<'a> Parser<'a> {
|
||||||
InnerAttributeParsePolicy::Permitted
|
InnerAttributeParsePolicy::Permitted
|
||||||
} else {
|
} else {
|
||||||
InnerAttributeParsePolicy::NotPermitted
|
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)
|
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 {
|
if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
|
||||||
self.expected_tokens.push(TokenType::Token(token::Not));
|
self.expected_tokens.push(TokenType::Token(token::Not));
|
||||||
}
|
}
|
||||||
|
|
||||||
let style = if self.token == token::Not {
|
let style = if self.token == token::Not {
|
||||||
self.bump();
|
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
|
ast::AttrStyle::Inner
|
||||||
} else {
|
} else {
|
||||||
ast::AttrStyle::Outer
|
ast::AttrStyle::Outer
|
||||||
|
@ -121,7 +113,32 @@ impl<'a> Parser<'a> {
|
||||||
self.expect(&token::CloseDelim(token::Bracket))?;
|
self.expect(&token::CloseDelim(token::Bracket))?;
|
||||||
let hi = self.prev_span;
|
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();
|
let token_str = self.this_token_to_string();
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
error: an inner attribute is not permitted following an outer attribute
|
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"]
|
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.
|
= 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