@@ -8,7 +8,7 @@ use rustc_ast_pretty::pprust;
88use rustc_errors:: Applicability ;
99use rustc_expand:: base:: * ;
1010use rustc_span:: symbol:: { sym, Ident , Symbol } ;
11- use rustc_span:: { FileNameDisplayPreference , Span } ;
11+ use rustc_span:: { ErrorGuaranteed , FileNameDisplayPreference , Span } ;
1212use std:: iter;
1313use thin_vec:: { thin_vec, ThinVec } ;
1414
@@ -128,12 +128,15 @@ pub fn expand_test_or_bench(
128128 } ;
129129 } ;
130130
131- // has_ *_signature will report any errors in the type so compilation
131+ // check_ *_signature will report any errors in the type so compilation
132132 // will fail. We shouldn't try to expand in this case because the errors
133133 // would be spurious.
134- if ( !is_bench && !has_test_signature ( cx, & item) )
135- || ( is_bench && !has_bench_signature ( cx, & item) )
136- {
134+ let check_result = if is_bench {
135+ check_bench_signature ( cx, & item, & fn_)
136+ } else {
137+ check_test_signature ( cx, & item, & fn_)
138+ } ;
139+ if check_result. is_err ( ) {
137140 return if is_stmt {
138141 vec ! [ Annotatable :: Stmt ( P ( cx. stmt_item( item. span, item) ) ) ]
139142 } else {
@@ -523,72 +526,62 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
523526 }
524527}
525528
526- fn has_test_signature ( cx : & ExtCtxt < ' _ > , i : & ast:: Item ) -> bool {
529+ fn check_test_signature (
530+ cx : & ExtCtxt < ' _ > ,
531+ i : & ast:: Item ,
532+ f : & ast:: Fn ,
533+ ) -> Result < ( ) , ErrorGuaranteed > {
527534 let has_should_panic_attr = attr:: contains_name ( & i. attrs , sym:: should_panic) ;
528535 let sd = & cx. sess . parse_sess . span_diagnostic ;
529- match & i. kind {
530- ast:: ItemKind :: Fn ( box ast:: Fn { sig, generics, .. } ) => {
531- if let ast:: Unsafe :: Yes ( span) = sig. header . unsafety {
532- sd. emit_err ( errors:: TestBadFn { span : i. span , cause : span, kind : "unsafe" } ) ;
533- return false ;
534- }
535- if let ast:: Async :: Yes { span, .. } = sig. header . asyncness {
536- sd. emit_err ( errors:: TestBadFn { span : i. span , cause : span, kind : "async" } ) ;
537- return false ;
538- }
539536
540- // If the termination trait is active, the compiler will check that the output
541- // type implements the `Termination` trait as `libtest` enforces that.
542- let has_output = match & sig. decl . output {
543- ast:: FnRetTy :: Default ( ..) => false ,
544- ast:: FnRetTy :: Ty ( t) if t. kind . is_unit ( ) => false ,
545- _ => true ,
546- } ;
547-
548- if !sig. decl . inputs . is_empty ( ) {
549- sd. span_err ( i. span , "functions used as tests can not have any arguments" ) ;
550- return false ;
551- }
537+ if let ast:: Unsafe :: Yes ( span) = f. sig . header . unsafety {
538+ return Err ( sd. emit_err ( errors:: TestBadFn { span : i. span , cause : span, kind : "unsafe" } ) ) ;
539+ }
552540
553- if has_should_panic_attr && has_output {
554- sd. span_err ( i. span , "functions using `#[should_panic]` must return `()`" ) ;
555- return false ;
556- }
541+ if let ast:: Async :: Yes { span, .. } = f. sig . header . asyncness {
542+ return Err ( sd. emit_err ( errors:: TestBadFn { span : i. span , cause : span, kind : "async" } ) ) ;
543+ }
557544
558- if generics. params . iter ( ) . any ( |param| !matches ! ( param. kind, GenericParamKind :: Lifetime ) )
559- {
560- sd. span_err (
561- i. span ,
562- "functions used as tests can not have any non-lifetime generic parameters" ,
563- ) ;
564- return false ;
565- }
545+ // If the termination trait is active, the compiler will check that the output
546+ // type implements the `Termination` trait as `libtest` enforces that.
547+ let has_output = match & f. sig . decl . output {
548+ ast:: FnRetTy :: Default ( ..) => false ,
549+ ast:: FnRetTy :: Ty ( t) if t. kind . is_unit ( ) => false ,
550+ _ => true ,
551+ } ;
566552
567- true
568- }
569- _ => {
570- // should be unreachable because `is_test_fn_item` should catch all non-fn items
571- debug_assert ! ( false ) ;
572- false
573- }
553+ if !f. sig . decl . inputs . is_empty ( ) {
554+ return Err ( sd. span_err ( i. span , "functions used as tests can not have any arguments" ) ) ;
574555 }
575- }
576556
577- fn has_bench_signature ( cx : & ExtCtxt < ' _ > , i : & ast:: Item ) -> bool {
578- let has_sig = match & i. kind {
579- // N.B., inadequate check, but we're running
580- // well before resolve, can't get too deep.
581- ast:: ItemKind :: Fn ( box ast:: Fn { sig, .. } ) => sig. decl . inputs . len ( ) == 1 ,
582- _ => false ,
583- } ;
557+ if has_should_panic_attr && has_output {
558+ return Err ( sd. span_err ( i. span , "functions using `#[should_panic]` must return `()`" ) ) ;
559+ }
560+
561+ if f. generics . params . iter ( ) . any ( |param| !matches ! ( param. kind, GenericParamKind :: Lifetime ) ) {
562+ return Err ( sd. span_err (
563+ i. span ,
564+ "functions used as tests can not have any non-lifetime generic parameters" ,
565+ ) ) ;
566+ }
567+
568+ Ok ( ( ) )
569+ }
584570
585- if !has_sig {
586- cx. sess . parse_sess . span_diagnostic . span_err (
571+ fn check_bench_signature (
572+ cx : & ExtCtxt < ' _ > ,
573+ i : & ast:: Item ,
574+ f : & ast:: Fn ,
575+ ) -> Result < ( ) , ErrorGuaranteed > {
576+ // N.B., inadequate check, but we're running
577+ // well before resolve, can't get too deep.
578+ if f. sig . decl . inputs . len ( ) != 1 {
579+ return Err ( cx. sess . parse_sess . span_diagnostic . span_err (
587580 i. span ,
588581 "functions used as benches must have \
589582 signature `fn(&mut Bencher) -> impl Termination`",
590- ) ;
583+ ) ) ;
591584 }
592585
593- has_sig
586+ Ok ( ( ) )
594587}
0 commit comments