diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_builtin_macros/src/test.rs | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_builtin_macros/src/test.rs')
-rw-r--r-- | compiler/rustc_builtin_macros/src/test.rs | 129 |
1 files changed, 57 insertions, 72 deletions
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 49ee276af..6bc4f6fc1 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -3,12 +3,12 @@ use crate::errors; /// 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::ptr::P; -use rustc_ast::{self as ast, attr}; +use rustc_ast::{self as ast, attr, GenericParamKind}; use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_expand::base::*; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{FileNameDisplayPreference, Span}; +use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span}; use std::iter; use thin_vec::{thin_vec, ThinVec}; @@ -122,23 +122,26 @@ pub fn expand_test_or_bench( let ast::ItemKind::Fn(fn_) = &item.kind else { not_testable_error(cx, attr_sp, Some(&item)); return if is_stmt { - vec![Annotatable::Stmt(P(ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: item.span, - kind: ast::StmtKind::Item(item), - }))] + vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))] } else { vec![Annotatable::Item(item)] }; }; - // has_*_signature will report any errors in the type so compilation + // check_*_signature will report any errors in the type so compilation // will fail. We shouldn't try to expand in this case because the errors // would be spurious. - if (!is_bench && !has_test_signature(cx, &item)) - || (is_bench && !has_bench_signature(cx, &item)) - { - return vec![Annotatable::Item(item)]; + let check_result = if is_bench { + check_bench_signature(cx, &item, &fn_) + } else { + check_test_signature(cx, &item, &fn_) + }; + if check_result.is_err() { + return if is_stmt { + vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))] + } else { + vec![Annotatable::Item(item)] + }; } let sp = cx.with_def_site_ctxt(item.span); @@ -523,75 +526,57 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType { } } -fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { +fn check_test_signature( + cx: &ExtCtxt<'_>, + i: &ast::Item, + f: &ast::Fn, +) -> Result<(), ErrorGuaranteed> { let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); let sd = &cx.sess.parse_sess.span_diagnostic; - match &i.kind { - ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => { - if let ast::Unsafe::Yes(span) = sig.header.unsafety { - sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }); - return false; - } - if let ast::Async::Yes { span, .. } = sig.header.asyncness { - sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }); - 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; - } + if let ast::Unsafe::Yes(span) = f.sig.header.unsafety { + return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" })); + } - match (has_output, has_should_panic_attr) { - (true, true) => { - sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); - false - } - (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, - } - } - _ => { - // should be unreachable because `is_test_fn_item` should catch all non-fn items - debug_assert!(false); - false - } + if let ast::Async::Yes { span, .. } = f.sig.header.asyncness { + return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" })); } -} -fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_sig = match &i.kind { - // N.B., inadequate check, but we're running - // well before resolve, can't get too deep. - ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1, - _ => 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 &f.sig.decl.output { + ast::FnRetTy::Default(..) => false, + ast::FnRetTy::Ty(t) if t.kind.is_unit() => false, + _ => true, }; - if !has_sig { - cx.sess.parse_sess.span_diagnostic.span_err( + if !f.sig.decl.inputs.is_empty() { + return Err(sd.span_err(i.span, "functions used as tests can not have any arguments")); + } + + if has_should_panic_attr && has_output { + return Err(sd.span_err(i.span, "functions using `#[should_panic]` must return `()`")); + } + + if f.generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) { + return Err(sd.span_err( i.span, - "functions used as benches must have \ - signature `fn(&mut Bencher) -> impl Termination`", - ); + "functions used as tests can not have any non-lifetime generic parameters", + )); } - has_sig + Ok(()) +} + +fn check_bench_signature( + cx: &ExtCtxt<'_>, + i: &ast::Item, + f: &ast::Fn, +) -> Result<(), ErrorGuaranteed> { + // N.B., inadequate check, but we're running + // well before resolve, can't get too deep. + if f.sig.decl.inputs.len() != 1 { + return Err(cx.sess.parse_sess.span_diagnostic.emit_err(errors::BenchSig { span: i.span })); + } + Ok(()) } |