From 5ab0548500a30134496ba28eb2291b0523b7346a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 22 Mar 2022 00:36:47 +0100 Subject: [PATCH] Stop flagging certain inner attrs as outer ones --- .../rustc_builtin_macros/src/source_util.rs | 11 +++++--- compiler/rustc_parse/src/parser/attr.rs | 26 +++++++++++-------- src/test/ui/parser/attr.rs | 1 - src/test/ui/parser/attr.stderr | 10 +------ .../issues/auxiliary/issue-94340-inc.rs | 3 +++ src/test/ui/parser/issues/issue-94340.rs | 8 ++++++ src/test/ui/parser/issues/issue-94340.stderr | 20 ++++++++++++++ 7 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs create mode 100644 src/test/ui/parser/issues/issue-94340.rs create mode 100644 src/test/ui/parser/issues/issue-94340.stderr diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index be628c9202cbd..ece250f61d54f 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -141,7 +141,7 @@ pub fn expand_include<'cx>( fn make_items(mut self: Box>) -> Option; 1]>> { let mut ret = SmallVec::new(); - while self.p.token != token::Eof { + loop { match self.p.parse_item(ForceCollect::No) { Err(mut err) => { err.emit(); @@ -149,9 +149,12 @@ pub fn expand_include<'cx>( } Ok(Some(item)) => ret.push(item), Ok(None) => { - let token = pprust::token_to_string(&self.p.token); - let msg = format!("expected item, found `{}`", token); - self.p.struct_span_err(self.p.token.span, &msg).emit(); + if self.p.token != token::Eof { + let token = pprust::token_to_string(&self.p.token); + let msg = format!("expected item, found `{}`", token); + self.p.struct_span_err(self.p.token.span, &msg).emit(); + } + break; } } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 9865588cff4f5..1724bab5caa43 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -13,7 +13,7 @@ use tracing::debug; #[derive(Debug)] pub enum InnerAttrPolicy<'a> { Permitted, - Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option }, + Forbidden { reason: &'a str, saw_doc_comment: bool, prev_outer_attr_sp: Option }, } 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 \ pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden { reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG, saw_doc_comment: false, - prev_attr_sp: None, + prev_outer_attr_sp: None, }; enum OuterAttributeType { @@ -34,14 +34,16 @@ enum OuterAttributeType { impl<'a> Parser<'a> { /// Parses attributes that appear before an item. pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { - let mut attrs: Vec = Vec::new(); + let mut outer_attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; let start_pos = self.token_cursor.num_next_calls; loop { let attr = if self.check(&token::Pound) { + let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span); + let inner_error_reason = if just_parsed_doc_comment { "an inner attribute is not permitted following an outer doc comment" - } else if !attrs.is_empty() { + } else if prev_outer_attr_sp.is_some() { "an inner attribute is not permitted following an outer attribute" } else { DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG @@ -49,7 +51,7 @@ impl<'a> Parser<'a> { let inner_parse_policy = InnerAttrPolicy::Forbidden { reason: inner_error_reason, saw_doc_comment: just_parsed_doc_comment, - prev_attr_sp: attrs.last().map(|a| a.span), + prev_outer_attr_sp, }; just_parsed_doc_comment = false; Some(self.parse_attribute(inner_parse_policy)?) @@ -97,12 +99,14 @@ impl<'a> Parser<'a> { }; if let Some(attr) = attr { - attrs.push(attr); + if attr.style == ast::AttrStyle::Outer { + outer_attrs.push(attr); + } } else { break; } } - Ok(AttrWrapper::new(attrs.into(), start_pos)) + Ok(AttrWrapper::new(outer_attrs.into(), start_pos)) } /// Matches `attribute = # ! [ meta_item ]`. @@ -215,15 +219,15 @@ impl<'a> Parser<'a> { } pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) { - if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy { - let prev_attr_note = + if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_outer_attr_sp } = policy { + let prev_outer_attr_note = if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" }; let mut diag = self.struct_span_err(attr_sp, reason); - if let Some(prev_attr_sp) = prev_attr_sp { + if let Some(prev_outer_attr_sp) = prev_outer_attr_sp { diag.span_label(attr_sp, "not permitted following an outer attribute") - .span_label(prev_attr_sp, prev_attr_note); + .span_label(prev_outer_attr_sp, prev_outer_attr_note); } diag.note( diff --git a/src/test/ui/parser/attr.rs b/src/test/ui/parser/attr.rs index 91a4abbd03860..42b2dfde85577 100644 --- a/src/test/ui/parser/attr.rs +++ b/src/test/ui/parser/attr.rs @@ -3,5 +3,4 @@ fn main() {} #![lang = "foo"] //~ ERROR an inner attribute is not permitted in this context - //~| ERROR definition of an unknown language item: `foo` fn foo() {} diff --git a/src/test/ui/parser/attr.stderr b/src/test/ui/parser/attr.stderr index 3cec61fe41eea..3527274bd0f8c 100644 --- a/src/test/ui/parser/attr.stderr +++ b/src/test/ui/parser/attr.stderr @@ -3,7 +3,6 @@ error: an inner attribute is not permitted in this context | LL | #![lang = "foo"] | ^^^^^^^^^^^^^^^^ -LL | LL | fn foo() {} | ----------- the inner attribute doesn't annotate this function | @@ -14,12 +13,5 @@ LL - #![lang = "foo"] LL + #[lang = "foo"] | -error[E0522]: definition of an unknown language item: `foo` - --> $DIR/attr.rs:5:1 - | -LL | #![lang = "foo"] - | ^^^^^^^^^^^^^^^^ definition of unknown language item `foo` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0522`. diff --git a/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs b/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs new file mode 100644 index 0000000000000..9429e514339cf --- /dev/null +++ b/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs @@ -0,0 +1,3 @@ +// include file for issue-94340.rs +#![deny(rust_2018_idioms)] +#![deny(unused_must_use)] diff --git a/src/test/ui/parser/issues/issue-94340.rs b/src/test/ui/parser/issues/issue-94340.rs new file mode 100644 index 0000000000000..d0fb84a689a33 --- /dev/null +++ b/src/test/ui/parser/issues/issue-94340.rs @@ -0,0 +1,8 @@ +// Make sure that unexpected inner attributes are not labeled as outer ones in diagnostics when +// trying to parse an item and that they are subsequently ignored not triggering confusing extra +// diagnostics like "expected item after attributes" which is not true for `include!` which can +// include empty files. + +include!("auxiliary/issue-94340-inc.rs"); + +fn main() {} diff --git a/src/test/ui/parser/issues/issue-94340.stderr b/src/test/ui/parser/issues/issue-94340.stderr new file mode 100644 index 0000000000000..9fd7c38a80b77 --- /dev/null +++ b/src/test/ui/parser/issues/issue-94340.stderr @@ -0,0 +1,20 @@ +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:2:1 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:3:1 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: aborting due to 2 previous errors +