summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_expand
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_expand')
-rw-r--r--compiler/rustc_expand/Cargo.toml2
-rw-r--r--compiler/rustc_expand/locales/en-US.ftl138
-rw-r--r--compiler/rustc_expand/src/base.rs62
-rw-r--r--compiler/rustc_expand/src/build.rs74
-rw-r--r--compiler/rustc_expand/src/config.rs13
-rw-r--r--compiler/rustc_expand/src/errors.rs43
-rw-r--r--compiler/rustc_expand/src/lib.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs30
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs2
-rw-r--r--compiler/rustc_expand/src/module.rs4
-rw-r--r--compiler/rustc_expand/src/parse/tests.rs5
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs14
-rw-r--r--compiler/rustc_expand/src/tests.rs20
15 files changed, 323 insertions, 103 deletions
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index 192f54171..c971714e0 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -24,5 +24,5 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.8"
+thin-vec = "0.2.12"
tracing = "0.1"
diff --git a/compiler/rustc_expand/locales/en-US.ftl b/compiler/rustc_expand/locales/en-US.ftl
new file mode 100644
index 000000000..cfae781bd
--- /dev/null
+++ b/compiler/rustc_expand/locales/en-US.ftl
@@ -0,0 +1,138 @@
+expand_explain_doc_comment_outer =
+ outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
+
+expand_explain_doc_comment_inner =
+ inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
+
+expand_expr_repeat_no_syntax_vars =
+ attempted to repeat an expression containing no syntax variables matched as repeating at this depth
+
+expand_must_repeat_once =
+ this must repeat at least once
+
+expand_count_repetition_misplaced =
+ `count` can not be placed inside the inner-most repetition
+
+expand_meta_var_expr_unrecognized_var =
+ variable `{$key}` is not recognized in meta-variable expression
+
+expand_var_still_repeating =
+ variable '{$ident}' is still repeating at this depth
+
+expand_meta_var_dif_seq_matchers = {$msg}
+
+expand_macro_const_stability =
+ macros cannot have const stability attributes
+ .label = invalid const stability attribute
+ .label2 = const stability attribute affects this macro
+
+expand_macro_body_stability =
+ macros cannot have body stability attributes
+ .label = invalid body stability attribute
+ .label2 = body stability attribute affects this macro
+
+expand_resolve_relative_path =
+ cannot resolve relative path in non-file source `{$path}`
+
+expand_attr_no_arguments =
+ attribute must have either one or two arguments
+
+expand_not_a_meta_item =
+ not a meta item
+
+expand_only_one_word =
+ must only be one word
+
+expand_cannot_be_name_of_macro =
+ `{$trait_ident}` cannot be a name of {$macro_type} macro
+
+expand_arg_not_attributes =
+ second argument must be `attributes`
+
+expand_attributes_wrong_form =
+ attribute must be of form: `attributes(foo, bar)`
+
+expand_attribute_meta_item =
+ attribute must be a meta item, not a literal
+
+expand_attribute_single_word =
+ attribute must only be a single word
+
+expand_helper_attribute_name_invalid =
+ `{$name}` cannot be a name of derive helper attribute
+
+expand_expected_comma_in_list =
+ expected token: `,`
+
+expand_only_one_argument =
+ {$name} takes 1 argument
+
+expand_takes_no_arguments =
+ {$name} takes no arguments
+
+expand_feature_included_in_edition =
+ the feature `{$feature}` is included in the Rust {$edition} edition
+
+expand_feature_removed =
+ feature has been removed
+ .label = feature has been removed
+ .reason = {$reason}
+
+expand_feature_not_allowed =
+ the feature `{$name}` is not in the list of allowed features
+
+expand_recursion_limit_reached =
+ recursion limit reached while expanding `{$descr}`
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+expand_malformed_feature_attribute =
+ malformed `feature` attribute input
+ .expected = expected just one word
+
+expand_remove_expr_not_supported =
+ removing an expression is not supported in this position
+
+expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
+expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
+expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
+expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
+expand_invalid_cfg_expected_syntax = expected syntax is
+
+expand_wrong_fragment_kind =
+ non-{$kind} macro in {$kind} position: {$name}
+
+expand_unsupported_key_value =
+ key-value macro attributes are not supported
+
+expand_incomplete_parse =
+ macro expansion ignores token `{$token}` and any following
+ .label = caused by the macro expansion here
+ .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
+ .suggestion_add_semi = you might be missing a semicolon here
+
+expand_remove_node_not_supported =
+ removing {$descr} is not supported in this position
+
+expand_module_circular =
+ circular modules: {$modules}
+
+expand_module_in_block =
+ cannot declare a non-inline module inside a block unless it has a path attribute
+ .note = maybe `use` the module `{$name}` instead of redeclaring it
+
+expand_module_file_not_found =
+ file not found for module `{$name}`
+ .help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
+
+expand_module_multiple_candidates =
+ file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
+ .help = delete or rename one of them to remove the ambiguity
+
+expand_trace_macro = trace_macro
+
+expand_proc_macro_panicked =
+ proc macro panicked
+ .help = message: {$message}
+
+expand_proc_macro_derive_tokens =
+ proc-macro derive produced unparseable tokens
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 951d59246..22bc90f5c 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1,15 +1,11 @@
#![deny(rustc::untranslatable_diagnostic)]
-use crate::errors::{
- ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
- AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
- MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
- ResolveRelativePath, TakesNoArguments,
-};
+use crate::errors;
use crate::expand::{self, AstFragment, Invocation};
use crate::module::DirOwnership;
use rustc_ast::attr::MarkedAttrs;
+use rustc_ast::mut_visit::DummyAstNode;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Nonterminal};
use rustc_ast::tokenstream::TokenStream;
@@ -33,10 +29,11 @@ use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
-
+use std::default::Default;
use std::iter;
use std::path::{Path, PathBuf};
use std::rc::Rc;
+use thin_vec::ThinVec;
pub(crate) use rustc_span::hygiene::MacroKind;
@@ -558,7 +555,7 @@ impl DummyResult {
pub fn raw_expr(sp: Span, is_error: bool) -> P<ast::Expr> {
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
- kind: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(Vec::new()) },
+ kind: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(ThinVec::new()) },
span: sp,
attrs: ast::AttrVec::new(),
tokens: None,
@@ -574,7 +571,7 @@ impl DummyResult {
pub fn raw_ty(sp: Span, is_error: bool) -> P<ast::Ty> {
P(ast::Ty {
id: ast::DUMMY_NODE_ID,
- kind: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(Vec::new()) },
+ kind: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(ThinVec::new()) },
span: sp,
tokens: None,
})
@@ -645,6 +642,10 @@ impl MacResult for DummyResult {
fn make_variants(self: Box<DummyResult>) -> Option<SmallVec<[ast::Variant; 1]>> {
Some(SmallVec::new())
}
+
+ fn make_crate(self: Box<DummyResult>) -> Option<ast::Crate> {
+ Some(DummyAstNode::dummy())
+ }
}
/// A syntax extension kind.
@@ -796,13 +797,13 @@ impl SyntaxExtension {
.unwrap_or_else(|| (None, helper_attrs));
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
if let Some((_, sp)) = const_stability {
- sess.emit_err(MacroConstStability {
+ sess.emit_err(errors::MacroConstStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
}
if let Some((_, sp)) = body_stability {
- sess.emit_err(MacroBodyStability {
+ sess.emit_err(errors::MacroBodyStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
@@ -1142,8 +1143,8 @@ impl<'a> ExtCtxt<'a> {
self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
}
pub fn trace_macros_diag(&mut self) {
- for (sp, notes) in self.expansions.iter() {
- let mut db = self.sess.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro");
+ for (span, notes) in self.expansions.iter() {
+ let mut db = self.sess.parse_sess.create_note(errors::TraceMacro { span: *span });
for note in notes {
db.note(note);
}
@@ -1197,7 +1198,7 @@ pub fn resolve_path(
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
- return Err(ResolveRelativePath {
+ return Err(errors::ResolveRelativePath {
span,
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
}
@@ -1279,7 +1280,7 @@ pub fn expr_to_string(
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
if !tts.is_empty() {
- cx.emit_err(TakesNoArguments { span, name });
+ cx.emit_err(errors::TakesNoArguments { span, name });
}
}
@@ -1307,14 +1308,14 @@ pub fn get_single_str_from_tts(
) -> Option<Symbol> {
let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
return None;
}
let ret = parse_expr(&mut p)?;
let _ = p.eat(&token::Comma);
if p.token != token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
}
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
}
@@ -1336,7 +1337,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec<
continue;
}
if p.token != token::Eof {
- cx.emit_err(ExpectedCommaInList { span: p.token.span });
+ cx.emit_err(errors::ExpectedCommaInList { span: p.token.span });
return None;
}
}
@@ -1353,51 +1354,58 @@ pub fn parse_macro_name_and_helper_attrs(
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
if list.len() != 1 && list.len() != 2 {
- diag.emit_err(AttrNoArguments { span: attr.span });
+ diag.emit_err(errors::AttrNoArguments { span: attr.span });
return None;
}
let Some(trait_attr) = list[0].meta_item() else {
- diag.emit_err(NotAMetaItem {span: list[0].span()});
+ diag.emit_err(errors::NotAMetaItem {span: list[0].span()});
return None;
};
let trait_ident = match trait_attr.ident() {
Some(trait_ident) if trait_attr.is_word() => trait_ident,
_ => {
- diag.emit_err(OnlyOneWord { span: trait_attr.span });
+ diag.emit_err(errors::OnlyOneWord { span: trait_attr.span });
return None;
}
};
if !trait_ident.name.can_be_raw() {
- diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
+ diag.emit_err(errors::CannotBeNameOfMacro {
+ span: trait_attr.span,
+ trait_ident,
+ macro_type,
+ });
}
let attributes_attr = list.get(1);
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
if !attr.has_name(sym::attributes) {
- diag.emit_err(ArgumentNotAttributes { span: attr.span() });
+ diag.emit_err(errors::ArgumentNotAttributes { span: attr.span() });
}
attr.meta_item_list()
.unwrap_or_else(|| {
- diag.emit_err(AttributesWrongForm { span: attr.span() });
+ diag.emit_err(errors::AttributesWrongForm { span: attr.span() });
&[]
})
.iter()
.filter_map(|attr| {
let Some(attr) = attr.meta_item() else {
- diag.emit_err(AttributeMetaItem { span: attr.span() });
+ diag.emit_err(errors::AttributeMetaItem { span: attr.span() });
return None;
};
let ident = match attr.ident() {
Some(ident) if attr.is_word() => ident,
_ => {
- diag.emit_err(AttributeSingleWord { span: attr.span });
+ diag.emit_err(errors::AttributeSingleWord { span: attr.span });
return None;
}
};
if !ident.name.can_be_raw() {
- diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
+ diag.emit_err(errors::HelperAttributeNameInvalid {
+ span: attr.span,
+ name: ident,
+ });
}
Some(ident.name)
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 9b16e79d4..8a78c3296 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -5,7 +5,7 @@ use rustc_ast::{attr, token, util::literal};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-use thin_vec::ThinVec;
+use thin_vec::{thin_vec, ThinVec};
impl<'a> ExtCtxt<'a> {
pub fn path(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
@@ -125,16 +125,20 @@ impl<'a> ExtCtxt<'a> {
pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef {
ast::PolyTraitRef {
- bound_generic_params: Vec::new(),
+ bound_generic_params: ThinVec::new(),
trait_ref: self.trait_ref(path),
span,
}
}
- pub fn trait_bound(&self, path: ast::Path) -> ast::GenericBound {
+ pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
ast::GenericBound::Trait(
self.poly_trait_ref(path.span, path),
- ast::TraitBoundModifier::None,
+ if is_const {
+ ast::TraitBoundModifier::MaybeConst
+ } else {
+ ast::TraitBoundModifier::None
+ },
)
}
@@ -217,14 +221,14 @@ impl<'a> ExtCtxt<'a> {
pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
self.block(
expr.span,
- vec![ast::Stmt {
+ thin_vec![ast::Stmt {
id: ast::DUMMY_NODE_ID,
span: expr.span,
kind: ast::StmtKind::Expr(expr),
}],
)
}
- pub fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> {
+ pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block> {
P(ast::Block {
stmts,
id: ast::DUMMY_NODE_ID,
@@ -272,22 +276,31 @@ impl<'a> ExtCtxt<'a> {
self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
}
+ pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
+ self.expr(sp, ast::ExprKind::Paren(e))
+ }
+
pub fn expr_call(
&self,
span: Span,
expr: P<ast::Expr>,
- args: Vec<P<ast::Expr>>,
+ args: ThinVec<P<ast::Expr>>,
) -> P<ast::Expr> {
self.expr(span, ast::ExprKind::Call(expr, args))
}
- pub fn expr_call_ident(&self, span: Span, id: Ident, args: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_call_ident(
+ &self,
+ span: Span,
+ id: Ident,
+ args: ThinVec<P<ast::Expr>>,
+ ) -> P<ast::Expr> {
self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args))
}
pub fn expr_call_global(
&self,
sp: Span,
fn_path: Vec<Ident>,
- args: Vec<P<ast::Expr>>,
+ args: ThinVec<P<ast::Expr>>,
) -> P<ast::Expr> {
let pathexpr = self.expr_path(self.path_global(sp, fn_path));
self.expr_call(sp, pathexpr, args)
@@ -310,7 +323,7 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
path: ast::Path,
- fields: Vec<ast::ExprField>,
+ fields: ThinVec<ast::ExprField>,
) -> P<ast::Expr> {
self.expr(
span,
@@ -326,7 +339,7 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
id: Ident,
- fields: Vec<ast::ExprField>,
+ fields: ThinVec<ast::ExprField>,
) -> P<ast::Expr> {
self.expr_struct(span, self.path_ident(span, id), fields)
}
@@ -364,12 +377,12 @@ impl<'a> ExtCtxt<'a> {
}
/// `[expr1, expr2, ...]`
- pub fn expr_array(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
self.expr(sp, ast::ExprKind::Array(exprs))
}
/// `&[expr1, expr2, ...]`
- pub fn expr_array_ref(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
self.expr_addr_of(sp, self.expr_array(sp, exprs))
}
@@ -379,14 +392,14 @@ impl<'a> ExtCtxt<'a> {
pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
- self.expr_call_global(sp, some, vec![expr])
+ self.expr_call_global(sp, some, thin_vec![expr])
}
pub fn expr_none(&self, sp: Span) -> P<ast::Expr> {
let none = self.std_path(&[sym::option, sym::Option, sym::None]);
self.expr_path(self.path_global(sp, none))
}
- pub fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
self.expr(sp, ast::ExprKind::Tup(exprs))
}
@@ -394,7 +407,7 @@ impl<'a> ExtCtxt<'a> {
self.expr_call_global(
span,
[sym::std, sym::rt, sym::begin_panic].iter().map(|s| Ident::new(*s, span)).collect(),
- vec![self.expr_str(span, msg)],
+ thin_vec![self.expr_str(span, msg)],
)
}
@@ -404,7 +417,7 @@ impl<'a> ExtCtxt<'a> {
pub fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
- self.expr_call_global(sp, ok, vec![expr])
+ self.expr_call_global(sp, ok, thin_vec![expr])
}
pub fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> {
@@ -418,12 +431,12 @@ impl<'a> ExtCtxt<'a> {
let binding_expr = self.expr_ident(sp, binding_variable);
// `Ok(__try_var)` pattern
- let ok_pat = self.pat_tuple_struct(sp, ok_path, vec![binding_pat.clone()]);
+ let ok_pat = self.pat_tuple_struct(sp, ok_path, thin_vec![binding_pat.clone()]);
// `Err(__try_var)` (pattern and expression respectively)
- let err_pat = self.pat_tuple_struct(sp, err_path.clone(), vec![binding_pat]);
+ let err_pat = self.pat_tuple_struct(sp, err_path.clone(), thin_vec![binding_pat]);
let err_inner_expr =
- self.expr_call(sp, self.expr_path(err_path), vec![binding_expr.clone()]);
+ self.expr_call(sp, self.expr_path(err_path), thin_vec![binding_expr.clone()]);
// `return Err(__try_var)`
let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr)));
@@ -433,7 +446,7 @@ impl<'a> ExtCtxt<'a> {
let err_arm = self.arm(sp, err_pat, err_expr);
// `match head { Ok() => ..., Err() => ... }`
- self.expr_match(sp, head, vec![ok_arm, err_arm])
+ self.expr_match(sp, head, thin_vec![ok_arm, err_arm])
}
pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
@@ -465,7 +478,7 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
path: ast::Path,
- subpats: Vec<P<ast::Pat>>,
+ subpats: ThinVec<P<ast::Pat>>,
) -> P<ast::Pat> {
self.pat(span, PatKind::TupleStruct(None, path, subpats))
}
@@ -473,18 +486,18 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
path: ast::Path,
- field_pats: Vec<ast::PatField>,
+ field_pats: ThinVec<ast::PatField>,
) -> P<ast::Pat> {
self.pat(span, PatKind::Struct(None, path, field_pats, false))
}
- pub fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
+ pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
self.pat(span, PatKind::Tuple(pats))
}
pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
let path = self.path_global(span, some);
- self.pat_tuple_struct(span, path, vec![pat])
+ self.pat_tuple_struct(span, path, thin_vec![pat])
}
pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
@@ -503,7 +516,7 @@ impl<'a> ExtCtxt<'a> {
self.arm(span, self.pat_wild(span), self.expr_unreachable(span))
}
- pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> {
+ pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
self.expr(span, ast::ExprKind::Match(arg, arms))
}
@@ -554,7 +567,12 @@ impl<'a> ExtCtxt<'a> {
self.lambda(span, vec![ident], body)
}
- pub fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>, ident: Ident) -> P<ast::Expr> {
+ pub fn lambda_stmts_1(
+ &self,
+ span: Span,
+ stmts: ThinVec<ast::Stmt>,
+ ident: Ident,
+ ) -> P<ast::Expr> {
self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
}
@@ -571,7 +589,7 @@ impl<'a> ExtCtxt<'a> {
}
// `self` is unused but keep it as method for the convenience use.
- pub fn fn_decl(&self, inputs: Vec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
+ pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
P(ast::FnDecl { inputs, output })
}
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 1fcbdfd9b..01500c2c7 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -24,6 +24,7 @@ use rustc_session::Session;
use rustc_span::edition::{Edition, ALL_EDITIONS};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
+use thin_vec::ThinVec;
/// A folder that strips out items that do not belong in the current configuration.
pub struct StripUnconfigured<'a> {
@@ -206,7 +207,7 @@ pub fn features(
None => {
// The entire crate is unconfigured.
krate.attrs = ast::AttrVec::new();
- krate.items = Vec::new();
+ krate.items = ThinVec::new();
Features::default()
}
Some(attrs) => {
@@ -238,12 +239,10 @@ macro_rules! configure {
impl<'a> StripUnconfigured<'a> {
pub fn configure<T: HasAttrs + HasTokens>(&self, mut node: T) -> Option<T> {
self.process_cfg_attrs(&mut node);
- if self.in_cfg(node.attrs()) {
+ self.in_cfg(node.attrs()).then(|| {
self.try_configure_tokens(&mut node);
- Some(node)
- } else {
- None
- }
+ node
+ })
}
fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) {
@@ -257,7 +256,7 @@ impl<'a> StripUnconfigured<'a> {
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 }
+ self.in_cfg(&attrs).then_some(attrs)
}
/// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`.
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index afe5169d3..e5102a952 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -65,7 +65,7 @@ pub(crate) struct MacroConstStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(label2)]
+ #[label(expand_label2)]
pub head_span: Span,
}
@@ -75,7 +75,7 @@ pub(crate) struct MacroBodyStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(label2)]
+ #[label(expand_label2)]
pub head_span: Span,
}
@@ -188,7 +188,7 @@ pub(crate) struct FeatureRemoved<'a> {
}
#[derive(Subdiagnostic)]
-#[note(reason)]
+#[note(expand_reason)]
pub(crate) struct FeatureRemovedReason<'a> {
pub reason: &'a str,
}
@@ -223,12 +223,12 @@ pub(crate) struct MalformedFeatureAttribute {
#[derive(Subdiagnostic)]
pub(crate) enum MalformedFeatureAttributeHelp {
- #[label(expected)]
+ #[label(expand_expected)]
Label {
#[primary_span]
span: Span,
},
- #[suggestion(expected, code = "{suggestion}", applicability = "maybe-incorrect")]
+ #[suggestion(expand_expected, code = "{suggestion}", applicability = "maybe-incorrect")]
Suggestion {
#[primary_span]
span: Span,
@@ -306,7 +306,7 @@ pub(crate) struct IncompleteParse<'a> {
pub kind_name: &'a str,
#[suggestion(
- suggestion_add_semi,
+ expand_suggestion_add_semi,
style = "verbose",
code = ";",
applicability = "maybe-incorrect"
@@ -340,7 +340,7 @@ pub(crate) struct ModuleInBlock {
}
#[derive(Subdiagnostic)]
-#[note(note)]
+#[note(expand_note)]
pub(crate) struct ModuleInBlockName {
#[primary_span]
pub span: Span,
@@ -368,3 +368,32 @@ pub(crate) struct ModuleMultipleCandidates {
pub default_path: String,
pub secondary_path: String,
}
+
+#[derive(Diagnostic)]
+#[diag(expand_trace_macro)]
+pub struct TraceMacro {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_proc_macro_panicked)]
+pub(crate) struct ProcMacroPanicked {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub message: Option<ProcMacroPanickedHelp>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(expand_help)]
+pub(crate) struct ProcMacroPanickedHelp {
+ pub message: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_proc_macro_derive_tokens)]
+pub struct ProcMacroDeriveTokens {
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 897268566..634e206e5 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -20,6 +20,9 @@ extern crate tracing;
extern crate proc_macro as pm;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
mod placeholders;
mod proc_macro_server;
@@ -60,3 +63,5 @@ mod tokenstream {
mod mut_visit {
mod tests;
}
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 2e199541b..283e68a68 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -503,7 +503,7 @@ impl TtParser {
mp.push_match(metavar_idx, seq_depth, MatchedSeq(vec![]));
}
- if op == KleeneOp::ZeroOrMore || op == KleeneOp::ZeroOrOne {
+ if matches!(op, KleeneOp::ZeroOrMore | KleeneOp::ZeroOrOne) {
// Try zero matches of this sequence, by skipping over it.
self.cur_mps.push(MatcherPos {
idx: idx_first_after,
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 4ebd75f01..5679cdcbb 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -10,13 +10,12 @@ use crate::mbe::transcribe::transcribe;
use rustc_ast as ast;
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind, TokenKind::*};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream};
+use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
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, ErrorGuaranteed};
-use rustc_feature::Features;
use rustc_lint_defs::builtin::{
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
};
@@ -212,7 +211,6 @@ fn expand_macro<'cx>(
};
let arm_span = rhses[i].span();
- let rhs_spans = rhs.tts.iter().map(|t| t.span()).collect::<Vec<_>>();
// rhs has holes ( `$id` and `$(...)` that need filled)
let mut tts = match transcribe(cx, &named_matches, &rhs, rhs_span, transparency) {
Ok(tts) => tts,
@@ -224,12 +222,25 @@ fn expand_macro<'cx>(
// Replace all the tokens for the corresponding positions in the macro, to maintain
// proper positions in error reporting, while maintaining the macro_backtrace.
- if rhs_spans.len() == tts.len() {
+ if tts.len() == rhs.tts.len() {
tts = tts.map_enumerated(|i, tt| {
let mut tt = tt.clone();
- let mut sp = rhs_spans[i];
- sp = sp.with_ctxt(tt.span().ctxt());
- tt.set_span(sp);
+ let rhs_tt = &rhs.tts[i];
+ let ctxt = tt.span().ctxt();
+ match (&mut tt, rhs_tt) {
+ // preserve the delim spans if able
+ (
+ TokenTree::Delimited(target_sp, ..),
+ mbe::TokenTree::Delimited(source_sp, ..),
+ ) => {
+ target_sp.open = source_sp.open.with_ctxt(ctxt);
+ target_sp.close = source_sp.close.with_ctxt(ctxt);
+ }
+ _ => {
+ let sp = rhs_tt.span().with_ctxt(ctxt);
+ tt.set_span(sp);
+ }
+ }
tt
});
}
@@ -367,7 +378,6 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
/// Converts a macro item into a syntax extension.
pub fn compile_declarative_macro(
sess: &Session,
- features: &Features,
def: &ast::Item,
edition: Edition,
) -> (SyntaxExtension, Vec<(usize, Span)>) {
@@ -496,7 +506,7 @@ pub fn compile_declarative_macro(
true,
&sess.parse_sess,
def.id,
- features,
+ sess.features_untracked(),
edition,
)
.pop()
@@ -520,7 +530,7 @@ pub fn compile_declarative_macro(
false,
&sess.parse_sess,
def.id,
- features,
+ sess.features_untracked(),
edition,
)
.pop()
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 99fe47454..de34df011 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -1,5 +1,5 @@
use rustc_ast::token::{self, Delimiter};
-use rustc_ast::tokenstream::{CursorRef, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree};
use rustc_ast::{LitIntType, LitKind};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, PResult};
@@ -72,7 +72,7 @@ impl MetaVarExpr {
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
fn check_trailing_token<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
) -> PResult<'sess, ()> {
if let Some(tt) = iter.next() {
@@ -88,7 +88,7 @@ fn check_trailing_token<'sess>(
/// Parse a meta-variable `count` expression: `count(ident[, depth])`
fn parse_count<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, MetaVarExpr> {
@@ -99,7 +99,7 @@ fn parse_count<'sess>(
/// Parses the depth used by index(depth) and length(depth).
fn parse_depth<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, usize> {
@@ -126,7 +126,7 @@ fn parse_depth<'sess>(
/// Parses an generic ident
fn parse_ident<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, Ident> {
@@ -152,7 +152,7 @@ fn parse_ident<'sess>(
/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
/// iterator is not modified and the result is `false`.
-fn try_eat_comma(iter: &mut CursorRef<'_>) -> bool {
+fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) {
let _ = iter.next();
return true;
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b79835be7..47a8b4bc4 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -282,7 +282,7 @@ pub(super) fn transcribe<'a>(
}
// There should be no meta-var declarations in the invocation of a macro.
- mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"),
+ mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl`"),
}
}
}
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 07f47a9c3..3779af19e 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -12,8 +12,8 @@ use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use std::iter::once;
-
use std::path::{self, Path, PathBuf};
+use thin_vec::ThinVec;
#[derive(Copy, Clone)]
pub enum DirOwnership {
@@ -31,7 +31,7 @@ pub struct ModulePathSuccess {
}
pub(crate) struct ParsedExternalMod {
- pub items: Vec<P<Item>>,
+ pub items: ThinVec<P<Item>>,
pub spans: ModSpans,
pub file_path: PathBuf,
pub dir_path: PathBuf,
diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs
index 0726d922c..8b37728b6 100644
--- a/compiler/rustc_expand/src/parse/tests.rs
+++ b/compiler/rustc_expand/src/parse/tests.rs
@@ -18,7 +18,10 @@ use rustc_span::{BytePos, FileName, Pos, Span};
use std::path::PathBuf;
fn sess() -> ParseSess {
- ParseSess::new(FilePathMapping::empty())
+ ParseSess::new(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ FilePathMapping::empty(),
+ )
}
/// Parses an item.
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index e9a691920..ddba14417 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -1,4 +1,5 @@
use crate::base::{self, *};
+use crate::errors;
use crate::proc_macro_server;
use rustc_ast as ast;
@@ -60,11 +61,12 @@ impl base::BangProcMacro for BangProcMacro {
let strategy = exec_strategy(ecx);
let server = proc_macro_server::Rustc::new(ecx);
self.client.run(&strategy, server, input, proc_macro_backtrace).map_err(|e| {
- let mut err = ecx.struct_span_err(span, "proc macro panicked");
- if let Some(s) = e.as_str() {
- err.help(&format!("message: {}", s));
- }
- err.emit()
+ ecx.sess.emit_err(errors::ProcMacroPanicked {
+ span,
+ message: e
+ .as_str()
+ .map(|message| errors::ProcMacroPanickedHelp { message: message.into() }),
+ })
})
}
}
@@ -174,7 +176,7 @@ impl MultiItemModifier for DeriveProcMacro {
// fail if there have been errors emitted
if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
- ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
+ ecx.sess.emit_err(errors::ProcMacroDeriveTokens { span });
}
ExpandResult::Ready(items)
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 8f3bea29f..480d95b77 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -8,7 +8,7 @@ use rustc_span::{BytePos, Span};
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::EmitterWriter;
-use rustc_errors::{Handler, MultiSpan, PResult};
+use rustc_errors::{Handler, MultiSpan, PResult, TerminalUrl};
use std::io;
use std::io::prelude::*;
@@ -34,18 +34,23 @@ where
/// Maps a string to tts, using a made-up filename.
pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
- let ps = ParseSess::new(FilePathMapping::empty());
+ let ps = ParseSess::new(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ FilePathMapping::empty(),
+ );
source_file_to_stream(
&ps,
ps.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str),
None,
)
- .0
}
/// Parses a string, returns a crate.
pub(crate) fn string_to_crate(source_str: String) -> ast::Crate {
- let ps = ParseSess::new(FilePathMapping::empty());
+ let ps = ParseSess::new(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ FilePathMapping::empty(),
+ );
with_error_checking_parse(source_str, &ps, |p| p.parse_crate_mod())
}
@@ -127,8 +132,10 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
create_default_session_if_not_set_then(|_| {
let output = Arc::new(Mutex::new(Vec::new()));
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ false,
+ );
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
@@ -152,6 +159,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
None,
false,
false,
+ TerminalUrl::No,
);
let handler = Handler::with_emitter(true, None, Box::new(emitter));
#[allow(rustc::untranslatable_diagnostic)]