diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 95abf55291506..85277bcca4df4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -24,7 +24,7 @@ pub use UnsafeSource::*; use crate::ptr::P; use crate::token::{self, CommentKind, DelimToken}; -use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; +use crate::tokenstream::{DelimSpan, PreexpTokenStream, TokenStream, TokenTree}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; @@ -926,10 +926,8 @@ impl Stmt { self.kind = match self.kind { StmtKind::Expr(expr) => StmtKind::Semi(expr), StmtKind::MacCall(mac) => { - StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs }| MacCallStmt { - mac, - style: MacStmtStyle::Semicolon, - attrs, + StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs, tokens }| { + MacCallStmt { mac, style: MacStmtStyle::Semicolon, attrs, tokens } })) } kind => kind, @@ -973,6 +971,7 @@ pub struct MacCallStmt { pub mac: MacCall, pub style: MacStmtStyle, pub attrs: AttrVec, + pub tokens: Option, } #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)] @@ -998,6 +997,7 @@ pub struct Local { pub init: Option>, pub span: Span, pub attrs: AttrVec, + pub tokens: Option, } /// An arm of a 'match'. @@ -1066,7 +1066,7 @@ pub struct Expr { pub kind: ExprKind, pub span: Span, pub attrs: AttrVec, - pub tokens: Option, + pub tokens: Option, } // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -2436,6 +2436,7 @@ pub struct Attribute { /// or the construct this attribute is contained within (inner). pub style: AttrStyle, pub span: Span, + pub tokens: Option, } #[derive(Clone, Encodable, Decodable, Debug)] @@ -2582,7 +2583,7 @@ pub struct Item { /// /// Note that the tokens here do not include the outer attributes, but will /// include inner attributes. - pub tokens: Option, + pub tokens: Option, } impl Item { diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 2782869fb885a..c1dc03fa417f5 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -8,7 +8,7 @@ use crate::ast::{Path, PathSegment}; use crate::mut_visit::visit_clobber; use crate::ptr::P; use crate::token::{self, CommentKind, Token}; -use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing}; +use crate::tokenstream::{DelimSpan, PreexpTokenStream, TokenStream, TokenTree, TreeAndSpacing}; use rustc_index::bit_set::GrowableBitSet; use rustc_span::source_map::{BytePos, Spanned}; @@ -334,7 +334,7 @@ pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attri } pub fn mk_attr_from_item(style: AttrStyle, item: AttrItem, span: Span) -> Attribute { - Attribute { kind: AttrKind::Normal(item), id: mk_attr_id(), style, span } + Attribute { kind: AttrKind::Normal(item), id: mk_attr_id(), style, span, tokens: None } } /// Returns an inner attribute with the given value and span. @@ -353,7 +353,13 @@ pub fn mk_doc_comment( data: Symbol, span: Span, ) -> Attribute { - Attribute { kind: AttrKind::DocComment(comment_kind, data), id: mk_attr_id(), style, span } + Attribute { + kind: AttrKind::DocComment(comment_kind, data), + id: mk_attr_id(), + style, + span, + tokens: None, + } } pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool { @@ -585,6 +591,7 @@ impl NestedMetaItem { pub trait HasAttrs: Sized { fn attrs(&self) -> &[Attribute]; fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)); + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)); } impl HasAttrs for Spanned { @@ -594,6 +601,9 @@ impl HasAttrs for Spanned { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { self.node.visit_attrs(f); } + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)) { + self.node.visit_tokens(f) + } } impl HasAttrs for Vec { @@ -603,6 +613,7 @@ impl HasAttrs for Vec { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { f(self) } + fn visit_tokens(&mut self, _f: impl FnOnce(&mut PreexpTokenStream)) {} } impl HasAttrs for AttrVec { @@ -616,6 +627,7 @@ impl HasAttrs for AttrVec { vec.into() }); } + fn visit_tokens(&mut self, _f: impl FnOnce(&mut PreexpTokenStream)) {} } impl HasAttrs for P { @@ -625,6 +637,21 @@ impl HasAttrs for P { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { (**self).visit_attrs(f); } + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)) { + (**self).visit_tokens(f) + } +} + +impl HasAttrs for Option { + fn attrs(&self) -> &[Attribute] { + self.as_ref().map_or(&[], |inner| inner.attrs()) + } + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + self.as_mut().map(|inner| inner.visit_attrs(f)); + } + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)) { + self.as_mut().map(|inner| inner.visit_tokens(f)); + } } impl HasAttrs for StmtKind { @@ -632,7 +659,8 @@ impl HasAttrs for StmtKind { match *self { StmtKind::Local(ref local) => local.attrs(), StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), - StmtKind::Empty | StmtKind::Item(..) => &[], + StmtKind::Item(..) => &[], + StmtKind::Empty => &[], StmtKind::MacCall(ref mac) => mac.attrs.attrs(), } } @@ -641,12 +669,24 @@ impl HasAttrs for StmtKind { match self { StmtKind::Local(local) => local.visit_attrs(f), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), - StmtKind::Empty | StmtKind::Item(..) => {} + StmtKind::Item(item) => item.visit_attrs(f), + StmtKind::Empty => {} StmtKind::MacCall(mac) => { mac.attrs.visit_attrs(f); } } } + + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)) { + match self { + StmtKind::Local(local) => local.visit_tokens(f), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_tokens(f), + // FIXME: Is this correct? + StmtKind::Item(item) => item.visit_tokens(f), + StmtKind::Empty => {} + StmtKind::MacCall(mac) => mac.attrs.visit_tokens(f), + } + } } impl HasAttrs for Stmt { @@ -657,6 +697,9 @@ impl HasAttrs for Stmt { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { self.kind.visit_attrs(f); } + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)) { + self.kind.visit_tokens(f); + } } macro_rules! derive_has_attrs { @@ -669,11 +712,36 @@ macro_rules! derive_has_attrs { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { self.attrs.visit_attrs(f); } + fn visit_tokens(&mut self, _f: impl FnOnce(&mut PreexpTokenStream)) {} + } + )* } +} + +macro_rules! derive_has_attrs_with_tokens { + ($($ty:path),*) => { $( + impl HasAttrs for $ty { + fn attrs(&self) -> &[Attribute] { + &self.attrs + } + + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + self.attrs.visit_attrs(f); + } + + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)) { + if let Some(tokens) = self.tokens.as_mut() { + f(tokens) + } + } } )* } } derive_has_attrs! { - Item, Expr, Local, ast::AssocItem, ast::ForeignItem, ast::StructField, ast::Arm, + ast::StructField, ast::Arm, ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam } + +derive_has_attrs_with_tokens! { + Expr, Item, Local, ast::AssocItem, ast::ForeignItem +} diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 425ef83b57af5..eda6a133356fe 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -567,7 +567,7 @@ pub fn noop_visit_parenthesized_parameter_data( } pub fn noop_visit_local(local: &mut P, vis: &mut T) { - let Local { id, pat, ty, init, span, attrs } = local.deref_mut(); + let Local { id, pat, ty, init, span, attrs, tokens: _ } = local.deref_mut(); vis.visit_id(id); vis.visit_pat(pat); visit_opt(ty, |ty| vis.visit_ty(ty)); @@ -577,7 +577,7 @@ pub fn noop_visit_local(local: &mut P, vis: &mut T) { } pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { - let Attribute { kind, id: _, style: _, span } = attr; + let Attribute { kind, id: _, style: _, span, tokens: _ } = attr; match kind { AttrKind::Normal(AttrItem { path, args, tokens: _ }) => { vis.visit_path(path); @@ -1311,7 +1311,7 @@ pub fn noop_flat_map_stmt_kind( StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(), StmtKind::Empty => smallvec![StmtKind::Empty], StmtKind::MacCall(mut mac) => { - let MacCallStmt { mac: mac_, style: _, attrs } = mac.deref_mut(); + let MacCallStmt { mac: mac_, style: _, attrs, tokens: _ } = mac.deref_mut(); vis.visit_mac(mac_); visit_thin_attrs(attrs, vis); smallvec![StmtKind::MacCall(mac)] diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index f201f0b5c6643..7db1331c62a23 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -403,6 +403,10 @@ impl Cursor { pub fn look_ahead(&self, n: usize) -> Option { self.stream.0[self.index..].get(n).map(|(tree, _)| tree.clone()) } + + pub fn index(&self) -> usize { + self.index + } } #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] @@ -428,3 +432,85 @@ impl DelimSpan { self.open.with_hi(self.close.hi()) } } + +#[derive(Clone, Debug, Default, Encodable, Decodable)] +pub struct PreexpTokenStream(pub Lrc>); + +#[derive(Clone, Debug, Encodable, Decodable)] +pub enum PreexpTokenTree { + Token(Token), + Delimited(DelimSpan, DelimToken, PreexpTokenStream), + OuterAttributes(AttributesData), +} + +impl PreexpTokenStream { + pub fn new(tokens: Vec<(PreexpTokenTree, Spacing)>) -> PreexpTokenStream { + PreexpTokenStream(Lrc::new(tokens)) + } + + pub fn replace_attributes(&mut self, f: impl FnOnce(&mut AttributesData)) { + if let &[(PreexpTokenTree::OuterAttributes(ref data), joint)] = &**self.0 { + let mut data = data.clone(); + f(&mut data); + *self = PreexpTokenStream::new(vec![(PreexpTokenTree::OuterAttributes(data), joint)]); + } else { + panic!("Expected a single PreexpTokenTree::OuterAttributes, found {:?}", self); + } + } + + pub fn to_tokenstream(self) -> TokenStream { + let trees: Vec<_> = self + .0 + .iter() + .flat_map(|tree| match &tree.0 { + PreexpTokenTree::Token(inner) => { + smallvec![(TokenTree::Token(inner.clone()), tree.1)].into_iter() + } + PreexpTokenTree::Delimited(span, delim, stream) => smallvec![( + TokenTree::Delimited(*span, *delim, stream.clone().to_tokenstream()), + tree.1, + )] + .into_iter(), + PreexpTokenTree::OuterAttributes(data) => { + let flat: SmallVec<[_; 1]> = data + .attrs + .iter() + .filter(|attr| attr.style == crate::AttrStyle::Outer) + .flat_map(|attr| { + attr.tokens.as_ref().expect("Missing tokens").0.iter().cloned() + }) + .chain(data.tokens.clone().to_tokenstream().0.iter().cloned()) + .collect(); + flat.into_iter() + } + }) + .collect(); + TokenStream::new(trees) + } + + pub fn from_tokenstream(stream: TokenStream) -> PreexpTokenStream { + let trees: Vec<_> = stream + .0 + .iter() + .cloned() + .map(|tree| { + let new_tree = match tree.0 { + TokenTree::Token(token) => PreexpTokenTree::Token(token), + TokenTree::Delimited(sp, delim, inner) => PreexpTokenTree::Delimited( + sp, + delim, + PreexpTokenStream::from_tokenstream(inner), + ), + }; + (new_tree, tree.1) + }) + .collect(); + PreexpTokenStream::new(trees) + } +} + +#[derive(Clone, Debug, Encodable, Decodable)] +pub struct AttributesData { + pub attrs: Vec, + pub tokens: PreexpTokenStream, +} diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 86fd87f6c42c5..0becd658f41ee 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -692,7 +692,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr), StmtKind::Empty => {} StmtKind::MacCall(ref mac) => { - let MacCallStmt { ref mac, style: _, ref attrs } = **mac; + let MacCallStmt { ref mac, style: _, ref attrs, tokens: _ } = **mac; visitor.visit_mac(mac); for attr in attrs.iter() { visitor.visit_attribute(attr); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a28d022c66139..eda5bfb521926 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -972,7 +972,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data), }; - Attribute { kind, id: attr.id, style: attr.style, span: attr.span } + Attribute { kind, id: attr.id, style: attr.style, span: attr.span, tokens: None } } fn lower_mac_args(&mut self, args: &MacArgs) -> MacArgs { diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index d84b3956475d8..a51c797331f4a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -132,6 +132,7 @@ fn stmt_let_underscore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P) -> as id: ast::DUMMY_NODE_ID, span: sp, attrs: ast::AttrVec::new(), + tokens: None, }); ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp, tokens: None } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 926e3dbfc5266..73fb5528973e2 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -4,7 +4,7 @@ use crate::module::DirectoryOwnership; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token; -use rustc_ast::tokenstream::{self, TokenStream}; +use rustc_ast::tokenstream::{self, PreexpTokenStream, TokenStream}; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_ast::{self as ast, Attribute, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; @@ -81,6 +81,24 @@ impl HasAttrs for Annotatable { Annotatable::Variant(v) => v.visit_attrs(f), } } + + fn visit_tokens(&mut self, f: impl FnOnce(&mut PreexpTokenStream)) { + match self { + Annotatable::Item(item) => item.visit_tokens(f), + Annotatable::TraitItem(trait_item) => trait_item.visit_tokens(f), + Annotatable::ImplItem(impl_item) => impl_item.visit_tokens(f), + Annotatable::ForeignItem(foreign_item) => foreign_item.visit_tokens(f), + Annotatable::Stmt(stmt) => stmt.visit_tokens(f), + Annotatable::Expr(expr) => expr.visit_tokens(f), + Annotatable::Arm(arm) => arm.visit_tokens(f), + Annotatable::Field(field) => field.visit_tokens(f), + Annotatable::FieldPat(fp) => fp.visit_tokens(f), + Annotatable::GenericParam(gp) => gp.visit_tokens(f), + Annotatable::Param(p) => p.visit_tokens(f), + Annotatable::StructField(sf) => sf.visit_tokens(f), + Annotatable::Variant(v) => v.visit_tokens(f), + } + } } impl Annotatable { diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index a5a7ee6c9a349..3181120912a3a 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -180,6 +180,7 @@ impl<'a> ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span: sp, attrs: AttrVec::new(), + tokens: None, }); ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -198,6 +199,7 @@ impl<'a> ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, span, attrs: AttrVec::new(), + tokens: None, }); ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span, tokens: None } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index dd087ab91509b..4f7f9d95b39d9 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -3,7 +3,11 @@ use rustc_ast::attr::HasAttrs; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, AttrItem, Attribute, MetaItem}; +use rustc_ast::token::{self, DelimToken, Token}; +use rustc_ast::tokenstream::{ + DelimSpan, PreexpTokenStream, PreexpTokenTree, Spacing, TokenStream, TokenTree, +}; +use rustc_ast::{self as ast, Attribute, MetaItem}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::map_in_place::MapInPlace; @@ -12,6 +16,7 @@ use rustc_feature::{Feature, Features, State as FeatureState}; use rustc_feature::{ ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES, }; +use rustc_parse::parser::attr::CfgAttrItem; use rustc_parse::{parse_in, validate_attr}; use rustc_session::parse::feature_err; use rustc_session::Session; @@ -237,9 +242,20 @@ const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ #the-cfg_attr-attribute>"; impl<'a> StripUnconfigured<'a> { - pub fn configure(&mut self, mut node: T) -> Option { + pub fn configure_with_tokens( + &mut self, + mut node: T, + config_tokens: bool, + ) -> Option { self.process_cfg_attrs(&mut node); - self.in_cfg(node.attrs()).then_some(node) + self.in_cfg(node.attrs().iter()).then(|| { + node.visit_tokens(|tokens| *tokens = self.configure_tokens(tokens, config_tokens)); + node + }) + } + + pub fn configure(&mut self, node: T) -> Option { + self.configure_with_tokens(node, true) } /// Parse and expand all `cfg_attr` attributes into a list of attributes @@ -249,9 +265,41 @@ impl<'a> StripUnconfigured<'a> { /// attributes and is in the original source code. Gives compiler errors if /// the syntax of any `cfg_attr` is incorrect. pub fn process_cfg_attrs(&mut self, node: &mut T) { - node.visit_attrs(|attrs| { - attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); - }); + node.visit_attrs(|attrs| attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr))); + } + + fn configure_tokens( + &mut self, + stream: &PreexpTokenStream, + config_tokens: bool, + ) -> PreexpTokenStream { + let trees: Vec<_> = stream + .0 + .iter() + .flat_map(|tree| match tree.0.clone() { + PreexpTokenTree::OuterAttributes(mut data) => { + data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); + + if self.in_cfg(data.attrs.iter()) { + if config_tokens { + data.tokens = self.configure_tokens(&data.tokens, config_tokens); + } + Some((PreexpTokenTree::OuterAttributes(data), tree.1)).into_iter() + } else { + None.into_iter() + } + } + PreexpTokenTree::Delimited(sp, delim, mut inner) => { + if config_tokens { + inner = self.configure_tokens(&inner, config_tokens); + } + Some((PreexpTokenTree::Delimited(sp, delim, inner), tree.1)) + } + .into_iter(), + token_tree @ PreexpTokenTree::Token(_) => Some((token_tree, tree.1)).into_iter(), + }) + .collect(); + PreexpTokenStream::new(trees) } /// Parse and expand a single `cfg_attr` attribute into a list of attributes @@ -288,14 +336,28 @@ impl<'a> StripUnconfigured<'a> { // `#[cfg_attr(false, cfg_attr(true, some_attr))]`. expanded_attrs .into_iter() - .flat_map(|(item, span)| { - let attr = attr::mk_attr_from_item(attr.style, item, span); + .flat_map(|item| { + let mut attr = attr::mk_attr_from_item(attr.style, item.item, item.span); + // Construct synthetic `#[]` tokens + let tokens = vec![ + (TokenTree::Token(Token::new(token::Pound, attr.span)), Spacing::Alone), + ( + TokenTree::Delimited( + DelimSpan::from_single(attr.span), + DelimToken::Bracket, + item.tokens, + ), + Spacing::Alone, + ), + ]; + + attr.tokens = Some(TokenStream::new(tokens)); self.process_cfg_attr(attr) }) .collect() } - fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> { + fn parse_cfg_attr(&mut self, attr: &Attribute) -> Option<(MetaItem, Vec)> { match attr.get_normal_item().args { ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => { let msg = "wrong `cfg_attr` delimiters"; @@ -316,7 +378,7 @@ impl<'a> StripUnconfigured<'a> { None } - fn error_malformed_cfg_attr_missing(&self, span: Span) { + fn error_malformed_cfg_attr_missing(&mut self, span: Span) { self.sess .parse_sess .span_diagnostic @@ -332,8 +394,8 @@ impl<'a> StripUnconfigured<'a> { } /// Determines if a node with the given attributes should be included in this configuration. - pub fn in_cfg(&self, attrs: &[Attribute]) -> bool { - attrs.iter().all(|attr| { + pub fn in_cfg<'b>(&self, mut attrs: impl Iterator) -> bool { + attrs.all(|attr| { if !is_cfg(self.sess, attr) { return true; } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e5cfb866938e5..0a64cc17ee083 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -494,6 +494,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut item = self.fully_configure(item); item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive))); + if item.derive_allowed() { + if let Annotatable::Item(item) = &mut item { + let tokens = if let Some(tokens) = item.tokens.as_mut() { + tokens + } else { + panic!("Missing tokens for {:?}", item); + }; + tokens.replace_attributes(|data| { + data.attrs.retain(|a| !a.has_name(sym::derive)) + }); + } else { + panic!("Derive on non-item {:?}", item); + } + } + tracing::debug!("item after: {:?}", item); + let mut derive_placeholders = Vec::with_capacity(derives.len()); invocations.reserve(derives.len()); for path in derives { @@ -764,7 +780,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if *mark_used { self.cx.sess.mark_attr_used(&attr); } - item.visit_attrs(|attrs| attrs.push(attr)); + + item.visit_attrs(|attrs| attrs.push(attr.clone())); + + item.visit_tokens(|tokens| { + tokens.replace_attributes(|data| data.attrs.push(attr)); + }); + fragment_kind.expect_from_annotatables(iter::once(item)) } _ => unreachable!(), @@ -1053,19 +1075,26 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn find_attr_invoc( &self, - attrs: &mut Vec, + attr_target: &mut (impl HasAttrs + std::fmt::Debug), after_derive: &mut bool, ) -> Option { - let attr = attrs - .iter() - .position(|a| { - if a.has_name(sym::derive) { - *after_derive = true; - } - !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a) - }) - .map(|i| attrs.remove(i)); + let mut attr = None; + + attr_target.visit_attrs(|attrs| { + attrs + .iter() + .position(|a| { + if a.has_name(sym::derive) { + *after_derive = true; + } + !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a) + }) + .map(|i| attr = Some(attrs.remove(i))); + }); + + let mut has_inner = false; if let Some(attr) = &attr { + has_inner = attr.style == ast::AttrStyle::Inner; if !self.cx.ecfg.custom_inner_attributes() && attr.style == ast::AttrStyle::Inner && !attr.has_name(sym::test) @@ -1079,18 +1108,56 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { .emit(); } } + + let mut token_attr = None; + // Only attempt to replace tokens if we actually + // removed an attribute from the AST struct. + // We may end up collecting tokens for an AST struct + // even if `attrs_require_tokens` returns `false`, if + // a macro-rules matcher ends up forcing token collection. + // In this case, our collected tokens will not be a single + // `PreexpTokenStream::OuterAttributes`. + // + // To handle this case, we only attempt to modify the `TokenStream` + // if we actually need to do so - that is, if we need to remove + // a corresponding attribute that was removed from the parsed + // AST struct. + // + // FIXME: Support inner attributes. + // For now, we don't attempt to modify the TokenStream, which will + // cause us to use the pretty-print/retokenized stream later + // on due to the mismatch. + if attr.is_some() && !has_inner { + attr_target.visit_tokens(|tokens| { + tokens.replace_attributes(|data| { + token_attr = data + .attrs + .iter() + .position(|a| !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a)) + .map(|i| data.attrs.remove(i)); + + if token_attr.is_some() != attr.is_some() { + panic!( + "Mismatched AST and tokens: ast={:?} token_attr={:?}\ndata={:?}", + attr, token_attr, data + ); + } + }); + }); + } + attr } /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. fn classify_item( &mut self, - item: &mut impl HasAttrs, + item: &mut (impl HasAttrs + std::fmt::Debug), ) -> (Option, Vec, /* after_derive */ bool) { - let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); + let (mut traits, mut after_derive) = (Vec::new(), false); + let attr = self.find_attr_invoc(item, &mut after_derive); item.visit_attrs(|mut attrs| { - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); traits = collect_derives(&mut self.cx, &mut attrs); }); @@ -1102,19 +1169,17 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { /// is a breaking change) fn classify_nonitem( &mut self, - nonitem: &mut impl HasAttrs, + nonitem: &mut (impl HasAttrs + std::fmt::Debug), ) -> (Option, /* after_derive */ bool) { - let (mut attr, mut after_derive) = (None, false); + let mut after_derive = false; - nonitem.visit_attrs(|mut attrs| { - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); - }); + let attr = self.find_attr_invoc(nonitem, &mut after_derive); (attr, after_derive) } fn configure(&mut self, node: T) -> Option { - self.cfg.configure(node) + self.cfg.configure_with_tokens(node, false) } // Detect use of feature-gated or invalid attributes on macro invocations @@ -1357,7 +1422,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { // we'll expand attributes on expressions separately if !stmt.is_expr() { let (attr, derives, after_derive) = if stmt.is_item() { - self.classify_item(&mut stmt) + (None, vec![], false) + //self.classify_item(&mut stmt) } else { // ignore derives on non-item statements so it falls through // to the unused-attributes lint @@ -1379,7 +1445,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } if let StmtKind::MacCall(mac) = stmt.kind { - let MacCallStmt { mac, style, attrs } = mac.into_inner(); + let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner(); self.check_attributes(&attrs); let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts(); @@ -1785,6 +1851,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { span: at.span, id: at.id, style: at.style, + tokens: None, }; } else { noop_visit_attribute(at, self) diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 47247294f5dc6..49a8fb3171d4a 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -6,6 +6,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] +#![recursion_limit = "256"] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 4c9271a58df58..adc7f023b007e 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -104,6 +104,7 @@ pub fn placeholder( mac: mac_placeholder(), style: ast::MacStmtStyle::Braces, attrs: ast::AttrVec::new(), + tokens: None, }); ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac), tokens: None } }]), diff --git a/compiler/rustc_middle/src/ich/impls_syntax.rs b/compiler/rustc_middle/src/ich/impls_syntax.rs index e3d4655831b32..5182dbaf88e35 100644 --- a/compiler/rustc_middle/src/ich/impls_syntax.rs +++ b/compiler/rustc_middle/src/ich/impls_syntax.rs @@ -40,7 +40,7 @@ impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> { debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name))); debug_assert!(!attr.is_doc_comment()); - let ast::Attribute { kind, id: _, style, span } = attr; + let ast::Attribute { kind, id: _, style, span, tokens: _ } = attr; if let ast::AttrKind::Normal(item) = kind { item.hash_stable(self, hasher); style.hash_stable(self, hasher); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 21bbdc9ba8dce..928b3b21ec299 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -266,7 +266,8 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke // before we fall back to the stringification. let tokens = match *nt { Nonterminal::NtItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) + debug!("converting item tokenstream: {:?}", item.tokens); + item.tokens.clone().map(|t| t.to_tokenstream()) } Nonterminal::NtBlock(ref block) => block.tokens.clone(), Nonterminal::NtStmt(ref stmt) => { @@ -291,8 +292,10 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => { if expr.tokens.is_none() { debug!("missing tokens for expr {:?}", expr); + } else { + debug!("converting expr tokenstream: {:?}", expr.tokens); } - prepend_attrs(sess, &expr.attrs, expr.tokens.as_ref(), span) + expr.tokens.clone().map(|t| t.to_tokenstream()) } }; @@ -326,12 +329,16 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke // tokens such as extra braces and commas, don't happen. if let Some(tokens) = tokens { if tokenstream_probably_equal_for_proc_macro(&tokens, &tokens_for_real, sess) { + debug!("matching tokens: {:?}", tokens); + debug!("reparsed tokens: {:?}", tokens_for_real); return tokens; } info!( "cached tokens found, but they're not \"probably equal\", \ going with stringified version" ); + info!("cached stringified: {:?}", pprust::tts_to_string(&tokens)); + info!("reparsed stringified: {:?}", pprust::tts_to_string(&tokens_for_real)); info!("cached tokens: {:?}", tokens); info!("reparsed tokens: {:?}", tokens_for_real); } @@ -541,66 +548,3 @@ fn token_probably_equal_for_proc_macro(first: &Token, other: &Token) -> bool { _ => panic!("forgot to add a token?"), } } - -fn prepend_attrs( - sess: &ParseSess, - attrs: &[ast::Attribute], - tokens: Option<&tokenstream::TokenStream>, - span: rustc_span::Span, -) -> Option { - let tokens = tokens?; - if attrs.is_empty() { - return Some(tokens.clone()); - } - let mut builder = tokenstream::TokenStreamBuilder::new(); - for attr in attrs { - assert_eq!( - attr.style, - ast::AttrStyle::Outer, - "inner attributes should prevent cached tokens from existing" - ); - - let source = pprust::attribute_to_string(attr); - let macro_filename = FileName::macro_expansion_source_code(&source); - - let item = match attr.kind { - ast::AttrKind::Normal(ref item) => item, - ast::AttrKind::DocComment(..) => { - let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); - builder.push(stream); - continue; - } - }; - - // synthesize # [ $path $tokens ] manually here - let mut brackets = tokenstream::TokenStreamBuilder::new(); - - // For simple paths, push the identifier directly - if item.path.segments.len() == 1 && item.path.segments[0].args.is_none() { - let ident = item.path.segments[0].ident; - let token = token::Ident(ident.name, ident.as_str().starts_with("r#")); - brackets.push(tokenstream::TokenTree::token(token, ident.span)); - - // ... and for more complicated paths, fall back to a reparse hack that - // should eventually be removed. - } else { - let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); - brackets.push(stream); - } - - brackets.push(item.args.outer_tokens()); - - // The span we list here for `#` and for `[ ... ]` are both wrong in - // that it encompasses more than each token, but it hopefully is "good - // enough" for now at least. - builder.push(tokenstream::TokenTree::token(token::Pound, attr.span)); - let delim_span = tokenstream::DelimSpan::from_single(attr.span); - builder.push(tokenstream::TokenTree::Delimited( - delim_span, - token::DelimToken::Bracket, - brackets.build(), - )); - } - builder.push(tokens.clone()); - Some(builder.build()) -} diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 98f94098bfc15..13ccb82354ca1 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,10 +1,15 @@ -use super::{Parser, PathStyle}; +use super::{FlatToken, Parser, PathStyle}; use rustc_ast as ast; -use rustc_ast::attr; -use rustc_ast::token::{self, Nonterminal}; +use rustc_ast::attr::{self, HasAttrs}; +use rustc_ast::token::{self, Nonterminal, Token, TokenKind}; +use rustc_ast::tokenstream::{ + AttributesData, DelimSpan, PreexpTokenStream, PreexpTokenTree, Spacing, TokenStream, +}; +use rustc_ast::{AttrVec, Attribute}; use rustc_ast_pretty::pprust; -use rustc_errors::{error_code, PResult}; -use rustc_span::Span; +use rustc_errors::{error_code, Handler, PResult}; +use rustc_span::symbol::sym; +use rustc_span::{Span, DUMMY_SP}; use tracing::debug; @@ -17,6 +22,12 @@ pub(super) enum InnerAttrPolicy<'a> { const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ permitted in this context"; +pub struct CfgAttrItem { + pub item: ast::AttrItem, + pub span: Span, + pub tokens: TokenStream, +} + pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden { reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG, saw_doc_comment: false, @@ -24,47 +35,60 @@ pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPo }; impl<'a> Parser<'a> { - /// Parses attributes that appear before an item. - pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { + fn has_any_attributes(&mut self) -> bool { + self.check(&token::Pound) || matches!(self.token.kind, token::DocComment(..)) + } + + fn parse_outer_attributes_(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; + loop { - debug!("parse_outer_attributes: self.token={:?}", self.token); - if self.check(&token::Pound) { - 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() { - "an inner attribute is not permitted following an outer attribute" + let (attr, tokens) = self.collect_tokens_keep_in_stream(false, |this| { + debug!("parse_outer_attributes: self.token={:?}", this.token); + if this.check(&token::Pound) { + 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() { + "an inner attribute is not permitted following an outer attribute" + } else { + DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG + }; + 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), + }; + let attr = this.parse_attribute_with_inner_parse_policy(inner_parse_policy)?; + just_parsed_doc_comment = false; + Ok((Some(attr), Vec::new())) // Attributes don't have their own attributes + } else if let token::DocComment(comment_kind, attr_style, data) = this.token.kind { + let attr = + attr::mk_doc_comment(comment_kind, attr_style, data, this.token.span); + if attr.style != ast::AttrStyle::Outer { + this.sess + .span_diagnostic + .struct_span_err_with_code( + this.token.span, + "expected outer doc comment", + error_code!(E0753), + ) + .note( + "inner doc comments like this (starting with \ + `//!` or `/*!`) can only appear before items", + ) + .emit(); + } + this.bump(); + just_parsed_doc_comment = true; + Ok((Some(attr), Vec::new())) } else { - DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG - }; - 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), - }; - let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?; - attrs.push(attr); - just_parsed_doc_comment = false; - } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { - let attr = attr::mk_doc_comment(comment_kind, attr_style, data, self.token.span); - if attr.style != ast::AttrStyle::Outer { - self.sess - .span_diagnostic - .struct_span_err_with_code( - self.token.span, - "expected outer doc comment", - error_code!(E0753), - ) - .note( - "inner doc comments like this (starting with \ - `//!` or `/*!`) can only appear before items", - ) - .emit(); + Ok((None, Vec::new())) } + })?; + if let Some(mut attr) = attr { + attr.tokens = Some(tokens.to_tokenstream()); attrs.push(attr); - self.bump(); - just_parsed_doc_comment = true; } else { break; } @@ -72,6 +96,76 @@ impl<'a> Parser<'a> { Ok(attrs) } + pub(super) fn parse_or_use_outer_attributes< + R: HasAttrs, + F: FnOnce(&mut Self, AttrVec) -> PResult<'a, R>, + >( + &mut self, + already_parsed_attrs: Option, + f: F, + ) -> PResult<'a, (R, Option)> { + let in_derive = self.in_derive; + let needs_tokens = |attrs: &[Attribute]| attrs_require_tokens(in_derive, attrs); + + let make_capture_res = |this: &mut Self, f: F, attrs: AttrVec| { + let (res, tokens) = this.collect_tokens(|this| { + let mut new_attrs = attrs.clone().to_vec(); + + let old_in_derive = this.in_derive; + this.in_derive = + old_in_derive || new_attrs.iter().any(|attr| attr.has_name(sym::derive)); + let res = f(this, attrs); + this.in_derive = old_in_derive; + + let mut res = res?; + + res.visit_attrs(|attrs| { + new_attrs = attrs.clone(); + }); + Ok((res, new_attrs)) + })?; + Ok((res, Some(tokens))) + }; + + if let Some(attrs) = already_parsed_attrs { + if needs_tokens(&attrs) { + return make_capture_res(self, f, attrs); + } else { + return f(self, attrs).map(|res| (res, None)); + } + } else { + // If we are already collecting tokens, we need to + // perform token collection here even if we have no + // outer attributes, since there may be inner attributes + // parsed by 'f'. + if !self.has_any_attributes() && !self.in_derive { + return Ok((f(self, AttrVec::new())?, None)); + } + + let attrs = self.parse_outer_attributes_()?; + if !needs_tokens(&attrs) { + return Ok((f(self, attrs.into())?, None)); + } + + return make_capture_res(self, f, attrs.into()); + } + } + + pub(super) fn parse_outer_attributes( + &mut self, + f: impl FnOnce(&mut Self, Vec) -> PResult<'a, R>, + ) -> PResult<'a, R> { + self.parse_outer_attributes_with_tokens(f).map(|(res, _tokens)| res) + } + + /// Parses attributes that appear before an item. + pub(super) fn parse_outer_attributes_with_tokens( + &mut self, + f: impl FnOnce(&mut Self, Vec) -> PResult<'a, R>, + ) -> PResult<'a, (R, Option)> { + self.parse_or_use_outer_attributes(None, |this, attrs| f(this, attrs.into())) + } + /// Matches `attribute = # ! [ meta_item ]`. /// /// If `permit_inner` is `true`, then a leading `!` indicates an inner @@ -174,20 +268,29 @@ impl<'a> Parser<'a> { crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = vec![]; loop { - // Only try to parse if it is an inner attribute (has `!`). - if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) { - let attr = self.parse_attribute(true)?; - assert_eq!(attr.style, ast::AttrStyle::Inner); - attrs.push(attr); - } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { - // We need to get the position of this token before we bump. - let attr = attr::mk_doc_comment(comment_kind, attr_style, data, self.token.span); - if attr.style == ast::AttrStyle::Inner { - attrs.push(attr); - self.bump(); + let (attr, tokens) = self.collect_tokens_no_attrs(|this| { + // Only try to parse if it is an inner attribute (has `!`). + if this.check(&token::Pound) && this.look_ahead(1, |t| t == &token::Not) { + let attr = this.parse_attribute(true)?; + assert_eq!(attr.style, ast::AttrStyle::Inner); + Ok(Some(attr)) + } else if let token::DocComment(comment_kind, attr_style, data) = this.token.kind { + // We need to get the position of this token before we bump. + let attr = + attr::mk_doc_comment(comment_kind, attr_style, data, this.token.span); + if attr.style == ast::AttrStyle::Inner { + this.bump(); + Ok(Some(attr)) + } else { + Ok(None) + } } else { - break; + Ok(None) } + })?; + if let Some(mut attr) = attr { + attr.tokens = Some(tokens.to_tokenstream()); + attrs.push(attr) } else { break; } @@ -212,7 +315,7 @@ impl<'a> Parser<'a> { } /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. - pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> { + pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec)> { let cfg_predicate = self.parse_meta_item()?; self.expect(&token::Comma)?; @@ -220,8 +323,14 @@ impl<'a> Parser<'a> { let mut expanded_attrs = Vec::with_capacity(1); while self.token.kind != token::Eof { let lo = self.token.span; - let item = self.parse_attr_item()?; - expanded_attrs.push((item, lo.to(self.prev_token.span))); + let (item, tokens) = + self.collect_tokens(|this| this.parse_attr_item().map(|item| (item, Vec::new())))?; + expanded_attrs.push(CfgAttrItem { + item, + span: lo.to(self.prev_token.span), + tokens: tokens.to_tokenstream(), + }); + if !self.eat(&token::Comma) { break; } @@ -301,4 +410,146 @@ impl<'a> Parser<'a> { let msg = format!("expected unsuffixed literal or identifier, found `{}`", found); Err(self.struct_span_err(self.token.span, &msg)) } + + pub(super) fn collect_tokens_keep_in_stream( + &mut self, + keep_in_stream: bool, + f: impl FnOnce(&mut Self) -> PResult<'a, (R, Vec)>, + ) -> PResult<'a, (R, PreexpTokenStream)> { + let start_pos = self.token_cursor.collecting_buf.len() - 1; + let prev_collecting = std::mem::replace(&mut self.token_cursor.is_collecting, true); + + let ret = f(self); + + let err_stream = if ret.is_err() { + // Rustdoc tries to parse an item, and then cancels the error + // if it fails. + // FIXME: Come up with a better way of doing this + if !self.is_rustdoc { + self.sess + .span_diagnostic + .delay_span_bug(self.token.span, "Parse error during token collection"); + } + Some(PreexpTokenStream::new(vec![])) + } else { + None + }; + + fn make_stream( + handler: &Handler, + iter: impl Iterator, + err_stream: Option, + ) -> PreexpTokenStream { + err_stream.unwrap_or_else(|| make_preexp_stream(handler, iter)) + } + + let last_token = self.token_cursor.collecting_buf.pop().unwrap(); + let mut stream = if prev_collecting { + if keep_in_stream { + make_stream( + &self.sess.span_diagnostic, + self.token_cursor.collecting_buf[start_pos..].iter().cloned(), + err_stream, + ) + } else { + make_stream( + &self.sess.span_diagnostic, + self.token_cursor.collecting_buf.drain(start_pos..), + err_stream, + ) + } + } else { + debug_assert_eq!(start_pos, 0); + make_stream( + &self.sess.span_diagnostic, + std::mem::take(&mut self.token_cursor.collecting_buf).into_iter(), + err_stream, + ) + }; + + if let Ok((_, attrs)) = ret.as_ref() { + if !attrs.is_empty() { + let data = AttributesData { attrs: attrs.clone(), tokens: stream }; + let tree = (PreexpTokenTree::OuterAttributes(data.clone()), Spacing::Alone); + stream = PreexpTokenStream::new(vec![tree]); + + if prev_collecting { + assert!(keep_in_stream); + self.token_cursor.collecting_buf.splice( + start_pos.., + std::iter::once((FlatToken::OuterAttributes(data), Spacing::Alone)), + ); + } + } + } + + self.token_cursor.collecting_buf.push(last_token); + self.token_cursor.is_collecting = prev_collecting; + + Ok((ret?.0, stream)) + } +} + +fn make_preexp_stream( + handler: &Handler, + tokens: impl Iterator, +) -> PreexpTokenStream { + #[derive(Debug)] + struct FrameData { + open: Span, + inner: Vec<(PreexpTokenTree, Spacing)>, + } + let mut stack = vec![FrameData { open: DUMMY_SP, inner: vec![] }]; + for tree in tokens { + match tree.0 { + FlatToken::Token(Token { kind: TokenKind::OpenDelim(_), span }) => { + stack.push(FrameData { open: span, inner: vec![] }); + } + FlatToken::Token(Token { kind: TokenKind::CloseDelim(delim), span }) => { + let frame_data = stack.pop().expect("Token stack was empty!"); + let dspan = DelimSpan::from_pair(frame_data.open, span); + let stream = PreexpTokenStream::new(frame_data.inner); + let delimited = PreexpTokenTree::Delimited(dspan, delim, stream); + stack + .last_mut() + .expect("Bottom token frame is missing!") + .inner + .push((delimited, Spacing::Alone)); + } + FlatToken::Token(token) => stack + .last_mut() + .expect("Bottom token frame is missing!") + .inner + .push((PreexpTokenTree::Token(token), tree.1)), + FlatToken::OuterAttributes(data) => stack + .last_mut() + .expect("Bottom token frame is missing!") + .inner + .push((PreexpTokenTree::OuterAttributes(data), Spacing::Alone)), + } + } + let final_buf = stack.pop().expect("Missing final buf!"); + if !stack.is_empty() { + handler.delay_span_bug( + stack[0].open, + &format!("Stack should be empty: final_buf={:?} stack={:?}", final_buf, stack), + ); + } + PreexpTokenStream::new(final_buf.inner) +} + +pub fn attrs_require_tokens(in_derive: bool, attrs: &[Attribute]) -> bool { + attrs.iter().any(|attr| { + if let Some(ident) = attr.ident() { + ident.name == sym::derive + // We only need tokens for 'cfgs' inside a derive, + // since cfg-stripping occurs before derive expansion + || (ident.name == sym::cfg && in_derive) + // This might apply a custom attribute/derive + || ident.name == sym::cfg_attr + || !rustc_feature::is_builtin_attr_name(ident.name) + } else { + true + } + }) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 69d13b5cf53a2..762d1c1c82b4a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -17,7 +17,6 @@ use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use std::mem; -use tracing::debug; /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression /// dropped into the token stream, which happens while parsing the result of @@ -446,23 +445,25 @@ impl<'a> Parser<'a> { _ => RangeLimits::Closed, }; let op = AssocOp::from_token(&self.token); - let attrs = self.parse_or_use_outer_attributes(attrs)?; - let lo = self.token.span; - self.bump(); - let (span, opt_end) = if self.is_at_start_of_range_notation_rhs() { - // RHS must be parsed with more associativity than the dots. - self.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed) - .map(|x| (lo.to(x.span), Some(x)))? - } else { - (lo, None) - }; - Ok(self.mk_expr(span, self.mk_range(None, opt_end, limits)?, attrs)) + let (mut expr, tokens) = self.parse_or_use_outer_attributes(attrs, |this, attrs| { + let lo = this.token.span; + this.bump(); + let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { + // RHS must be parsed with more associativity than the dots. + this.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed) + .map(|x| (lo.to(x.span), Some(x)))? + } else { + (lo, None) + }; + Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits)?, attrs)) + })?; + expr.tokens = tokens; + Ok(expr) } /// Parses a prefix-unary-operator expr. fn parse_prefix_expr(&mut self, attrs: Option) -> PResult<'a, P> { - let attrs = self.parse_or_use_outer_attributes(attrs)?; - self.maybe_collect_tokens(!attrs.is_empty(), |this| { + let (mut expr, tokens) = self.parse_or_use_outer_attributes(attrs, |this, attrs| { let lo = this.token.span; // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr() let (hi, ex) = match this.token.uninterpolate().kind { @@ -475,10 +476,12 @@ impl<'a> Parser<'a> { token::Ident(..) if this.is_mistaken_not_ident_negation() => { this.recover_not_expr(lo) } - _ => return this.parse_dot_or_call_expr(Some(attrs)), + _ => return this.parse_dot_or_call_expr(attrs), }?; Ok(this.mk_expr(lo.to(hi), ex, attrs)) - }) + })?; + expr.tokens = tokens; + Ok(expr) } fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P)> { @@ -748,8 +751,7 @@ impl<'a> Parser<'a> { } /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. - fn parse_dot_or_call_expr(&mut self, attrs: Option) -> PResult<'a, P> { - let attrs = self.parse_or_use_outer_attributes(attrs)?; + fn parse_dot_or_call_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { let base = self.parse_bottom_expr(); let (span, base) = self.interpolated_or_expr_span(base)?; self.parse_dot_or_call_expr_with(base, span, attrs) @@ -1079,21 +1081,6 @@ impl<'a> Parser<'a> { } } - fn maybe_collect_tokens( - &mut self, - has_outer_attrs: bool, - f: impl FnOnce(&mut Self) -> PResult<'a, P>, - ) -> PResult<'a, P> { - if has_outer_attrs { - let (mut expr, tokens) = self.collect_tokens(f)?; - debug!("maybe_collect_tokens: Collected tokens for {:?} (tokens {:?}", expr, tokens); - expr.tokens = Some(tokens); - Ok(expr) - } else { - f(self) - } - } - fn parse_lit_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.token.span; match self.parse_opt_lit() { @@ -1611,20 +1598,21 @@ impl<'a> Parser<'a> { /// Parses a parameter in a closure header (e.g., `|arg, arg|`). fn parse_fn_block_param(&mut self) -> PResult<'a, Param> { let lo = self.token.span; - let attrs = self.parse_outer_attributes()?; - let pat = self.parse_pat(PARAM_EXPECTED)?; - let ty = if self.eat(&token::Colon) { - self.parse_ty()? - } else { - self.mk_ty(self.prev_token.span, TyKind::Infer) - }; - Ok(Param { - attrs: attrs.into(), - ty, - pat, - span: lo.to(self.token.span), - id: DUMMY_NODE_ID, - is_placeholder: false, + self.parse_outer_attributes(|this, attrs| { + let pat = this.parse_pat(PARAM_EXPECTED)?; + let ty = if this.eat(&token::Colon) { + this.parse_ty()? + } else { + this.mk_ty(this.prev_token.span, TyKind::Infer) + }; + Ok(Param { + attrs: attrs.into(), + ty, + pat, + span: lo.to(this.token.span), + id: DUMMY_NODE_ID, + is_placeholder: false, + }) }) } @@ -1640,7 +1628,8 @@ impl<'a> Parser<'a> { let thn = if self.eat_keyword(kw::Else) || !cond.returns() { self.error_missing_if_cond(lo, cond.span) } else { - let attrs = self.parse_outer_attributes()?; // For recovery. + // For recovery. + let attrs = self.parse_outer_attributes(|_this, attrs| Ok(attrs))?; let not_block = self.token != token::OpenDelim(token::Brace); let block = self.parse_block().map_err(|mut err| { if not_block { @@ -1697,15 +1686,16 @@ impl<'a> Parser<'a> { /// Parses an `else { ... }` expression (`else` token already eaten). fn parse_else_expr(&mut self) -> PResult<'a, P> { let ctx_span = self.prev_token.span; // `else` - let attrs = self.parse_outer_attributes()?; // For recovery. - let expr = if self.eat_keyword(kw::If) { - self.parse_if_expr(AttrVec::new())? - } else { - let blk = self.parse_block()?; - self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()) - }; - self.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs); - Ok(expr) + self.parse_outer_attributes(|this, attrs| { + let expr = if this.eat_keyword(kw::If) { + this.parse_if_expr(AttrVec::new())? + } else { + let blk = this.parse_block()?; + this.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()) + }; + this.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs); + Ok(expr) + }) } fn error_on_if_block_attrs( @@ -1855,86 +1845,88 @@ impl<'a> Parser<'a> { } pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { - let attrs = self.parse_outer_attributes()?; - let lo = self.token.span; - let pat = self.parse_top_pat(GateOr::No)?; - let guard = if self.eat_keyword(kw::If) { - let if_span = self.prev_token.span; - let cond = self.parse_expr()?; - if let ExprKind::Let(..) = cond.kind { - // Remove the last feature gating of a `let` expression since it's stable. - self.sess.gated_spans.ungate_last(sym::let_chains, cond.span); - let span = if_span.to(cond.span); - self.sess.gated_spans.gate(sym::if_let_guard, span); - } - Some(cond) - } else { - None - }; - let arrow_span = self.token.span; - self.expect(&token::FatArrow)?; - let arm_start_span = self.token.span; + self.parse_outer_attributes(|this, attrs| { + let lo = this.token.span; + let pat = this.parse_top_pat(GateOr::No)?; + let guard = if this.eat_keyword(kw::If) { + let if_span = this.prev_token.span; + let cond = this.parse_expr()?; + if let ExprKind::Let(..) = cond.kind { + // Remove the last feature gating of a `let` expression since it's stable. + this.sess.gated_spans.ungate_last(sym::let_chains, cond.span); + let span = if_span.to(cond.span); + this.sess.gated_spans.gate(sym::if_let_guard, span); + } + Some(cond) + } else { + None + }; + let arrow_span = this.token.span; + this.expect(&token::FatArrow)?; + let arm_start_span = this.token.span; - let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| { - err.span_label(arrow_span, "while parsing the `match` arm starting here"); - err - })?; + let expr = this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| { + err.span_label(arrow_span, "while parsing the `match` arm starting here"); + err + })?; - let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) - && self.token != token::CloseDelim(token::Brace); - - let hi = self.prev_token.span; - - if require_comma { - let sm = self.sess.source_map(); - self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]).map_err( - |mut err| { - match (sm.span_to_lines(expr.span), sm.span_to_lines(arm_start_span)) { - (Ok(ref expr_lines), Ok(ref arm_start_lines)) - if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col - && expr_lines.lines.len() == 2 - && self.token == token::FatArrow => - { - // We check whether there's any trailing code in the parse span, - // if there isn't, we very likely have the following: - // - // X | &Y => "y" - // | -- - missing comma - // | | - // | arrow_span - // X | &X => "x" - // | - ^^ self.token.span - // | | - // | parsed until here as `"y" & X` - err.span_suggestion_short( - arm_start_span.shrink_to_hi(), - "missing a comma here to end this `match` arm", - ",".to_owned(), - Applicability::MachineApplicable, - ); - } - _ => { - err.span_label( - arrow_span, - "while parsing the `match` arm starting here", - ); + let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) + && this.token != token::CloseDelim(token::Brace); + + let hi = this.prev_token.span; + + if require_comma { + let sm = this.sess.source_map(); + this.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]).map_err( + |mut err| { + match (sm.span_to_lines(expr.span), sm.span_to_lines(arm_start_span)) { + (Ok(ref expr_lines), Ok(ref arm_start_lines)) + if arm_start_lines.lines[0].end_col + == expr_lines.lines[0].end_col + && expr_lines.lines.len() == 2 + && this.token == token::FatArrow => + { + // We check whether there's any trailing code in the parse span, + // if there isn't, we very likely have the following: + // + // X | &Y => "y" + // | -- - missing comma + // | | + // | arrow_span + // X | &X => "x" + // | - ^^ self.token.span + // | | + // | parsed until here as `"y" & X` + err.span_suggestion_short( + arm_start_span.shrink_to_hi(), + "missing a comma here to end this `match` arm", + ",".to_owned(), + Applicability::MachineApplicable, + ); + } + _ => { + err.span_label( + arrow_span, + "while parsing the `match` arm starting here", + ); + } } - } - err - }, - )?; - } else { - self.eat(&token::Comma); - } + err + }, + )?; + } else { + this.eat(&token::Comma); + } - Ok(ast::Arm { - attrs, - pat, - guard, - body: expr, - span: lo.to(hi), - id: DUMMY_NODE_ID, - is_placeholder: false, + Ok(ast::Arm { + attrs, + pat, + guard, + body: expr, + span: lo.to(hi), + id: DUMMY_NODE_ID, + is_placeholder: false, + }) }) } @@ -2169,30 +2161,32 @@ impl<'a> Parser<'a> { /// Parses `ident (COLON expr)?`. fn parse_field(&mut self) -> PResult<'a, Field> { - let attrs = self.parse_outer_attributes()?.into(); - let lo = self.token.span; + self.parse_outer_attributes(|this, attrs| { + let attrs = attrs.into(); + let lo = this.token.span; - // Check if a colon exists one ahead. This means we're parsing a fieldname. - let is_shorthand = !self.look_ahead(1, |t| t == &token::Colon || t == &token::Eq); - let (ident, expr) = if is_shorthand { - // Mimic `x: x` for the `x` field shorthand. - let ident = self.parse_ident_common(false)?; - let path = ast::Path::from_ident(ident); - (ident, self.mk_expr(ident.span, ExprKind::Path(None, path), AttrVec::new())) - } else { - let ident = self.parse_field_name()?; - self.error_on_eq_field_init(ident); - self.bump(); // `:` - (ident, self.parse_expr()?) - }; - Ok(ast::Field { - ident, - span: lo.to(expr.span), - expr, - is_shorthand, - attrs, - id: DUMMY_NODE_ID, - is_placeholder: false, + // Check if a colon exists one ahead. This means we're parsing a fieldname. + let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq); + let (ident, expr) = if is_shorthand { + // Mimic `x: x` for the `x` field shorthand. + let ident = this.parse_ident_common(false)?; + let path = ast::Path::from_ident(ident); + (ident, this.mk_expr(ident.span, ExprKind::Path(None, path), AttrVec::new())) + } else { + let ident = this.parse_field_name()?; + this.error_on_eq_field_init(ident); + this.bump(); // `:` + (ident, this.parse_expr()?) + }; + Ok(ast::Field { + ident, + span: lo.to(expr.span), + expr, + is_shorthand, + attrs, + id: DUMMY_NODE_ID, + is_placeholder: false, + }) }) } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index dd99a7587dd54..b1421a83e7ee7 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -73,67 +73,88 @@ impl<'a> Parser<'a> { pub(super) fn parse_generic_params(&mut self) -> PResult<'a, Vec> { let mut params = Vec::new(); loop { - let attrs = self.parse_outer_attributes()?; - if self.check_lifetime() { - let lifetime = self.expect_lifetime(); - // Parse lifetime parameter. - let bounds = - if self.eat(&token::Colon) { self.parse_lt_param_bounds() } else { Vec::new() }; - params.push(ast::GenericParam { - ident: lifetime.ident, - id: lifetime.id, - attrs: attrs.into(), - bounds, - kind: ast::GenericParamKind::Lifetime, - is_placeholder: false, - }); - } else if self.check_keyword(kw::Const) { - // Parse const parameter. - params.push(self.parse_const_param(attrs)?); - } else if self.check_ident() { - // Parse type parameter. - params.push(self.parse_ty_param(attrs)?); - } else if self.token.can_begin_type() { - // Trying to write an associated type bound? (#26271) - let snapshot = self.clone(); - match self.parse_ty_where_predicate() { - Ok(where_predicate) => { - self.struct_span_err( - where_predicate.span(), - "bounds on associated types do not belong here", - ) - .span_label(where_predicate.span(), "belongs in `where` clause") - .emit(); - } - Err(mut err) => { - err.cancel(); - *self = snapshot; - break; - } - } - } else { - // Check for trailing attributes and stop parsing. - if !attrs.is_empty() { - if !params.is_empty() { - self.struct_span_err( - attrs[0].span, - "trailing attribute after generic parameter", - ) - .span_label(attrs[0].span, "attributes must go before parameters") - .emit(); + let mut should_break = false; + let param = self.parse_outer_attributes(|this, attrs| { + let param = if this.check_lifetime() { + let lifetime = this.expect_lifetime(); + // Parse lifetime parameter. + let bounds = if this.eat(&token::Colon) { + this.parse_lt_param_bounds() } else { - self.struct_span_err(attrs[0].span, "attribute without generic parameters") + Vec::new() + }; + Some(ast::GenericParam { + ident: lifetime.ident, + id: lifetime.id, + attrs: attrs.into(), + bounds, + kind: ast::GenericParamKind::Lifetime, + is_placeholder: false, + }) + } else if this.check_keyword(kw::Const) { + // Parse const parameter. + Some(this.parse_const_param(attrs)?) + } else if this.check_ident() { + // Parse type parameter. + Some(this.parse_ty_param(attrs)?) + } else if this.token.can_begin_type() { + // Trying to write an associated type bound? (#26271) + let snapshot = this.clone(); + match this.parse_ty_where_predicate() { + Ok(where_predicate) => { + this.struct_span_err( + where_predicate.span(), + "bounds on associated types do not belong here", + ) + .span_label(where_predicate.span(), "belongs in `where` clause") + .emit(); + + None + } + Err(mut err) => { + err.cancel(); + *this = snapshot; + None + } + } + } else { + // Check for trailing attributes and stop parsing. + if !attrs.is_empty() { + if !params.is_empty() { + this.struct_span_err( + attrs[0].span, + "trailing attribute after generic parameter", + ) + .span_label(attrs[0].span, "attributes must go before parameters") + .emit(); + } else { + this.struct_span_err( + attrs[0].span, + "attribute without generic parameters", + ) .span_label( attrs[0].span, "attributes are only permitted when preceding parameters", ) .emit(); + } + } + None + }; + if param.is_some() { + if !this.eat(&token::Comma) { + should_break = true; } } - break; - } + Ok(param) + })?; - if !self.eat(&token::Comma) { + if let Some(param) = param { + params.push(param); + if should_break { + break; + } + } else { break; } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 26ca99801277b..b38dc4c5a3cf5 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -3,11 +3,14 @@ use super::ty::{AllowPlus, RecoverQPath}; use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; +use crate::parser::attr::attrs_require_tokens; use rustc_ast::ptr::P; -use rustc_ast::token::{self, TokenKind}; -use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; -use rustc_ast::{self as ast, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID}; +use rustc_ast::token::{self, DelimToken, TokenKind}; +use rustc_ast::tokenstream::{ + AttributesData, DelimSpan, PreexpTokenStream, PreexpTokenTree, Spacing, TokenStream, TokenTree, +}; +use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID}; use rustc_ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod}; use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; use rustc_ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; @@ -98,8 +101,17 @@ impl<'a> Parser<'a> { } fn parse_item_(&mut self, req_name: ReqName) -> PResult<'a, Option> { - let attrs = self.parse_outer_attributes()?; - self.parse_item_common(attrs, true, false, req_name) + let res = self.parse_outer_attributes_with_tokens(|this, attrs| { + this.parse_item_common(attrs, true, false, req_name) + }); + res.map(|(mut item, tokens)| { + if let Some(item) = item.as_mut() { + if item.tokens.is_none() { + item.tokens = tokens; + } + } + item + }) } pub(super) fn parse_item_common( @@ -110,51 +122,44 @@ impl<'a> Parser<'a> { req_name: ReqName, ) -> PResult<'a, Option> { maybe_whole!(self, NtItem, |item| { - let mut item = item; + let mut item = item.into_inner(); + + if !attrs.is_empty() { + if let Some(tokens) = item.tokens.as_mut() { + if let &[(PreexpTokenTree::OuterAttributes(ref data), joint)] = &**tokens.0 { + let mut data = data.clone(); + let mut attrs = attrs.clone(); + mem::swap(&mut data.attrs, &mut attrs); + data.attrs.extend(attrs); + debug!("new data: {:?}", data); + *tokens = PreexpTokenStream::new(vec![( + PreexpTokenTree::OuterAttributes(data), + joint, + )]); + } else { + assert!( + !attrs_require_tokens(self.in_derive, &item.attrs), + "Attributes needed tokens: {:?}", + item.attrs + ); + let data = AttributesData { attrs: attrs.clone(), tokens: tokens.clone() }; + *tokens = PreexpTokenStream::new(vec![( + PreexpTokenTree::OuterAttributes(data), + Spacing::Alone, + )]) + } + } else { + panic!("Missing tokens for {:?}", item); + } + } + mem::swap(&mut item.attrs, &mut attrs); item.attrs.extend(attrs); - Some(item.into_inner()) + Some(item) }); - let mut unclosed_delims = vec![]; - let has_attrs = !attrs.is_empty(); - let parse_item = |this: &mut Self| { - let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); - unclosed_delims.append(&mut this.unclosed_delims); - item - }; - - let (mut item, tokens) = if has_attrs { - let (item, tokens) = self.collect_tokens(parse_item)?; - (item, Some(tokens)) - } else { - (parse_item(self)?, None) - }; - - self.unclosed_delims.append(&mut unclosed_delims); - - // Once we've parsed an item and recorded the tokens we got while - // parsing we may want to store `tokens` into the item we're about to - // return. Note, though, that we specifically didn't capture tokens - // related to outer attributes. The `tokens` field here may later be - // used with procedural macros to convert this item back into a token - // stream, but during expansion we may be removing attributes as we go - // along. - // - // If we've got inner attributes then the `tokens` we've got above holds - // these inner attributes. If an inner attribute is expanded we won't - // actually remove it from the token stream, so we'll just keep yielding - // it (bad!). To work around this case for now we just avoid recording - // `tokens` if we detect any inner attributes. This should help keep - // expansion correct, but we should fix this bug one day! - if let Some(tokens) = tokens { - if let Some(item) = &mut item { - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - } - } - Ok(item) + let item = self.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); + item } fn parse_item_common_( @@ -1060,11 +1065,7 @@ impl<'a> Parser<'a> { let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; - let (variants, _) = - self.parse_delim_comma_seq(token::Brace, |p| p.parse_enum_variant()).map_err(|e| { - self.recover_stmt(); - e - })?; + let (variants, _) = self.parse_enum_body()?; let enum_definition = EnumDef { variants: variants.into_iter().filter_map(|v| v).collect() }; @@ -1072,40 +1073,57 @@ impl<'a> Parser<'a> { } fn parse_enum_variant(&mut self) -> PResult<'a, Option> { - let variant_attrs = self.parse_outer_attributes()?; - let vlo = self.token.span; + self.parse_outer_attributes(|this, variant_attrs| { + let vlo = this.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - if !self.recover_nested_adt_item(kw::Enum)? { - return Ok(None); - } - let ident = self.parse_ident()?; + let vis = this.parse_visibility(FollowedByType::No)?; + if !this.recover_nested_adt_item(kw::Enum)? { + this.eat(&token::Comma); + return Ok(None); + } + let ident = this.parse_ident()?; - let struct_def = if self.check(&token::OpenDelim(token::Brace)) { - // Parse a struct variant. - let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, recovered) - } else if self.check(&token::OpenDelim(token::Paren)) { - VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID) - } else { - VariantData::Unit(DUMMY_NODE_ID) - }; + let struct_def = if this.check(&token::OpenDelim(token::Brace)) { + // Parse a struct variant. + let (fields, recovered) = this.parse_record_struct_body()?; + VariantData::Struct(fields, recovered) + } else if this.check(&token::OpenDelim(token::Paren)) { + VariantData::Tuple(this.parse_tuple_struct_body("enum")?, DUMMY_NODE_ID) + } else { + VariantData::Unit(DUMMY_NODE_ID) + }; - let disr_expr = - if self.eat(&token::Eq) { Some(self.parse_anon_const_expr()?) } else { None }; + let disr_expr = + if this.eat(&token::Eq) { Some(this.parse_anon_const_expr()?) } else { None }; - let vr = ast::Variant { - ident, - vis, - id: DUMMY_NODE_ID, - attrs: variant_attrs, - data: struct_def, - disr_expr, - span: vlo.to(self.prev_token.span), - is_placeholder: false, - }; + if !matches!(this.token.kind, token::CloseDelim(..)) { + if let Err(mut e) = this.expect(&token::Comma) { + if this.token.is_ident() { + let sp = this.sess.source_map().next_point(this.prev_token.span); + e.span_suggestion( + sp, + "try adding a comma", + ",".into(), + Applicability::MachineApplicable, + ) + .emit(); + } + } + } - Ok(Some(vr)) + let vr = ast::Variant { + ident, + vis, + id: DUMMY_NODE_ID, + attrs: variant_attrs, + data: struct_def, + disr_expr, + span: vlo.to(this.prev_token.span), + is_placeholder: false, + }; + + Ok(Some(vr)) + }) } /// Parses `struct Foo { ... }`. @@ -1147,7 +1165,7 @@ impl<'a> Parser<'a> { VariantData::Struct(fields, recovered) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { - let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID); + let body = VariantData::Tuple(self.parse_tuple_struct_body("struct")?, DUMMY_NODE_ID); generics.where_clause = self.parse_where_clause()?; self.expect_semi()?; body @@ -1192,11 +1210,26 @@ impl<'a> Parser<'a> { fn parse_record_struct_body( &mut self, ) -> PResult<'a, (Vec, /* recovered */ bool)> { + self.parse_struct_or_enum_body("struct", DelimToken::Brace, |this| { + this.parse_struct_decl_field() + }) + } + + fn parse_enum_body(&mut self) -> PResult<'a, (Vec>, bool)> { + self.parse_struct_or_enum_body("enum", DelimToken::Brace, |this| this.parse_enum_variant()) + } + + fn parse_struct_or_enum_body( + &mut self, + name: &str, + delim: DelimToken, + mut parse: impl FnMut(&mut Self) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, /* recovered */ bool)> { let mut fields = Vec::new(); let mut recovered = false; - if self.eat(&token::OpenDelim(token::Brace)) { - while self.token != token::CloseDelim(token::Brace) { - let field = self.parse_struct_decl_field().map_err(|e| { + if self.eat(&token::OpenDelim(delim)) { + while self.token != token::CloseDelim(delim) { + let field = parse(self).map_err(|e| { self.consume_block(token::Brace, ConsumeClosingDelim::No); recovered = true; e @@ -1209,45 +1242,75 @@ impl<'a> Parser<'a> { } } } - self.eat(&token::CloseDelim(token::Brace)); + self.eat(&token::CloseDelim(delim)); } else { + let delim_descr = match delim { + DelimToken::Paren => "(", + DelimToken::Bracket => "[", + DelimToken::Brace => "{", + DelimToken::NoDelim => panic!("Delimiter `NoDelim` not supported!"), + }; let token_str = super::token_descr(&self.token); - let msg = &format!("expected `where`, or `{{` after struct name, found {}", token_str); + let msg = &format!( + "expected `where`, or `{}` after {} name, found {}", + delim_descr, name, token_str + ); let mut err = self.struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected `where`, or `{` after struct name"); + err.span_label( + self.token.span, + &format!("expected `where`, or `{}` after {} name", delim_descr, name), + ); return Err(err); } Ok((fields, recovered)) } - fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec> { + fn parse_tuple_struct_body(&mut self, name: &str) -> PResult<'a, Vec> { // This is the case where we find `struct Foo(T) where T: Copy;` // Unit like structs are handled in parse_item_struct function - self.parse_paren_comma_seq(|p| { - let attrs = p.parse_outer_attributes()?; - let lo = p.token.span; - let vis = p.parse_visibility(FollowedByType::Yes)?; - let ty = p.parse_ty()?; - Ok(StructField { - span: lo.to(ty.span), - vis, - ident: None, - id: DUMMY_NODE_ID, - ty, - attrs, - is_placeholder: false, + let (fields, _) = self.parse_struct_or_enum_body(name, DelimToken::Paren, |p| { + p.parse_outer_attributes(|p, attrs| { + let lo = p.token.span; + let vis = p.parse_visibility(FollowedByType::Yes)?; + let ty = p.parse_ty()?; + + if !matches!(p.token.kind, token::CloseDelim(..)) { + if let Err(mut e) = p.expect(&token::Comma) { + if p.token.is_ident() { + let sp = p.sess.source_map().next_point(p.prev_token.span); + e.span_suggestion( + sp, + "try adding a comma", + ",".into(), + Applicability::MachineApplicable, + ) + .emit(); + } + } + } + + Ok(StructField { + span: lo.to(ty.span), + vis, + ident: None, + id: DUMMY_NODE_ID, + ty, + attrs, + is_placeholder: false, + }) }) - }) - .map(|(r, _)| r) + })?; + Ok(fields) } /// Parses an element of a struct declaration. fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> { - let attrs = self.parse_outer_attributes()?; - let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - self.parse_single_struct_field(lo, vis, attrs) + self.parse_outer_attributes(|this, attrs| { + let lo = this.token.span; + let vis = this.parse_visibility(FollowedByType::No)?; + this.parse_single_struct_field(lo, vis, attrs) + }) } /// Parses a structure field declaration. @@ -1684,75 +1747,75 @@ impl<'a> Parser<'a> { /// - `self` is syntactically allowed when `first_param` holds. fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResult<'a, Param> { let lo = self.token.span; - let attrs = self.parse_outer_attributes()?; - - // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. - if let Some(mut param) = self.parse_self_param()? { - param.attrs = attrs.into(); - return if first_param { Ok(param) } else { self.recover_bad_self_param(param) }; - } + self.parse_outer_attributes(|this, attrs| { + // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. + if let Some(mut param) = this.parse_self_param()? { + param.attrs = attrs.into(); + return if first_param { Ok(param) } else { this.recover_bad_self_param(param) }; + } - let is_name_required = match self.token.kind { - token::DotDotDot => false, - _ => req_name(self.token.span.edition()), - }; - let (pat, ty) = if is_name_required || self.is_named_param() { - debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); + let is_name_required = match this.token.kind { + token::DotDotDot => false, + _ => req_name(this.token.span.edition()), + }; + let (pat, ty) = if is_name_required || this.is_named_param() { + debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); + + let pat = this.parse_fn_param_pat()?; + if let Err(mut err) = this.expect(&token::Colon) { + return if let Some(ident) = + this.parameter_without_type(&mut err, pat, is_name_required, first_param) + { + err.emit(); + Ok(dummy_arg(ident)) + } else { + Err(err) + }; + } - let pat = self.parse_fn_param_pat()?; - if let Err(mut err) = self.expect(&token::Colon) { - return if let Some(ident) = - self.parameter_without_type(&mut err, pat, is_name_required, first_param) + this.eat_incorrect_doc_comment_for_param_type(); + (pat, this.parse_ty_for_param()?) + } else { + debug!("parse_param_general ident_to_pat"); + let parser_snapshot_before_ty = this.clone(); + this.eat_incorrect_doc_comment_for_param_type(); + let mut ty = this.parse_ty_for_param(); + if ty.is_ok() + && this.token != token::Comma + && this.token != token::CloseDelim(token::Paren) { - err.emit(); - Ok(dummy_arg(ident)) - } else { - Err(err) - }; - } - - self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_for_param()?) - } else { - debug!("parse_param_general ident_to_pat"); - let parser_snapshot_before_ty = self.clone(); - self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_for_param(); - if ty.is_ok() - && self.token != token::Comma - && self.token != token::CloseDelim(token::Paren) - { - // This wasn't actually a type, but a pattern looking like a type, - // so we are going to rollback and re-parse for recovery. - ty = self.unexpected(); - } - match ty { - Ok(ty) => { - let ident = Ident::new(kw::Invalid, self.prev_token.span); - let bm = BindingMode::ByValue(Mutability::Not); - let pat = self.mk_pat_ident(ty.span, bm, ident); - (pat, ty) + // This wasn't actually a type, but a pattern looking like a type, + // so we are going to rollback and re-parse for recovery. + ty = this.unexpected(); } - // If this is a C-variadic argument and we hit an error, return the error. - Err(err) if self.token == token::DotDotDot => return Err(err), - // Recover from attempting to parse the argument as a type without pattern. - Err(mut err) => { - err.cancel(); - *self = parser_snapshot_before_ty; - self.recover_arg_parse()? + match ty { + Ok(ty) => { + let ident = Ident::new(kw::Invalid, this.prev_token.span); + let bm = BindingMode::ByValue(Mutability::Not); + let pat = this.mk_pat_ident(ty.span, bm, ident); + (pat, ty) + } + // If this is a C-variadic argument and we hit an error, return the error. + Err(err) if this.token == token::DotDotDot => return Err(err), + // Recover from attempting to parse the argument as a type without pattern. + Err(mut err) => { + err.cancel(); + *this = parser_snapshot_before_ty; + this.recover_arg_parse()? + } } - } - }; + }; - let span = lo.to(self.token.span); + let span = lo.to(this.token.span); - Ok(Param { - attrs: attrs.into(), - id: ast::DUMMY_NODE_ID, - is_placeholder: false, - pat, - span, - ty, + Ok(Param { + attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, + is_placeholder: false, + pat, + span, + ty, + }) }) } @@ -1871,11 +1934,10 @@ impl<'a> Parser<'a> { } fn recover_first_param(&mut self) -> &'static str { - match self - .parse_outer_attributes() - .and_then(|_| self.parse_self_param()) - .map_err(|mut e| e.cancel()) - { + let res = self + .parse_outer_attributes(|this, _attrs| this.parse_self_param()) + .map_err(|mut err| err.cancel()); + match res { Ok(Some(_)) => "method", _ => "function", } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 7340c5744808c..2dbbff66b5480 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -15,9 +15,12 @@ pub use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{self, DelimToken, Token, TokenKind}; -use rustc_ast::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndSpacing}; +use rustc_ast::tokenstream::{ + self, AttributesData, DelimSpan, PreexpTokenStream, PreexpTokenTree, Spacing, TokenStream, + TokenTree, +}; use rustc_ast::DUMMY_NODE_ID; -use rustc_ast::{self as ast, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe}; +use rustc_ast::{self as ast, AttrStyle, Attribute, Const, CrateSugar, Extern, Unsafe}; use rustc_ast::{Async, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult}; @@ -106,6 +109,8 @@ pub struct Parser<'a> { pub last_type_ascription: Option<(Span, bool /* likely path typo */)>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. subparser_name: Option<&'static str>, + pub is_rustdoc: bool, + in_derive: bool, } impl<'a> Drop for Parser<'a> { @@ -118,8 +123,8 @@ impl<'a> Drop for Parser<'a> { struct TokenCursor { frame: TokenCursorFrame, stack: Vec, - cur_token: Option, - collecting: Option, + collecting_buf: Vec<(FlatToken, Spacing)>, + is_collecting: bool, } #[derive(Clone)] @@ -129,24 +134,13 @@ struct TokenCursorFrame { open_delim: bool, tree_cursor: tokenstream::Cursor, close_delim: bool, + modified_stream: Vec<(PreexpTokenTree, Spacing)>, } -/// Used to track additional state needed by `collect_tokens` -#[derive(Clone, Debug)] -struct Collecting { - /// Holds the current tokens captured during the most - /// recent call to `collect_tokens` - buf: Vec, - /// The depth of the `TokenCursor` stack at the time - /// collection was started. When we encounter a `TokenTree::Delimited`, - /// we want to record the `TokenTree::Delimited` itself, - /// but *not* any of the inner tokens while we are inside - /// the new frame (this would cause us to record duplicate tokens). - /// - /// This `depth` fields tracks stack depth we are recording tokens. - /// Only tokens encountered at this depth will be recorded. See - /// `TokenCursor::next` for more details. - depth: usize, +#[derive(Clone)] +enum FlatToken { + Token(Token), + OuterAttributes(AttributesData), } impl TokenCursorFrame { @@ -157,6 +151,7 @@ impl TokenCursorFrame { open_delim: delim == token::NoDelim, tree_cursor: tts.clone().into_trees(), close_delim: delim == token::NoDelim, + modified_stream: vec![], } } } @@ -176,29 +171,19 @@ impl TokenCursor { self.frame = frame; continue; } else { - return Token::new(token::Eof, DUMMY_SP); + (TokenTree::Token(Token::new(token::Eof, DUMMY_SP)), Spacing::Alone) }; - // Don't set an open delimiter as our current token - we want - // to leave it as the full `TokenTree::Delimited` from the previous - // iteration of this loop - if !matches!(tree.0, TokenTree::Token(Token { kind: TokenKind::OpenDelim(_), .. })) { - self.cur_token = Some(tree.clone()); - } - - if let Some(collecting) = &mut self.collecting { - if collecting.depth == self.stack.len() { - debug!( - "TokenCursor::next(): collected {:?} at depth {:?}", - tree, - self.stack.len() - ); - collecting.buf.push(tree.clone()) + match tree.0.clone() { + TokenTree::Token(token) => { + if self.is_collecting { + self.collecting_buf.push((FlatToken::Token(token.clone()), tree.1)); + } else { + self.collecting_buf[0] = (FlatToken::Token(token.clone()), tree.1); + debug_assert_eq!(self.collecting_buf.len(), 1); + } + return token; } - } - - match tree.0 { - TokenTree::Token(token) => return token, TokenTree::Delimited(sp, delim, tts) => { let frame = TokenCursorFrame::new(sp, delim, &tts); self.stack.push(mem::replace(&mut self.frame, frame)); @@ -355,8 +340,12 @@ impl<'a> Parser<'a> { token_cursor: TokenCursor { frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, &tokens), stack: Vec::new(), - cur_token: None, - collecting: None, + // Will get overwritten when we bump the parser below + collecting_buf: vec![( + FlatToken::Token(Token::new(token::Eof, DUMMY_SP)), + Spacing::Alone, + )], + is_collecting: false, }, desugar_doc_comments, unmatched_angle_bracket_count: 0, @@ -365,6 +354,8 @@ impl<'a> Parser<'a> { last_unexpected_token_span: None, last_type_ascription: None, subparser_name, + is_rustdoc: false, + in_derive: false, }; // Make parser point to the first token. @@ -947,28 +938,23 @@ impl<'a> Parser<'a> { ) } - fn parse_or_use_outer_attributes( - &mut self, - already_parsed_attrs: Option, - ) -> PResult<'a, AttrVec> { - if let Some(attrs) = already_parsed_attrs { - Ok(attrs) - } else { - self.parse_outer_attributes().map(|a| a.into()) - } - } - /// Parses a single token tree from the input. pub(crate) fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { token::OpenDelim(..) => { - let frame = mem::replace( - &mut self.token_cursor.frame, - self.token_cursor.stack.pop().unwrap(), - ); - self.token = Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close); + let depth = self.token_cursor.stack.len(); + while !(depth == self.token_cursor.stack.len() + && matches!(self.token.kind, token::CloseDelim(_))) + { + self.bump(); + } + let frame = &self.token_cursor.frame; + let stream = frame.tree_cursor.stream.clone(); + let span = frame.span; + let delim = frame.delim; + // Consume close delimiter self.bump(); - TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream) + TokenTree::Delimited(span, delim, stream) } token::CloseDelim(_) | token::Eof => unreachable!(), _ => { @@ -1157,6 +1143,13 @@ impl<'a> Parser<'a> { } } + pub fn collect_tokens_no_attrs( + &mut self, + f: impl FnOnce(&mut Self) -> PResult<'a, R>, + ) -> PResult<'a, (R, PreexpTokenStream)> { + self.collect_tokens(|this| f(this).map(|res| (res, Vec::new()))) + } + /// Records all tokens consumed by the provided callback, /// including the current token. These tokens are collected /// into a `TokenStream`, and returned along with the result @@ -1175,80 +1168,9 @@ impl<'a> Parser<'a> { /// a parsed AST item, which always has matching delimiters. pub fn collect_tokens( &mut self, - f: impl FnOnce(&mut Self) -> PResult<'a, R>, - ) -> PResult<'a, (R, TokenStream)> { - // Record all tokens we parse when parsing this item. - let tokens: Vec = self.token_cursor.cur_token.clone().into_iter().collect(); - debug!("collect_tokens: starting with {:?}", tokens); - - // We need special handling for the case where `collect_tokens` is called - // on an opening delimeter (e.g. '('). At this point, we have already pushed - // a new frame - however, we want to record the original `TokenTree::Delimited`, - // for consistency with the case where we start recording one token earlier. - // See `TokenCursor::next` to see how `cur_token` is set up. - let prev_depth = - if matches!(self.token_cursor.cur_token, Some((TokenTree::Delimited(..), _))) { - if self.token_cursor.stack.is_empty() { - // There is nothing below us in the stack that - // the function could consume, so the only thing it can legally - // capture is the entire contents of the current frame. - return Ok((f(self)?, TokenStream::new(tokens))); - } - // We have already recorded the full `TokenTree::Delimited` when we created - // our `tokens` vector at the start of this function. We are now inside - // a new frame corresponding to the `TokenTree::Delimited` we already recoreded. - // We don't want to record any of the tokens inside this frame, since they - // will be duplicates of the tokens nested inside the `TokenTree::Delimited`. - // Therefore, we set our recording depth to the *previous* frame. This allows - // us to record a sequence like: `(foo).bar()`: the `(foo)` will be recored - // as our initial `cur_token`, while the `.bar()` will be recored after we - // pop the `(foo)` frame. - self.token_cursor.stack.len() - 1 - } else { - self.token_cursor.stack.len() - }; - let prev_collecting = - self.token_cursor.collecting.replace(Collecting { buf: tokens, depth: prev_depth }); - - let ret = f(self); - - let mut collected_tokens = if let Some(collecting) = self.token_cursor.collecting.take() { - collecting.buf - } else { - let msg = "our vector went away?"; - debug!("collect_tokens: {}", msg); - self.sess.span_diagnostic.delay_span_bug(self.token.span, &msg); - // This can happen due to a bad interaction of two unrelated recovery mechanisms - // with mismatched delimiters *and* recovery lookahead on the likely typo - // `pub ident(` (#62895, different but similar to the case above). - return Ok((ret?, TokenStream::default())); - }; - - debug!("collect_tokens: got raw tokens {:?}", collected_tokens); - - // If we're not at EOF our current token wasn't actually consumed by - // `f`, but it'll still be in our list that we pulled out. In that case - // put it back. - let extra_token = if self.token != token::Eof { collected_tokens.pop() } else { None }; - - if let Some(mut collecting) = prev_collecting { - // If we were previously collecting at the same depth, - // then the previous call to `collect_tokens` needs to see - // the tokens we just recorded. - // - // If we were previously recording at an lower `depth`, - // then the previous `collect_tokens` call already recorded - // this entire frame in the form of a `TokenTree::Delimited`, - // so there is nothing else for us to do. - if collecting.depth == prev_depth { - collecting.buf.extend(collected_tokens.iter().cloned()); - collecting.buf.extend(extra_token); - debug!("collect_tokens: updating previous buf to {:?}", collecting); - } - self.token_cursor.collecting = Some(collecting) - } - - Ok((ret?, TokenStream::new(collected_tokens))) + f: impl FnOnce(&mut Self) -> PResult<'a, (R, Vec)>, + ) -> PResult<'a, (R, PreexpTokenStream)> { + self.collect_tokens_keep_in_stream(true, f) } /// `::{` or `::*` diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 15660fd574c13..c8a1823476b8f 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -98,33 +98,38 @@ impl<'a> Parser<'a> { // in advance whether or not a proc-macro will be (transitively) invoked, // we always capture tokens for any `Nonterminal` which needs them. Ok(match kind { - NonterminalKind::Item => match self.collect_tokens(|this| this.parse_item())? { - (Some(mut item), tokens) => { - // If we captured tokens during parsing (due to outer attributes), - // use those. - if item.tokens.is_none() { - item.tokens = Some(tokens); + NonterminalKind::Item => { + match self.collect_tokens_no_attrs(|this| this.parse_item())? { + (Some(mut item), tokens) => { + // If we captured tokens during parsing (due to outer attributes), + // use those. + if item.tokens.is_none() { + item.tokens = Some(tokens); + } + token::NtItem(item) + } + (None, _) => { + return Err( + self.struct_span_err(self.token.span, "expected an item keyword") + ); } - token::NtItem(item) - } - (None, _) => { - return Err(self.struct_span_err(self.token.span, "expected an item keyword")); } - }, + } NonterminalKind::Block => { - let (mut block, tokens) = self.collect_tokens(|this| this.parse_block())?; + let (mut block, tokens) = + self.collect_tokens_no_attrs(|this| this.parse_block())?; // We have have eaten an NtBlock, which could already have tokens if block.tokens.is_none() { - block.tokens = Some(tokens); + block.tokens = Some(tokens.to_tokenstream()); } token::NtBlock(block) } NonterminalKind::Stmt => { - let (stmt, tokens) = self.collect_tokens(|this| this.parse_stmt())?; + let (stmt, tokens) = self.collect_tokens_no_attrs(|this| this.parse_stmt())?; match stmt { Some(mut s) => { if s.tokens.is_none() { - s.tokens = Some(tokens); + s.tokens = Some(tokens.to_tokenstream()); } token::NtStmt(s) } @@ -134,15 +139,16 @@ impl<'a> Parser<'a> { } } NonterminalKind::Pat => { - let (mut pat, tokens) = self.collect_tokens(|this| this.parse_pat(None))?; + let (mut pat, tokens) = + self.collect_tokens_no_attrs(|this| this.parse_pat(None))?; // We have have eaten an NtPat, which could already have tokens if pat.tokens.is_none() { - pat.tokens = Some(tokens); + pat.tokens = Some(tokens.to_tokenstream()); } token::NtPat(pat) } NonterminalKind::Expr => { - let (mut expr, tokens) = self.collect_tokens(|this| this.parse_expr())?; + let (mut expr, tokens) = self.collect_tokens_no_attrs(|this| this.parse_expr())?; // If we captured tokens during parsing (due to outer attributes), // use those. if expr.tokens.is_none() { @@ -152,7 +158,7 @@ impl<'a> Parser<'a> { } NonterminalKind::Literal => { let (mut lit, tokens) = - self.collect_tokens(|this| this.parse_literal_maybe_minus())?; + self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?; // We have have eaten a nonterminal, which could already have tokens if lit.tokens.is_none() { lit.tokens = Some(tokens); @@ -160,10 +166,10 @@ impl<'a> Parser<'a> { token::NtLiteral(lit) } NonterminalKind::Ty => { - let (mut ty, tokens) = self.collect_tokens(|this| this.parse_ty())?; + let (mut ty, tokens) = self.collect_tokens_no_attrs(|this| this.parse_ty())?; // We have an eaten an NtTy, which could already have tokens if ty.tokens.is_none() { - ty.tokens = Some(tokens); + ty.tokens = Some(tokens.to_tokenstream()); } token::NtTy(ty) } @@ -180,28 +186,29 @@ impl<'a> Parser<'a> { } NonterminalKind::Path => { let (mut path, tokens) = - self.collect_tokens(|this| this.parse_path(PathStyle::Type))?; + self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?; // We have have eaten an NtPath, which could already have tokens if path.tokens.is_none() { - path.tokens = Some(tokens); + path.tokens = Some(tokens.to_tokenstream()); } token::NtPath(path) } NonterminalKind::Meta => { - let (mut attr, tokens) = self.collect_tokens(|this| this.parse_attr_item())?; + let (mut attr, tokens) = + self.collect_tokens_no_attrs(|this| this.parse_attr_item())?; // We may have eaten a nonterminal, which could already have tokens if attr.tokens.is_none() { - attr.tokens = Some(tokens); + attr.tokens = Some(tokens.to_tokenstream()); } token::NtMeta(P(attr)) } NonterminalKind::TT => token::NtTT(self.parse_token_tree()), NonterminalKind::Vis => { - let (mut vis, tokens) = - self.collect_tokens(|this| this.parse_visibility(FollowedByType::Yes))?; + let (mut vis, tokens) = self + .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?; // We may have etan an `NtVis`, which could already have tokens if vis.tokens.is_none() { - vis.tokens = Some(tokens); + vis.tokens = Some(tokens.to_tokenstream()); } token::NtVis(vis) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 2c0133a24dcb1..88ff2547d5490 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -831,102 +831,107 @@ impl<'a> Parser<'a> { let mut etc_span = None; while self.token != token::CloseDelim(token::Brace) { - let attrs = match self.parse_outer_attributes() { - Ok(attrs) => attrs, - Err(err) => { - if let Some(mut delayed) = delayed_err { + let field_pat = self.parse_outer_attributes(|this, attrs| { + let lo = this.token.span; + + // check that a comma comes after every field + if !ate_comma { + let err = this.struct_span_err(this.prev_token.span, "expected `,`"); + if let Some(delayed) = delayed_err.as_mut() { delayed.emit(); } return Err(err); } - }; - let lo = self.token.span; - - // check that a comma comes after every field - if !ate_comma { - let err = self.struct_span_err(self.prev_token.span, "expected `,`"); - if let Some(mut delayed) = delayed_err { - delayed.emit(); - } - return Err(err); - } - ate_comma = false; + ate_comma = false; - if self.check(&token::DotDot) || self.token == token::DotDotDot { - etc = true; - let mut etc_sp = self.token.span; + if this.check(&token::DotDot) || this.token == token::DotDotDot { + etc = true; + let mut etc_sp = this.token.span; - self.recover_one_fewer_dotdot(); - self.bump(); // `..` || `...` + this.recover_one_fewer_dotdot(); + this.bump(); // `..` || `...` - if self.token == token::CloseDelim(token::Brace) { - etc_span = Some(etc_sp); - break; - } - let token_str = super::token_descr(&self.token); - let msg = &format!("expected `}}`, found {}", token_str); - let mut err = self.struct_span_err(self.token.span, msg); - - err.span_label(self.token.span, "expected `}`"); - let mut comma_sp = None; - if self.token == token::Comma { - // Issue #49257 - let nw_span = self.sess.source_map().span_until_non_whitespace(self.token.span); - etc_sp = etc_sp.to(nw_span); - err.span_label( - etc_sp, - "`..` must be at the end and cannot have a trailing comma", - ); - comma_sp = Some(self.token.span); - self.bump(); - ate_comma = true; - } - - etc_span = Some(etc_sp.until(self.token.span)); - if self.token == token::CloseDelim(token::Brace) { - // If the struct looks otherwise well formed, recover and continue. - if let Some(sp) = comma_sp { - err.span_suggestion_short( - sp, - "remove this comma", - String::new(), - Applicability::MachineApplicable, - ); + if this.token == token::CloseDelim(token::Brace) { + etc_span = Some(etc_sp); + return Ok(None); } - err.emit(); - break; - } else if self.token.is_ident() && ate_comma { - // Accept fields coming after `..,`. - // This way we avoid "pattern missing fields" errors afterwards. - // We delay this error until the end in order to have a span for a - // suggested fix. - if let Some(mut delayed_err) = delayed_err { - delayed_err.emit(); - return Err(err); - } else { - delayed_err = Some(err); + let token_str = super::token_descr(&this.token); + let msg = &format!("expected `}}`, found {}", token_str); + let mut err = this.struct_span_err(this.token.span, msg); + + err.span_label(this.token.span, "expected `}`"); + let mut comma_sp = None; + if this.token == token::Comma { + // Issue #49257 + let nw_span = + this.sess.source_map().span_until_non_whitespace(this.token.span); + etc_sp = etc_sp.to(nw_span); + err.span_label( + etc_sp, + "`..` must be at the end and cannot have a trailing comma", + ); + comma_sp = Some(this.token.span); + this.bump(); + ate_comma = true; } - } else { - if let Some(mut err) = delayed_err { + + etc_span = Some(etc_sp.until(this.token.span)); + if this.token == token::CloseDelim(token::Brace) { + // If the struct looks otherwise well formed, recover and continue. + if let Some(sp) = comma_sp { + err.span_suggestion_short( + sp, + "remove this comma", + String::new(), + Applicability::MachineApplicable, + ); + } err.emit(); + return Ok(None); + } else if this.token.is_ident() && ate_comma { + // Accept fields coming after `..,`. + // This way we avoid "pattern missing fields" errors afterwards. + // We delay this error until the end in order to have a span for a + // suggested fix. + if let Some(delayed_err) = delayed_err.as_mut() { + delayed_err.emit(); + return Err(err); + } else { + delayed_err = Some(err); + } + } else { + if let Some(err) = delayed_err.as_mut() { + err.emit(); + } + return Err(err); } - return Err(err); } - } - fields.push(match self.parse_pat_field(lo, attrs) { - Ok(field) => field, + let field_pat = match this.parse_pat_field(lo, attrs) { + Ok(field) => field, + Err(err) => { + if let Some(delayed_err) = delayed_err.as_mut() { + delayed_err.emit(); + } + return Err(err); + } + }; + ate_comma = this.eat(&token::Comma); + Ok(Some(field_pat)) + }); + match field_pat { + Ok(Some(field_pat)) => fields.push(field_pat), + Ok(None) => break, Err(err) => { - if let Some(mut delayed_err) = delayed_err { - delayed_err.emit(); + if let Some(delayed) = delayed_err.as_mut() { + delayed.emit(); } return Err(err); } - }); - ate_comma = self.eat(&token::Comma); + } } - if let Some(mut err) = delayed_err { + if let Some(err) = delayed_err.as_mut() { if let Some(etc_span) = etc_span { err.multipart_suggestion( "move the `..` to the end of the field list", diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index fd1c6b25aec63..56d489f1df4ba 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -33,43 +33,68 @@ impl<'a> Parser<'a> { fn parse_stmt_without_recovery(&mut self) -> PResult<'a, Option> { maybe_whole!(self, NtStmt, |x| Some(x)); - let attrs = self.parse_outer_attributes()?; - let lo = self.token.span; - - let stmt = if self.eat_keyword(kw::Let) { - self.parse_local_mk(lo, attrs.into())? - } else if self.is_kw_followed_by_ident(kw::Mut) { - self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut")? - } else if self.is_kw_followed_by_ident(kw::Auto) { - self.bump(); // `auto` - let msg = "write `let` instead of `auto` to introduce a new variable"; - self.recover_stmt_local(lo, attrs.into(), msg, "let")? - } else if self.is_kw_followed_by_ident(sym::var) { - self.bump(); // `var` - let msg = "write `let` instead of `var` to introduce a new variable"; - self.recover_stmt_local(lo, attrs.into(), msg, "let")? - } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { - // We have avoided contextual keywords like `union`, items with `crate` visibility, - // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something - // that starts like a path (1 token), but it fact not a path. - // Also, we avoid stealing syntax from `parse_item_`. - self.parse_stmt_path_start(lo, attrs)? - } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? { - // FIXME: Bad copy of attrs - self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) - } else if self.eat(&token::Semi) { - // Do not attempt to parse an expression if we're done here. - self.error_outer_attrs(&attrs); - self.mk_stmt(lo, StmtKind::Empty) - } else if self.token != token::CloseDelim(token::Brace) { - // Remainder are line-expr stmts. - let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?; - self.mk_stmt(lo.to(e.span), StmtKind::Expr(e)) - } else { - self.error_outer_attrs(&attrs); - return Ok(None); + let (mut stmt, tokens) = self.parse_outer_attributes_with_tokens(|this, attrs| { + let lo = this.token.span; + + let stmt = if this.eat_keyword(kw::Let) { + this.parse_local_mk(lo, attrs.into())? + } else if this.is_kw_followed_by_ident(kw::Mut) { + this.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut")? + } else if this.is_kw_followed_by_ident(kw::Auto) { + this.bump(); // `auto` + let msg = "write `let` instead of `auto` to introduce a new variable"; + this.recover_stmt_local(lo, attrs.into(), msg, "let")? + } else if this.is_kw_followed_by_ident(sym::var) { + this.bump(); // `var` + let msg = "write `let` instead of `var` to introduce a new variable"; + this.recover_stmt_local(lo, attrs.into(), msg, "let")? + } else if this.check_path() + && !this.token.is_qpath_start() + && !this.is_path_start_item() + { + // We have avoided contextual keywords like `union`, items with `crate` visibility, + // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something + // that starts like a path (1 token), but it fact not a path. + // Also, we avoid stealing syntax from `parse_item_`. + this.parse_stmt_path_start(lo, attrs)? + } else if let Some(item) = + this.parse_item_common(attrs.clone(), false, true, |_| true)? + { + // FIXME: Bad copy of attrs + this.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) + } else if this.eat(&token::Semi) { + // Do not attempt to parse an expression if we're done here. + this.error_outer_attrs(&attrs); + this.mk_stmt(lo, StmtKind::Empty) + } else if this.token != token::CloseDelim(token::Brace) { + // Remainder are line-expr stmts. + let e = this.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?; + this.mk_stmt(lo.to(e.span), StmtKind::Expr(e)) + } else { + this.error_outer_attrs(&attrs); + return Ok(None); + }; + Ok(Some(stmt)) + })?; + let old_tokens = match stmt.as_mut() { + Some(Stmt { kind: StmtKind::Local(local), .. }) => Some(&mut local.tokens), + Some(Stmt { kind: StmtKind::Item(item), .. }) => Some(&mut item.tokens), + Some(Stmt { kind: StmtKind::Expr(expr) | StmtKind::Semi(expr), .. }) => { + // FIXME: Attribute parsing should do this for us. + Some(&mut expr.tokens) + } + Some(Stmt { kind: StmtKind::Empty, .. }) => None, + Some(Stmt { kind: StmtKind::MacCall(mac), .. }) => Some(&mut mac.tokens), + None => None, }; - Ok(Some(stmt)) + + if let Some(old_tokens) = old_tokens { + if old_tokens.is_none() { + *old_tokens = tokens; + } + } + + Ok(stmt) } fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec) -> PResult<'a, Stmt> { @@ -107,7 +132,7 @@ impl<'a> Parser<'a> { let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof { - StmtKind::MacCall(P(MacCallStmt { mac, style, attrs })) + StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None })) } else { // Since none of the above applied, this is an expression statement macro. let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new()); @@ -219,7 +244,7 @@ impl<'a> Parser<'a> { } }; let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span }; - Ok(P(ast::Local { ty, pat, init, id: DUMMY_NODE_ID, span: lo.to(hi), attrs })) + Ok(P(ast::Local { ty, pat, init, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None })) } /// Parses the RHS of a local variable declaration (e.g., '= 14;'). diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 7b7c152d8abbf..b3cb938b229e1 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -432,6 +432,8 @@ pub fn make_test( } }; + parser.is_rustdoc = true; + loop { match parser.parse_item() { Ok(Some(item)) => { diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.32bit.mir b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.32bit.mir index 832f18e14c25d..794eee42296d0 100644 --- a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.32bit.mir @@ -1,11 +1,11 @@ // MIR for `Test::X` 0 mir_map fn Test::X(_1: usize) -> Test { - let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 bb0: { - ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 + discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 + return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 } } diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.64bit.mir b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.64bit.mir index 832f18e14c25d..794eee42296d0 100644 --- a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.64bit.mir +++ b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.64bit.mir @@ -1,11 +1,11 @@ // MIR for `Test::X` 0 mir_map fn Test::X(_1: usize) -> Test { - let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + let mut _0: Test; // return place in scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 bb0: { - ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 - return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:13 + ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 + discriminant(_0) = 0; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 + return; // scope 0 at $DIR/unusual-item-types.rs:16:5: 16:14 } } diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout index 3d7d476cf6c05..fb311a9045b35 100644 --- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout +++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index a4ce6061b4c9d..d1e0f409948c2 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0},"tokens":null}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.rs b/src/test/ui/conditional-compilation/cfg-attr-parse.rs index 8ca31c118369c..9c7cc3698a628 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-parse.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-parse.rs @@ -2,10 +2,12 @@ // Completely empty `cfg_attr` input #[cfg_attr()] //~ error: malformed `cfg_attr` attribute input +//~| error: malformed `cfg_attr` attribute input struct NoConfigurationPredicate; // Zero attributes, zero trailing comma (comma manatory here) #[cfg_attr(all())] //~ error: expected `,`, found end of `cfg_attr` +//~^ error: expected `,`, found end of `cfg_attr` struct A0C0; // Zero attributes, one trailing comma @@ -14,6 +16,7 @@ struct A0C1; // Zero attributes, two trailing commas #[cfg_attr(all(),,)] //~ ERROR expected identifier +//~| ERROR expected identifier struct A0C2; // One attribute, no trailing comma @@ -26,6 +29,7 @@ struct A1C1; // One attribute, two trailing commas #[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier +//~| ERROR expected identifier struct A1C2; // Two attributes, no trailing comma @@ -38,18 +42,23 @@ struct A2C1; // Two attributes, two trailing commas #[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier +//~| ERROR expected identifier struct A2C2; // Wrong delimiter `[` #[cfg_attr[all(),,]] -//~^ ERROR wrong `cfg_attr` delimiters -//~| ERROR expected identifier, found `,` +//~^ error wrong `cfg_attr` delimiters +//~| error expected identifier, found `,` +//~| error wrong `cfg_attr` delimiters +//~| error expected identifier, found `,` struct BracketZero; // Wrong delimiter `{` #[cfg_attr{all(),,}] -//~^ ERROR wrong `cfg_attr` delimiters -//~| ERROR expected identifier, found `,` +//~^ error wrong `cfg_attr` delimiters +//~| error wrong `cfg_attr` delimiters +//~| error expected identifier, found `,` +//~| error expected identifier, found `,` struct BraceZero; fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr index 3a590d3282d46..1713c532c8f51 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr @@ -6,8 +6,16 @@ LL | #[cfg_attr()] | = note: for more information, visit +error: malformed `cfg_attr` attribute input + --> $DIR/cfg-attr-parse.rs:4:1 + | +LL | #[cfg_attr()] + | ^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]` + | + = note: for more information, visit + error: expected `,`, found end of `cfg_attr` input - --> $DIR/cfg-attr-parse.rs:8:17 + --> $DIR/cfg-attr-parse.rs:9:17 | LL | #[cfg_attr(all())] | ^ expected `,` @@ -15,8 +23,26 @@ LL | #[cfg_attr(all())] = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit +error: expected `,`, found end of `cfg_attr` input + --> $DIR/cfg-attr-parse.rs:9:17 + | +LL | #[cfg_attr(all())] + | ^ expected `,` + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:18:18 + | +LL | #[cfg_attr(all(),,)] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:16:18 + --> $DIR/cfg-attr-parse.rs:18:18 | LL | #[cfg_attr(all(),,)] | ^ expected identifier @@ -25,7 +51,7 @@ LL | #[cfg_attr(all(),,)] = note: for more information, visit error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:28:28 + --> $DIR/cfg-attr-parse.rs:31:28 | LL | #[cfg_attr(all(), must_use,,)] | ^ expected identifier @@ -34,7 +60,25 @@ LL | #[cfg_attr(all(), must_use,,)] = note: for more information, visit error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:40:40 + --> $DIR/cfg-attr-parse.rs:31:28 + | +LL | #[cfg_attr(all(), must_use,,)] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:44:40 + | +LL | #[cfg_attr(all(), must_use, deprecated,,)] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:44:40 | LL | #[cfg_attr(all(), must_use, deprecated,,)] | ^ expected identifier @@ -43,7 +87,27 @@ LL | #[cfg_attr(all(), must_use, deprecated,,)] = note: for more information, visit error: wrong `cfg_attr` delimiters - --> $DIR/cfg-attr-parse.rs:44:11 + --> $DIR/cfg-attr-parse.rs:49:11 + | +LL | #[cfg_attr[all(),,]] + | ^^^^^^^^^ + | +help: the delimiters should be `(` and `)` + | +LL | #[cfg_attr(all(),,)] + | ^ ^ + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:49:18 + | +LL | #[cfg_attr[all(),,]] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: wrong `cfg_attr` delimiters + --> $DIR/cfg-attr-parse.rs:49:11 | LL | #[cfg_attr[all(),,]] | ^^^^^^^^^ @@ -54,7 +118,7 @@ LL | #[cfg_attr(all(),,)] | ^ ^ error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:44:18 + --> $DIR/cfg-attr-parse.rs:49:18 | LL | #[cfg_attr[all(),,]] | ^ expected identifier @@ -63,7 +127,27 @@ LL | #[cfg_attr[all(),,]] = note: for more information, visit error: wrong `cfg_attr` delimiters - --> $DIR/cfg-attr-parse.rs:50:11 + --> $DIR/cfg-attr-parse.rs:57:11 + | +LL | #[cfg_attr{all(),,}] + | ^^^^^^^^^ + | +help: the delimiters should be `(` and `)` + | +LL | #[cfg_attr(all(),,)] + | ^ ^ + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:57:18 + | +LL | #[cfg_attr{all(),,}] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: wrong `cfg_attr` delimiters + --> $DIR/cfg-attr-parse.rs:57:11 | LL | #[cfg_attr{all(),,}] | ^^^^^^^^^ @@ -74,7 +158,7 @@ LL | #[cfg_attr(all(),,)] | ^ ^ error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:50:18 + --> $DIR/cfg-attr-parse.rs:57:18 | LL | #[cfg_attr{all(),,}] | ^ expected identifier @@ -82,5 +166,5 @@ LL | #[cfg_attr{all(),,}] = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit -error: aborting due to 9 previous errors +error: aborting due to 18 previous errors diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 72607629d3c10..1961245c984bb 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -2,7 +2,7 @@ warning: variant is never constructed: `Void` --> $DIR/derive-uninhabited-enum-38885.rs:13:5 | LL | Void(Void), - | ^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: `-W dead-code` implied by `-W unused` diff --git a/src/test/ui/discrim/discrim-overflow-2.stderr b/src/test/ui/discrim/discrim-overflow-2.stderr index 198ebe9eb51f9..4f6adb72c95bf 100644 --- a/src/test/ui/discrim/discrim-overflow-2.stderr +++ b/src/test/ui/discrim/discrim-overflow-2.stderr @@ -2,7 +2,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:15:9 | LL | OhNo, - | ^^^^ overflowed on value after 127 + | ^^^^^ overflowed on value after 127 | = note: explicitly set `OhNo = -128` if that is desired outcome @@ -10,7 +10,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:24:9 | LL | OhNo, - | ^^^^ overflowed on value after 255 + | ^^^^^ overflowed on value after 255 | = note: explicitly set `OhNo = 0` if that is desired outcome @@ -18,7 +18,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:33:9 | LL | OhNo, - | ^^^^ overflowed on value after 32767 + | ^^^^^ overflowed on value after 32767 | = note: explicitly set `OhNo = -32768` if that is desired outcome @@ -26,7 +26,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:42:9 | LL | OhNo, - | ^^^^ overflowed on value after 65535 + | ^^^^^ overflowed on value after 65535 | = note: explicitly set `OhNo = 0` if that is desired outcome @@ -34,7 +34,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:51:9 | LL | OhNo, - | ^^^^ overflowed on value after 2147483647 + | ^^^^^ overflowed on value after 2147483647 | = note: explicitly set `OhNo = -2147483648` if that is desired outcome @@ -42,7 +42,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:60:9 | LL | OhNo, - | ^^^^ overflowed on value after 4294967295 + | ^^^^^ overflowed on value after 4294967295 | = note: explicitly set `OhNo = 0` if that is desired outcome @@ -50,7 +50,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:69:9 | LL | OhNo, - | ^^^^ overflowed on value after 9223372036854775807 + | ^^^^^ overflowed on value after 9223372036854775807 | = note: explicitly set `OhNo = -9223372036854775808` if that is desired outcome @@ -58,7 +58,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow-2.rs:78:9 | LL | OhNo, - | ^^^^ overflowed on value after 18446744073709551615 + | ^^^^^ overflowed on value after 18446744073709551615 | = note: explicitly set `OhNo = 0` if that is desired outcome diff --git a/src/test/ui/discrim/discrim-overflow.stderr b/src/test/ui/discrim/discrim-overflow.stderr index a2ae4863f9f79..8dd362cfd2e74 100644 --- a/src/test/ui/discrim/discrim-overflow.stderr +++ b/src/test/ui/discrim/discrim-overflow.stderr @@ -2,7 +2,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:13:9 | LL | OhNo, - | ^^^^ overflowed on value after 127 + | ^^^^^ overflowed on value after 127 | = note: explicitly set `OhNo = -128` if that is desired outcome @@ -10,7 +10,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:24:9 | LL | OhNo, - | ^^^^ overflowed on value after 255 + | ^^^^^ overflowed on value after 255 | = note: explicitly set `OhNo = 0` if that is desired outcome @@ -18,7 +18,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:35:9 | LL | OhNo, - | ^^^^ overflowed on value after 32767 + | ^^^^^ overflowed on value after 32767 | = note: explicitly set `OhNo = -32768` if that is desired outcome @@ -26,7 +26,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:46:9 | LL | OhNo, - | ^^^^ overflowed on value after 65535 + | ^^^^^ overflowed on value after 65535 | = note: explicitly set `OhNo = 0` if that is desired outcome @@ -34,7 +34,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:58:9 | LL | OhNo, - | ^^^^ overflowed on value after 2147483647 + | ^^^^^ overflowed on value after 2147483647 | = note: explicitly set `OhNo = -2147483648` if that is desired outcome @@ -42,7 +42,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:70:9 | LL | OhNo, - | ^^^^ overflowed on value after 4294967295 + | ^^^^^ overflowed on value after 4294967295 | = note: explicitly set `OhNo = 0` if that is desired outcome @@ -50,7 +50,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:82:9 | LL | OhNo, - | ^^^^ overflowed on value after 9223372036854775807 + | ^^^^^ overflowed on value after 9223372036854775807 | = note: explicitly set `OhNo = -9223372036854775808` if that is desired outcome @@ -58,7 +58,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/discrim-overflow.rs:94:9 | LL | OhNo, - | ^^^^ overflowed on value after 18446744073709551615 + | ^^^^^ overflowed on value after 18446744073709551615 | = note: explicitly set `OhNo = 0` if that is desired outcome diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr index 3570012fc3752..c5c257e4f5a5a 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr @@ -18,7 +18,7 @@ LL | XE::XEmpty3 => () LL | XEmpty3 {}, | ------- `XE::XEmpty3` defined here LL | XEmpty4, - | ------- similarly named unit variant `XEmpty4` defined here + | -------- similarly named unit variant `XEmpty4` defined here | help: use struct pattern syntax instead | diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr index aac872ba0ecca..5b7f1e66822b3 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr @@ -19,7 +19,7 @@ LL | XEmpty3 {}, | ------- `XE::XEmpty3` defined here LL | XEmpty4, LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ---------- similarly named tuple variant `XEmpty5` defined here | help: use struct pattern syntax instead | @@ -51,7 +51,7 @@ LL | XEmpty3 {}, | ------- `XE::XEmpty3` defined here LL | XEmpty4, LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ---------- similarly named tuple variant `XEmpty5` defined here | help: use struct pattern syntax instead | diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr index 7b0d9717e63a2..b5a57d85adda3 100644 --- a/src/test/ui/empty/empty-struct-tuple-pat.stderr +++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr @@ -34,9 +34,9 @@ LL | XE::XEmpty5 => (), ::: $DIR/auxiliary/empty-struct.rs:7:5 | LL | XEmpty4, - | ------- similarly named unit variant `XEmpty4` defined here + | -------- similarly named unit variant `XEmpty4` defined here LL | XEmpty5(), - | --------- `XE::XEmpty5` defined here + | ---------- `XE::XEmpty5` defined here | help: use the tuple variant pattern syntax instead | diff --git a/src/test/ui/empty/empty-struct-unit-pat.stderr b/src/test/ui/empty/empty-struct-unit-pat.stderr index 8ee14a3d01d89..ef2d50c6ced07 100644 --- a/src/test/ui/empty/empty-struct-unit-pat.stderr +++ b/src/test/ui/empty/empty-struct-unit-pat.stderr @@ -59,7 +59,7 @@ LL | XE::XEmpty4() => (), ::: $DIR/auxiliary/empty-struct.rs:8:5 | LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ---------- similarly named tuple variant `XEmpty5` defined here error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4` --> $DIR/empty-struct-unit-pat.rs:46:9 @@ -78,7 +78,7 @@ LL | XE::XEmpty4(..) => (), ::: $DIR/auxiliary/empty-struct.rs:8:5 | LL | XEmpty5(), - | --------- similarly named tuple variant `XEmpty5` defined here + | ---------- similarly named tuple variant `XEmpty5` defined here error: aborting due to 8 previous errors diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr index b5f61e6e991d8..59045bf0957d1 100644 --- a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr +++ b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr @@ -23,10 +23,10 @@ LL | Unit = 1, | ^ disallowed custom discriminant LL | LL | Tuple() = 2, - | ----------- tuple variant defined here + | ------------ tuple variant defined here LL | LL | Struct{} = 3, - | ------------ struct variant defined here + | ------------- struct variant defined here | = note: see issue #60553 for more information = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable diff --git a/src/test/ui/enum/enum-size-variance.stderr b/src/test/ui/enum/enum-size-variance.stderr index 6012033dc62d4..ff4820f819874 100644 --- a/src/test/ui/enum/enum-size-variance.stderr +++ b/src/test/ui/enum/enum-size-variance.stderr @@ -2,7 +2,7 @@ warning: enum variant is more than three times larger (32 bytes) than the next l --> $DIR/enum-size-variance.rs:18:5 | LL | L(i64, i64, i64, i64), - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/enum-size-variance.rs:3:9 diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index a3610099294da..5b648d318d0a1 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -2,7 +2,7 @@ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has --> $DIR/E0023.rs:11:9 | LL | Apple(String, String), - | --------------------- tuple variant defined here + | ---------------------- tuple variant defined here ... LL | Fruit::Apple(a) => {}, | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 @@ -11,7 +11,7 @@ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has --> $DIR/E0023.rs:12:9 | LL | Apple(String, String), - | --------------------- tuple variant defined here + | ---------------------- tuple variant defined here ... LL | Fruit::Apple(a, b, c) => {}, | ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3 @@ -20,7 +20,7 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has --> $DIR/E0023.rs:13:9 | LL | Pear(u32), - | --------- tuple variant defined here + | ---------- tuple variant defined here ... LL | Fruit::Pear(1, 2) => {}, | ^^^^^^^^^^^^^^^^^ expected 1 field, found 2 @@ -29,7 +29,7 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has --> $DIR/E0023.rs:14:9 | LL | Orange((String, String)), - | ------------------------ tuple variant defined here + | ------------------------- tuple variant defined here ... LL | Fruit::Orange(a, b) => {}, | ^^^^^^^^^^^^^^^^^^^ expected 1 field, found 2 @@ -43,7 +43,7 @@ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has --> $DIR/E0023.rs:15:9 | LL | Banana(()), - | ---------- tuple variant defined here + | ----------- tuple variant defined here ... LL | Fruit::Banana() => {}, | ^^^^^^^^^^^^^^^ expected 1 field, found 0 diff --git a/src/test/ui/error-codes/E0370.stderr b/src/test/ui/error-codes/E0370.stderr index 7fb622ee80bbf..21e8eb88955f4 100644 --- a/src/test/ui/error-codes/E0370.stderr +++ b/src/test/ui/error-codes/E0370.stderr @@ -2,7 +2,7 @@ error[E0370]: enum discriminant overflowed --> $DIR/E0370.rs:7:5 | LL | Y, - | ^ overflowed on value after 9223372036854775807 + | ^^ overflowed on value after 9223372036854775807 | = note: explicitly set `Y = -9223372036854775808` if that is desired outcome diff --git a/src/test/ui/error-codes/E0618.stderr b/src/test/ui/error-codes/E0618.stderr index 6ddda3bf8b528..70ba3a8791344 100644 --- a/src/test/ui/error-codes/E0618.stderr +++ b/src/test/ui/error-codes/E0618.stderr @@ -2,7 +2,7 @@ error[E0618]: expected function, found enum variant `X::Entry` --> $DIR/E0618.rs:6:5 | LL | Entry, - | ----- `X::Entry` defined here + | ------ `X::Entry` defined here ... LL | X::Entry(); | ^^^^^^^^-- diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs index d44f78d4fab27..4a6f506798ab3 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs @@ -8,6 +8,7 @@ extern crate cfg_target_thread_local; extern { #[cfg_attr(target_thread_local, thread_local)] //~^ `cfg(target_thread_local)` is experimental and subject to change + //~| `cfg(target_thread_local)` is experimental and subject to change static FOO: u32; } diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr index af59c71414773..7ef9fda92cc1d 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr @@ -7,6 +7,15 @@ LL | #[cfg_attr(target_thread_local, thread_local)] = note: see issue #29594 for more information = help: add `#![feature(cfg_target_thread_local)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: `cfg(target_thread_local)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-thread-local.rs:9:16 + | +LL | #[cfg_attr(target_thread_local, thread_local)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29594 for more information + = help: add `#![feature(cfg_target_thread_local)]` to the crate attributes to enable + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-15524.stderr b/src/test/ui/issues/issue-15524.stderr index 1702dad34ca0c..58142ba66e6fc 100644 --- a/src/test/ui/issues/issue-15524.stderr +++ b/src/test/ui/issues/issue-15524.stderr @@ -13,7 +13,7 @@ LL | A = 1, | - first use of `1` ... LL | D, - | ^ enum already has `1` + | ^^ enum already has `1` error[E0081]: discriminant value `1` already exists --> $DIR/issue-15524.rs:11:9 diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr index f95afb9c1fdc7..45af4a5237734 100644 --- a/src/test/ui/issues/issue-32004.stderr +++ b/src/test/ui/issues/issue-32004.stderr @@ -2,7 +2,7 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple varian --> $DIR/issue-32004.rs:10:9 | LL | Bar(i32), - | -------- `Foo::Bar` defined here + | --------- `Foo::Bar` defined here LL | Baz | --- similarly named unit variant `Baz` defined here ... diff --git a/src/test/ui/issues/issue-47706.stderr b/src/test/ui/issues/issue-47706.stderr index c84d8ecb4c9e6..634943ac22f86 100644 --- a/src/test/ui/issues/issue-47706.stderr +++ b/src/test/ui/issues/issue-47706.stderr @@ -11,7 +11,7 @@ error[E0593]: function is expected to take 0 arguments, but it takes 1 argument --> $DIR/issue-47706.rs:27:9 | LL | Bar(i32), - | -------- takes 1 argument + | --------- takes 1 argument ... LL | fn foo(f: F) | --- required by a bound in this diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr index de71e1d1a6666..bfdbdf2d2cffc 100644 --- a/src/test/ui/issues/issue-5100.stderr +++ b/src/test/ui/issues/issue-5100.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-5100.rs:8:9 | LL | enum A { B, C } - | - unit variant defined here + | -- unit variant defined here ... LL | match (true, false) { | ------------- this expression has type `(bool, bool)` diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr index eb0428341020f..8c0a9f6ea5d88 100644 --- a/src/test/ui/issues/issue-63983.stderr +++ b/src/test/ui/issues/issue-63983.stderr @@ -2,7 +2,7 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple varian --> $DIR/issue-63983.rs:8:9 | LL | Tuple(i32), - | ---------- `MyEnum::Tuple` defined here + | ----------- `MyEnum::Tuple` defined here ... LL | MyEnum::Tuple => "", | ^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `MyEnum::Tuple(_)` @@ -11,7 +11,7 @@ error[E0532]: expected unit struct, unit variant or constant, found struct varia --> $DIR/issue-63983.rs:10:9 | LL | Struct{ s: i32 }, - | ---------------- `MyEnum::Struct` defined here + | ----------------- `MyEnum::Struct` defined here ... LL | MyEnum::Struct => "", | ^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `MyEnum::Struct { s }` diff --git a/src/test/ui/issues/issue-7867.stderr b/src/test/ui/issues/issue-7867.stderr index 0d3121d60455d..e3db4feb194dd 100644 --- a/src/test/ui/issues/issue-7867.stderr +++ b/src/test/ui/issues/issue-7867.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-7867.rs:7:9 | LL | enum A { B, C } - | - unit variant defined here + | -- unit variant defined here ... LL | match (true, false) { | ------------- this expression has type `(bool, bool)` diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index 3905d1a06bdfe..44413090c3236 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -14,7 +14,7 @@ error: variant is never constructed: `X` --> $DIR/lint-dead-code-4.rs:15:5 | LL | X, - | ^ + | ^^ error: variant is never constructed: `Y` --> $DIR/lint-dead-code-4.rs:16:5 @@ -24,7 +24,7 @@ LL | | a: String, LL | | b: i32, LL | | c: i32, LL | | }, - | |_____^ + | |______^ error: enum is never used: `ABC` --> $DIR/lint-dead-code-4.rs:24:6 @@ -36,7 +36,7 @@ error: variant is never constructed: `I` --> $DIR/lint-dead-code-4.rs:36:5 | LL | I, - | ^ + | ^^ error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:39:9 diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr index 519add826273f..6b79f6c67baa0 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -14,13 +14,13 @@ error: variant is never constructed: `Variant5` --> $DIR/lint-dead-code-5.rs:13:5 | LL | Variant5 { _x: isize }, - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ error: variant is never constructed: `Variant6` --> $DIR/lint-dead-code-5.rs:14:5 | LL | Variant6(isize), - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: enum is never used: `Enum3` --> $DIR/lint-dead-code-5.rs:35:6 diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr index b93d6d4ac1866..bf0c39b7fb5e1 100644 --- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -2,7 +2,7 @@ error: variant is never constructed: `Bar` --> $DIR/unused-struct-variant.rs:8:5 | LL | Bar(B), - | ^^^^^^ + | ^^^^^^^ | note: the lint level is defined here --> $DIR/unused-struct-variant.rs:1:9 diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr index a547f5af4b082..f85efc72c06ec 100644 --- a/src/test/ui/lint/dead-code/unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -2,7 +2,7 @@ error: variant is never constructed: `Variant1` --> $DIR/unused-variant.rs:5:5 | LL | Variant1, - | ^^^^^^^^ + | ^^^^^^^^^ | note: the lint level is defined here --> $DIR/unused-variant.rs:1:9 diff --git a/src/test/ui/malformed/malformed-special-attrs.rs b/src/test/ui/malformed/malformed-special-attrs.rs index 05b7ebe466662..ad6ee48ec047e 100644 --- a/src/test/ui/malformed/malformed-special-attrs.rs +++ b/src/test/ui/malformed/malformed-special-attrs.rs @@ -1,7 +1,9 @@ #[cfg_attr] //~ ERROR malformed `cfg_attr` attribute +//~| ERROR malformed `cfg_attr` attribute struct S1; #[cfg_attr = ""] //~ ERROR malformed `cfg_attr` attribute +//~| ERROR malformed `cfg_attr` attribute struct S2; #[derive] //~ ERROR malformed `derive` attribute diff --git a/src/test/ui/malformed/malformed-special-attrs.stderr b/src/test/ui/malformed/malformed-special-attrs.stderr index 6f535e03e6aec..06ae9a1a99975 100644 --- a/src/test/ui/malformed/malformed-special-attrs.stderr +++ b/src/test/ui/malformed/malformed-special-attrs.stderr @@ -7,7 +7,23 @@ LL | #[cfg_attr] = note: for more information, visit error: malformed `cfg_attr` attribute input - --> $DIR/malformed-special-attrs.rs:4:1 + --> $DIR/malformed-special-attrs.rs:1:1 + | +LL | #[cfg_attr] + | ^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]` + | + = note: for more information, visit + +error: malformed `cfg_attr` attribute input + --> $DIR/malformed-special-attrs.rs:5:1 + | +LL | #[cfg_attr = ""] + | ^^^^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]` + | + = note: for more information, visit + +error: malformed `cfg_attr` attribute input + --> $DIR/malformed-special-attrs.rs:5:1 | LL | #[cfg_attr = ""] | ^^^^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]` @@ -15,16 +31,16 @@ LL | #[cfg_attr = ""] = note: for more information, visit error: malformed `derive` attribute input - --> $DIR/malformed-special-attrs.rs:7:1 + --> $DIR/malformed-special-attrs.rs:9:1 | LL | #[derive] | ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]` error: malformed `derive` attribute input - --> $DIR/malformed-special-attrs.rs:10:1 + --> $DIR/malformed-special-attrs.rs:12:1 | LL | #[derive = ""] | ^^^^^^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]` -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index c2298d6fbbf02..e9c44957de987 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -2,7 +2,7 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has --> $DIR/match-pattern-field-mismatch.rs:10:11 | LL | Rgb(usize, usize, usize), - | ------------------------ tuple variant defined here + | ------------------------- tuple variant defined here ... LL | Color::Rgb(_, _) => { } | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index ded3173f45b2e..b03f32eab0599 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -46,9 +46,9 @@ error[E0423]: expected value, found struct variant `m7::V` --> $DIR/namespace-mix.rs:100:11 | LL | V {}, - | ---- `m7::V` defined here + | ----- `m7::V` defined here LL | TV(), - | ---- similarly named tuple variant `TV` defined here + | ----- similarly named tuple variant `TV` defined here ... LL | check(m7::V); | ^^^^^ @@ -79,7 +79,7 @@ LL | check(xm7::V); LL | V {}, | - `xm7::V` defined here LL | TV(), - | ---- similarly named tuple variant `TV` defined here + | ----- similarly named tuple variant `TV` defined here | help: use struct literal syntax instead | diff --git a/src/test/ui/parser/issue-62895.rs b/src/test/ui/parser/issue-62895.rs index 53f17405d79f4..8edcee2e41792 100644 --- a/src/test/ui/parser/issue-62895.rs +++ b/src/test/ui/parser/issue-62895.rs @@ -5,7 +5,9 @@ mod _ { //~ ERROR expected identifier pub fn g() -> isizee { //~ ERROR cannot find type `isizee` in this scope mod _ { //~ ERROR expected identifier pub g() -> is //~ ERROR missing `fn` for function definition -(), w20); +(), w20); //~ ERROR mismatched } (), w20); //~ ERROR expected item, found `;` +//~^ ERROR mismatched + } diff --git a/src/test/ui/parser/issue-62895.stderr b/src/test/ui/parser/issue-62895.stderr index ed4d2340fc5bb..aa796a9fd7f79 100644 --- a/src/test/ui/parser/issue-62895.stderr +++ b/src/test/ui/parser/issue-62895.stderr @@ -27,6 +27,24 @@ error: expected item, found `;` LL | (), w20); | ^ help: remove this semicolon +error: mismatched closing delimiter: `)` + --> $DIR/issue-62895.rs:8:8 + | +LL | mod _ { + | - unclosed delimiter +LL | pub g() -> is +LL | (), w20); + | ^ mismatched closing delimiter + +error: mismatched closing delimiter: `)` + --> $DIR/issue-62895.rs:10:8 + | +LL | mod _ { + | - unclosed delimiter +... +LL | (), w20); + | ^ mismatched closing delimiter + error[E0412]: cannot find type `isizee` in this scope --> $DIR/issue-62895.rs:5:15 | @@ -41,7 +59,7 @@ LL | fn v() -> isize { | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0308, E0412. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issue-68890.rs b/src/test/ui/parser/issue-68890.rs index bab4ed7f800c5..e85597b12a240 100644 --- a/src/test/ui/parser/issue-68890.rs +++ b/src/test/ui/parser/issue-68890.rs @@ -1,4 +1,9 @@ -enum e{A((?'a a+?+l))} +enum E{A((?'a a+?+l))} //~^ ERROR `?` may only modify trait bounds, not lifetime bounds //~| ERROR expected one of `)`, `+`, or `,` -//~| ERROR expected item, found `)` +//~| ERROR expected identifier, found `)` +//~| ERROR cannot find trait +//~| ERROR use of undeclared lifetime +//~| WARN trait objects without + +fn main() {} diff --git a/src/test/ui/parser/issue-68890.stderr b/src/test/ui/parser/issue-68890.stderr index 2a3bf6b41f02e..18f61f8fa1c43 100644 --- a/src/test/ui/parser/issue-68890.stderr +++ b/src/test/ui/parser/issue-68890.stderr @@ -1,20 +1,46 @@ error: `?` may only modify trait bounds, not lifetime bounds --> $DIR/issue-68890.rs:1:11 | -LL | enum e{A((?'a a+?+l))} +LL | enum E{A((?'a a+?+l))} | ^ error: expected one of `)`, `+`, or `,`, found `a` --> $DIR/issue-68890.rs:1:15 | -LL | enum e{A((?'a a+?+l))} +LL | enum E{A((?'a a+?+l))} | ^ expected one of `)`, `+`, or `,` -error: expected item, found `)` +error: expected identifier, found `)` --> $DIR/issue-68890.rs:1:21 | -LL | enum e{A((?'a a+?+l))} - | ^ expected item +LL | enum E{A((?'a a+?+l))} + | ^ expected identifier -error: aborting due to 3 previous errors +error[E0405]: cannot find trait `l` in this scope + --> $DIR/issue-68890.rs:1:19 + | +LL | enum E{A((?'a a+?+l))} + | ^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-68890.rs:1:10 + | +LL | enum E{A((?'a a+?+l))} + | ^^^^^^^^^^ help: use `dyn`: `dyn (?'a a+?+l` + | + = note: `#[warn(bare_trait_objects)]` on by default + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-68890.rs:1:12 + | +LL | enum E{A((?'a a+?+l))} + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes + +error: aborting due to 5 previous errors; 1 warning emitted +Some errors have detailed explanations: E0261, E0405. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/parser/recover-enum.rs b/src/test/ui/parser/recover-enum.rs index 08dd939e2c023..44f870048b25f 100644 --- a/src/test/ui/parser/recover-enum.rs +++ b/src/test/ui/parser/recover-enum.rs @@ -1,11 +1,11 @@ fn main() { enum Test { - Very //~ HELP missing `,` - Bad(usize) //~ HELP missing `,` - //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad` - Stuff { a: usize } //~ HELP missing `,` - //~^ ERROR expected one of `,`, `=`, or `}`, found `Stuff` + Very //~ HELP try adding a comma + Bad(usize) //~ HELP try adding a comma + //~^ ERROR expected one of `(`, `,`, `=`, or `{`, found `Bad` + Stuff { a: usize } //~ HELP try adding a comma + //~^ ERROR expected one of `,` or `=`, found `Stuff` Here - //~^ ERROR expected one of `,`, `=`, or `}`, found `Here` + //~^ ERROR expected one of `,` or `=`, found `Here` } } diff --git a/src/test/ui/parser/recover-enum.stderr b/src/test/ui/parser/recover-enum.stderr index a2b650e4f4eb7..33318e656eb71 100644 --- a/src/test/ui/parser/recover-enum.stderr +++ b/src/test/ui/parser/recover-enum.stderr @@ -1,34 +1,34 @@ -error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad` +error: expected one of `(`, `,`, `=`, or `{`, found `Bad` --> $DIR/recover-enum.rs:4:9 | LL | Very | - | | - | expected one of `(`, `,`, `=`, `{`, or `}` - | help: missing `,` + | expected one of `(`, `,`, `=`, or `{` + | help: try adding a comma: `,` LL | Bad(usize) | ^^^ unexpected token -error: expected one of `,`, `=`, or `}`, found `Stuff` +error: expected one of `,` or `=`, found `Stuff` --> $DIR/recover-enum.rs:6:9 | LL | Bad(usize) | - | | - | expected one of `,`, `=`, or `}` - | help: missing `,` + | expected one of `,` or `=` + | help: try adding a comma: `,` LL | LL | Stuff { a: usize } | ^^^^^ unexpected token -error: expected one of `,`, `=`, or `}`, found `Here` +error: expected one of `,` or `=`, found `Here` --> $DIR/recover-enum.rs:8:9 | LL | Stuff { a: usize } | - | | - | expected one of `,`, `=`, or `}` - | help: missing `,` + | expected one of `,` or `=` + | help: try adding a comma: `,` LL | LL | Here | ^^^^ unexpected token diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr index 89232a519d7b2..9e4b93018ed02 100644 --- a/src/test/ui/parser/recover-from-bad-variant.stderr +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -13,7 +13,7 @@ error[E0532]: expected tuple struct or tuple variant, found struct variant `Enum --> $DIR/recover-from-bad-variant.rs:10:9 | LL | Foo { a: usize, b: usize }, - | -------------------------- `Enum::Foo` defined here + | --------------------------- `Enum::Foo` defined here ... LL | Enum::Foo(a, b) => {} | ^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `Enum::Foo { a, b }` diff --git a/src/test/ui/parser/removed-syntax-enum-newtype.rs b/src/test/ui/parser/removed-syntax-enum-newtype.rs index 518f90b2b8368..669644e74d6f2 100644 --- a/src/test/ui/parser/removed-syntax-enum-newtype.rs +++ b/src/test/ui/parser/removed-syntax-enum-newtype.rs @@ -1 +1 @@ -enum e = isize; //~ ERROR expected one of `<`, `where`, or `{`, found `=` +enum e = isize; //~ ERROR expected `where`, or `{` after enum name, found `=` diff --git a/src/test/ui/parser/removed-syntax-enum-newtype.stderr b/src/test/ui/parser/removed-syntax-enum-newtype.stderr index 2daa6249b4ce0..a16ec84a0cdc7 100644 --- a/src/test/ui/parser/removed-syntax-enum-newtype.stderr +++ b/src/test/ui/parser/removed-syntax-enum-newtype.stderr @@ -1,8 +1,8 @@ -error: expected one of `<`, `where`, or `{`, found `=` +error: expected `where`, or `{` after enum name, found `=` --> $DIR/removed-syntax-enum-newtype.rs:1:8 | LL | enum e = isize; - | ^ expected one of `<`, `where`, or `{` + | ^ expected `where`, or `{` after enum name error: aborting due to previous error diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr index 79f044a0675b7..a96c0dd962275 100644 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr +++ b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr @@ -13,9 +13,9 @@ LL | Black = 0x000000, LL | White = 0xffffff, | ^^^^^^^^ disallowed custom discriminant LL | Other(usize), - | ------------ tuple variant defined here + | ------------- tuple variant defined here LL | Other2(usize, usize), - | -------------------- tuple variant defined here + | --------------------- tuple variant defined here | = note: see issue #60553 for more information = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index cbc90b5397d8b..d60693375d545 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -22,7 +22,7 @@ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has --> $DIR/issue-74539.rs:8:9 | LL | A(u8, u8), - | --------- tuple variant defined here + | ---------- tuple variant defined here ... LL | E::A(x @ ..) => { | ^^^^^^^^^^^^ expected 2 fields, found 1 diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index 497c93b29497c..3b1b73b017281 100644 --- a/src/test/ui/pattern/pattern-error-continue.stderr +++ b/src/test/ui/pattern/pattern-error-continue.stderr @@ -8,7 +8,7 @@ error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D` --> $DIR/pattern-error-continue.rs:18:9 | LL | B(isize, isize), - | --------------- similarly named tuple variant `B` defined here + | ---------------- similarly named tuple variant `B` defined here ... LL | A::D(_) => (), | ^^^- @@ -19,7 +19,7 @@ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has --> $DIR/pattern-error-continue.rs:17:9 | LL | B(isize, isize), - | --------------- tuple variant defined here + | ---------------- tuple variant defined here ... LL | A::B(_, _, _) => (), | ^^^^^^^^^^^^^ expected 2 fields, found 3 diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.rs b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs index e0f248c67e8b3..cf4cb0c688b1b 100644 --- a/src/test/ui/proc-macro/issue-75930-derive-cfg.rs +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs @@ -1,29 +1,64 @@ // check-pass -// compile-flags: -Z span-debug +// compile-flags: -Z span-debug --error-format human // aux-build:test-macros.rs // Regression test for issue #75930 // Tests that we cfg-strip all targets before invoking // a derive macro +// We need '--error-format human' to stop compiletest from +// trying to interpret proc-macro output as JSON messages +// (a pretty-printed struct may cause a line to start with '{) #[macro_use] extern crate test_macros; +#[print_helper(a)] +#[cfg_attr(not(FALSE), allow(dead_code))] +#[print_attr] #[derive(Print)] +#[print_helper(b)] struct Foo<#[cfg(FALSE)] A, B> { #[cfg(FALSE)] first: String, - second: bool, + #[cfg_attr(FALSE, deny(warnings))] second: bool, third: [u8; { #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner; #[cfg(FALSE)] let a = 25; match true { #[cfg(FALSE)] true => {}, - false => {}, + #[cfg_attr(not(FALSE), allow(warnings))] false => {}, _ => {} }; + + #[print_helper(should_be_removed)] + fn removed_fn() { + #![cfg(FALSE)] + } + + #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { + #![cfg(not(FALSE))] + let my_val = true; + } + + enum TupleEnum { + Foo( + #[cfg(FALSE)] u8, + #[cfg(FALSE)] bool, + #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] String, u8 + ) + } + + struct TupleStruct( + #[cfg(FALSE)] String, + #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] bool, + u8 + ); + 0 }], + #[print_helper(d)] fourth: B } diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout index 0371133a3f705..2fe821612c907 100644 --- a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout @@ -1,76 +1,1351 @@ -PRINT-DERIVE INPUT (DISPLAY): struct Foo < B > +PRINT-ATTR INPUT (DISPLAY): #[allow(dead_code)] #[derive(Print)] #[print_helper(b)] #[print_helper(a)] +struct Foo < #[cfg(FALSE)] A, B > +{ + #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second : + bool, third : + [u8 ; + { + #[cfg(FALSE)] struct Bar ; #[cfg(not(FALSE))] struct Inner ; + #[cfg(FALSE)] let a = 25 ; match true + { + #[cfg(FALSE)] true => { }, + #[cfg_attr(not(FALSE), allow(warnings))] false => { }, _ => { } + } ; #[print_helper(should_be_removed)] fn removed_fn() + { # ! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn + kept_fn() { # ! [cfg(not(FALSE))] let my_val = true ; } enum + TupleEnum + { + Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] String, u8) + } struct + TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] bool, u8) ; 0 + }], #[print_helper(d)] fourth : B +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:16:24: 16:40 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:16:24: 16:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/issue-75930-derive-cfg.rs:16:30: 16:39 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:16:29: 16:40 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:16:24: 16:40 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:18:1: 18:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "derive", + span: $DIR/issue-75930-derive-cfg.rs:18:3: 18:9 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "Print", + span: $DIR/issue-75930-derive-cfg.rs:18:10: 18:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:18:9: 18:16 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:18:2: 18:17 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "b", + span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:15:1: 15:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:15:3: 15:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:15:16: 15:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:15:15: 15:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:15:2: 15:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:20:1: 20:7 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:20:8: 20:11 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:20:11: 20:12 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:20:12: 20:13 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:20:14: 20:17 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:20:18: 20:23 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:20:17: 20:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:20:13: 20:25 (#0), + }, + Ident { + ident: "A", + span: $DIR/issue-75930-derive-cfg.rs:20:26: 20:27 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:20:27: 20:28 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:20:29: 20:30 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:20:30: 20:31 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:21:5: 21:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:21:7: 21:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:21:11: 21:16 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:10: 21:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:6: 21:18 (#0), + }, + Ident { + ident: "first", + span: $DIR/issue-75930-derive-cfg.rs:21:19: 21:24 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:25 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:21:26: 21:32 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:21:32: 21:33 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:22:5: 22:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:22:7: 22:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:22:16: 22:21 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:22:21: 22:22 (#0), + }, + Ident { + ident: "deny", + span: $DIR/issue-75930-derive-cfg.rs:22:23: 22:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:22:28: 22:36 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:22:27: 22:37 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:22:15: 22:38 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:22:6: 22:39 (#0), + }, + Ident { + ident: "second", + span: $DIR/issue-75930-derive-cfg.rs:22:40: 22:46 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:22:46: 22:47 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:22:48: 22:52 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:22:52: 22:53 (#0), + }, + Ident { + ident: "third", + span: $DIR/issue-75930-derive-cfg.rs:23:5: 23:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:23:10: 23:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:23:13: 23:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:23:15: 23:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:24:9: 24:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:24:11: 24:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:14: 24:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:10: 24:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:24:23: 24:29 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/issue-75930-derive-cfg.rs:24:30: 24:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:24:33: 24:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:9: 25:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:25:15: 25:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:25:19: 25:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:18: 25:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:14: 25:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:10: 25:27 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:25:28: 25:34 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/issue-75930-derive-cfg.rs:25:35: 25:40 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:40: 25:41 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:9: 26:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:26:11: 26:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:26:15: 26:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:26:14: 26:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:26:10: 26:22 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:26:23: 26:26 (#0), + }, + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:26:27: 26:28 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:29: 26:30 (#0), + }, + Literal { + kind: Integer, + symbol: "25", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:26:31: 26:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:33: 26:34 (#0), + }, + Ident { + ident: "match", + span: $DIR/issue-75930-derive-cfg.rs:27:9: 27:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:27:15: 27:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:28:19: 28:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:18: 28:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:14: 28:26 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:28:27: 28:31 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:28:32: 28:34 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:32: 28:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:28:35: 28:37 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:37: 28:38 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:13: 29:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:29:15: 29:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:29:24: 29:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:29:28: 29:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:27: 29:34 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:34: 29:35 (#0), + }, + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:29:36: 29:41 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:29:42: 29:50 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:41: 29:51 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:23: 29:52 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:14: 29:53 (#0), + }, + Ident { + ident: "false", + span: $DIR/issue-75930-derive-cfg.rs:29:54: 29:59 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:29:60: 29:62 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:60: 29:62 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:29:63: 29:65 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:65: 29:66 (#0), + }, + Ident { + ident: "_", + span: $DIR/issue-75930-derive-cfg.rs:30:13: 30:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:20: 31:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:10: 31:11 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:33:9: 33:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:33:11: 33:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "should_be_removed", + span: $DIR/issue-75930-derive-cfg.rs:33:24: 33:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:33:23: 33:42 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:33:10: 33:43 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:34:9: 34:11 (#0), + }, + Ident { + ident: "removed_fn", + span: $DIR/issue-75930-derive-cfg.rs:34:12: 34:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:34:22: 34:24 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:35:14: 35:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:35:16: 35:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:35:20: 35:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:35:19: 35:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:27 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:25: 36:10 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:38:9: 38:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:38:11: 38:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "c", + span: $DIR/issue-75930-derive-cfg.rs:38:24: 38:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:23: 38:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:10: 38:27 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:38:28: 38:29 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:38:30: 38:33 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:38:34: 38:37 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:38:38: 38:43 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:37: 38:44 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:33: 38:45 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:29: 38:46 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:38:47: 38:49 (#0), + }, + Ident { + ident: "kept_fn", + span: $DIR/issue-75930-derive-cfg.rs:38:50: 38:57 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:38:57: 38:59 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:39:13: 39:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:39:14: 39:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:39:16: 39:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:39:20: 39:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:39:24: 39:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:23: 39:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:19: 39:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:15: 39:32 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:40:13: 40:16 (#0), + }, + Ident { + ident: "my_val", + span: $DIR/issue-75930-derive-cfg.rs:40:17: 40:23 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:40:24: 40:25 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:40:26: 40:30 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:40:30: 40:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:60: 41:10 (#0), + }, + Ident { + ident: "enum", + span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:13 (#0), + }, + Ident { + ident: "TupleEnum", + span: $DIR/issue-75930-derive-cfg.rs:43:14: 43:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:45:19: 45:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:45:23: 45:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:45:22: 45:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:45:18: 45:30 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:45:31: 45:33 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:33: 45:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:46:17: 46:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:46:19: 46:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:46:23: 46:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:46:22: 46:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:46:18: 46:30 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:46:31: 46:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:46:35: 46:36 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:47:17: 47:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:47:19: 47:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:47:23: 47:26 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:47:27: 47:32 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:47:26: 47:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:47:22: 47:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:47:18: 47:35 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:47:36: 47:39 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:47:39: 47:40 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:48:17: 48:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:48:19: 48:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:48:23: 48:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:48:22: 48:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:48:18: 48:30 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:48:31: 48:37 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:48:37: 48:38 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:48:39: 48:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:16: 49:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:24: 50:10 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:52:9: 52:15 (#0), + }, + Ident { + ident: "TupleStruct", + span: $DIR/issue-75930-derive-cfg.rs:52:16: 52:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:53:13: 53:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:53:15: 53:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:53:19: 53:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:53:18: 53:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:53:14: 53:26 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:53:27: 53:33 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:53:33: 53:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:54:13: 54:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:54:15: 54:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:54:19: 54:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:54:23: 54:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:54:22: 54:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:54:18: 54:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:54:14: 54:31 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:54:32: 54:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:54:35: 54:36 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:55:13: 55:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:55:15: 55:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:55:19: 55:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:55:18: 55:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:55:14: 55:26 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:55:27: 55:31 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:55:31: 55:32 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:56:13: 56:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:27: 57:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:57:10: 57:11 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:59:9: 59:10 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:23:17: 60:6 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:23:12: 60:7 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:60:7: 60:8 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:61:5: 61:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:61:7: 61:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "d", + span: $DIR/issue-75930-derive-cfg.rs:61:20: 61:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:61:19: 61:22 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:61:6: 61:23 (#0), + }, + Ident { + ident: "fourth", + span: $DIR/issue-75930-derive-cfg.rs:62:5: 62:11 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:62:11: 62:12 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:62:13: 62:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:20:32: 63:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): #[allow(dead_code)] #[print_helper(b)] #[print_helper(a)] struct Foo < B > { second : bool, third : [u8 ; { - #[cfg(not(FALSE))] struct Inner ; match true - { false => { } _ => { } } ; 0 - }], fourth : B, + #[cfg(not(FALSE))] struct Inner ; ; match true + { #[allow(warnings)] false => { }, _ => { } } ; #[print_helper(c)] + #[cfg(not(FALSE))] fn kept_fn() + { # ! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum + { Foo(#[cfg(not(FALSE))] i32, u8) } struct + TupleStruct(#[cfg(not(FALSE))] i32, u8) ; 0 + }], #[print_helper(d)] fourth : B } PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:16:24: 16:40 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:16:24: 16:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/issue-75930-derive-cfg.rs:16:30: 16:39 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:16:29: 16:40 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:16:24: 16:40 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "b", + span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:15:1: 15:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:15:3: 15:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:15:16: 15:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:15:15: 15:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:15:2: 15:19 (#0), + }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:1: 20:7 (#0), }, Ident { ident: "Foo", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:8: 20:11 (#0), }, Punct { ch: '<', - spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:20:11: 20:12 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:29: 20:30 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:30: 20:31 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "second", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:40: 22:46 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:46: 22:47 (#0), }, Ident { ident: "bool", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:48: 22:52 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:52: 22:53 (#0), }, Ident { ident: "third", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:5: 23:10 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:10: 23:11 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:13: 23:15 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:15: 23:16 (#0), }, Group { delimiter: Brace, @@ -78,144 +1353,479 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:9: 25:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:14 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:15: 25:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:19: 25:24 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:18: 25:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:14: 25:26 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:10: 25:27 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:28: 25:34 (#0), }, Ident { ident: "Inner", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:35: 25:40 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:40: 25:41 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:33: 26:34 (#0), }, Ident { ident: "match", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:9: 27:14 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:15: 27:19 (#0), }, Group { delimiter: Brace, stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:36: 29:51 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:29:36: 29:41 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:29:42: 29:50 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:41: 29:51 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:36: 29:51 (#0), + }, Ident { ident: "false", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:29:54: 29:59 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:29:60: 29:62 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:29:60: 29:62 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:29:63: 29:65 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:65: 29:66 (#0), }, Ident { ident: "_", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:13: 30:14 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:17 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:17 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:20: 31:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:10: 31:11 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:38:9: 38:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:38:11: 38:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "c", + span: $DIR/issue-75930-derive-cfg.rs:38:24: 38:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:23: 38:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:10: 38:27 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:38:28: 38:29 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:38:30: 38:33 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:38:34: 38:37 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:38:38: 38:43 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:37: 38:44 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:33: 38:45 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:29: 38:46 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:38:47: 38:49 (#0), + }, + Ident { + ident: "kept_fn", + span: $DIR/issue-75930-derive-cfg.rs:38:50: 38:57 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:38:57: 38:59 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:39:13: 39:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:39:14: 39:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:39:16: 39:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:39:20: 39:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:39:24: 39:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:23: 39:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:19: 39:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:15: 39:32 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:40:13: 40:16 (#0), + }, + Ident { + ident: "my_val", + span: $DIR/issue-75930-derive-cfg.rs:40:17: 40:23 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:40:24: 40:25 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:40:26: 40:30 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:40:30: 40:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:60: 41:10 (#0), + }, + Ident { + ident: "enum", + span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:13 (#0), + }, + Ident { + ident: "TupleEnum", + span: $DIR/issue-75930-derive-cfg.rs:43:14: 43:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:47:17: 47:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:47:19: 47:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:47:23: 47:26 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:47:27: 47:32 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:47:26: 47:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:47:22: 47:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:47:18: 47:35 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:47:36: 47:39 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:47:39: 47:40 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:48:39: 48:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:16: 49:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:24: 50:10 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:52:9: 52:15 (#0), + }, + Ident { + ident: "TupleStruct", + span: $DIR/issue-75930-derive-cfg.rs:52:16: 52:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:54:13: 54:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:54:15: 54:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:54:19: 54:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:54:23: 54:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:54:22: 54:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:54:18: 54:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:54:14: 54:31 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:54:32: 54:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:54:35: 54:36 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:56:13: 56:15 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:52:27: 57:10 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:10: 57:11 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:9: 59:10 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:17: 60:6 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:12: 60:7 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:60:7: 60:8 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:61:5: 61:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:61:7: 61:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "d", + span: $DIR/issue-75930-derive-cfg.rs:61:20: 61:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:61:19: 61:22 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:61:6: 61:23 (#0), }, Ident { ident: "fourth", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:62:5: 62:11 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:62:11: 62:12 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:62:13: 62:14 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:32: 63:2 (#0), }, ] diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr index 5ae2583f01c60..47094408d560d 100644 --- a/src/test/ui/proc-macro/parent-source-spans.stderr +++ b/src/test/ui/proc-macro/parent-source-spans.stderr @@ -148,7 +148,7 @@ LL | one!("hello", "world"); ::: $SRC_DIR/core/src/result.rs:LL:COL | LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), - | --------------------------------------------------- similarly named tuple variant `Ok` defined here + | ---------------------------------------------------- similarly named tuple variant `Ok` defined here | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -164,7 +164,7 @@ LL | two!("yay", "rust"); ::: $SRC_DIR/core/src/result.rs:LL:COL | LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), - | --------------------------------------------------- similarly named tuple variant `Ok` defined here + | ---------------------------------------------------- similarly named tuple variant `Ok` defined here | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -180,7 +180,7 @@ LL | three!("hip", "hop"); ::: $SRC_DIR/core/src/result.rs:LL:COL | LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), - | --------------------------------------------------- similarly named tuple variant `Ok` defined here + | ---------------------------------------------------- similarly named tuple variant `Ok` defined here | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/weird-attr-capture.rs b/src/test/ui/proc-macro/weird-attr-capture.rs new file mode 100644 index 0000000000000..939e2a807a37e --- /dev/null +++ b/src/test/ui/proc-macro/weird-attr-capture.rs @@ -0,0 +1,22 @@ +// check-pass +// +// Makes sure we don't ICE when token capturing is triggered +// in an usual way + +macro_rules! as_item { + ($($i:item)*) => {$($i)*}; +} + +macro_rules! concat_attrs { + ($($attrs:tt)*) => { + as_item! { + $($attrs)* + pub struct Foo; + } + } +} + +concat_attrs! { #[cfg(not(FALSE))] } + + +fn main() {} diff --git a/src/test/ui/repr/repr-transparent.stderr b/src/test/ui/repr/repr-transparent.stderr index cbc74fbb6a2cf..accc8a09c536c 100644 --- a/src/test/ui/repr/repr-transparent.stderr +++ b/src/test/ui/repr/repr-transparent.stderr @@ -90,9 +90,9 @@ error[E0731]: transparent enum needs exactly one variant, but has 2 LL | enum TooManyVariants { | ^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 LL | Foo(String), - | ----------- + | ------------ LL | Bar, - | --- too many variants in `TooManyVariants` + | ---- too many variants in `TooManyVariants` error[E0691]: zero-sized field in transparent enum has alignment larger than 1 --> $DIR/repr-transparent.rs:65:14 diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 32eff15119648..2207983995ad9 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -34,7 +34,7 @@ error[E0423]: expected value, found struct variant `Z::Struct` LL | / Struct { LL | | s: u8, LL | | }, - | |_____________- `Z::Struct` defined here + | |______________- `Z::Struct` defined here ... LL | let _: Z = Z::Struct; | ^^^^^^^^^ help: use struct literal syntax instead: `Z::Struct { s: val }` @@ -73,7 +73,7 @@ error[E0423]: expected value, found struct variant `m::E::Struct` LL | / Struct { LL | | s: u8, LL | | }, - | |_________- `m::E::Struct` defined here + | |__________- `m::E::Struct` defined here ... LL | let _: E = m::E::Struct; | ^^^^^^^^^^^^ help: use struct literal syntax instead: `m::E::Struct { s: val }` @@ -105,7 +105,7 @@ error[E0423]: expected value, found struct variant `E::Struct` LL | / Struct { LL | | s: u8, LL | | }, - | |_________- `E::Struct` defined here + | |__________- `E::Struct` defined here ... LL | let _: E = E::Struct; | ^^^^^^^^^ help: use struct literal syntax instead: `E::Struct { s: val }` @@ -185,7 +185,7 @@ error[E0423]: expected value, found struct variant `m::n::Z::Struct` LL | / Struct { LL | | s: u8, LL | | }, - | |_____________- `m::n::Z::Struct` defined here + | |______________- `m::n::Z::Struct` defined here ... LL | let _: Z = m::n::Z::Struct; | ^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `m::n::Z::Struct { s: val }` @@ -260,7 +260,7 @@ error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:27:20 | LL | Fn(u8), - | ------ fn(u8) -> Z {Z::Fn} defined here + | ------- fn(u8) -> Z {Z::Fn} defined here ... LL | let _: Z = Z::Fn; | - ^^^^^ expected enum `Z`, found fn item @@ -278,7 +278,7 @@ error[E0618]: expected function, found enum variant `Z::Unit` --> $DIR/privacy-enum-ctor.rs:31:17 | LL | Unit, - | ---- `Z::Unit` defined here + | ----- `Z::Unit` defined here ... LL | let _ = Z::Unit(); | ^^^^^^^-- @@ -294,7 +294,7 @@ error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:43:16 | LL | Fn(u8), - | ------ fn(u8) -> E {E::Fn} defined here + | ------- fn(u8) -> E {E::Fn} defined here ... LL | let _: E = m::E::Fn; | - ^^^^^^^^ expected enum `E`, found fn item @@ -312,7 +312,7 @@ error[E0618]: expected function, found enum variant `m::E::Unit` --> $DIR/privacy-enum-ctor.rs:47:16 | LL | Unit, - | ---- `m::E::Unit` defined here + | ----- `m::E::Unit` defined here ... LL | let _: E = m::E::Unit(); | ^^^^^^^^^^-- @@ -328,7 +328,7 @@ error[E0308]: mismatched types --> $DIR/privacy-enum-ctor.rs:51:16 | LL | Fn(u8), - | ------ fn(u8) -> E {E::Fn} defined here + | ------- fn(u8) -> E {E::Fn} defined here ... LL | let _: E = E::Fn; | - ^^^^^ expected enum `E`, found fn item @@ -346,7 +346,7 @@ error[E0618]: expected function, found enum variant `E::Unit` --> $DIR/privacy-enum-ctor.rs:55:16 | LL | Unit, - | ---- `E::Unit` defined here + | ----- `E::Unit` defined here ... LL | let _: E = E::Unit(); | ^^^^^^^-- diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index fbdbb0c9930a6..32421e62b3f52 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -8,7 +8,7 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:14:47 @@ -20,7 +20,7 @@ note: the unit variant `Unit` is defined here --> $DIR/auxiliary/variants.rs:4:23 | LL | #[non_exhaustive] Unit, - | ^^^^ + | ^^^^^ error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:18:32 @@ -32,7 +32,7 @@ note: the unit variant `Unit` is defined here --> $DIR/auxiliary/variants.rs:4:23 | LL | #[non_exhaustive] Unit, - | ^^^^ + | ^^^^^ error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:20:32 @@ -44,7 +44,7 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:26:35 @@ -56,7 +56,7 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^^^^^^ + | ^^^^^^^^^^^ error[E0639]: cannot create non-exhaustive variant using struct expression --> $DIR/variant.rs:8:26 diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 9b2febb1393e1..408a37c4522cb 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -2,9 +2,9 @@ error[E0423]: expected value, found struct variant `E::B` --> $DIR/fn-or-tuple-struct-without-args.rs:36:16 | LL | A(usize), - | -------- similarly named tuple variant `A` defined here + | --------- similarly named tuple variant `A` defined here LL | B { a: usize }, - | -------------- `E::B` defined here + | --------------- `E::B` defined here ... LL | let _: E = E::B; | ^^^^ @@ -130,7 +130,7 @@ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:35:16 | LL | A(usize), - | -------- fn(usize) -> E {E::A} defined here + | --------- fn(usize) -> E {E::A} defined here ... LL | let _: E = E::A; | - ^^^^ expected enum `E`, found fn item diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr index b0de3ee42e339..72be43954265d 100644 --- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr +++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -20,7 +20,7 @@ error[E0618]: expected function, found enum variant `Alias::Unit` --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:5 | LL | enum Enum { Braced {}, Unit, Tuple() } - | ---- `Alias::Unit` defined here + | ----- `Alias::Unit` defined here ... LL | Alias::Unit(); | ^^^^^^^^^^^-- diff --git a/src/test/ui/variants/variant-size-differences.stderr b/src/test/ui/variants/variant-size-differences.stderr index 241a757d44523..ef5d3904033de 100644 --- a/src/test/ui/variants/variant-size-differences.stderr +++ b/src/test/ui/variants/variant-size-differences.stderr @@ -2,7 +2,7 @@ error: enum variant is more than three times larger (1024 bytes) than the next l --> $DIR/variant-size-differences.rs:5:5 | LL | VBig([u8; 1024]), - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/variant-size-differences.rs:1:9