summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_builtin_macros
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_builtin_macros')
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml2
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs93
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs71
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_accessible.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/concat.rs28
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs108
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs59
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs22
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs15
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/decodable.rs23
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs21
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs225
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/ty.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs43
-rw-r--r--compiler/rustc_builtin_macros/src/edition_panic.rs36
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs34
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs36
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/standard_library_imports.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs142
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs23
-rw-r--r--compiler/rustc_builtin_macros/src/type_ascribe.rs35
-rw-r--r--compiler/rustc_builtin_macros/src/util.rs11
37 files changed, 621 insertions, 517 deletions
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index 6469d0d7b..467fa932a 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -23,5 +23,5 @@ rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.8"
+thin-vec = "0.2.9"
tracing = "0.1"
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
new file mode 100644
index 000000000..95e38e4b0
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -0,0 +1,93 @@
+use crate::util::check_builtin_macro_attribute;
+
+use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind};
+use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe};
+use rustc_expand::base::{Annotatable, ExtCtxt};
+use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::Span;
+use thin_vec::thin_vec;
+
+pub fn expand(
+ ecx: &mut ExtCtxt<'_>,
+ _span: Span,
+ meta_item: &ast::MetaItem,
+ item: Annotatable,
+) -> Vec<Annotatable> {
+ check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler);
+
+ let orig_item = item.clone();
+
+ // Allow using `#[alloc_error_handler]` on an item statement
+ // FIXME - if we get deref patterns, use them to reduce duplication here
+ let (item, is_stmt, sig_span) =
+ if let Annotatable::Item(item) = &item
+ && let ItemKind::Fn(fn_kind) = &item.kind
+ {
+ (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ } else if let Annotatable::Stmt(stmt) = &item
+ && let StmtKind::Item(item) = &stmt.kind
+ && let ItemKind::Fn(fn_kind) = &item.kind
+ {
+ (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ } else {
+ ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
+ return vec![orig_item.clone()];
+ };
+
+ // Generate a bunch of new items using the AllocFnFactory
+ let span = ecx.with_def_site_ctxt(item.span);
+
+ // Generate item statements for the allocator methods.
+ let stmts = vec![generate_handler(ecx, item.ident, span, sig_span)];
+
+ // Generate anonymous constant serving as container for the allocator methods.
+ let const_ty = ecx.ty(sig_span, TyKind::Tup(Vec::new()));
+ let const_body = ecx.expr_block(ecx.block(span, stmts));
+ let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
+ let const_item = if is_stmt {
+ Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
+ } else {
+ Annotatable::Item(const_item)
+ };
+
+ // Return the original item and the new methods.
+ vec![orig_item, const_item]
+}
+
+// #[rustc_std_internal_symbol]
+// unsafe fn __rg_oom(size: usize, align: usize) -> ! {
+// handler(core::alloc::Layout::from_size_align_unchecked(size, align))
+// }
+fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt {
+ let usize = cx.path_ident(span, Ident::new(sym::usize, span));
+ let ty_usize = cx.ty_path(usize);
+ let size = Ident::from_str_and_span("size", span);
+ let align = Ident::from_str_and_span("align", span);
+
+ let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]);
+ let layout_new = cx.expr_path(cx.path(span, layout_new));
+ let layout =
+ cx.expr_call(span, layout_new, vec![cx.expr_ident(span, size), cx.expr_ident(span, align)]);
+
+ let call = cx.expr_call_ident(sig_span, handler, vec![layout]);
+
+ let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never));
+ let params = vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)];
+ let decl = cx.fn_decl(params, never);
+ let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() };
+ let sig = FnSig { decl, header, span: span };
+
+ let body = Some(cx.block_expr(call));
+ let kind = ItemKind::Fn(Box::new(Fn {
+ defaultness: ast::Defaultness::Final,
+ sig,
+ generics: Generics::default(),
+ body,
+ }));
+
+ let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
+
+ let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
+ cx.stmt_item(sig_span, item)
+}
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index a1051d990..900c44274 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -172,7 +172,11 @@ pub fn parse_asm_args<'a>(
// If it can't possibly expand to a string, provide diagnostics here to include other
// things it could have been.
match template.kind {
- ast::ExprKind::Lit(ast::Lit { kind: ast::LitKind::Str(..), .. }) => {}
+ ast::ExprKind::Lit(token_lit)
+ if matches!(
+ token_lit.kind,
+ token::LitKind::Str | token::LitKind::StrRaw(_)
+ ) => {}
ast::ExprKind::MacCall(..) => {}
_ => {
let errstr = if is_global_asm {
@@ -560,7 +564,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
template_strs.push((
template_str,
- template_snippet.as_ref().map(|s| Symbol::intern(s)),
+ template_snippet.as_deref().map(Symbol::intern),
template_sp,
));
let template_str = template_str.as_str();
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index 119724b50..8555c3593 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -4,7 +4,7 @@ use crate::edition_panic::use_panic_2021;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
-use rustc_ast::{Expr, ExprKind, MacArgs, MacCall, MacDelimiter, Path, PathSegment, UnOp};
+use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, MacDelimiter, Path, PathSegment, UnOp};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, PResult};
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
@@ -54,11 +54,11 @@ pub fn expand_assert<'cx>(
call_site_span,
ExprKind::MacCall(P(MacCall {
path: panic_path(),
- args: P(MacArgs::Delimited(
- DelimSpan::from_single(call_site_span),
- MacDelimiter::Parenthesis,
+ args: P(DelimArgs {
+ dspan: DelimSpan::from_single(call_site_span),
+ delim: MacDelimiter::Parenthesis,
tokens,
- )),
+ }),
prior_type_ascription: None,
})),
);
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index bb6839360..93b07801e 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -1,10 +1,9 @@
use rustc_ast::{
- attr,
ptr::P,
token,
tokenstream::{DelimSpan, TokenStream, TokenTree},
- BinOpKind, BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability,
- Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
+ BinOpKind, BorrowKind, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MacDelimiter, MethodCall,
+ Mutability, Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
@@ -107,7 +106,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
(
UseTree {
prefix: this.cx.path(this.span, vec![Ident::with_dummy_span(sym)]),
- kind: UseTreeKind::Simple(None, DUMMY_NODE_ID, DUMMY_NODE_ID),
+ kind: UseTreeKind::Simple(None),
span: this.span,
},
DUMMY_NODE_ID,
@@ -118,10 +117,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.cx.item(
self.span,
Ident::empty(),
- thin_vec![self.cx.attribute(attr::mk_list_item(
- Ident::new(sym::allow, self.span),
- vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))],
- ))],
+ thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
ItemKind::Use(UseTree {
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
kind: UseTreeKind::Nested(vec![
@@ -181,11 +177,11 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.span,
ExprKind::MacCall(P(MacCall {
path: panic_path,
- args: P(MacArgs::Delimited(
- DelimSpan::from_single(self.span),
- MacDelimiter::Parenthesis,
- initial.into_iter().chain(captures).collect::<TokenStream>(),
- )),
+ args: P(DelimArgs {
+ dspan: DelimSpan::from_single(self.span),
+ delim: MacDelimiter::Parenthesis,
+ tokens: initial.into_iter().chain(captures).collect::<TokenStream>(),
+ }),
prior_type_ascription: None,
})),
)
@@ -195,19 +191,19 @@ impl<'cx, 'a> Context<'cx, 'a> {
///
/// See [Self::manage_initial_capture] and [Self::manage_try_capture]
fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
- match (*expr).kind {
- ExprKind::AddrOf(_, mutability, ref mut local_expr) => {
+ match &mut expr.kind {
+ ExprKind::AddrOf(_, mutability, local_expr) => {
self.with_is_consumed_management(
matches!(mutability, Mutability::Mut),
|this| this.manage_cond_expr(local_expr)
);
}
- ExprKind::Array(ref mut local_exprs) => {
+ ExprKind::Array(local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => {
+ ExprKind::Binary(op, lhs, rhs) => {
self.with_is_consumed_management(
matches!(
op.node,
@@ -230,56 +226,56 @@ impl<'cx, 'a> Context<'cx, 'a> {
}
);
}
- ExprKind::Call(_, ref mut local_exprs) => {
+ ExprKind::Call(_, local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Cast(ref mut local_expr, _) => {
+ ExprKind::Cast(local_expr, _) => {
self.manage_cond_expr(local_expr);
}
- ExprKind::Index(ref mut prefix, ref mut suffix) => {
+ ExprKind::Index(prefix, suffix) => {
self.manage_cond_expr(prefix);
self.manage_cond_expr(suffix);
}
- ExprKind::MethodCall(_, _,ref mut local_exprs, _) => {
- for local_expr in local_exprs.iter_mut() {
- self.manage_cond_expr(local_expr);
+ ExprKind::MethodCall(call) => {
+ for arg in &mut call.args {
+ self.manage_cond_expr(arg);
}
}
- ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => {
+ ExprKind::Path(_, Path { segments, .. }) if let [path_segment] = &segments[..] => {
let path_ident = path_segment.ident;
self.manage_initial_capture(expr, path_ident);
}
- ExprKind::Paren(ref mut local_expr) => {
+ ExprKind::Paren(local_expr) => {
self.manage_cond_expr(local_expr);
}
- ExprKind::Range(ref mut prefix, ref mut suffix, _) => {
- if let Some(ref mut elem) = prefix {
+ ExprKind::Range(prefix, suffix, _) => {
+ if let Some(elem) = prefix {
self.manage_cond_expr(elem);
}
- if let Some(ref mut elem) = suffix {
+ if let Some(elem) = suffix {
self.manage_cond_expr(elem);
}
}
- ExprKind::Repeat(ref mut local_expr, ref mut elem) => {
+ ExprKind::Repeat(local_expr, elem) => {
self.manage_cond_expr(local_expr);
self.manage_cond_expr(&mut elem.value);
}
- ExprKind::Struct(ref mut elem) => {
+ ExprKind::Struct(elem) => {
for field in &mut elem.fields {
self.manage_cond_expr(&mut field.expr);
}
- if let StructRest::Base(ref mut local_expr) = elem.rest {
+ if let StructRest::Base(local_expr) = &mut elem.rest {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Tup(ref mut local_exprs) => {
+ ExprKind::Tup(local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Unary(un_op, ref mut local_expr) => {
+ ExprKind::Unary(un_op, local_expr) => {
self.with_is_consumed_management(
matches!(un_op, UnOp::Neg | UnOp::Not),
|this| this.manage_cond_expr(local_expr)
@@ -296,17 +292,18 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Block(_, _)
| ExprKind::Box(_)
| ExprKind::Break(_, _)
- | ExprKind::Closure(_, _, _, _, _, _, _)
+ | ExprKind::Closure(_)
| ExprKind::ConstBlock(_)
| ExprKind::Continue(_)
| ExprKind::Err
| ExprKind::Field(_, _)
| ExprKind::ForLoop(_, _, _, _)
| ExprKind::If(_, _, _)
+ | ExprKind::IncludedBytes(..)
| ExprKind::InlineAsm(_)
| ExprKind::Let(_, _, _)
| ExprKind::Lit(_)
- | ExprKind::Loop(_, _)
+ | ExprKind::Loop(_, _, _)
| ExprKind::MacCall(_)
| ExprKind::Match(_, _)
| ExprKind::Path(_, _)
@@ -441,12 +438,12 @@ fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
fn expr_method_call(
cx: &ExtCtxt<'_>,
- path: PathSegment,
+ seg: PathSegment,
receiver: P<Expr>,
args: Vec<P<Expr>>,
span: Span,
) -> P<Expr> {
- cx.expr(span, ExprKind::MethodCall(path, receiver, args, span))
+ cx.expr(span, ExprKind::MethodCall(Box::new(MethodCall { seg, receiver, args, span })))
}
fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
index cb5359dd1..4e4cafc71 100644
--- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
@@ -34,12 +34,13 @@ impl MultiItemModifier for Expander {
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable,
+ _is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
- let attr = &ecx.attribute(meta_item.clone());
- validate_attr::check_builtin_attribute(
+ validate_attr::check_builtin_meta_item(
&ecx.sess.parse_sess,
- attr,
+ &meta_item,
+ ast::AttrStyle::Outer,
sym::cfg_accessible,
template,
);
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index 41f4e8c23..e2d71825d 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -1,6 +1,7 @@
use rustc_ast as ast;
use rustc_ast::tokenstream::TokenStream;
use rustc_expand::base::{self, DummyResult};
+use rustc_session::errors::report_lit_error;
use rustc_span::symbol::Symbol;
use std::string::String;
@@ -18,31 +19,34 @@ pub fn expand_concat(
let mut has_errors = false;
for e in es {
match e.kind {
- ast::ExprKind::Lit(ref lit) => match lit.kind {
- ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) => {
+ ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
+ Ok(ast::LitKind::Str(s, _) | ast::LitKind::Float(s, _)) => {
accumulator.push_str(s.as_str());
}
- ast::LitKind::Char(c) => {
+ Ok(ast::LitKind::Char(c)) => {
accumulator.push(c);
}
- ast::LitKind::Int(
- i,
- ast::LitIntType::Unsigned(_)
- | ast::LitIntType::Signed(_)
- | ast::LitIntType::Unsuffixed,
- ) => {
+ Ok(ast::LitKind::Int(i, _)) => {
accumulator.push_str(&i.to_string());
}
- ast::LitKind::Bool(b) => {
+ Ok(ast::LitKind::Bool(b)) => {
accumulator.push_str(&b.to_string());
}
- ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => {
+ Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
cx.span_err(e.span, "cannot concatenate a byte string literal");
+ has_errors = true;
+ }
+ Ok(ast::LitKind::Err) => {
+ has_errors = true;
}
- ast::LitKind::Err => {
+ Err(err) => {
+ report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span);
has_errors = true;
}
},
+ ast::ExprKind::IncludedBytes(..) => {
+ cx.span_err(e.span, "cannot concatenate a byte string literal")
+ }
ast::ExprKind::Err => {
has_errors = true;
}
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 66e86bf21..d1124145d 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -2,18 +2,22 @@ use rustc_ast as ast;
use rustc_ast::{ptr::P, tokenstream::TokenStream};
use rustc_errors::Applicability;
use rustc_expand::base::{self, DummyResult};
+use rustc_session::errors::report_lit_error;
+use rustc_span::Span;
/// Emits errors for literal expressions that are invalid inside and outside of an array.
-fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_nested: bool) {
- let ast::ExprKind::Lit(lit) = &expr.kind else {
- unreachable!();
- };
- match lit.kind {
- ast::LitKind::Char(_) => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate character literals");
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
+fn invalid_type_err(
+ cx: &mut base::ExtCtxt<'_>,
+ token_lit: ast::token::Lit,
+ span: Span,
+ is_nested: bool,
+) {
+ match ast::LitKind::from_token_lit(token_lit) {
+ Ok(ast::LitKind::Char(_)) => {
+ let mut err = cx.struct_span_err(span, "cannot concatenate character literals");
+ if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
- expr.span,
+ span,
"try using a byte character",
format!("b{}", snippet),
Applicability::MachineApplicable,
@@ -21,13 +25,13 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
.emit();
}
}
- ast::LitKind::Str(_, _) => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate string literals");
+ Ok(ast::LitKind::Str(_, _)) => {
+ let mut err = cx.struct_span_err(span, "cannot concatenate string literals");
// suggestion would be invalid if we are nested
if !is_nested {
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
+ if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
- expr.span,
+ span,
"try using a byte string",
format!("b{}", snippet),
Applicability::MachineApplicable,
@@ -36,18 +40,18 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
}
err.emit();
}
- ast::LitKind::Float(_, _) => {
- cx.span_err(expr.span, "cannot concatenate float literals");
+ Ok(ast::LitKind::Float(_, _)) => {
+ cx.span_err(span, "cannot concatenate float literals");
}
- ast::LitKind::Bool(_) => {
- cx.span_err(expr.span, "cannot concatenate boolean literals");
+ Ok(ast::LitKind::Bool(_)) => {
+ cx.span_err(span, "cannot concatenate boolean literals");
}
- ast::LitKind::Err => {}
- ast::LitKind::Int(_, _) if !is_nested => {
- let mut err = cx.struct_span_err(expr.span, "cannot concatenate numeric literals");
- if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
+ Ok(ast::LitKind::Err) => {}
+ Ok(ast::LitKind::Int(_, _)) if !is_nested => {
+ let mut err = cx.struct_span_err(span, "cannot concatenate numeric literals");
+ if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
- expr.span,
+ span,
"try wrapping the number in an array",
format!("[{}]", snippet),
Applicability::MachineApplicable,
@@ -55,17 +59,20 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
}
err.emit();
}
- ast::LitKind::Int(
+ Ok(ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
- ) => {
+ )) => {
assert!(val > u8::MAX.into()); // must be an error
- cx.span_err(expr.span, "numeric literal is out of bounds");
+ cx.span_err(span, "numeric literal is out of bounds");
+ }
+ Ok(ast::LitKind::Int(_, _)) => {
+ cx.span_err(span, "numeric literal is not a `u8`");
}
- ast::LitKind::Int(_, _) => {
- cx.span_err(expr.span, "numeric literal is not a `u8`");
+ Ok(ast::LitKind::ByteStr(_) | ast::LitKind::Byte(_)) => unreachable!(),
+ Err(err) => {
+ report_lit_error(&cx.sess.parse_sess, err, token_lit, span);
}
- _ => unreachable!(),
}
}
@@ -83,14 +90,14 @@ fn handle_array_element(
*has_errors = true;
None
}
- ast::ExprKind::Lit(ref lit) => match lit.kind {
- ast::LitKind::Int(
+ ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
+ Ok(ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
- ) if val <= u8::MAX.into() => Some(val as u8),
+ )) if val <= u8::MAX.into() => Some(val as u8),
- ast::LitKind::Byte(val) => Some(val),
- ast::LitKind::ByteStr(_) => {
+ Ok(ast::LitKind::Byte(val)) => Some(val),
+ Ok(ast::LitKind::ByteStr(_)) => {
if !*has_errors {
cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
.note("byte strings are treated as arrays of bytes")
@@ -102,12 +109,22 @@ fn handle_array_element(
}
_ => {
if !*has_errors {
- invalid_type_err(cx, expr, true);
+ invalid_type_err(cx, token_lit, expr.span, true);
}
*has_errors = true;
None
}
},
+ ast::ExprKind::IncludedBytes(..) => {
+ if !*has_errors {
+ cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
+ .note("byte strings are treated as arrays of bytes")
+ .help("try flattening the array")
+ .emit();
+ }
+ *has_errors = true;
+ None
+ }
_ => {
missing_literals.push(expr.span);
None
@@ -127,8 +144,8 @@ pub fn expand_concat_bytes(
let mut missing_literals = vec![];
let mut has_errors = false;
for e in es {
- match e.kind {
- ast::ExprKind::Array(ref exprs) => {
+ match &e.kind {
+ ast::ExprKind::Array(exprs) => {
for expr in exprs {
if let Some(elem) =
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
@@ -137,10 +154,10 @@ pub fn expand_concat_bytes(
}
}
}
- ast::ExprKind::Repeat(ref expr, ref count) => {
- if let ast::ExprKind::Lit(ast::Lit {
- kind: ast::LitKind::Int(count_val, _), ..
- }) = count.value.kind
+ ast::ExprKind::Repeat(expr, count) => {
+ if let ast::ExprKind::Lit(token_lit) = count.value.kind
+ && let Ok(ast::LitKind::Int(count_val, _)) =
+ ast::LitKind::from_token_lit(token_lit)
{
if let Some(elem) =
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
@@ -153,20 +170,23 @@ pub fn expand_concat_bytes(
cx.span_err(count.value.span, "repeat count is not a positive number");
}
}
- ast::ExprKind::Lit(ref lit) => match lit.kind {
- ast::LitKind::Byte(val) => {
+ &ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
+ Ok(ast::LitKind::Byte(val)) => {
accumulator.push(val);
}
- ast::LitKind::ByteStr(ref bytes) => {
+ Ok(ast::LitKind::ByteStr(ref bytes)) => {
accumulator.extend_from_slice(&bytes);
}
_ => {
if !has_errors {
- invalid_type_err(cx, &e, false);
+ invalid_type_err(cx, token_lit, e.span, false);
}
has_errors = true;
}
},
+ ast::ExprKind::IncludedBytes(bytes) => {
+ accumulator.extend_from_slice(bytes);
+ }
ast::ExprKind::Err => {
has_errors = true;
}
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index e0fb7affb..fa5a45730 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -1,7 +1,7 @@
use crate::cfg_eval::cfg_eval;
use rustc_ast as ast;
-use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
+use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_errors::{struct_span_err, Applicability};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate;
@@ -10,7 +10,7 @@ use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
-pub(crate) struct Expander;
+pub(crate) struct Expander(pub bool);
impl MultiItemModifier for Expander {
fn expand(
@@ -19,6 +19,7 @@ impl MultiItemModifier for Expander {
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable,
+ _: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
let sess = ecx.sess;
if report_bad_target(sess, &item, span) {
@@ -32,46 +33,48 @@ impl MultiItemModifier for Expander {
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
let template =
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
- let attr =
- attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone());
- validate_attr::check_builtin_attribute(
+ validate_attr::check_builtin_meta_item(
&sess.parse_sess,
- &attr,
+ &meta_item,
+ ast::AttrStyle::Outer,
sym::derive,
template,
);
- let mut resolutions: Vec<_> = attr
- .meta_item_list()
- .unwrap_or_default()
- .into_iter()
- .filter_map(|nested_meta| match nested_meta {
- NestedMetaItem::MetaItem(meta) => Some(meta),
- NestedMetaItem::Literal(lit) => {
- // Reject `#[derive("Debug")]`.
- report_unexpected_literal(sess, &lit);
- None
- }
- })
- .map(|meta| {
- // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
- report_path_args(sess, &meta);
- meta.path
- })
- .map(|path| (path, dummy_annotatable(), None))
- .collect();
+ let mut resolutions = match &meta_item.kind {
+ MetaItemKind::List(list) => {
+ list.iter()
+ .filter_map(|nested_meta| match nested_meta {
+ NestedMetaItem::MetaItem(meta) => Some(meta),
+ NestedMetaItem::Lit(lit) => {
+ // Reject `#[derive("Debug")]`.
+ report_unexpected_meta_item_lit(sess, &lit);
+ None
+ }
+ })
+ .map(|meta| {
+ // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
+ // paths.
+ report_path_args(sess, &meta);
+ meta.path.clone()
+ })
+ .map(|path| (path, dummy_annotatable(), None, self.0))
+ .collect()
+ }
+ _ => vec![],
+ };
// Do not configure or clone items unless necessary.
match &mut resolutions[..] {
[] => {}
- [(_, first_item, _), others @ ..] => {
+ [(_, first_item, ..), others @ ..] => {
*first_item = cfg_eval(
sess,
features,
item.clone(),
ecx.current_expansion.lint_node_id,
);
- for (_, item, _) in others {
+ for (_, item, _, _) in others {
*item = first_item.clone();
}
}
@@ -126,7 +129,7 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
bad_target
}
-fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) {
+fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
let help_msg = match lit.token_lit.kind {
token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => {
format!("try using `#[derive({})]`", lit.token_lit.symbol)
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 7bd344467..240167146 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -1,4 +1,3 @@
-use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::deriving::path_std;
@@ -12,16 +11,17 @@ pub fn expand_deriving_copy(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
let trait_def = TraitDef {
span,
path: path_std!(marker::Copy),
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: true,
methods: Vec::new(),
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push);
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index fa8685f5f..d59b3b8c8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -14,6 +14,7 @@ pub fn expand_deriving_clone(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
// The simple form is `fn clone(&self) -> Self { *self }`, possibly with
// some additional `AssertParamIsClone` assertions.
@@ -31,10 +32,10 @@ pub fn expand_deriving_clone(
let bounds;
let substructure;
let is_simple;
- match *item {
- Annotatable::Item(ref annitem) => match annitem.kind {
- ItemKind::Struct(_, Generics { ref params, .. })
- | ItemKind::Enum(_, Generics { ref params, .. }) => {
+ match item {
+ Annotatable::Item(annitem) => match &annitem.kind {
+ ItemKind::Struct(_, Generics { params, .. })
+ | ItemKind::Enum(_, Generics { params, .. }) => {
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
if has_derive_copy
@@ -67,14 +68,12 @@ pub fn expand_deriving_clone(
_ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
}
- let inline = cx.meta_word(span, sym::inline);
- let attrs = thin_vec![cx.attribute(inline)];
+ let attrs = thin_vec![cx.attr_word(sym::inline, span)];
let trait_def = TraitDef {
span,
path: path_std!(clone::Clone),
skip_path_as_bound: false,
additional_bounds: bounds,
- generics: Bounds::empty(),
supports_unions: true,
methods: vec![MethodDef {
name: sym::clone,
@@ -87,6 +86,7 @@ pub fn expand_deriving_clone(
combine_substructure: substructure,
}],
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand_ext(cx, mitem, item, push, is_simple)
@@ -166,13 +166,13 @@ fn cs_clone(
};
let vdata;
- match *substr.fields {
- Struct(vdata_, ref af) => {
+ match substr.fields {
+ Struct(vdata_, af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident]);
all_fields = af;
- vdata = vdata_;
+ vdata = *vdata_;
}
- EnumMatching(.., variant, ref af) => {
+ EnumMatching(.., variant, af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]);
all_fields = af;
vdata = &variant.data;
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index eab67b0d3..f861d47ed 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -5,7 +5,7 @@ use crate::deriving::path_std;
use rustc_ast::{self as ast, MetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::symbol::sym;
use rustc_span::Span;
use thin_vec::thin_vec;
@@ -15,19 +15,19 @@ pub fn expand_deriving_eq(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
let span = cx.with_def_site_ctxt(span);
- let inline = cx.meta_word(span, sym::inline);
- let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
- let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
- let no_coverage = cx.meta_word(span, sym::no_coverage);
- let attrs = thin_vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)];
+ let attrs = thin_vec![
+ cx.attr_word(sym::inline, span),
+ cx.attr_nested_word(sym::doc, sym::hidden, span),
+ cx.attr_word(sym::no_coverage, span)
+ ];
let trait_def = TraitDef {
span,
path: path_std!(cmp::Eq),
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: true,
methods: vec![MethodDef {
name: sym::assert_receiver_is_total_eq,
@@ -42,6 +42,7 @@ pub fn expand_deriving_eq(
})),
}],
associated_types: Vec::new(),
+ is_const,
};
super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push);
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 7f117981a..96d18c7af 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -13,15 +13,14 @@ pub fn expand_deriving_ord(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
- let inline = cx.meta_word(span, sym::inline);
- let attrs = thin_vec![cx.attribute(inline)];
+ let attrs = thin_vec![cx.attr_word(sym::inline, span)];
let trait_def = TraitDef {
span,
path: path_std!(cmp::Ord),
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: false,
methods: vec![MethodDef {
name: sym::cmp,
@@ -34,6 +33,7 @@ pub fn expand_deriving_ord(
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
}],
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push)
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index 236cbccaf..7f95551fc 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -14,6 +14,7 @@ pub fn expand_deriving_partial_eq(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
let base = true;
@@ -67,8 +68,7 @@ pub fn expand_deriving_partial_eq(
// No need to generate `ne`, the default suffices, and not generating it is
// faster.
- let inline = cx.meta_word(span, sym::inline);
- let attrs = thin_vec![cx.attribute(inline)];
+ let attrs = thin_vec![cx.attr_word(sym::inline, span)];
let methods = vec![MethodDef {
name: sym::eq,
generics: Bounds::empty(),
@@ -85,10 +85,10 @@ pub fn expand_deriving_partial_eq(
path: path_std!(cmp::PartialEq),
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: false,
methods,
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push)
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 4173403a1..5c4e5b7f8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -13,13 +13,13 @@ pub fn expand_deriving_partial_ord(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
let ordering_ty = Path(path_std!(cmp::Ordering));
let ret_ty =
Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
- let inline = cx.meta_word(span, sym::inline);
- let attrs = thin_vec![cx.attribute(inline)];
+ let attrs = thin_vec![cx.attr_word(sym::inline, span)];
let partial_cmp_def = MethodDef {
name: sym::partial_cmp,
@@ -39,10 +39,10 @@ pub fn expand_deriving_partial_ord(
path: path_std!(cmp::PartialOrd),
skip_path_as_bound: false,
additional_bounds: vec![],
- generics: Bounds::empty(),
supports_unions: false,
methods: vec![partial_cmp_def],
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push)
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 2cf614ed9..544d971b2 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -13,6 +13,7 @@ pub fn expand_deriving_debug(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
// &mut ::std::fmt::Formatter
let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut);
@@ -22,7 +23,6 @@ pub fn expand_deriving_debug(
path: path_std!(fmt::Debug),
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: false,
methods: vec![MethodDef {
name: sym::fmt,
@@ -37,6 +37,7 @@ pub fn expand_deriving_debug(
})),
}],
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push)
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index d669f6168..62af02c2b 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -16,6 +16,7 @@ pub fn expand_deriving_rustc_decodable(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
let krate = sym::rustc_serialize;
let typaram = sym::__D;
@@ -25,7 +26,6 @@ pub fn expand_deriving_rustc_decodable(
path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global),
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: false,
methods: vec![MethodDef {
name: sym::decode,
@@ -55,6 +55,7 @@ pub fn expand_deriving_rustc_decodable(
})),
}],
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push)
@@ -77,11 +78,11 @@ fn decodable_substructure(
let blkarg = Ident::new(sym::_d, trait_span);
let blkdecoder = cx.expr_ident(trait_span, blkarg);
- let expr = match *substr.fields {
- StaticStruct(_, ref summary) => {
- let nfields = match *summary {
- Unnamed(ref fields, _) => fields.len(),
- Named(ref fields) => fields.len(),
+ let expr = match substr.fields {
+ StaticStruct(_, summary) => {
+ let nfields = match summary {
+ Unnamed(fields, _) => fields.len(),
+ Named(fields) => fields.len(),
};
let fn_read_struct_field_path: Vec<_> =
cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct_field]);
@@ -118,7 +119,7 @@ fn decodable_substructure(
],
)
}
- StaticEnum(_, ref fields) => {
+ StaticEnum(_, fields) => {
let variant = Ident::new(sym::i, trait_span);
let mut arms = Vec::with_capacity(fields.len() + 1);
@@ -193,10 +194,10 @@ fn decode_static_fields<F>(
where
F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>,
{
- match *fields {
- Unnamed(ref fields, is_tuple) => {
+ match fields {
+ Unnamed(fields, is_tuple) => {
let path_expr = cx.expr_path(outer_pat_path);
- if !is_tuple {
+ if !*is_tuple {
path_expr
} else {
let fields = fields
@@ -208,7 +209,7 @@ where
cx.expr_call(trait_span, path_expr, fields)
}
}
- Named(ref fields) => {
+ Named(fields) => {
// use the field's span to get nicer error messages.
let fields = fields
.iter()
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 17df9fb27..eb66c4a69 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -16,17 +16,16 @@ pub fn expand_deriving_default(
mitem: &ast::MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
- let inline = cx.meta_word(span, sym::inline);
- let attrs = thin_vec![cx.attribute(inline)];
+ let attrs = thin_vec![cx.attr_word(sym::inline, span)];
let trait_def = TraitDef {
span,
path: Path::new(vec![kw::Default, sym::Default]),
skip_path_as_bound: has_a_default_variant(item),
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: false,
methods: vec![MethodDef {
name: kw::Default,
@@ -47,6 +46,7 @@ pub fn expand_deriving_default(
})),
}],
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push)
}
@@ -62,15 +62,12 @@ fn default_struct_substructure(
let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
let expr = match summary {
- Unnamed(ref fields, is_tuple) => {
- if !is_tuple {
- cx.expr_ident(trait_span, substr.type_ident)
- } else {
- let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
- cx.expr_call_ident(trait_span, substr.type_ident, exprs)
- }
+ Unnamed(_, false) => cx.expr_ident(trait_span, substr.type_ident),
+ Unnamed(fields, true) => {
+ let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
+ cx.expr_call_ident(trait_span, substr.type_ident, exprs)
}
- Named(ref fields) => {
+ Named(fields) => {
let default_fields = fields
.iter()
.map(|&(ident, span)| cx.field_imm(span, ident, default_call(span)))
@@ -145,7 +142,7 @@ fn extract_default_variant<'a>(
let suggestion = default_variants
.iter()
.filter_map(|v| {
- if v.ident == variant.ident {
+ if v.span == variant.span {
None
} else {
Some((cx.sess.find_by_name(&v.attrs, kw::Default)?.span, String::new()))
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index f83f58b97..68bc0ff2e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -100,6 +100,7 @@ pub fn expand_deriving_rustc_encodable(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
let krate = sym::rustc_serialize;
let typaram = sym::__S;
@@ -109,7 +110,6 @@ pub fn expand_deriving_rustc_encodable(
path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global),
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: false,
methods: vec![MethodDef {
name: sym::encode,
@@ -139,6 +139,7 @@ pub fn expand_deriving_rustc_encodable(
})),
}],
associated_types: Vec::new(),
+ is_const,
};
trait_def.expand(cx, mitem, item, push)
@@ -163,8 +164,8 @@ fn encodable_substructure(
],
));
- match *substr.fields {
- Struct(_, ref fields) => {
+ match substr.fields {
+ Struct(_, fields) => {
let fn_emit_struct_field_path =
cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
let mut stmts = Vec::new();
@@ -223,7 +224,7 @@ fn encodable_substructure(
BlockOrExpr::new_expr(expr)
}
- EnumMatching(idx, _, variant, ref fields) => {
+ EnumMatching(idx, _, variant, fields) => {
// We're not generating an AST that the borrow checker is expecting,
// so we need to generate a unique local variable to take the
// mutable loan out on, otherwise we get conflicts which don't
@@ -273,7 +274,7 @@ fn encodable_substructure(
vec![
blkencoder,
name,
- cx.expr_usize(trait_span, idx),
+ cx.expr_usize(trait_span, *idx),
cx.expr_usize(trait_span, fields.len()),
blk,
],
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 16ee3aa89..beac591bf 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -171,7 +171,7 @@ use rustc_ast::{GenericArg, GenericParamKind, VariantData};
use rustc_attr as attr;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use std::cell::RefCell;
use std::iter;
use std::ops::Not;
@@ -195,15 +195,14 @@ pub struct TraitDef<'a> {
/// other than the current trait
pub additional_bounds: Vec<Ty>,
- /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder`
- pub generics: Bounds,
-
/// Can this trait be derived for unions?
pub supports_unions: bool,
pub methods: Vec<MethodDef<'a>>,
pub associated_types: Vec<(Ident, Ty)>,
+
+ pub is_const: bool,
}
pub struct MethodDef<'a> {
@@ -301,12 +300,12 @@ struct TypeParameter {
ty: P<ast::Ty>,
}
-// The code snippets built up for derived code are sometimes used as blocks
-// (e.g. in a function body) and sometimes used as expressions (e.g. in a match
-// arm). This structure avoids committing to either form until necessary,
-// avoiding the insertion of any unnecessary blocks.
-//
-// The statements come before the expression.
+/// The code snippets built up for derived code are sometimes used as blocks
+/// (e.g. in a function body) and sometimes used as expressions (e.g. in a match
+/// arm). This structure avoids committing to either form until necessary,
+/// avoiding the insertion of any unnecessary blocks.
+///
+/// The statements come before the expression.
pub struct BlockOrExpr(Vec<ast::Stmt>, Option<P<Expr>>);
impl BlockOrExpr {
@@ -370,15 +369,14 @@ fn find_type_parameters(
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
fn visit_ty(&mut self, ty: &'a ast::Ty) {
- if let ast::TyKind::Path(_, ref path) = ty.kind {
- if let Some(segment) = path.segments.first() {
- if self.ty_param_names.contains(&segment.ident.name) {
- self.type_params.push(TypeParameter {
- bound_generic_params: self.bound_generic_params_stack.clone(),
- ty: P(ty.clone()),
- });
- }
- }
+ if let ast::TyKind::Path(_, path) = &ty.kind
+ && let Some(segment) = path.segments.first()
+ && self.ty_param_names.contains(&segment.ident.name)
+ {
+ self.type_params.push(TypeParameter {
+ bound_generic_params: self.bound_generic_params_stack.clone(),
+ ty: P(ty.clone()),
+ });
}
visit::walk_ty(self, ty)
@@ -429,8 +427,8 @@ impl<'a> TraitDef<'a> {
push: &mut dyn FnMut(Annotatable),
from_scratch: bool,
) {
- match *item {
- Annotatable::Item(ref item) => {
+ match item {
+ Annotatable::Item(item) => {
let is_packed = item.attrs.iter().any(|attr| {
for r in attr::find_repr_attrs(&cx.sess, attr) {
if let attr::ReprPacked(_) = r {
@@ -439,38 +437,37 @@ impl<'a> TraitDef<'a> {
}
false
});
- let has_no_type_params = match item.kind {
- ast::ItemKind::Struct(_, ref generics)
- | ast::ItemKind::Enum(_, ref generics)
- | ast::ItemKind::Union(_, ref generics) => !generics
+ let has_no_type_params = match &item.kind {
+ ast::ItemKind::Struct(_, generics)
+ | ast::ItemKind::Enum(_, generics)
+ | ast::ItemKind::Union(_, generics) => !generics
.params
.iter()
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
_ => unreachable!(),
};
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
- let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id);
+ let copy_fields =
+ is_packed && has_no_type_params && cx.resolver.has_derive_copy(container_id);
- let newitem = match item.kind {
- ast::ItemKind::Struct(ref struct_def, ref generics) => self.expand_struct_def(
+ let newitem = match &item.kind {
+ ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
cx,
&struct_def,
item.ident,
generics,
from_scratch,
- is_packed,
- always_copy,
+ copy_fields,
),
- ast::ItemKind::Enum(ref enum_def, ref generics) => {
- // We ignore `is_packed`/`always_copy` here, because
- // `repr(packed)` enums cause an error later on.
+ ast::ItemKind::Enum(enum_def, generics) => {
+ // We ignore `is_packed` here, because `repr(packed)`
+ // enums cause an error later on.
//
// This can only cause further compilation errors
- // downstream in blatantly illegal code, so it
- // is fine.
+ // downstream in blatantly illegal code, so it is fine.
self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
}
- ast::ItemKind::Union(ref struct_def, ref generics) => {
+ ast::ItemKind::Union(struct_def, generics) => {
if self.supports_unions {
self.expand_struct_def(
cx,
@@ -478,8 +475,7 @@ impl<'a> TraitDef<'a> {
item.ident,
generics,
from_scratch,
- is_packed,
- always_copy,
+ copy_fields,
)
} else {
cx.span_err(mitem.span, "this trait cannot be derived for unions");
@@ -581,19 +577,21 @@ impl<'a> TraitDef<'a> {
})
});
- let Generics { mut params, mut where_clause, .. } =
- self.generics.to_generics(cx, self.span, type_ident, generics);
+ let mut where_clause = ast::WhereClause::default();
where_clause.span = generics.where_clause.span;
let ctxt = self.span.ctxt();
let span = generics.span.with_ctxt(ctxt);
// Create the generic parameters
- params.extend(generics.params.iter().map(|param| match &param.kind {
- GenericParamKind::Lifetime { .. } => param.clone(),
- GenericParamKind::Type { .. } => {
- // I don't think this can be moved out of the loop, since
- // a GenericBound requires an ast id
- let bounds: Vec<_> =
+ let params: Vec<_> = generics
+ .params
+ .iter()
+ .map(|param| match &param.kind {
+ GenericParamKind::Lifetime { .. } => param.clone(),
+ GenericParamKind::Type { .. } => {
+ // I don't think this can be moved out of the loop, since
+ // a GenericBound requires an ast id
+ let bounds: Vec<_> =
// extra restrictions on the generics parameters to the
// type being derived upon
self.additional_bounds.iter().map(|p| {
@@ -606,21 +604,22 @@ impl<'a> TraitDef<'a> {
param.bounds.iter().cloned()
).collect();
- cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None)
- }
- GenericParamKind::Const { ty, kw_span, .. } => {
- let const_nodefault_kind = GenericParamKind::Const {
- ty: ty.clone(),
- kw_span: kw_span.with_ctxt(ctxt),
-
- // We can't have default values inside impl block
- default: None,
- };
- let mut param_clone = param.clone();
- param_clone.kind = const_nodefault_kind;
- param_clone
- }
- }));
+ cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None)
+ }
+ GenericParamKind::Const { ty, kw_span, .. } => {
+ let const_nodefault_kind = GenericParamKind::Const {
+ ty: ty.clone(),
+ kw_span: kw_span.with_ctxt(ctxt),
+
+ // We can't have default values inside impl block
+ default: None,
+ };
+ let mut param_clone = param.clone();
+ param_clone.kind = const_nodefault_kind;
+ param_clone
+ }
+ })
+ .collect();
// and similarly for where clauses
where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
@@ -663,12 +662,11 @@ impl<'a> TraitDef<'a> {
for field_ty_param in field_ty_params {
// if we have already handled this type, skip it
- if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind {
- if p.segments.len() == 1
- && ty_param_names.contains(&p.segments[0].ident.name)
- {
- continue;
- };
+ if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
+ && let [sole_segment] = &*p.segments
+ && ty_param_names.contains(&sole_segment.ident.name)
+ {
+ continue;
}
let mut bounds: Vec<_> = self
.additional_bounds
@@ -718,7 +716,7 @@ impl<'a> TraitDef<'a> {
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
let self_type = cx.ty_path(path);
- let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
+ let attr = cx.attr_word(sym::automatically_derived, self.span);
let attrs = thin_vec![attr];
let opt_trait_ref = Some(trait_ref);
@@ -730,7 +728,7 @@ impl<'a> TraitDef<'a> {
unsafety: ast::Unsafe::No,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
- constness: ast::Const::No,
+ constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
generics: trait_generics,
of_trait: opt_trait_ref,
self_ty: self_type,
@@ -746,8 +744,7 @@ impl<'a> TraitDef<'a> {
type_ident: Ident,
generics: &Generics,
from_scratch: bool,
- is_packed: bool,
- always_copy: bool,
+ copy_fields: bool,
) -> P<ast::Item> {
let field_tys: Vec<P<ast::Ty>> =
struct_def.fields().iter().map(|field| field.ty.clone()).collect();
@@ -775,8 +772,7 @@ impl<'a> TraitDef<'a> {
type_ident,
&selflike_args,
&nonselflike_args,
- is_packed,
- always_copy,
+ copy_fields,
)
};
@@ -1014,19 +1010,9 @@ impl<'a> MethodDef<'a> {
/// }
/// }
/// ```
- /// If the struct doesn't impl `Copy`, we use let-destructuring with `ref`:
- /// ```
- /// # struct A { x: u8, y: u8 }
- /// impl PartialEq for A {
- /// fn eq(&self, other: &A) -> bool {
- /// let Self { x: ref __self_0_0, y: ref __self_0_1 } = *self;
- /// let Self { x: ref __self_1_0, y: ref __self_1_1 } = *other;
- /// *__self_0_0 == *__self_1_0 && *__self_0_1 == *__self_1_1
- /// }
- /// }
- /// ```
- /// This latter case only works if the fields match the alignment required
- /// by the `packed(N)` attribute. (We'll get errors later on if not.)
+ /// If the struct doesn't impl `Copy`, we use the normal `&self.x`. This
+ /// only works if the fields match the alignment required by the
+ /// `packed(N)` attribute. (We'll get errors later on if not.)
fn expand_struct_method_body<'b>(
&self,
cx: &mut ExtCtxt<'_>,
@@ -1035,54 +1021,19 @@ impl<'a> MethodDef<'a> {
type_ident: Ident,
selflike_args: &[P<Expr>],
nonselflike_args: &[P<Expr>],
- is_packed: bool,
- always_copy: bool,
+ copy_fields: bool,
) -> BlockOrExpr {
- let span = trait_.span;
assert!(selflike_args.len() == 1 || selflike_args.len() == 2);
- let mk_body = |cx, selflike_fields| {
- self.call_substructure_method(
- cx,
- trait_,
- type_ident,
- nonselflike_args,
- &Struct(struct_def, selflike_fields),
- )
- };
-
- if !is_packed {
- let selflike_fields =
- trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, false);
- mk_body(cx, selflike_fields)
- } else if always_copy {
- let selflike_fields =
- trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, true);
- mk_body(cx, selflike_fields)
- } else {
- // Neither packed nor copy. Need to use ref patterns.
- let prefixes: Vec<_> =
- (0..selflike_args.len()).map(|i| format!("__self_{}", i)).collect();
- let addr_of = always_copy;
- let selflike_fields =
- trait_.create_struct_pattern_fields(cx, struct_def, &prefixes, addr_of);
- let mut body = mk_body(cx, selflike_fields);
-
- let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]);
- let by_ref = ByRef::from(is_packed && !always_copy);
- let patterns =
- trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, by_ref);
-
- // Do the let-destructuring.
- let mut stmts: Vec<_> = iter::zip(selflike_args, patterns)
- .map(|(selflike_arg_expr, pat)| {
- let selflike_arg_expr = cx.expr_deref(span, selflike_arg_expr.clone());
- cx.stmt_let_pat(span, pat, selflike_arg_expr)
- })
- .collect();
- stmts.extend(std::mem::take(&mut body.0));
- BlockOrExpr(stmts, body.1)
- }
+ let selflike_fields =
+ trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, copy_fields);
+ self.call_substructure_method(
+ cx,
+ trait_,
+ type_ident,
+ nonselflike_args,
+ &Struct(struct_def, selflike_fields),
+ )
}
fn expand_static_struct_method_body(
@@ -1252,9 +1203,7 @@ impl<'a> MethodDef<'a> {
// A single arm has form (&VariantK, &VariantK, ...) => BodyK
// (see "Final wrinkle" note below for why.)
- let addr_of = false; // because enums can't be repr(packed)
- let fields =
- trait_.create_struct_pattern_fields(cx, &variant.data, &prefixes, addr_of);
+ let fields = trait_.create_struct_pattern_fields(cx, &variant.data, &prefixes);
let sp = variant.span.with_ctxt(trait_.span.ctxt());
let variant_path = cx.path(sp, vec![type_ident, variant.ident]);
@@ -1517,15 +1466,13 @@ impl<'a> TraitDef<'a> {
cx: &mut ExtCtxt<'_>,
struct_def: &'a VariantData,
prefixes: &[String],
- addr_of: bool,
) -> Vec<FieldInfo> {
self.create_fields(struct_def, |i, _struct_field, sp| {
prefixes
.iter()
.map(|prefix| {
let ident = self.mk_pattern_ident(prefix, i);
- let expr = cx.expr_path(cx.path_ident(sp, ident));
- if addr_of { cx.expr_addr_of(sp, expr) } else { expr }
+ cx.expr_path(cx.path_ident(sp, ident))
})
.collect()
})
@@ -1536,7 +1483,7 @@ impl<'a> TraitDef<'a> {
cx: &mut ExtCtxt<'_>,
selflike_args: &[P<Expr>],
struct_def: &'a VariantData,
- copy: bool,
+ copy_fields: bool,
) -> Vec<FieldInfo> {
self.create_fields(struct_def, |i, struct_field, sp| {
selflike_args
@@ -1555,7 +1502,7 @@ impl<'a> TraitDef<'a> {
}),
),
);
- if copy {
+ if copy_fields {
field_expr = cx.expr_block(
cx.block(struct_field.span, vec![cx.stmt_expr(field_expr)]),
);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
index 36e2e2930..eaa488190 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
@@ -115,7 +115,7 @@ impl Ty {
self_ty: Ident,
generics: &Generics,
) -> ast::Path {
- match *self {
+ match self {
Self_ => {
let params: Vec<_> = generics
.params
@@ -135,7 +135,7 @@ impl Ty {
cx.path_all(span, false, vec![self_ty], params)
}
- Path(ref p) => p.to_path(cx, span, self_ty, generics),
+ Path(p) => p.to_path(cx, span, self_ty, generics),
Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"),
Unit => cx.span_bug(span, "unit in a path in generic `derive`"),
}
@@ -180,10 +180,7 @@ impl Bounds {
let params = self
.bounds
.iter()
- .map(|t| {
- let (name, ref bounds) = *t;
- mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)
- })
+ .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, &bounds, self_ty, self_generics))
.collect();
Generics {
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 6e9d5f08b..c136bb714 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -13,6 +13,7 @@ pub fn expand_deriving_hash(
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
+ is_const: bool,
) {
let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std);
@@ -24,7 +25,6 @@ pub fn expand_deriving_hash(
path,
skip_path_as_bound: false,
additional_bounds: Vec::new(),
- generics: Bounds::empty(),
supports_unions: false,
methods: vec![MethodDef {
name: sym::hash,
@@ -39,6 +39,7 @@ pub fn expand_deriving_hash(
})),
}],
associated_types: Vec::new(),
+ is_const,
};
hash_trait_def.expand(cx, mitem, item, push);
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index ee346047a..de657e4e6 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -38,9 +38,10 @@ pub mod partial_ord;
pub mod generic;
-pub(crate) struct BuiltinDerive(
- pub(crate) fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)),
-);
+pub(crate) type BuiltinDeriveFn =
+ fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool);
+
+pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn);
impl MultiItemModifier for BuiltinDerive {
fn expand(
@@ -49,6 +50,7 @@ impl MultiItemModifier for BuiltinDerive {
span: Span,
meta_item: &MetaItem,
item: Annotatable,
+ is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
// FIXME: Built-in derives often forget to give spans contexts,
// so we are doing it here in a centralized way.
@@ -57,21 +59,28 @@ impl MultiItemModifier for BuiltinDerive {
match item {
Annotatable::Stmt(stmt) => {
if let ast::StmtKind::Item(item) = stmt.into_inner().kind {
- (self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| {
- // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
- // to the function
- items.push(Annotatable::Stmt(P(ast::Stmt {
- id: ast::DUMMY_NODE_ID,
- kind: ast::StmtKind::Item(a.expect_item()),
- span,
- })));
- });
+ (self.0)(
+ ecx,
+ span,
+ meta_item,
+ &Annotatable::Item(item),
+ &mut |a| {
+ // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
+ // to the function
+ items.push(Annotatable::Stmt(P(ast::Stmt {
+ id: ast::DUMMY_NODE_ID,
+ kind: ast::StmtKind::Item(a.expect_item()),
+ span,
+ })));
+ },
+ is_derive_const,
+ );
} else {
unreachable!("should have already errored on non-item statement")
}
}
_ => {
- (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
+ (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const);
}
}
ExpandResult::Ready(items)
@@ -116,12 +125,12 @@ fn inject_impl_of_structural_trait(
structural_path: generic::ty::Path,
push: &mut dyn FnMut(Annotatable),
) {
- let Annotatable::Item(ref item) = *item else {
+ let Annotatable::Item(item) = item else {
unreachable!();
};
- let generics = match item.kind {
- ItemKind::Struct(_, ref generics) | ItemKind::Enum(_, ref generics) => generics,
+ let generics = match &item.kind {
+ ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics,
// Do not inject `impl Structural for Union`. (`PartialEq` does not
// support unions, so we will see error downstream.)
ItemKind::Union(..) => return,
@@ -179,7 +188,7 @@ fn inject_impl_of_structural_trait(
.cloned(),
);
// Mark as `automatically_derived` to avoid some silly lints.
- attrs.push(cx.attribute(cx.meta_word(span, sym::automatically_derived)));
+ attrs.push(cx.attr_word(sym::automatically_derived, span));
let newitem = cx.item(
span,
diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs
index 3f1a8b3bc..b2a21611d 100644
--- a/compiler/rustc_builtin_macros/src/edition_panic.rs
+++ b/compiler/rustc_builtin_macros/src/edition_panic.rs
@@ -6,15 +6,15 @@ use rustc_span::edition::Edition;
use rustc_span::symbol::sym;
use rustc_span::Span;
-// This expands to either
-// - `$crate::panic::panic_2015!(...)` or
-// - `$crate::panic::panic_2021!(...)`
-// depending on the edition.
-//
-// This is used for both std::panic!() and core::panic!().
-//
-// `$crate` will refer to either the `std` or `core` crate depending on which
-// one we're expanding from.
+/// This expands to either
+/// - `$crate::panic::panic_2015!(...)` or
+/// - `$crate::panic::panic_2021!(...)`
+/// depending on the edition.
+///
+/// This is used for both std::panic!() and core::panic!().
+///
+/// `$crate` will refer to either the `std` or `core` crate depending on which
+/// one we're expanding from.
pub fn expand_panic<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
@@ -24,10 +24,10 @@ pub fn expand_panic<'cx>(
expand(mac, cx, sp, tts)
}
-// This expands to either
-// - `$crate::panic::unreachable_2015!(...)` or
-// - `$crate::panic::unreachable_2021!(...)`
-// depending on the edition.
+/// This expands to either
+/// - `$crate::panic::unreachable_2015!(...)` or
+/// - `$crate::panic::unreachable_2021!(...)`
+/// depending on the edition.
pub fn expand_unreachable<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
@@ -58,11 +58,11 @@ fn expand<'cx>(
.collect(),
tokens: None,
},
- args: P(MacArgs::Delimited(
- DelimSpan::from_single(sp),
- MacDelimiter::Parenthesis,
- tts,
- )),
+ args: P(DelimArgs {
+ dspan: DelimSpan::from_single(sp),
+ delim: MacDelimiter::Parenthesis,
+ tokens: tts,
+ }),
prior_type_ascription: None,
})),
),
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index b8828fa67..0b4e545f7 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
tts: TokenStream,
) -> Box<dyn base::MacResult + 'cx> {
let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
- Some(ref exprs) if exprs.is_empty() => {
+ Some(exprs) if exprs.is_empty() => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return DummyResult::any(sp);
}
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index ecd16736e..6f7fc3a95 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -13,23 +13,23 @@ pub(crate) mod printf {
impl<'a> Substitution<'a> {
pub fn as_str(&self) -> &str {
- match *self {
- Substitution::Format(ref fmt) => fmt.span,
+ match self {
+ Substitution::Format(fmt) => fmt.span,
Substitution::Escape(_) => "%%",
}
}
pub fn position(&self) -> Option<InnerSpan> {
- match *self {
- Substitution::Format(ref fmt) => Some(fmt.position),
- Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
+ match self {
+ Substitution::Format(fmt) => Some(fmt.position),
+ &Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
}
}
pub fn set_position(&mut self, start: usize, end: usize) {
match self {
- Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end),
- Substitution::Escape(ref mut pos) => *pos = (start, end),
+ Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end),
+ Substitution::Escape(pos) => *pos = (start, end),
}
}
@@ -38,8 +38,8 @@ pub(crate) mod printf {
/// This ignores cases where the substitution does not have an exact equivalent, or where
/// the substitution would be unnecessary.
pub fn translate(&self) -> Result<String, Option<String>> {
- match *self {
- Substitution::Format(ref fmt) => fmt.translate(),
+ match self {
+ Substitution::Format(fmt) => fmt.translate(),
Substitution::Escape(_) => Err(None),
}
}
@@ -635,23 +635,17 @@ pub mod shell {
}
pub fn position(&self) -> Option<InnerSpan> {
- match self {
- Substitution::Ordinal(_, pos)
- | Substitution::Name(_, pos)
- | Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)),
- }
+ let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+ Some(InnerSpan::new(pos.0, pos.1))
}
pub fn set_position(&mut self, start: usize, end: usize) {
- match self {
- Substitution::Ordinal(_, ref mut pos)
- | Substitution::Name(_, ref mut pos)
- | Substitution::Escape(ref mut pos) => *pos = (start, end),
- }
+ let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+ *pos = (start, end);
}
pub fn translate(&self) -> Result<String, Option<String>> {
- match *self {
+ match self {
Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Escape(_) => Err(None),
diff --git a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
index fc7442470..df773910d 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
@@ -100,7 +100,7 @@ fn test_iter() {
let s = "The %d'th word %% is: `%.*s` %!\n";
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
assert_eq!(
- subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
+ subs.iter().map(Option::as_deref).collect::<Vec<_>>(),
vec![Some("{}"), None, Some("{:.*}"), None]
);
}
diff --git a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
index f5f82732f..93a7afcd6 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
@@ -39,7 +39,7 @@ fn test_iter() {
let s = "The $0'th word $$ is: `$WORD` $!\n";
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
assert_eq!(
- subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
+ subs.iter().map(Option::as_deref).collect::<Vec<_>>(),
vec![Some("{0}"), None, Some("{WORD}")]
);
}
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 45b9b8ab6..41531580c 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -20,27 +20,23 @@ pub fn expand(
check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
let orig_item = item.clone();
- let not_static = || {
- ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
- vec![orig_item.clone()]
- };
// Allow using `#[global_allocator]` on an item statement
// FIXME - if we get deref patterns, use them to reduce duplication here
- let (item, is_stmt, ty_span) = match &item {
- Annotatable::Item(item) => match item.kind {
- ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)),
- _ => return not_static(),
- },
- Annotatable::Stmt(stmt) => match &stmt.kind {
- StmtKind::Item(item_) => match item_.kind {
- ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)),
- _ => return not_static(),
- },
- _ => return not_static(),
- },
- _ => return not_static(),
- };
+ let (item, is_stmt, ty_span) =
+ if let Annotatable::Item(item) = &item
+ && let ItemKind::Static(ty, ..) = &item.kind
+ {
+ (item, false, ecx.with_def_site_ctxt(ty.span))
+ } else if let Annotatable::Stmt(stmt) = &item
+ && let StmtKind::Item(item) = &stmt.kind
+ && let ItemKind::Static(ty, ..) = &item.kind
+ {
+ (item, true, ecx.with_def_site_ctxt(ty.span))
+ } else {
+ ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
+ return vec![orig_item.clone()]
+ };
// Generate a bunch of new items using the AllocFnFactory
let span = ecx.with_def_site_ctxt(item.span);
@@ -115,9 +111,7 @@ impl AllocFnFactory<'_, '_> {
}
fn attrs(&self) -> AttrVec {
- let special = sym::rustc_std_internal_symbol;
- let special = self.cx.meta_word(self.span, special);
- thin_vec![self.cx.attribute(special)]
+ thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span)]
}
fn arg_ty(
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index c7ea7de8f..75cfac723 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -25,6 +25,7 @@ use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro;
use rustc_span::symbol::sym;
+mod alloc_error_handler;
mod assert;
mod cfg;
mod cfg_accessible;
@@ -44,6 +45,7 @@ mod log_syntax;
mod source_util;
mod test;
mod trace_macros;
+mod type_ascribe;
mod util;
pub mod asm;
@@ -91,13 +93,16 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
unreachable: edition_panic::expand_unreachable,
stringify: source_util::expand_stringify,
trace_macros: trace_macros::expand_trace_macros,
+ type_ascribe: type_ascribe::expand_type_ascribe,
}
register_attr! {
+ alloc_error_handler: alloc_error_handler::expand,
bench: test::expand_bench,
cfg_accessible: cfg_accessible::Expander,
cfg_eval: cfg_eval::expand,
- derive: derive::Expander,
+ derive: derive::Expander(false),
+ derive_const: derive::Expander(true),
global_allocator: global_allocator::expand,
test: test::expand_test,
test_case: test::expand_test_case,
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index ebe1c3663..ece660cf6 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -1,6 +1,3 @@
-use std::mem;
-
-use rustc_ast::attr;
use rustc_ast::ptr::P;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{self as ast, NodeId};
@@ -13,6 +10,7 @@ use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use smallvec::smallvec;
+use std::mem;
struct ProcMacroDerive {
id: NodeId,
@@ -365,14 +363,8 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
cx.expr_array_ref(span, decls),
)
.map(|mut i| {
- let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
- i.attrs.push(cx.attribute(attr));
-
- let deprecated_attr = attr::mk_nested_word_item(Ident::new(sym::deprecated, span));
- let allow_deprecated_attr =
- attr::mk_list_item(Ident::new(sym::allow, span), vec![deprecated_attr]);
- i.attrs.push(cx.attribute(allow_deprecated_attr));
-
+ i.attrs.push(cx.attr_word(sym::rustc_proc_macro_decls, span));
+ i.attrs.push(cx.attr_nested_word(sym::allow, sym::deprecated, span));
i
});
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index d78bbc3c9..0b17e92ef 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -164,7 +164,7 @@ pub fn expand_include<'cx>(
Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id })
}
-// include_str! : read the given file, insert it as a literal string expr
+/// `include_str!`: read the given file, insert it as a literal string expr
pub fn expand_include_str(
cx: &mut ExtCtxt<'_>,
sp: Span,
@@ -216,7 +216,10 @@ pub fn expand_include_bytes(
}
};
match cx.source_map().load_binary_file(&file) {
- Ok(bytes) => base::MacEager::expr(cx.expr_byte_str(sp, bytes)),
+ Ok(bytes) => {
+ let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes.into()));
+ base::MacEager::expr(expr)
+ }
Err(e) => {
cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
DummyResult::any(sp)
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index 49ef538f0..f73f20c84 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -52,7 +52,7 @@ pub fn inject(
cx.item(
span,
ident,
- thin_vec![cx.attribute(cx.meta_word(span, sym::macro_use))],
+ thin_vec![cx.attr_word(sym::macro_use, span)],
ast::ItemKind::ExternCrate(None),
),
);
@@ -79,7 +79,7 @@ pub fn inject(
let use_item = cx.item(
span,
Ident::empty(),
- thin_vec![cx.attribute(cx.meta_word(span, sym::prelude_import))],
+ thin_vec![cx.attr_word(sym::prelude_import, span)],
ast::ItemKind::Use(ast::UseTree {
prefix: cx.path(span, import_path),
kind: ast::UseTreeKind::Glob,
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index fee5d04cd..f5f02fc77 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -2,7 +2,6 @@
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
use rustc_ast as ast;
-use rustc_ast::attr;
use rustc_ast::ptr::P;
use rustc_ast_pretty::pprust;
use rustc_errors::Applicability;
@@ -13,13 +12,13 @@ use rustc_span::Span;
use std::iter;
use thin_vec::thin_vec;
-// #[test_case] is used by custom test authors to mark tests
-// When building for test, it needs to make the item public and gensym the name
-// Otherwise, we'll omit the item. This behavior means that any item annotated
-// with #[test_case] is never addressable.
-//
-// We mark item with an inert attribute "rustc_test_marker" which the test generation
-// logic will pick up on.
+/// #[test_case] is used by custom test authors to mark tests
+/// When building for test, it needs to make the item public and gensym the name
+/// Otherwise, we'll omit the item. This behavior means that any item annotated
+/// with #[test_case] is never addressable.
+///
+/// We mark item with an inert attribute "rustc_test_marker" which the test generation
+/// logic will pick up on.
pub fn expand_test_case(
ecx: &mut ExtCtxt<'_>,
attr_sp: Span,
@@ -47,11 +46,7 @@ pub fn expand_test_case(
tokens: None,
};
item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
- item.attrs.push(ecx.attribute(attr::mk_name_value_item_str(
- Ident::new(sym::rustc_test_marker, sp),
- test_path_symbol,
- sp,
- )));
+ item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
item
});
@@ -112,7 +107,7 @@ pub fn expand_test_or_bench(
};
// Note: non-associated fn items are already handled by `expand_test_or_bench`
- if !matches!(item.kind, ast::ItemKind::Fn(_)) {
+ let ast::ItemKind::Fn(fn_) = &item.kind else {
let diag = &cx.sess.parse_sess.span_diagnostic;
let msg = "the `#[test]` attribute may only be used on a non-associated function";
let mut err = match item.kind {
@@ -130,7 +125,7 @@ pub fn expand_test_or_bench(
.emit();
return vec![Annotatable::Item(item)];
- }
+ };
// has_*_signature will report any errors in the type so compilation
// will fail. We shouldn't try to expand in this case because the errors
@@ -141,12 +136,14 @@ pub fn expand_test_or_bench(
return vec![Annotatable::Item(item)];
}
- let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp));
+ let sp = cx.with_def_site_ctxt(item.span);
+ let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span());
+ let attr_sp = cx.with_def_site_ctxt(attr_sp);
let test_id = Ident::new(sym::test, attr_sp);
// creates test::$name
- let test_path = |name| cx.path(sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
+ let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
// creates test::ShouldPanic::$name
let should_panic_path = |name| {
@@ -192,7 +189,7 @@ pub fn expand_test_or_bench(
vec![
// super::$test_fn(b)
cx.expr_call(
- sp,
+ ret_ty_sp,
cx.expr_path(cx.path(sp, vec![item.ident])),
vec![cx.expr_ident(sp, b)],
),
@@ -216,7 +213,11 @@ pub fn expand_test_or_bench(
cx.expr_path(test_path("assert_test_result")),
vec![
// $test_fn()
- cx.expr_call(sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![]), // )
+ cx.expr_call(
+ ret_ty_sp,
+ cx.expr_path(cx.path(sp, vec![item.ident])),
+ vec![],
+ ), // )
],
), // }
), // )
@@ -235,16 +236,9 @@ pub fn expand_test_or_bench(
Ident::new(item.ident.name, sp),
thin_vec![
// #[cfg(test)]
- cx.attribute(attr::mk_list_item(
- Ident::new(sym::cfg, attr_sp),
- vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))],
- )),
+ cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
// #[rustc_test_marker = "test_case_sort_key"]
- cx.attribute(attr::mk_name_value_item_str(
- Ident::new(sym::rustc_test_marker, attr_sp),
- test_path_symbol,
- attr_sp,
- )),
+ cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp),
]
.into(),
// const $ident: test::TestDescAndFn =
@@ -472,61 +466,67 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
let sd = &cx.sess.parse_sess.span_diagnostic;
- if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
- if let ast::Unsafe::Yes(span) = sig.header.unsafety {
- sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
- .span_label(span, "`unsafe` because of this")
- .emit();
- return false;
- }
- if let ast::Async::Yes { span, .. } = sig.header.asyncness {
- sd.struct_span_err(i.span, "async functions cannot be used for tests")
- .span_label(span, "`async` because of this")
- .emit();
- return false;
- }
-
- // If the termination trait is active, the compiler will check that the output
- // type implements the `Termination` trait as `libtest` enforces that.
- let has_output = match sig.decl.output {
- ast::FnRetTy::Default(..) => false,
- ast::FnRetTy::Ty(ref t) if t.kind.is_unit() => false,
- _ => true,
- };
-
- if !sig.decl.inputs.is_empty() {
- sd.span_err(i.span, "functions used as tests can not have any arguments");
- return false;
- }
+ match &i.kind {
+ ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
+ if let ast::Unsafe::Yes(span) = sig.header.unsafety {
+ sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
+ .span_label(span, "`unsafe` because of this")
+ .emit();
+ return false;
+ }
+ if let ast::Async::Yes { span, .. } = sig.header.asyncness {
+ sd.struct_span_err(i.span, "async functions cannot be used for tests")
+ .span_label(span, "`async` because of this")
+ .emit();
+ return false;
+ }
- match (has_output, has_should_panic_attr) {
- (true, true) => {
- sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
- false
+ // If the termination trait is active, the compiler will check that the output
+ // type implements the `Termination` trait as `libtest` enforces that.
+ let has_output = match &sig.decl.output {
+ ast::FnRetTy::Default(..) => false,
+ ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
+ _ => true,
+ };
+
+ if !sig.decl.inputs.is_empty() {
+ sd.span_err(i.span, "functions used as tests can not have any arguments");
+ return false;
}
- (true, false) => {
- if !generics.params.is_empty() {
- sd.span_err(i.span, "functions used as tests must have signature fn() -> ()");
+
+ match (has_output, has_should_panic_attr) {
+ (true, true) => {
+ sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
false
- } else {
- true
}
+ (true, false) => {
+ if !generics.params.is_empty() {
+ sd.span_err(
+ i.span,
+ "functions used as tests must have signature fn() -> ()",
+ );
+ false
+ } else {
+ true
+ }
+ }
+ (false, _) => true,
}
- (false, _) => true,
}
- } else {
- // should be unreachable because `is_test_fn_item` should catch all non-fn items
- false
+ _ => {
+ // should be unreachable because `is_test_fn_item` should catch all non-fn items
+ debug_assert!(false);
+ false
+ }
}
}
fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
- let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
+ let has_sig = match &i.kind {
// N.B., inadequate check, but we're running
// well before resolve, can't get too deep.
- sig.decl.inputs.len() == 1
- } else {
- false
+ ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1,
+ _ => false,
};
if !has_sig {
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index b8b8351a3..ad8871080 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -34,8 +34,8 @@ struct TestCtxt<'a> {
test_runner: Option<ast::Path>,
}
-// Traverse the crate, collecting all the test functions, eliding any
-// existing main functions, and synthesizing a main test harness
+/// Traverse the crate, collecting all the test functions, eliding any
+/// existing main functions, and synthesizing a main test harness
pub fn inject(sess: &Session, resolver: &mut dyn ResolverExpand, krate: &mut ast::Crate) {
let span_diagnostic = sess.diagnostic();
let panic_strategy = sess.panic_strategy();
@@ -131,8 +131,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
// We don't want to recurse into anything other than mods, since
// mods or tests inside of functions will break things
- if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ref spans)) = item.kind {
- let ast::ModSpans { inner_span: span, inject_use_span: _ } = *spans;
+ if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
+ item.kind
+ {
let prev_tests = mem::take(&mut self.tests);
noop_visit_item_kind(&mut item.kind, self);
self.add_test_cases(item.id, span, prev_tests);
@@ -185,13 +186,12 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
let item = match entry_point_type(self.sess, &item, self.depth) {
EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
- let allow_ident = Ident::new(sym::allow, self.def_site);
- let dc_nested =
- attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site));
- let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
- let allow_dead_code = attr::mk_attr_outer(
+ let allow_dead_code = attr::mk_attr_nested_word(
&self.sess.parse_sess.attr_id_generator,
- allow_dead_code_item,
+ ast::AttrStyle::Outer,
+ sym::allow,
+ sym::dead_code,
+ self.def_site,
);
let attrs = attrs
.into_iter()
@@ -309,8 +309,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
);
// #[rustc_main]
- let main_meta = ecx.meta_word(sp, sym::rustc_main);
- let main_attr = ecx.attribute(main_meta);
+ let main_attr = ecx.attr_word(sym::rustc_main, sp);
// pub fn main() { ... }
let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
diff --git a/compiler/rustc_builtin_macros/src/type_ascribe.rs b/compiler/rustc_builtin_macros/src/type_ascribe.rs
new file mode 100644
index 000000000..72b85af14
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/type_ascribe.rs
@@ -0,0 +1,35 @@
+use rustc_ast::ptr::P;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{token, Expr, ExprKind, Ty};
+use rustc_errors::PResult;
+use rustc_expand::base::{self, DummyResult, ExtCtxt, MacEager};
+use rustc_span::Span;
+
+pub fn expand_type_ascribe(
+ cx: &mut ExtCtxt<'_>,
+ span: Span,
+ tts: TokenStream,
+) -> Box<dyn base::MacResult + 'static> {
+ let (expr, ty) = match parse_ascribe(cx, tts) {
+ Ok(parsed) => parsed,
+ Err(mut err) => {
+ err.emit();
+ return DummyResult::any(span);
+ }
+ };
+
+ let asc_expr = cx.expr(span, ExprKind::Type(expr, ty));
+
+ return MacEager::expr(asc_expr);
+}
+
+fn parse_ascribe<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Expr>, P<Ty>)> {
+ let mut parser = cx.new_parser_from_tts(stream);
+
+ let expr = parser.parse_expr()?;
+ parser.expect(&token::Comma)?;
+
+ let ty = parser.parse_ty()?;
+
+ Ok((expr, ty))
+}
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index 527fe50ef..83812631c 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -1,4 +1,4 @@
-use rustc_ast::{Attribute, MetaItem};
+use rustc_ast::{AttrStyle, Attribute, MetaItem};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_feature::AttributeTemplate;
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
@@ -8,8 +8,13 @@ use rustc_span::Symbol;
pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
// All the built-in macro attributes are "words" at the moment.
let template = AttributeTemplate { word: true, ..Default::default() };
- let attr = ecx.attribute(meta_item.clone());
- validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template);
+ validate_attr::check_builtin_meta_item(
+ &ecx.sess.parse_sess,
+ &meta_item,
+ AttrStyle::Outer,
+ name,
+ template,
+ );
}
/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when