summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_builtin_macros/src/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_builtin_macros/src/test.rs')
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs142
1 files changed, 71 insertions, 71 deletions
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 {