Skip to content

Commit 648d644

Browse files
authored
Rollup merge of #95189 - fmease:fix-issue-94340, r=estebank
Stop flagging unexpected inner attributes as outer ones in certain diagnostics Fixes #94340. In the issue to-be-fixed I write that the general message _an inner attribute is not permitted in this context_ should be more specific noting that the “context” is the `include` macro. This, however, cannot be achieved without touching a lot of things and passing a flag to the `parse_expr` and `parse_item` calls in `expand_include`. This seems rather hacky to me. That's why I left it as it. `Span::from_expansion` does not apply either AFAIK. `@rustbot` label A-diagnostics T-compiler
2 parents 8cd6080 + 5ab0548 commit 648d644

File tree

7 files changed

+54
-25
lines changed

7 files changed

+54
-25
lines changed

compiler/rustc_builtin_macros/src/source_util.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -141,17 +141,20 @@ pub fn expand_include<'cx>(
141141

142142
fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
143143
let mut ret = SmallVec::new();
144-
while self.p.token != token::Eof {
144+
loop {
145145
match self.p.parse_item(ForceCollect::No) {
146146
Err(mut err) => {
147147
err.emit();
148148
break;
149149
}
150150
Ok(Some(item)) => ret.push(item),
151151
Ok(None) => {
152-
let token = pprust::token_to_string(&self.p.token);
153-
let msg = format!("expected item, found `{}`", token);
154-
self.p.struct_span_err(self.p.token.span, &msg).emit();
152+
if self.p.token != token::Eof {
153+
let token = pprust::token_to_string(&self.p.token);
154+
let msg = format!("expected item, found `{}`", token);
155+
self.p.struct_span_err(self.p.token.span, &msg).emit();
156+
}
157+
155158
break;
156159
}
157160
}

compiler/rustc_parse/src/parser/attr.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use tracing::debug;
1313
#[derive(Debug)]
1414
pub enum InnerAttrPolicy<'a> {
1515
Permitted,
16-
Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
16+
Forbidden { reason: &'a str, saw_doc_comment: bool, prev_outer_attr_sp: Option<Span> },
1717
}
1818

1919
const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
@@ -22,7 +22,7 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
2222
pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden {
2323
reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
2424
saw_doc_comment: false,
25-
prev_attr_sp: None,
25+
prev_outer_attr_sp: None,
2626
};
2727

2828
enum OuterAttributeType {
@@ -34,22 +34,24 @@ enum OuterAttributeType {
3434
impl<'a> Parser<'a> {
3535
/// Parses attributes that appear before an item.
3636
pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
37-
let mut attrs: Vec<ast::Attribute> = Vec::new();
37+
let mut outer_attrs: Vec<ast::Attribute> = Vec::new();
3838
let mut just_parsed_doc_comment = false;
3939
let start_pos = self.token_cursor.num_next_calls;
4040
loop {
4141
let attr = if self.check(&token::Pound) {
42+
let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span);
43+
4244
let inner_error_reason = if just_parsed_doc_comment {
4345
"an inner attribute is not permitted following an outer doc comment"
44-
} else if !attrs.is_empty() {
46+
} else if prev_outer_attr_sp.is_some() {
4547
"an inner attribute is not permitted following an outer attribute"
4648
} else {
4749
DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
4850
};
4951
let inner_parse_policy = InnerAttrPolicy::Forbidden {
5052
reason: inner_error_reason,
5153
saw_doc_comment: just_parsed_doc_comment,
52-
prev_attr_sp: attrs.last().map(|a| a.span),
54+
prev_outer_attr_sp,
5355
};
5456
just_parsed_doc_comment = false;
5557
Some(self.parse_attribute(inner_parse_policy)?)
@@ -97,12 +99,14 @@ impl<'a> Parser<'a> {
9799
};
98100

99101
if let Some(attr) = attr {
100-
attrs.push(attr);
102+
if attr.style == ast::AttrStyle::Outer {
103+
outer_attrs.push(attr);
104+
}
101105
} else {
102106
break;
103107
}
104108
}
105-
Ok(AttrWrapper::new(attrs.into(), start_pos))
109+
Ok(AttrWrapper::new(outer_attrs.into(), start_pos))
106110
}
107111

108112
/// Matches `attribute = # ! [ meta_item ]`.
@@ -215,15 +219,15 @@ impl<'a> Parser<'a> {
215219
}
216220

217221
pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
218-
if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy {
219-
let prev_attr_note =
222+
if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_outer_attr_sp } = policy {
223+
let prev_outer_attr_note =
220224
if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" };
221225

222226
let mut diag = self.struct_span_err(attr_sp, reason);
223227

224-
if let Some(prev_attr_sp) = prev_attr_sp {
228+
if let Some(prev_outer_attr_sp) = prev_outer_attr_sp {
225229
diag.span_label(attr_sp, "not permitted following an outer attribute")
226-
.span_label(prev_attr_sp, prev_attr_note);
230+
.span_label(prev_outer_attr_sp, prev_outer_attr_note);
227231
}
228232

229233
diag.note(

src/test/ui/parser/attr.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@
33
fn main() {}
44

55
#![lang = "foo"] //~ ERROR an inner attribute is not permitted in this context
6-
//~| ERROR definition of an unknown language item: `foo`
76
fn foo() {}

src/test/ui/parser/attr.stderr

+1-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ error: an inner attribute is not permitted in this context
33
|
44
LL | #![lang = "foo"]
55
| ^^^^^^^^^^^^^^^^
6-
LL |
76
LL | fn foo() {}
87
| ----------- the inner attribute doesn't annotate this function
98
|
@@ -14,12 +13,5 @@ LL - #![lang = "foo"]
1413
LL + #[lang = "foo"]
1514
|
1615

17-
error[E0522]: definition of an unknown language item: `foo`
18-
--> $DIR/attr.rs:5:1
19-
|
20-
LL | #![lang = "foo"]
21-
| ^^^^^^^^^^^^^^^^ definition of unknown language item `foo`
22-
23-
error: aborting due to 2 previous errors
16+
error: aborting due to previous error
2417

25-
For more information about this error, try `rustc --explain E0522`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// include file for issue-94340.rs
2+
#![deny(rust_2018_idioms)]
3+
#![deny(unused_must_use)]
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Make sure that unexpected inner attributes are not labeled as outer ones in diagnostics when
2+
// trying to parse an item and that they are subsequently ignored not triggering confusing extra
3+
// diagnostics like "expected item after attributes" which is not true for `include!` which can
4+
// include empty files.
5+
6+
include!("auxiliary/issue-94340-inc.rs");
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: an inner attribute is not permitted in this context
2+
--> $DIR/auxiliary/issue-94340-inc.rs:2:1
3+
|
4+
LL | #![deny(rust_2018_idioms)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
8+
= note: outer attributes, like `#[test]`, annotate the item following them
9+
10+
error: an inner attribute is not permitted in this context
11+
--> $DIR/auxiliary/issue-94340-inc.rs:3:1
12+
|
13+
LL | #![deny(unused_must_use)]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
17+
= note: outer attributes, like `#[test]`, annotate the item following them
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)