@@ -8,7 +8,7 @@ use rustc_ast_pretty::pprust;
8
8
use rustc_errors:: Applicability ;
9
9
use rustc_expand:: base:: * ;
10
10
use rustc_span:: symbol:: { sym, Ident , Symbol } ;
11
- use rustc_span:: { FileNameDisplayPreference , Span } ;
11
+ use rustc_span:: { ErrorGuaranteed , FileNameDisplayPreference , Span } ;
12
12
use std:: iter;
13
13
use thin_vec:: { thin_vec, ThinVec } ;
14
14
@@ -128,12 +128,15 @@ pub fn expand_test_or_bench(
128
128
} ;
129
129
} ;
130
130
131
- // has_ *_signature will report any errors in the type so compilation
131
+ // check_ *_signature will report any errors in the type so compilation
132
132
// will fail. We shouldn't try to expand in this case because the errors
133
133
// 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 ( ) {
137
140
return if is_stmt {
138
141
vec ! [ Annotatable :: Stmt ( P ( cx. stmt_item( item. span, item) ) ) ]
139
142
} else {
@@ -523,72 +526,62 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
523
526
}
524
527
}
525
528
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 > {
527
534
let has_should_panic_attr = attr:: contains_name ( & i. attrs , sym:: should_panic) ;
528
535
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
- }
539
536
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
+ }
552
540
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
+ }
557
544
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
+ } ;
566
552
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" ) ) ;
574
555
}
575
- }
576
556
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
+ }
584
570
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 (
587
580
i. span ,
588
581
"functions used as benches must have \
589
582
signature `fn(&mut Bencher) -> impl Termination`",
590
- ) ;
583
+ ) ) ;
591
584
}
592
585
593
- has_sig
586
+ Ok ( ( ) )
594
587
}
0 commit comments