about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-11-11 20:51:38 +0530
committerGitHub <noreply@github.com>2022-11-11 20:51:38 +0530
commitbc9567fbf67977621663612450dc16a9fd4262a6 (patch)
tree0ae4d6b662e806664ae1dc1fcc409a8a7e52a4a6
parent978e7abeceed3c4d0d6c729c9e492890f478e8e1 (diff)
parent449a4404f5216a085cc0aa89042b39a4bdff5b51 (diff)
downloadrust-bc9567fbf67977621663612450dc16a9fd4262a6.tar.gz
rust-bc9567fbf67977621663612450dc16a9fd4262a6.zip
Rollup merge of #103445 - fmease:fix-50291, r=estebank
`#[test]`: Point at return type if `Termination` bound is unsatisfied

Together with #103142 (already merged) this fully fixes #50291.

I don't consider my current solution of changing a few spans “here and there” very clean since the
failed obligation is a `FunctionArgumentObligation` and we point at a type instead of a function argument.

If you agree with me on this point, I can offer to keep the spans of the existing nodes and instead inject
`let _: AssertRetTyIsTermination<$ret_ty>;` (type to be defined in `libtest`) similar to `AssertParamIsEq` etc.
used by some built-in derive-macros.

I haven't tried that approach yet though and cannot promise that it would actually work out or
be “cleaner” for that matter.

````@rustbot```` label A-libtest A-diagnostics
r? ````@estebank````
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs18
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr12
2 files changed, 17 insertions, 13 deletions
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index fee5d04cdae..b62840d4bc8 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -112,7 +112,7 @@ pub fn expand_test_or_bench(
     };
 
     // Note: non-associated fn items are already handled by `expand_test_or_bench`
-    if !matches!(item.kind, ast::ItemKind::Fn(_)) {
+    let ast::ItemKind::Fn(fn_) = &item.kind else {
         let diag = &cx.sess.parse_sess.span_diagnostic;
         let msg = "the `#[test]` attribute may only be used on a non-associated function";
         let mut err = match item.kind {
@@ -130,7 +130,7 @@ pub fn expand_test_or_bench(
             .emit();
 
         return vec![Annotatable::Item(item)];
-    }
+    };
 
     // has_*_signature will report any errors in the type so compilation
     // will fail. We shouldn't try to expand in this case because the errors
@@ -141,12 +141,14 @@ pub fn expand_test_or_bench(
         return vec![Annotatable::Item(item)];
     }
 
-    let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp));
+    let sp = cx.with_def_site_ctxt(item.span);
+    let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span());
+    let attr_sp = cx.with_def_site_ctxt(attr_sp);
 
     let test_id = Ident::new(sym::test, attr_sp);
 
     // creates test::$name
-    let test_path = |name| cx.path(sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
+    let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
 
     // creates test::ShouldPanic::$name
     let should_panic_path = |name| {
@@ -192,7 +194,7 @@ pub fn expand_test_or_bench(
                         vec![
                             // super::$test_fn(b)
                             cx.expr_call(
-                                sp,
+                                ret_ty_sp,
                                 cx.expr_path(cx.path(sp, vec![item.ident])),
                                 vec![cx.expr_ident(sp, b)],
                             ),
@@ -216,7 +218,11 @@ pub fn expand_test_or_bench(
                         cx.expr_path(test_path("assert_test_result")),
                         vec![
                             // $test_fn()
-                            cx.expr_call(sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![]), // )
+                            cx.expr_call(
+                                ret_ty_sp,
+                                cx.expr_path(cx.path(sp, vec![item.ident])),
+                                vec![],
+                            ), // )
                         ],
                     ), // }
                 ), // )
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index 6ee32314607..9577952119a 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -1,12 +1,10 @@
 error[E0277]: the trait bound `f32: Termination` is not satisfied
-  --> $DIR/termination-trait-test-wrong-type.rs:6:1
+  --> $DIR/termination-trait-test-wrong-type.rs:6:31
    |
-LL |   #[test]
-   |   ------- in this procedural macro expansion
-LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
-LL | |     "0".parse()
-LL | | }
-   | |_^ the trait `Termination` is not implemented for `f32`
+LL | #[test]
+   | ------- in this procedural macro expansion
+LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`
    |
    = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
 note: required by a bound in `assert_test_result`