1
Fork 0

Make more informative error on outer attr after inner

This commit is contained in:
Evgenii P 2019-07-27 16:45:45 +07:00
parent 09e3989758
commit 8b3f28cf0f
2 changed files with 37 additions and 17 deletions

View file

@ -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();

View file

@ -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.