Skip to content

Commit 5c70085

Browse files
authored
Rollup merge of rust-lang#63038 - eupn:outer-attribute-diag, r=estebank
Make more informative error on outer attribute after inner Fixes rust-lang#61218. ?r @estebank
2 parents c3c0309 + 693be44 commit 5c70085

File tree

5 files changed

+62
-25
lines changed

5 files changed

+62
-25
lines changed

src/libsyntax/parse/attr.rs

+45-16
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use crate::parse::{SeqSep, PResult};
44
use crate::parse::token::{self, Nonterminal, DelimToken};
55
use crate::parse::parser::{Parser, TokenType, PathStyle};
66
use crate::tokenstream::{TokenStream, TokenTree};
7+
use crate::source_map::Span;
78

89
use log::debug;
910
use smallvec::smallvec;
1011

1112
#[derive(Debug)]
1213
enum InnerAttributeParsePolicy<'a> {
1314
Permitted,
14-
NotPermitted { reason: &'a str },
15+
NotPermitted { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
1516
}
1617

1718
const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
@@ -42,7 +43,11 @@ impl<'a> Parser<'a> {
4243
DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
4344
};
4445
let inner_parse_policy =
45-
InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason };
46+
InnerAttributeParsePolicy::NotPermitted {
47+
reason: inner_error_reason,
48+
saw_doc_comment: just_parsed_doc_comment,
49+
prev_attr_sp: attrs.last().and_then(|a| Some(a.span))
50+
};
4651
let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
4752
attrs.push(attr);
4853
just_parsed_doc_comment = false;
@@ -76,8 +81,11 @@ impl<'a> Parser<'a> {
7681
let inner_parse_policy = if permit_inner {
7782
InnerAttributeParsePolicy::Permitted
7883
} else {
79-
InnerAttributeParsePolicy::NotPermitted
80-
{ reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG }
84+
InnerAttributeParsePolicy::NotPermitted {
85+
reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
86+
saw_doc_comment: false,
87+
prev_attr_sp: None
88+
}
8189
};
8290
self.parse_attribute_with_inner_parse_policy(inner_parse_policy)
8391
}
@@ -98,19 +106,9 @@ impl<'a> Parser<'a> {
98106
if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
99107
self.expected_tokens.push(TokenType::Token(token::Not));
100108
}
109+
101110
let style = if self.token == token::Not {
102111
self.bump();
103-
if let InnerAttributeParsePolicy::NotPermitted { reason } = inner_parse_policy
104-
{
105-
let span = self.token.span;
106-
self.diagnostic()
107-
.struct_span_err(span, reason)
108-
.note("inner attributes, like `#![no_std]`, annotate the item \
109-
enclosing them, and are usually found at the beginning of \
110-
source files. Outer attributes, like `#[test]`, annotate the \
111-
item following them.")
112-
.emit()
113-
}
114112
ast::AttrStyle::Inner
115113
} else {
116114
ast::AttrStyle::Outer
@@ -121,7 +119,38 @@ impl<'a> Parser<'a> {
121119
self.expect(&token::CloseDelim(token::Bracket))?;
122120
let hi = self.prev_span;
123121

124-
(lo.to(hi), path, tokens, style)
122+
let attr_sp = lo.to(hi);
123+
124+
// Emit error if inner attribute is encountered and not permitted
125+
if style == ast::AttrStyle::Inner {
126+
if let InnerAttributeParsePolicy::NotPermitted { reason,
127+
saw_doc_comment, prev_attr_sp } = inner_parse_policy {
128+
let prev_attr_note = if saw_doc_comment {
129+
"previous doc comment"
130+
} else {
131+
"previous outer attribute"
132+
};
133+
134+
let mut diagnostic = self
135+
.diagnostic()
136+
.struct_span_err(attr_sp, reason);
137+
138+
if let Some(prev_attr_sp) = prev_attr_sp {
139+
diagnostic
140+
.span_label(attr_sp, "not permitted following an outer attibute")
141+
.span_label(prev_attr_sp, prev_attr_note);
142+
}
143+
144+
diagnostic
145+
.note("inner attributes, like `#![no_std]`, annotate the item \
146+
enclosing them, and are usually found at the beginning of \
147+
source files. Outer attributes, like `#[test]`, annotate the \
148+
item following them.")
149+
.emit()
150+
}
151+
}
152+
153+
(attr_sp, path, tokens, style)
125154
}
126155
_ => {
127156
let token_str = self.this_token_to_string();

src/test/ui/issues/issue-45296.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: an inner attribute is not permitted in this context
2-
--> $DIR/issue-45296.rs:4:7
2+
--> $DIR/issue-45296.rs:4:5
33
|
44
LL | #![allow(unused_variables)]
5-
| ^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= 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.
88

src/test/ui/parser/attr.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: an inner attribute is not permitted in this context
2-
--> $DIR/attr.rs:5:3
2+
--> $DIR/attr.rs:5:1
33
|
44
LL | #![lang = "foo"]
5-
| ^
5+
| ^^^^^^^^^^^^^^^^
66
|
77
= 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.
88

src/test/ui/parser/inner-attr-after-doc-comment.stderr

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
error: an inner attribute is not permitted following an outer doc comment
2-
--> $DIR/inner-attr-after-doc-comment.rs:6:3
2+
--> $DIR/inner-attr-after-doc-comment.rs:6:1
33
|
4-
LL | #![recursion_limit="100"]
5-
| ^
4+
LL | / /**
5+
LL | | * My module
6+
LL | | */
7+
| |___- previous doc comment
8+
LL |
9+
LL | #![recursion_limit="100"]
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute
611
|
712
= 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.
813

src/test/ui/parser/inner-attr.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
error: an inner attribute is not permitted following an outer attribute
2-
--> $DIR/inner-attr.rs:3:3
2+
--> $DIR/inner-attr.rs:3:1
33
|
4+
LL | #[feature(lang_items)]
5+
| ---------------------- previous outer attribute
6+
LL |
47
LL | #![recursion_limit="100"]
5-
| ^
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute
69
|
710
= 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.
811

0 commit comments

Comments
 (0)