about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-01-20 18:42:10 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-01-20 18:42:10 -0800
commite33f7f7de1df090f890063296608dca65be55ac0 (patch)
tree270de458d4e9b868bebde2018f8ecd0caaf926bc
parente73069767f11d992f0dca7e31d53d7e1a77fd237 (diff)
downloadrust-e33f7f7de1df090f890063296608dca65be55ac0.tar.gz
rust-e33f7f7de1df090f890063296608dca65be55ac0.zip
Explain type mismatch cause pointing to return type when it is `impl Trait`
-rw-r--r--src/librustc_typeck/check/coercion.rs29
-rw-r--r--src/test/ui/impl-trait/equality.stderr5
-rw-r--r--src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr14
3 files changed, 39 insertions, 9 deletions
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index dd63b4f20fa..e3aae21584c 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1199,7 +1199,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                     (self.final_ty.unwrap_or(self.expected_ty), expression_ty)
                 };
 
-                let reason_label = "expected because of this statement";
                 let mut db;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
@@ -1244,9 +1243,19 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                         // as prior return coercions would not be relevant (#57664).
                         let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
                         let parent = fcx.tcx.hir().get(fcx.tcx.hir().get_parent_node(parent_id));
-                        if fcx.get_node_fn_decl(parent).is_some() && !pointing_at_return_type {
+                        if let (Some((fn_decl, _, _)), false) = (
+                            fcx.get_node_fn_decl(parent),
+                            pointing_at_return_type,
+                        ) {
                             if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
-                                db.span_label(*sp, reason_label);
+                                db.span_label(
+                                    fn_decl.output.span(),
+                                    "expected because this return type...",
+                                );
+                                db.span_label(*sp, format!(
+                                    "...is found to be `{}` here",
+                                    fcx.resolve_type_vars_with_obligations(expected),
+                                ));
                             }
                         }
                     }
@@ -1254,16 +1263,26 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                         db = fcx.report_mismatched_types(cause, expected, found, err);
                         let _id = fcx.tcx.hir().get_parent_node(_id);
                         let mut pointing_at_return_type = false;
+                        let mut return_sp = None;
                         if let Some((fn_decl, can_suggest)) = fcx.get_fn_decl(_id) {
                             pointing_at_return_type = fcx.suggest_missing_return_type(
                                 &mut db, &fn_decl, expected, found, can_suggest);
+                            if !pointing_at_return_type {
+                                return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
+                            }
                         }
                         if let (Some(sp), false) = (
                             fcx.ret_coercion_span.borrow().as_ref(),
                             pointing_at_return_type,
                         ) {
-                            if !sp.overlaps(cause.span) {
-                                db.span_label(*sp, reason_label);
+                            if let Some(return_sp) = return_sp {
+                                db.span_label(return_sp, "expected because this return type...");
+                                db.span_label( *sp, format!(
+                                    "...is found to be `{}` here",
+                                    fcx.resolve_type_vars_with_obligations(expected),
+                                ));
+                            } else if !sp.overlaps(cause.span) {
+                                db.span_label(*sp, "expected because of this statement");
                             }
                         }
                     }
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 57bd70de7c6..6cd9d07748c 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -1,8 +1,11 @@
 error[E0308]: mismatched types
   --> $DIR/equality.rs:15:5
    |
+LL | fn two(x: bool) -> impl Foo {
+   |                    -------- expected because this return type...
+LL |     if x {
 LL |         return 1_i32;
-   |                ----- expected because of this statement
+   |                ----- ...is found to be `i32` here
 LL |     }
 LL |     0_u32
    |     ^^^^^ expected i32, found u32
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
index 62da0787b02..5ebe00e624f 100644
--- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -1,8 +1,11 @@
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
    |
+LL | fn foo() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
 LL |         return 0i32;
-   |                ---- expected because of this statement
+   |                ---- ...is found to be `i32` here
 LL |     }
 LL |     1u32
    |     ^^^^ expected i32, found u32
@@ -13,8 +16,11 @@ LL |     1u32
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
    |
+LL | fn bar() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
 LL |         return 0i32;
-   |                ---- expected because of this statement
+   |                ---- ...is found to be `i32` here
 LL |     } else {
 LL |         return 1u32;
    |                ^^^^ expected i32, found u32
@@ -25,10 +31,12 @@ LL |         return 1u32;
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
    |
+LL |   fn baz() -> impl std::fmt::Display {
+   |               ---------------------- expected because this return type...
 LL | /     if false {
 LL | |     //~^ ERROR mismatched types
 LL | |         return 0i32;
-   | |                ---- expected because of this statement
+   | |                ---- ...is found to be `i32` here
 LL | |     } else {
 LL | |         1u32
 LL | |     }