diff options
Diffstat (limited to 'compiler/rustc_expand/src')
-rw-r--r-- | compiler/rustc_expand/src/base.rs | 58 | ||||
-rw-r--r-- | compiler/rustc_expand/src/build.rs | 43 | ||||
-rw-r--r-- | compiler/rustc_expand/src/config.rs | 74 | ||||
-rw-r--r-- | compiler/rustc_expand/src/errors.rs | 48 | ||||
-rw-r--r-- | compiler/rustc_expand/src/expand.rs | 40 | ||||
-rw-r--r-- | compiler/rustc_expand/src/lib.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_expand/src/mbe/macro_parser.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_expand/src/mbe/macro_rules.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_expand/src/mbe/metavar_expr.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_expand/src/mbe/transcribe.rs | 34 | ||||
-rw-r--r-- | compiler/rustc_expand/src/module.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_expand/src/placeholders.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_expand/src/proc_macro_server.rs | 71 |
13 files changed, 230 insertions, 175 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 6e093811f..e1da3ecde 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -6,7 +6,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{AssocCtxt, Visitor}; -use rustc_ast::{self as ast, Attribute, HasAttrs, Item, NodeId, PatKind}; +use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::{self, Lrc}; @@ -71,7 +71,7 @@ impl Annotatable { } } - pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { + pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { match self { Annotatable::Item(item) => item.visit_attrs(f), Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f), @@ -693,10 +693,6 @@ pub struct SyntaxExtension { pub span: Span, /// List of unstable features that are treated as stable inside this macro. pub allow_internal_unstable: Option<Lrc<[Symbol]>>, - /// Suppresses the `unsafe_code` lint for code produced by this macro. - pub allow_internal_unsafe: bool, - /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro. - pub local_inner_macros: bool, /// The macro's stability info. pub stability: Option<Stability>, /// The macro's deprecation info. @@ -708,6 +704,13 @@ pub struct SyntaxExtension { /// Built-in macros have a couple of special properties like availability /// in `#[no_implicit_prelude]` modules, so we have to keep this flag. pub builtin_name: Option<Symbol>, + /// Suppresses the `unsafe_code` lint for code produced by this macro. + pub allow_internal_unsafe: bool, + /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro. + pub local_inner_macros: bool, + /// Should debuginfo for the macro be collapsed to the outermost expansion site (in other + /// words, was the macro definition annotated with `#[collapse_debuginfo]`)? + pub collapse_debuginfo: bool, } impl SyntaxExtension { @@ -729,14 +732,15 @@ impl SyntaxExtension { SyntaxExtension { span: DUMMY_SP, allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, stability: None, deprecation: None, helper_attrs: Vec::new(), edition, builtin_name: None, kind, + allow_internal_unsafe: false, + local_inner_macros: false, + collapse_debuginfo: false, } } @@ -754,12 +758,13 @@ impl SyntaxExtension { let allow_internal_unstable = attr::allow_internal_unstable(sess, &attrs).collect::<Vec<Symbol>>(); - let mut local_inner_macros = false; - if let Some(macro_export) = sess.find_by_name(attrs, sym::macro_export) { - if let Some(l) = macro_export.meta_item_list() { - local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); - } - } + let allow_internal_unsafe = sess.contains_name(attrs, sym::allow_internal_unsafe); + let local_inner_macros = sess + .find_by_name(attrs, sym::macro_export) + .and_then(|macro_export| macro_export.meta_item_list()) + .map_or(false, |l| attr::list_contains_name(&l, sym::local_inner_macros)); + let collapse_debuginfo = sess.contains_name(attrs, sym::collapse_debuginfo); + tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); let (builtin_name, helper_attrs) = sess .find_by_name(attrs, sym::rustc_builtin_macro) @@ -772,7 +777,7 @@ impl SyntaxExtension { ) }) .unwrap_or_else(|| (None, helper_attrs)); - let (stability, const_stability) = attr::find_stability(&sess, attrs, span); + let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span); if let Some((_, sp)) = const_stability { sess.parse_sess .span_diagnostic @@ -784,19 +789,31 @@ impl SyntaxExtension { ) .emit(); } + if let Some((_, sp)) = body_stability { + sess.parse_sess + .span_diagnostic + .struct_span_err(sp, "macros cannot have body stability attributes") + .span_label(sp, "invalid body stability attribute") + .span_label( + sess.source_map().guess_head_span(span), + "body stability attribute affects this macro", + ) + .emit(); + } SyntaxExtension { kind, span, allow_internal_unstable: (!allow_internal_unstable.is_empty()) .then(|| allow_internal_unstable.into()), - allow_internal_unsafe: sess.contains_name(attrs, sym::allow_internal_unsafe), - local_inner_macros, stability: stability.map(|(s, _)| s), deprecation: attr::find_deprecation(&sess, attrs).map(|(d, _)| d), helper_attrs, edition, builtin_name, + allow_internal_unsafe, + local_inner_macros, + collapse_debuginfo, } } @@ -841,11 +858,12 @@ impl SyntaxExtension { call_site, self.span, self.allow_internal_unstable.clone(), - self.allow_internal_unsafe, - self.local_inner_macros, self.edition, macro_def_id, parent_module, + self.allow_internal_unsafe, + self.local_inner_macros, + self.collapse_debuginfo, ) } } @@ -1216,7 +1234,7 @@ pub fn expr_to_spanned_string<'a>( ); Some((err, true)) } - ast::LitKind::Err(_) => None, + ast::LitKind::Err => None, _ => Some((cx.struct_span_err(l.span, err_msg), false)), }, ast::ExprKind::Err => None, diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index fa3e2a4a5..50d2be3ce 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -3,6 +3,7 @@ use crate::base::ExtCtxt; use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp}; +use rustc_data_structures::sync::Lrc; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -106,14 +107,13 @@ impl<'a> ExtCtxt<'a> { &self, span: Span, ident: Ident, - attrs: Vec<ast::Attribute>, bounds: ast::GenericBounds, default: Option<P<ast::Ty>>, ) -> ast::GenericParam { ast::GenericParam { ident: ident.with_span_pos(span), id: ast::DUMMY_NODE_ID, - attrs: attrs.into(), + attrs: AttrVec::new(), bounds, kind: ast::GenericParamKind::Type { default }, is_placeholder: false, @@ -178,8 +178,7 @@ impl<'a> ExtCtxt<'a> { ex: P<ast::Expr>, ) -> ast::Stmt { let pat = if mutbl { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mut); - self.pat_ident_binding_mode(sp, ident, binding_mode) + self.pat_ident_binding_mode(sp, ident, ast::BindingAnnotation::MUT) } else { self.pat_ident(sp, ident) }; @@ -330,23 +329,38 @@ impl<'a> ExtCtxt<'a> { self.expr_struct(span, self.path_ident(span, id), fields) } - pub fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> { + fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> { let lit = ast::Lit::from_lit_kind(lit_kind, span); self.expr(span, ast::ExprKind::Lit(lit)) } + pub fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> { self.expr_lit( span, ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)), ) } + pub fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> { self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32))) } + pub fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> { self.expr_lit(sp, ast::LitKind::Bool(value)) } + pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> { + self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) + } + + pub fn expr_char(&self, sp: Span, ch: char) -> P<ast::Expr> { + self.expr_lit(sp, ast::LitKind::Char(ch)) + } + + pub fn expr_byte_str(&self, sp: Span, bytes: Vec<u8>) -> P<ast::Expr> { + self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes))) + } + /// `[expr1, expr2, ...]` pub fn expr_array(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> { self.expr(sp, ast::ExprKind::Array(exprs)) @@ -357,10 +371,6 @@ impl<'a> ExtCtxt<'a> { self.expr_addr_of(sp, self.expr_array(sp, exprs)) } - pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> { - self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) - } - pub fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr> { self.expr(sp, ast::ExprKind::Cast(expr, ty)) } @@ -434,17 +444,16 @@ impl<'a> ExtCtxt<'a> { self.pat(span, PatKind::Lit(expr)) } pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> { - let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Not); - self.pat_ident_binding_mode(span, ident, binding_mode) + self.pat_ident_binding_mode(span, ident, ast::BindingAnnotation::NONE) } pub fn pat_ident_binding_mode( &self, span: Span, ident: Ident, - bm: ast::BindingMode, + ann: ast::BindingAnnotation, ) -> P<ast::Pat> { - let pat = PatKind::Ident(bm, ident.with_span_pos(span), None); + let pat = PatKind::Ident(ann, ident.with_span_pos(span), None); self.pat(span, pat) } pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> { @@ -564,7 +573,7 @@ impl<'a> ExtCtxt<'a> { &self, span: Span, name: Ident, - attrs: Vec<ast::Attribute>, + attrs: ast::AttrVec, kind: ast::ItemKind, ) -> P<ast::Item> { // FIXME: Would be nice if our generated code didn't violate @@ -592,7 +601,7 @@ impl<'a> ExtCtxt<'a> { mutbl: ast::Mutability, expr: P<ast::Expr>, ) -> P<ast::Item> { - self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr))) + self.item(span, name, AttrVec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr))) } pub fn item_const( @@ -603,11 +612,11 @@ impl<'a> ExtCtxt<'a> { expr: P<ast::Expr>, ) -> P<ast::Item> { let def = ast::Defaultness::Final; - self.item(span, name, Vec::new(), ast::ItemKind::Const(def, ty, Some(expr))) + self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr))) } pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute { - attr::mk_attr_outer(mi) + attr::mk_attr_outer(&self.sess.parse_sess.attr_id_generator, mi) } pub fn meta_word(&self, sp: Span, w: Symbol) -> ast::MetaItem { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 3e1acf438..8d4e36407 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -2,9 +2,9 @@ use rustc_ast::ptr::P; use rustc_ast::token::{Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; +use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree}; use rustc_ast::tokenstream::{DelimSpan, Spacing}; -use rustc_ast::tokenstream::{LazyTokenStream, TokenTree}; +use rustc_ast::tokenstream::{LazyAttrTokenStream, TokenTree}; use rustc_ast::NodeId; use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem}; use rustc_attr as attr; @@ -215,7 +215,7 @@ pub fn features( let features = match strip_unconfigured.configure_krate_attrs(krate.attrs) { None => { // The entire crate is unconfigured. - krate.attrs = Vec::new(); + krate.attrs = ast::AttrVec::new(); krate.items = Vec::new(); Features::default() } @@ -259,27 +259,27 @@ impl<'a> StripUnconfigured<'a> { fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) { if self.config_tokens { if let Some(Some(tokens)) = node.tokens_mut() { - let attr_annotated_tokens = tokens.create_token_stream(); - *tokens = LazyTokenStream::new(self.configure_tokens(&attr_annotated_tokens)); + let attr_stream = tokens.to_attr_token_stream(); + *tokens = LazyAttrTokenStream::new(self.configure_tokens(&attr_stream)); } } } - fn configure_krate_attrs(&self, mut attrs: Vec<ast::Attribute>) -> Option<Vec<ast::Attribute>> { + fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> { attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); if self.in_cfg(&attrs) { Some(attrs) } else { None } } - /// Performs cfg-expansion on `stream`, producing a new `AttrAnnotatedTokenStream`. + /// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`. /// This is only used during the invocation of `derive` proc-macros, /// which require that we cfg-expand their entire input. /// Normal cfg-expansion operates on parsed AST nodes via the `configure` method - fn configure_tokens(&self, stream: &AttrAnnotatedTokenStream) -> AttrAnnotatedTokenStream { - fn can_skip(stream: &AttrAnnotatedTokenStream) -> bool { - stream.0.iter().all(|(tree, _spacing)| match tree { - AttrAnnotatedTokenTree::Attributes(_) => false, - AttrAnnotatedTokenTree::Token(_) => true, - AttrAnnotatedTokenTree::Delimited(_, _, inner) => can_skip(inner), + fn configure_tokens(&self, stream: &AttrTokenStream) -> AttrTokenStream { + fn can_skip(stream: &AttrTokenStream) -> bool { + stream.0.iter().all(|tree| match tree { + AttrTokenTree::Attributes(_) => false, + AttrTokenTree::Token(..) => true, + AttrTokenTree::Delimited(_, _, inner) => can_skip(inner), }) } @@ -290,38 +290,36 @@ impl<'a> StripUnconfigured<'a> { let trees: Vec<_> = stream .0 .iter() - .flat_map(|(tree, spacing)| match tree.clone() { - AttrAnnotatedTokenTree::Attributes(mut data) => { - let mut attrs: Vec<_> = std::mem::take(&mut data.attrs).into(); - attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); - data.attrs = attrs.into(); + .flat_map(|tree| match tree.clone() { + AttrTokenTree::Attributes(mut data) => { + data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); if self.in_cfg(&data.attrs) { - data.tokens = LazyTokenStream::new( - self.configure_tokens(&data.tokens.create_token_stream()), + data.tokens = LazyAttrTokenStream::new( + self.configure_tokens(&data.tokens.to_attr_token_stream()), ); - Some((AttrAnnotatedTokenTree::Attributes(data), *spacing)).into_iter() + Some(AttrTokenTree::Attributes(data)).into_iter() } else { None.into_iter() } } - AttrAnnotatedTokenTree::Delimited(sp, delim, mut inner) => { + AttrTokenTree::Delimited(sp, delim, mut inner) => { inner = self.configure_tokens(&inner); - Some((AttrAnnotatedTokenTree::Delimited(sp, delim, inner), *spacing)) + Some(AttrTokenTree::Delimited(sp, delim, inner)) .into_iter() } - AttrAnnotatedTokenTree::Token(ref token) if let TokenKind::Interpolated(ref nt) = token.kind => { + AttrTokenTree::Token(ref token, _) if let TokenKind::Interpolated(ref nt) = token.kind => { panic!( "Nonterminal should have been flattened at {:?}: {:?}", token.span, nt ); } - AttrAnnotatedTokenTree::Token(token) => { - Some((AttrAnnotatedTokenTree::Token(token), *spacing)).into_iter() + AttrTokenTree::Token(token, spacing) => { + Some(AttrTokenTree::Token(token, spacing)).into_iter() } }) .collect(); - AttrAnnotatedTokenStream::new(trees) + AttrTokenStream::new(trees) } /// Parse and expand all `cfg_attr` attributes into a list of attributes @@ -390,7 +388,7 @@ impl<'a> StripUnconfigured<'a> { attr: &Attribute, (item, item_span): (ast::AttrItem, Span), ) -> Attribute { - let orig_tokens = attr.tokens().to_tokenstream(); + let orig_tokens = attr.tokens(); // We are taking an attribute of the form `#[cfg_attr(pred, attr)]` // and producing an attribute of the form `#[attr]`. We @@ -406,27 +404,33 @@ impl<'a> StripUnconfigured<'a> { }; let pound_span = pound_token.span; - let mut trees = vec![(AttrAnnotatedTokenTree::Token(pound_token), Spacing::Alone)]; + let mut trees = vec![AttrTokenTree::Token(pound_token, Spacing::Alone)]; if attr.style == AttrStyle::Inner { // For inner attributes, we do the same thing for the `!` in `#![some_attr]` let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) = orig_trees.next().unwrap() else { panic!("Bad tokens for attribute {:?}", attr); }; - trees.push((AttrAnnotatedTokenTree::Token(bang_token), Spacing::Alone)); + trees.push(AttrTokenTree::Token(bang_token, Spacing::Alone)); } // We don't really have a good span to use for the synthesized `[]` // in `#[attr]`, so just use the span of the `#` token. - let bracket_group = AttrAnnotatedTokenTree::Delimited( + let bracket_group = AttrTokenTree::Delimited( DelimSpan::from_single(pound_span), Delimiter::Bracket, item.tokens .as_ref() .unwrap_or_else(|| panic!("Missing tokens for {:?}", item)) - .create_token_stream(), + .to_attr_token_stream(), + ); + trees.push(bracket_group); + let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees))); + let attr = attr::mk_attr_from_item( + &self.sess.parse_sess.attr_id_generator, + item, + tokens, + attr.style, + item_span, ); - trees.push((bracket_group, Spacing::Alone)); - let tokens = Some(LazyTokenStream::new(AttrAnnotatedTokenStream::new(trees))); - let attr = attr::mk_attr_from_item(item, tokens, attr.style, item_span); if attr.has_name(sym::crate_type) { self.sess.parse_sess.buffer_lint( rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs new file mode 100644 index 000000000..0feae0deb --- /dev/null +++ b/compiler/rustc_expand/src/errors.rs @@ -0,0 +1,48 @@ +use rustc_macros::SessionDiagnostic; +use rustc_span::symbol::MacroRulesNormalizedIdent; +use rustc_span::Span; + +#[derive(SessionDiagnostic)] +#[diag(expand::expr_repeat_no_syntax_vars)] +pub(crate) struct NoSyntaxVarsExprRepeat { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(expand::must_repeat_once)] +pub(crate) struct MustRepeatOnce { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(expand::count_repetition_misplaced)] +pub(crate) struct CountRepetitionMisplaced { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(expand::meta_var_expr_unrecognized_var)] +pub(crate) struct MetaVarExprUnrecognizedVar { + #[primary_span] + pub span: Span, + pub key: MacroRulesNormalizedIdent, +} + +#[derive(SessionDiagnostic)] +#[diag(expand::var_still_repeating)] +pub(crate) struct VarStillRepeating { + #[primary_span] + pub span: Span, + pub ident: MacroRulesNormalizedIdent, +} + +#[derive(SessionDiagnostic)] +#[diag(expand::meta_var_dif_seq_matchers)] +pub(crate) struct MetaVarsDifSeqMatchers { + #[primary_span] + pub span: Span, + pub msg: String, +} diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 93eeca5b2..c2add852a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -11,7 +11,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, ExprKind, ForeignItemKind}; +use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, AttrVec, ExprKind, ForeignItemKind}; use rustc_ast::{HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacArgs, MacStmtStyle, MetaItemKind, ModKind}; use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind}; @@ -306,7 +306,7 @@ pub struct Invocation { pub enum InvocationKind { Bang { - mac: ast::MacCall, + mac: P<ast::MacCall>, span: Span, }, Attr { @@ -1001,7 +1001,7 @@ enum AddSemicolon { /// of functionality used by `InvocationCollector`. trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { type OutputTy = SmallVec<[Self; 1]>; - type AttrsTy: Deref<Target = [ast::Attribute]> = Vec<ast::Attribute>; + type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec; const KIND: AstFragmentKind; fn to_annotatable(self) -> Annotatable; fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy; @@ -1017,7 +1017,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { fn is_mac_call(&self) -> bool { false } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { unreachable!() } fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {} @@ -1046,7 +1046,7 @@ impl InvocationCollectorNode for P<ast::Item> { fn is_mac_call(&self) -> bool { matches!(self.kind, ItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { ItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1154,7 +1154,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag> fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let item = self.wrapped.into_inner(); match item.kind { AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), @@ -1179,7 +1179,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag> fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let item = self.wrapped.into_inner(); match item.kind { AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), @@ -1202,7 +1202,7 @@ impl InvocationCollectorNode for P<ast::ForeignItem> { fn is_mac_call(&self) -> bool { matches!(self.kind, ForeignItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { ForeignItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1323,7 +1323,7 @@ impl InvocationCollectorNode for ast::Stmt { StmtKind::Local(..) | StmtKind::Empty => false, } } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { // We pull macro invocations (both attributes and fn-like macro calls) out of their // `StmtKind`s and treat them as statement macro invocations, not as items or expressions. let (add_semicolon, mac, attrs) = match self.kind { @@ -1333,7 +1333,7 @@ impl InvocationCollectorNode for ast::Stmt { } StmtKind::Item(item) => match item.into_inner() { ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => { - (mac.args.need_semicolon(), mac, attrs.into()) + (mac.args.need_semicolon(), mac, attrs) } _ => unreachable!(), }, @@ -1387,10 +1387,10 @@ impl InvocationCollectorNode for P<ast::Ty> { fn is_mac_call(&self) -> bool { matches!(self.kind, ast::TyKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { - TyKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No), + TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No), _ => unreachable!(), } } @@ -1411,10 +1411,10 @@ impl InvocationCollectorNode for P<ast::Pat> { fn is_mac_call(&self) -> bool { matches!(self.kind, PatKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { - PatKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No), + PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No), _ => unreachable!(), } } @@ -1439,7 +1439,7 @@ impl InvocationCollectorNode for P<ast::Expr> { fn is_mac_call(&self) -> bool { matches!(self.kind, ExprKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1466,7 +1466,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> { fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { let node = self.wrapped.into_inner(); match node.kind { ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1512,7 +1512,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis) } - fn collect_bang(&mut self, mac: ast::MacCall, kind: AstFragmentKind) -> AstFragment { + fn collect_bang(&mut self, mac: P<ast::MacCall>, kind: AstFragmentKind) -> AstFragment { // cache the macro call span so that it can be // easily adjusted for incremental compilation let span = mac.span(); @@ -1646,7 +1646,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize) { node.visit_attrs(|attrs| { - attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false)); + // Repeated `insert` calls is inefficient, but the number of + // insertions is almost always 0 or 1 in practice. + for cfg in self.cfg().expand_cfg_attr(attr, false).into_iter().rev() { + attrs.insert(pos, cfg) + } }); } diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 9d0232822..ffc9abe64 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -3,7 +3,7 @@ #![feature(associated_type_defaults)] #![feature(if_let_guard)] #![feature(let_chains)] -#![feature(let_else)] +#![cfg_attr(bootstrap, feature(let_else))] #![feature(macro_metavar_expr)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] @@ -15,6 +15,9 @@ #[macro_use] extern crate rustc_macros; +#[macro_use] +extern crate tracing; + extern crate proc_macro as pm; mod placeholders; @@ -26,6 +29,7 @@ pub mod base; pub mod build; #[macro_use] pub mod config; +pub mod errors; pub mod expand; pub mod module; pub mod proc_macro; diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 4fa91dfea..c8bdc3931 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -430,7 +430,7 @@ impl TtParser { } } MatcherLoc::Delimited => { - // Entering the delimeter is trivial. + // Entering the delimiter is trivial. mp.idx += 1; self.cur_mps.push(mp); } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index f7e1575af..7764ffd24 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -14,7 +14,7 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, @@ -32,7 +32,6 @@ use rustc_span::Span; use std::borrow::Cow; use std::collections::hash_map::Entry; use std::{mem, slice}; -use tracing::debug; pub(crate) struct ParserAnyMacro<'a> { parser: Parser<'a>, @@ -608,11 +607,7 @@ enum ExplainDocComment { }, } -fn annotate_doc_comment( - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, - sm: &SourceMap, - span: Span, -) { +fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) { if let Ok(src) = sm.span_to_snippet(span) { if src.starts_with("///") || src.starts_with("/**") { err.subdiagnostic(ExplainDocComment::Outer { span }); @@ -980,7 +975,7 @@ impl<'tt> TokenSet<'tt> { self.maybe_empty = false; } - // Adds `tok` to the set for `self`, marking sequence as non-empy. + // Adds `tok` to the set for `self`, marking sequence as non-empty. fn add_one(&mut self, tt: TtHandle<'tt>) { if !self.tokens.contains(&tt) { self.tokens.push(tt); diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index fc808401a..99fe47454 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -112,7 +112,7 @@ fn parse_depth<'sess>( "meta-variable expression depth must be a literal" )); }; - if let Ok(lit_kind) = LitKind::from_lit_token(*lit) + if let Ok(lit_kind) = LitKind::from_token_lit(*lit) && let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind && let Ok(n_usize) = usize::try_from(n_u128) { diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index e47ea83ac..bec6d1a2d 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,4 +1,8 @@ use crate::base::ExtCtxt; +use crate::errors::{ + CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce, + NoSyntaxVarsExprRepeat, VarStillRepeating, +}; use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch}; use crate::mbe::{self, MetaVarExpr}; use rustc_ast::mut_visit::{self, MutVisitor}; @@ -165,11 +169,7 @@ pub(super) fn transcribe<'a>( seq @ mbe::TokenTree::Sequence(_, delimited) => { match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { - return Err(cx.struct_span_err( - seq.span(), /* blame macro writer */ - "attempted to repeat an expression containing no syntax variables \ - matched as repeating at this depth", - )); + return Err(cx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); } LockstepIterSize::Contradiction(msg) => { @@ -177,7 +177,7 @@ pub(super) fn transcribe<'a>( // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. - return Err(cx.struct_span_err(seq.span(), &msg)); + return Err(cx.create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg })); } LockstepIterSize::Constraint(len, _) => { @@ -193,10 +193,7 @@ pub(super) fn transcribe<'a>( // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. - return Err(cx.struct_span_err( - sp.entire(), - "this must repeat at least once", - )); + return Err(cx.create_err(MustRepeatOnce { span: sp.entire() })); } } else { // 0 is the initial counter (we have done 0 repetitions so far). `len` @@ -239,10 +236,7 @@ pub(super) fn transcribe<'a>( } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. - return Err(cx.struct_span_err( - sp, /* blame the macro writer */ - &format!("variable '{}' is still repeating at this depth", ident), - )); + return Err(cx.create_err(VarStillRepeating { span: sp, ident })); } } } else { @@ -448,10 +442,7 @@ fn count_repetitions<'a>( match matched { MatchedTokenTree(_) | MatchedNonterminal(_) => { if declared_lhs_depth == 0 { - return Err(cx.struct_span_err( - sp.entire(), - "`count` can not be placed inside the inner-most repetition", - )); + return Err(cx.create_err(CountRepetitionMisplaced { span: sp.entire() })); } match depth_opt { None => Ok(1), @@ -499,12 +490,7 @@ where { let span = ident.span; let key = MacroRulesNormalizedIdent::new(ident); - interp.get(&key).ok_or_else(|| { - cx.struct_span_err( - span, - &format!("variable `{}` is not recognized in meta-variable expression", key), - ) - }) + interp.get(&key).ok_or_else(|| cx.create_err(MetaVarExprUnrecognizedVar { span, key })) } /// Used by meta-variable expressions when an user input is out of the actual declared bounds. For diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 0315d1163..9002a24e4 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -1,6 +1,6 @@ use crate::base::ModuleData; use rustc_ast::ptr::P; -use rustc_ast::{token, Attribute, Inline, Item, ModSpans}; +use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans}; use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed}; use rustc_parse::new_parser_from_file; use rustc_parse::validate_attr; @@ -48,7 +48,7 @@ pub(crate) fn parse_external_mod( span: Span, // The span to blame on errors. module: &ModuleData, mut dir_ownership: DirOwnership, - attrs: &mut Vec<Attribute>, + attrs: &mut AttrVec, ) -> ParsedExternalMod { // We bail on the first error, but that error does not cause a fatal error... (1) let result: Result<_, ModError<'_>> = try { @@ -63,9 +63,9 @@ pub(crate) fn parse_external_mod( // Actually parse the external file as a module. let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span)); - let (mut inner_attrs, items, inner_span) = + let (inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?; - attrs.append(&mut inner_attrs); + attrs.extend(inner_attrs); (items, inner_span, mp.file_path) }; // (1) ...instead, we return a dummy module. diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 0d5d6ee07..3b0d5ddb9 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -15,16 +15,16 @@ pub fn placeholder( id: ast::NodeId, vis: Option<ast::Visibility>, ) -> AstFragment { - fn mac_placeholder() -> ast::MacCall { - ast::MacCall { + fn mac_placeholder() -> P<ast::MacCall> { + P(ast::MacCall { path: ast::Path { span: DUMMY_SP, segments: Vec::new(), tokens: None }, args: P(ast::MacArgs::Empty), prior_type_ascription: None, - } + }) } let ident = Ident::empty(); - let attrs = Vec::new(); + let attrs = ast::AttrVec::new(); let vis = vis.unwrap_or(ast::Visibility { span: DUMMY_SP, kind: ast::VisibilityKind::Inherited, diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 7d9a4aed0..59a7b668a 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -6,7 +6,7 @@ use rustc_ast::tokenstream::{self, Spacing::*, TokenStream}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Diagnostic, MultiSpan, PResult}; +use rustc_errors::{MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; @@ -15,7 +15,7 @@ use rustc_span::symbol::{self, sym, Symbol}; use rustc_span::{BytePos, FileName, Pos, SourceFile, Span}; use pm::bridge::{ - server, DelimSpan, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree, + server, DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree, }; use pm::{Delimiter, Level, LineColumn}; use std::ops::Bound; @@ -368,8 +368,6 @@ impl server::Types for Rustc<'_, '_> { type FreeFunctions = FreeFunctions; type TokenStream = TokenStream; type SourceFile = Lrc<SourceFile>; - type MultiSpan = Vec<Span>; - type Diagnostic = Diagnostic; type Span = Span; type Symbol = Symbol; } @@ -436,6 +434,21 @@ impl server::FreeFunctions for Rustc<'_, '_> { span: self.call_site, }) } + + fn emit_diagnostic(&mut self, diagnostic: Diagnostic<Self::Span>) { + let mut diag = + rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message); + diag.set_span(MultiSpan::from_spans(diagnostic.spans)); + for child in diagnostic.children { + diag.sub( + child.level.to_internal(), + child.message, + MultiSpan::from_spans(child.spans), + None, + ); + } + self.sess().span_diagnostic.emit_diagnostic(&mut diag); + } } impl server::TokenStream for Rustc<'_, '_> { @@ -486,20 +499,26 @@ impl server::TokenStream for Rustc<'_, '_> { // We don't use `TokenStream::from_ast` as the tokenstream currently cannot // be recovered in the general case. match &expr.kind { - ast::ExprKind::Lit(l) if l.token.kind == token::Bool => Ok( - tokenstream::TokenStream::token_alone(token::Ident(l.token.symbol, false), l.span), - ), + ast::ExprKind::Lit(l) if l.token_lit.kind == token::Bool => { + Ok(tokenstream::TokenStream::token_alone( + token::Ident(l.token_lit.symbol, false), + l.span, + )) + } ast::ExprKind::Lit(l) => { - Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token), l.span)) + Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token_lit), l.span)) } ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { - ast::ExprKind::Lit(l) => match l.token { + ast::ExprKind::Lit(l) => match l.token_lit { token::Lit { kind: token::Integer | token::Float, .. } => { Ok(Self::TokenStream::from_iter([ // FIXME: The span of the `-` token is lost when // parsing, so we cannot faithfully recover it here. tokenstream::TokenTree::token_alone(token::BinOp(token::Minus), e.span), - tokenstream::TokenTree::token_alone(token::Literal(l.token), l.span), + tokenstream::TokenTree::token_alone( + token::Literal(l.token_lit), + l.span, + ), ])) } _ => Err(()), @@ -577,38 +596,6 @@ impl server::SourceFile for Rustc<'_, '_> { } } -impl server::MultiSpan for Rustc<'_, '_> { - fn new(&mut self) -> Self::MultiSpan { - vec![] - } - - fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) { - spans.push(span) - } -} - -impl server::Diagnostic for Rustc<'_, '_> { - fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic { - let mut diag = Diagnostic::new(level.to_internal(), msg); - diag.set_span(MultiSpan::from_spans(spans)); - diag - } - - fn sub( - &mut self, - diag: &mut Self::Diagnostic, - level: Level, - msg: &str, - spans: Self::MultiSpan, - ) { - diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None); - } - - fn emit(&mut self, mut diag: Self::Diagnostic) { - self.sess().span_diagnostic.emit_diagnostic(&mut diag); - } -} - impl server::Span for Rustc<'_, '_> { fn debug(&mut self, span: Self::Span) -> String { if self.ecx.ecfg.span_debug { |