diff options
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
21 files changed, 210 insertions, 33 deletions
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 00000000000..eaf1b1167cf --- /dev/null +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -0,0 +1,104 @@ +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(); + let not_function = || { + ecx.sess + .parse_sess + .span_diagnostic + .span_err(item.span(), "alloc_error_handler must be a function"); + vec![orig_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) = match &item { + Annotatable::Item(item) => match item.kind { + ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)), + _ => return not_function(), + }, + Annotatable::Stmt(stmt) => match &stmt.kind { + StmtKind::Item(item_) => match item_.kind { + ItemKind::Fn(ref fn_kind) => { + (item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) + } + _ => return not_function(), + }, + _ => return not_function(), + }, + _ => return not_function(), + }; + + // 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 special = sym::rustc_std_internal_symbol; + let special = cx.meta_word(span, special); + let attrs = thin_vec![cx.attribute(special)]; + + 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/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 973a8cb85c2..bb683936026 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -58,6 +58,7 @@ impl<'cx, 'a> Context<'cx, 'a> { /// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to: /// /// ```rust + /// #![feature(generic_assert_internals)] /// let elem = 1; /// { /// #[allow(unused_imports)] @@ -70,7 +71,7 @@ impl<'cx, 'a> Context<'cx, 'a> { /// __local_bind0 /// } == 1 /// ) { - /// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {}", __capture0) + /// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {:?}", __capture0) /// } /// } /// ``` diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 46b54eae384..5638c2f6180 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -36,7 +36,7 @@ pub fn expand_cfg( } #[derive(Diagnostic)] -#[diag(builtin_macros::requires_cfg_pattern)] +#[diag(builtin_macros_requires_cfg_pattern)] struct RequiresCfgPattern { #[primary_span] #[label] @@ -44,7 +44,7 @@ struct RequiresCfgPattern { } #[derive(Diagnostic)] -#[diag(builtin_macros::expected_one_cfg_pattern)] +#[diag(builtin_macros_expected_one_cfg_pattern)] struct OneCfgPattern { #[primary_span] span: Span, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 009f3c783d4..750f1fe121f 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -210,8 +210,15 @@ impl CfgEval<'_, '_> { } impl MutVisitor for CfgEval<'_, '_> { + #[instrument(level = "trace", skip(self))] fn visit_expr(&mut self, expr: &mut P<ast::Expr>) { - self.cfg.configure_expr(expr); + self.cfg.configure_expr(expr, false); + mut_visit::noop_visit_expr(expr, self); + } + + #[instrument(level = "trace", skip(self))] + fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) { + self.cfg.configure_expr(expr, true); mut_visit::noop_visit_expr(expr, self); } diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 77e0b6c55a8..7bd344467d0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -16,6 +16,7 @@ pub fn expand_deriving_copy( 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, diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index c7f2d95e72f..fa8685f5f4e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -72,6 +72,7 @@ pub fn expand_deriving_clone( let trait_def = TraitDef { span, path: path_std!(clone::Clone), + skip_path_as_bound: false, additional_bounds: bounds, generics: Bounds::empty(), supports_unions: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 5b556c5c9b9..eab67b0d354 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -25,6 +25,7 @@ pub fn expand_deriving_eq( 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, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 72625869558..7f117981a9a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -19,6 +19,7 @@ pub fn expand_deriving_ord( 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, 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 42ee65b570a..236cbccaf9f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -83,6 +83,7 @@ pub fn expand_deriving_partial_eq( let trait_def = TraitDef { span, path: path_std!(cmp::PartialEq), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, 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 516892aeda9..4173403a1b8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -37,6 +37,7 @@ pub fn expand_deriving_partial_ord( let trait_def = TraitDef { span, path: path_std!(cmp::PartialOrd), + skip_path_as_bound: false, additional_bounds: vec![], generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 4af7fd81653..2cf614ed947 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -20,6 +20,7 @@ pub fn expand_deriving_debug( let trait_def = TraitDef { span, path: path_std!(fmt::Debug), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 7174dbbe7ea..d669f616802 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -23,6 +23,7 @@ pub fn expand_deriving_rustc_decodable( let trait_def = TraitDef { span, 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, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index a94c8a996e6..17df9fb279a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -24,6 +24,7 @@ pub fn expand_deriving_default( 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, @@ -262,3 +263,22 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, ' } } } + +fn has_a_default_variant(item: &Annotatable) -> bool { + struct HasDefaultAttrOnVariant { + found: bool, + } + + impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant { + fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) { + if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) { + self.found = true; + } + // no need to subrecurse. + } + } + + let mut visitor = HasDefaultAttrOnVariant { found: false }; + item.visit_with(&mut visitor); + visitor.found +} diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index b220e54238f..f83f58b97d3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -107,6 +107,7 @@ pub fn expand_deriving_rustc_encodable( let trait_def = TraitDef { span, 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, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 3cc160adb53..16ee3aa89bb 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -174,6 +174,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::cell::RefCell; use std::iter; +use std::ops::Not; use std::vec; use thin_vec::thin_vec; use ty::{Bounds, Path, Ref, Self_, Ty}; @@ -187,6 +188,9 @@ pub struct TraitDef<'a> { /// Path of the trait, including any type parameters pub path: Path, + /// Whether to skip adding the current trait as a bound to the type parameters of the type. + pub skip_path_as_bound: bool, + /// Additional bounds required of any type parameters of the type, /// other than the current trait pub additional_bounds: Vec<Ty>, @@ -562,7 +566,7 @@ impl<'a> TraitDef<'a> { tokens: None, }, attrs: ast::AttrVec::new(), - kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias { + kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias { defaultness: ast::Defaultness::Final, generics: Generics::default(), where_clauses: ( @@ -596,7 +600,7 @@ impl<'a> TraitDef<'a> { cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) }).chain( // require the current trait - iter::once(cx.trait_bound(trait_path.clone())) + self.skip_path_as_bound.not().then(|| cx.trait_bound(trait_path.clone())) ).chain( // also add in any bounds from the declaration param.bounds.iter().cloned() @@ -1110,6 +1114,11 @@ impl<'a> MethodDef<'a> { /// ``` /// is equivalent to: /// ``` + /// #![feature(core_intrinsics)] + /// enum A { + /// A1, + /// A2(i32) + /// } /// impl ::core::cmp::PartialEq for A { /// #[inline] /// fn eq(&self, other: &A) -> bool { diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1f02e7ce77..6e9d5f08b94 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -22,6 +22,7 @@ pub fn expand_deriving_hash( let hash_trait_def = TraitDef { span, path, + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index a65d0bad6de..ee346047a0b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -131,6 +131,8 @@ fn inject_impl_of_structural_trait( // Create generics param list for where clauses and impl headers let mut generics = generics.clone(); + let ctxt = span.ctxt(); + // Create the type of `self`. // // in addition, remove defaults from generic params (impls cannot have them). @@ -138,16 +140,18 @@ fn inject_impl_of_structural_trait( .params .iter_mut() .map(|param| match &mut param.kind { - ast::GenericParamKind::Lifetime => { - ast::GenericArg::Lifetime(cx.lifetime(span, param.ident)) - } + ast::GenericParamKind::Lifetime => ast::GenericArg::Lifetime( + cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident), + ), ast::GenericParamKind::Type { default } => { *default = None; - ast::GenericArg::Type(cx.ty_ident(span, param.ident)) + ast::GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident)) } ast::GenericParamKind::Const { ty: _, kw_span: _, default } => { *default = None; - ast::GenericArg::Const(cx.const_ident(span, param.ident)) + ast::GenericArg::Const( + cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident), + ) } }) .collect(); @@ -174,6 +178,8 @@ 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))); let newitem = cx.item( span, diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index b15e2d084ef..8b07c110663 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -159,7 +159,7 @@ pub fn make_format_args( append_newline: bool, ) -> Result<FormatArgs, ()> { let msg = "format argument must be a string literal"; - let fmt_span = efmt.span; + let unexpanded_fmt_span = efmt.span; let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) { Ok(mut fmt) if append_newline => { fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); @@ -174,7 +174,7 @@ pub fn make_format_args( }; if !suggested { err.span_suggestion( - fmt_span.shrink_to_lo(), + unexpanded_fmt_span.shrink_to_lo(), "you might be missing a string literal to format with", format!("\"{}\", ", sugg_fmt), Applicability::MaybeIncorrect, @@ -192,7 +192,7 @@ pub fn make_format_args( }; let fmt_str = fmt_str.as_str(); // for the suggestions below - let fmt_snippet = ecx.source_map().span_to_snippet(fmt_span).ok(); + let fmt_snippet = ecx.source_map().span_to_snippet(unexpanded_fmt_span).ok(); let mut parser = parse::Parser::new( fmt_str, str_style, diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index f058503064b..bde0102186a 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -7,7 +7,7 @@ #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] -#![feature(is_some_with)] +#![feature(is_some_and)] #![feature(is_sorted)] #![feature(let_chains)] #![feature(proc_macro_internals)] @@ -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; @@ -94,6 +95,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { } register_attr! { + alloc_error_handler: alloc_error_handler::expand, bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 7efb6cc61ee..fee5d04cdae 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -36,13 +36,22 @@ pub fn expand_test_case( let sp = ecx.with_def_site_ctxt(attr_sp); let mut item = anno_item.expect_item(); item = item.map(|mut item| { + let test_path_symbol = Symbol::intern(&item_path( + // skip the name of the root module + &ecx.current_expansion.module.mod_path[1..], + &item.ident, + )); item.vis = ast::Visibility { span: item.vis.span, kind: ast::VisibilityKind::Public, tokens: None, }; item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); - item.attrs.push(ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker))); + item.attrs.push(ecx.attribute(attr::mk_name_value_item_str( + Ident::new(sym::rustc_test_marker, sp), + test_path_symbol, + sp, + ))); item }); @@ -115,7 +124,7 @@ pub fn expand_test_or_bench( // reworked in the future to not need it, it'd be nice. _ => diag.struct_span_err(attr_sp, msg).forget_guarantee(), }; - err.span_label(attr_sp, "the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions") + err.span_label(attr_sp, "the `#[test]` macro causes a function to be run on a test and has no effect on non-functions") .span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr())) .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect) .emit(); @@ -215,6 +224,12 @@ pub fn expand_test_or_bench( ) }; + let test_path_symbol = Symbol::intern(&item_path( + // skip the name of the root module + &cx.current_expansion.module.mod_path[1..], + &item.ident, + )); + let mut test_const = cx.item( sp, Ident::new(item.ident.name, sp), @@ -224,9 +239,14 @@ pub fn expand_test_or_bench( Ident::new(sym::cfg, attr_sp), vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))], )), - // #[rustc_test_marker] - cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)), - ], + // #[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, + )), + ] + .into(), // const $ident: test::TestDescAndFn = ast::ItemKind::Const( ast::Defaultness::Final, @@ -250,14 +270,7 @@ pub fn expand_test_or_bench( cx.expr_call( sp, cx.expr_path(test_path("StaticTestName")), - vec![cx.expr_str( - sp, - Symbol::intern(&item_path( - // skip the name of the root module - &cx.current_expansion.module.mod_path[1..], - &item.ident, - )), - )], + vec![cx.expr_str(sp, test_path_symbol)], ), ), // ignore: true | false diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 561ca00c719..b8b8351a36f 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -18,9 +18,11 @@ use thin_vec::thin_vec; use std::{iter, mem}; +#[derive(Clone)] struct Test { span: Span, ident: Ident, + name: Symbol, } struct TestCtxt<'a> { @@ -120,10 +122,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> { let mut item = i.into_inner(); - if is_test_case(&self.cx.ext_cx.sess, &item) { + if let Some(name) = get_test_name(&self.cx.ext_cx.sess, &item) { debug!("this is a test item"); - let test = Test { span: item.span, ident: item.ident }; + let test = Test { span: item.span, ident: item.ident, name }; self.tests.push(test); } @@ -357,9 +359,12 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> { debug!("building test vector from {} tests", cx.test_cases.len()); let ecx = &cx.ext_cx; + let mut tests = cx.test_cases.clone(); + tests.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str())); + ecx.expr_array_ref( sp, - cx.test_cases + tests .iter() .map(|test| { ecx.expr_addr_of(test.span, ecx.expr_path(ecx.path(test.span, vec![test.ident]))) @@ -368,8 +373,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> { ) } -fn is_test_case(sess: &Session, i: &ast::Item) -> bool { - sess.contains_name(&i.attrs, sym::rustc_test_marker) +fn get_test_name(sess: &Session, i: &ast::Item) -> Option<Symbol> { + sess.first_attr_value_str_by_name(&i.attrs, sym::rustc_test_marker) } fn get_test_runner( |
