@@ -320,56 +320,69 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
320
320
#[ derive( PartialEq ) ]
321
321
enum HasTestSignature {
322
322
Yes ,
323
- No ,
323
+ No ( BadTestSignature ) ,
324
+ }
325
+
326
+ #[ derive( PartialEq ) ]
327
+ enum BadTestSignature {
324
328
NotEvenAFunction ,
329
+ WrongTypeSignature ,
330
+ NoArgumentsAllowed ,
331
+ ShouldPanicOnlyWithNoArgs ,
325
332
}
326
333
327
334
fn is_test_fn ( cx : & TestCtxt , i : & ast:: Item ) -> bool {
328
335
let has_test_attr = attr:: contains_name ( & i. attrs , "test" ) ;
329
336
330
337
fn has_test_signature ( cx : & TestCtxt , i : & ast:: Item ) -> HasTestSignature {
338
+ let has_should_panic_attr = attr:: contains_name ( & i. attrs , "should_panic" ) ;
331
339
match i. node {
332
340
ast:: ItemKind :: Fn ( ref decl, _, _, _, ref generics, _) => {
333
341
// If the termination trait is active, the compiler will check that the output
334
342
// type implements the `Termination` trait as `libtest` enforces that.
335
- let output_matches = if cx. features . termination_trait_test {
336
- true
337
- } else {
338
- let no_output = match decl. output {
339
- ast:: FunctionRetTy :: Default ( ..) => true ,
340
- ast:: FunctionRetTy :: Ty ( ref t) if t. node == ast:: TyKind :: Tup ( vec ! [ ] ) => true ,
341
- _ => false
342
- } ;
343
-
344
- no_output && !generics. is_parameterized ( )
343
+ let has_output = match decl. output {
344
+ ast:: FunctionRetTy :: Default ( ..) => false ,
345
+ ast:: FunctionRetTy :: Ty ( ref t) if t. node == ast:: TyKind :: Tup ( vec ! [ ] ) => false ,
346
+ _ => true
345
347
} ;
346
348
347
- if decl. inputs . is_empty ( ) && output_matches {
348
- Yes
349
- } else {
350
- No
349
+ if !decl. inputs . is_empty ( ) {
350
+ return No ( BadTestSignature :: NoArgumentsAllowed ) ;
351
+ }
352
+
353
+ match ( has_output, cx. features . termination_trait_test , has_should_panic_attr) {
354
+ ( true , true , true ) => No ( BadTestSignature :: ShouldPanicOnlyWithNoArgs ) ,
355
+ ( true , true , false ) => if generics. is_parameterized ( ) {
356
+ No ( BadTestSignature :: WrongTypeSignature )
357
+ } else {
358
+ Yes
359
+ } ,
360
+ ( true , false , _) => No ( BadTestSignature :: WrongTypeSignature ) ,
361
+ ( false , _, _) => Yes
351
362
}
352
363
}
353
- _ => NotEvenAFunction ,
364
+ _ => No ( BadTestSignature :: NotEvenAFunction ) ,
354
365
}
355
366
}
356
367
357
368
let has_test_signature = if has_test_attr {
358
369
let diag = cx. span_diagnostic ;
359
370
match has_test_signature ( cx, i) {
360
371
Yes => true ,
361
- No => {
362
- if cx. features . termination_trait_test {
363
- diag. span_err ( i. span , "functions used as tests can not have any arguments" ) ;
364
- } else {
365
- diag. span_err ( i. span , "functions used as tests must have signature fn() -> ()" ) ;
372
+ No ( cause) => {
373
+ match cause {
374
+ BadTestSignature :: NotEvenAFunction =>
375
+ diag. span_err ( i. span , "only functions may be used as tests" ) ,
376
+ BadTestSignature :: WrongTypeSignature =>
377
+ diag. span_err ( i. span ,
378
+ "functions used as tests must have signature fn() -> ()" ) ,
379
+ BadTestSignature :: NoArgumentsAllowed =>
380
+ diag. span_err ( i. span , "functions used as tests can not have any arguments" ) ,
381
+ BadTestSignature :: ShouldPanicOnlyWithNoArgs =>
382
+ diag. span_err ( i. span , "functions using `#[should_panic]` must return `()`" ) ,
366
383
}
367
384
false
368
- } ,
369
- NotEvenAFunction => {
370
- diag. span_err ( i. span , "only functions may be used as tests" ) ;
371
- false
372
- } ,
385
+ }
373
386
}
374
387
} else {
375
388
false
@@ -407,7 +420,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
407
420
// well before resolve, can't get too deep.
408
421
input_cnt == 1 && output_matches
409
422
}
410
- _ => false
423
+ _ => false
411
424
}
412
425
}
413
426
0 commit comments