@@ -320,56 +320,69 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
320320#[ derive( PartialEq ) ]
321321enum HasTestSignature {
322322 Yes ,
323- No ,
323+ No ( BadTestSignature ) ,
324+ }
325+
326+ #[ derive( PartialEq ) ]
327+ enum BadTestSignature {
324328 NotEvenAFunction ,
329+ WrongTypeSignature ,
330+ NoArgumentsAllowed ,
331+ ShouldPanicOnlyWithNoArgs ,
325332}
326333
327334fn is_test_fn ( cx : & TestCtxt , i : & ast:: Item ) -> bool {
328335 let has_test_attr = attr:: contains_name ( & i. attrs , "test" ) ;
329336
330337 fn has_test_signature ( cx : & TestCtxt , i : & ast:: Item ) -> HasTestSignature {
338+ let has_should_panic_attr = attr:: contains_name ( & i. attrs , "should_panic" ) ;
331339 match i. node {
332340 ast:: ItemKind :: Fn ( ref decl, _, _, _, ref generics, _) => {
333341 // If the termination trait is active, the compiler will check that the output
334342 // 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
345347 } ;
346348
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
351362 }
352363 }
353- _ => NotEvenAFunction ,
364+ _ => No ( BadTestSignature :: NotEvenAFunction ) ,
354365 }
355366 }
356367
357368 let has_test_signature = if has_test_attr {
358369 let diag = cx. span_diagnostic ;
359370 match has_test_signature ( cx, i) {
360371 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 `()`" ) ,
366383 }
367384 false
368- } ,
369- NotEvenAFunction => {
370- diag. span_err ( i. span , "only functions may be used as tests" ) ;
371- false
372- } ,
385+ }
373386 }
374387 } else {
375388 false
@@ -407,7 +420,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
407420 // well before resolve, can't get too deep.
408421 input_cnt == 1 && output_matches
409422 }
410- _ => false
423+ _ => false
411424 }
412425 }
413426
0 commit comments