about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-12-20 14:00:30 -0800
committerEsteban Küber <esteban@kuber.com.ar>2018-12-20 14:00:30 -0800
commit59f643fc5f7f9de0896680ec41fc64087311bead (patch)
treef1168d351e08550a2b193cbe5b6fb5553cc85212
parentf4a421ee3cf1259f0750ac7fabd19da1d8551e4c (diff)
downloadrust-59f643fc5f7f9de0896680ec41fc64087311bead.tar.gz
rust-59f643fc5f7f9de0896680ec41fc64087311bead.zip
Point to return span when writing `return;` on non-() fn
-rw-r--r--src/librustc/hir/mod.rs9
-rw-r--r--src/librustc_typeck/check/coercion.rs3
-rw-r--r--src/librustc_typeck/check/mod.rs19
-rw-r--r--src/test/ui/error-codes/E0069.stderr4
-rw-r--r--src/test/ui/ret-non-nil.stderr4
-rw-r--r--src/test/ui/return/return-unit-from-diverging.stderr4
6 files changed, 37 insertions, 6 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 156d55b9e2f..58733a83b25 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1979,6 +1979,15 @@ pub enum FunctionRetTy {
     Return(P<Ty>),
 }
 
+impl fmt::Display for FunctionRetTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Return(ref ty) => print::to_string(print::NO_ANN, |s| s.print_type(ty)).fmt(f),
+            DefaultReturn(_) => "()".fmt(f),
+        }
+    }
+}
+
 impl FunctionRetTy {
     pub fn span(&self) -> Span {
         match *self {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 8d844fe3a69..0b99a30b67d 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1143,7 +1143,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
             // `expression_ty` will be unit).
             //
             // Another example is `break` with no argument expression.
-            assert!(expression_ty.is_unit());
             assert!(expression_ty.is_unit(), "if let hack without unit type");
             fcx.at(cause, fcx.param_env)
                .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
@@ -1190,7 +1189,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                         db = struct_span_err!(
                             fcx.tcx.sess, cause.span, E0069,
                             "`return;` in a function whose return type is not `()`");
-                        db.span_label(cause.span, "return type is not ()");
+                        db.span_label(cause.span, "return type is not `()`");
                     }
                     ObligationCauseCode::BlockTailExpression(blk_id) => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 8901f4b6b29..d40afbbc302 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4103,7 +4103,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 } else {
                     let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
                     let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
-                    coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
+                    if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
+                        coercion.coerce_forced_unit(
+                            self,
+                            &cause,
+                            &mut |db| {
+                                db.span_label(
+                                    fn_decl.output.span(),
+                                    format!(
+                                        "expected `{}` because of this return type",
+                                        fn_decl.output,
+                                    ),
+                                );
+                            },
+                            true,
+                        );
+                    } else {
+                        coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
+                    }
                 }
                 tcx.types.never
             }
diff --git a/src/test/ui/error-codes/E0069.stderr b/src/test/ui/error-codes/E0069.stderr
index 0ba1ed45663..12b778f42e2 100644
--- a/src/test/ui/error-codes/E0069.stderr
+++ b/src/test/ui/error-codes/E0069.stderr
@@ -1,8 +1,10 @@
 error[E0069]: `return;` in a function whose return type is not `()`
   --> $DIR/E0069.rs:12:5
    |
+LL | fn foo() -> u8 {
+   |             -- expected `u8` because of this return type
 LL |     return;
-   |     ^^^^^^ return type is not ()
+   |     ^^^^^^ return type is not `()`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/ret-non-nil.stderr b/src/test/ui/ret-non-nil.stderr
index 01f126bd11e..e0fdc8c67ed 100644
--- a/src/test/ui/ret-non-nil.stderr
+++ b/src/test/ui/ret-non-nil.stderr
@@ -2,7 +2,9 @@ error[E0069]: `return;` in a function whose return type is not `()`
   --> $DIR/ret-non-nil.rs:15:19
    |
 LL | fn g() -> isize { return; }
-   |                   ^^^^^^ return type is not ()
+   |           -----   ^^^^^^ return type is not `()`
+   |           |
+   |           expected `isize` because of this return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/return/return-unit-from-diverging.stderr b/src/test/ui/return/return-unit-from-diverging.stderr
index 38d4ca37366..5a9f0877cc6 100644
--- a/src/test/ui/return/return-unit-from-diverging.stderr
+++ b/src/test/ui/return/return-unit-from-diverging.stderr
@@ -1,8 +1,10 @@
 error[E0069]: `return;` in a function whose return type is not `()`
   --> $DIR/return-unit-from-diverging.rs:15:5
    |
+LL | fn fail() -> ! {
+   |              - expected `!` because of this return type
 LL |     return; //~ ERROR in a function whose return type is not
-   |     ^^^^^^ return type is not ()
+   |     ^^^^^^ return type is not `()`
 
 error: aborting due to previous error