about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/check/mod.rs108
-rw-r--r--src/test/ui/block-result/consider-removing-last-semi.stderr8
-rw-r--r--src/test/ui/block-result/issue-11714.stderr4
-rw-r--r--src/test/ui/block-result/issue-13428.stderr8
-rw-r--r--src/test/ui/break-while-condition.stderr4
-rw-r--r--src/test/ui/coercion/coercion-missing-tail-expected-type.stderr8
-rw-r--r--src/test/ui/issues/issue-10536.stderr4
-rw-r--r--src/test/ui/issues/issue-32323.stderr4
-rw-r--r--src/test/ui/issues/issue-43162.stderr4
-rw-r--r--src/test/ui/issues/issue-44023.stderr4
-rw-r--r--src/test/ui/issues/issue-6458-4.stderr4
-rw-r--r--src/test/ui/liveness/liveness-closure-require-ret.stderr6
-rw-r--r--src/test/ui/liveness/liveness-forgot-ret.stderr5
-rw-r--r--src/test/ui/liveness/liveness-issue-2163.stderr11
-rw-r--r--src/test/ui/liveness/liveness-missing-ret2.stderr4
-rw-r--r--src/test/ui/liveness/liveness-return-last-stmt-semi.stderr19
-rw-r--r--src/test/ui/missing/missing-return.stderr4
17 files changed, 132 insertions, 77 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index aa13087b484..381abcb977b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4796,16 +4796,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     // `consider_hint_about_removing_semicolon` will point at the last expression
                     // if it were a relevant part of the error. This improves usability in editors
                     // that highlight errors inline.
-                    let sp = if let Some((decl, _)) = self.get_fn_decl(blk.id) {
-                        decl.output.span()
+                    let (sp, fn_span) = if let Some((decl, ident)) = self.get_parent_fn_decl(blk.id) {
+                        (decl.output.span(), Some(ident.span))
                     } else {
-                        blk.span
+                        (blk.span, None)
                     };
                     coerce.coerce_forced_unit(self, &self.misc(sp), &mut |err| {
                         if let Some(expected_ty) = expected.only_has_type(self) {
-                            self.consider_hint_about_removing_semicolon(blk,
-                                                                        expected_ty,
-                                                                        err);
+                            self.consider_hint_about_removing_semicolon(blk, expected_ty, err);
+                        }
+                        if let Some(fn_span) = fn_span {
+                            err.span_label(
+                                fn_span,
+                                "this function's body doesn't return the expected type",
+                            );
                         }
                     }, false);
                 }
@@ -4830,45 +4834,53 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         ty
     }
 
+    /// Given a function block's `NodeId`, return its `FnDecl` , `None` otherwise.
+    fn get_parent_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, ast::Ident)> {
+        let parent = self.tcx.hir().get(self.tcx.hir().get_parent(blk_id));
+        self.get_node_fn_decl(parent).map(|(fn_decl, ident , _)| (fn_decl, ident))
+    }
+
+    /// Given a function `Node`, return its `FnDecl` , `None` otherwise.
+    fn get_node_fn_decl(&self, node: Node) -> Option<(hir::FnDecl, ast::Ident, bool)> {
+        if let Node::Item(&hir::Item {
+            ident, node: hir::ItemKind::Fn(ref decl, ..), ..
+        }) = node {
+            decl.clone().and_then(|decl| {
+                // This is less than ideal, it will not suggest a return type span on any
+                // method called `main`, regardless of whether it is actually the entry point,
+                // but it will still present it as the reason for the expected type.
+                Some((decl, ident, ident.name != Symbol::intern("main")))
+            })
+        } else if let Node::TraitItem(&hir::TraitItem {
+            ident, node: hir::TraitItemKind::Method(hir::MethodSig {
+                ref decl, ..
+            }, ..), ..
+        }) = node {
+            decl.clone().and_then(|decl| {
+                Some((decl, ident, true))
+            })
+        } else if let Node::ImplItem(&hir::ImplItem {
+            ident, node: hir::ImplItemKind::Method(hir::MethodSig {
+                ref decl, ..
+            }, ..), ..
+        }) = node {
+            decl.clone().and_then(|decl| {
+                Some((decl, ident, false))
+            })
+        } else {
+            None
+        }
+    }
+
     /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether a
     /// suggestion can be made, `None` otherwise.
     pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
         // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
         // `while` before reaching it, as block tail returns are not available in them.
-        if let Some(fn_id) = self.tcx.hir().get_return_block(blk_id) {
-            let parent = self.tcx.hir().get(fn_id);
-
-            if let Node::Item(&hir::Item {
-                ident, node: hir::ItemKind::Fn(ref decl, ..), ..
-            }) = parent {
-                decl.clone().and_then(|decl| {
-                    // This is less than ideal, it will not suggest a return type span on any
-                    // method called `main`, regardless of whether it is actually the entry point,
-                    // but it will still present it as the reason for the expected type.
-                    Some((decl, ident.name != Symbol::intern("main")))
-                })
-            } else if let Node::TraitItem(&hir::TraitItem {
-                node: hir::TraitItemKind::Method(hir::MethodSig {
-                    ref decl, ..
-                }, ..), ..
-            }) = parent {
-                decl.clone().and_then(|decl| {
-                    Some((decl, true))
-                })
-            } else if let Node::ImplItem(&hir::ImplItem {
-                node: hir::ImplItemKind::Method(hir::MethodSig {
-                    ref decl, ..
-                }, ..), ..
-            }) = parent {
-                decl.clone().and_then(|decl| {
-                    Some((decl, false))
-                })
-            } else {
-                None
-            }
-        } else {
-            None
-        }
+        self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
+            let parent = self.tcx.hir().get(blk_id);
+            self.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
+        })
     }
 
     /// On implicit return expressions with mismatched types, provide the following suggestions:
@@ -4876,13 +4888,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     ///  - Point out the method's return type as the reason for the expected type
     ///  - Possible missing semicolon
     ///  - Possible missing return type if the return type is the default, and not `fn main()`
-    pub fn suggest_mismatched_types_on_tail(&self,
-                                            err: &mut DiagnosticBuilder<'tcx>,
-                                            expression: &'gcx hir::Expr,
-                                            expected: Ty<'tcx>,
-                                            found: Ty<'tcx>,
-                                            cause_span: Span,
-                                            blk_id: ast::NodeId) {
+    pub fn suggest_mismatched_types_on_tail(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        expression: &'gcx hir::Expr,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+        cause_span: Span,
+        blk_id: ast::NodeId,
+    ) {
         self.suggest_missing_semicolon(err, expression, expected, cause_span);
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
             self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr
index ce8c624cdad..79e7a536cdc 100644
--- a/src/test/ui/block-result/consider-removing-last-semi.stderr
+++ b/src/test/ui/block-result/consider-removing-last-semi.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/consider-removing-last-semi.rs:1:11
    |
 LL | fn f() -> String {  //~ ERROR mismatched types
-   |           ^^^^^^ expected struct `std::string::String`, found ()
+   |    -      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     0u8;
 LL |     "bla".to_string();
    |                      - help: consider removing this semicolon
@@ -14,7 +16,9 @@ error[E0308]: mismatched types
   --> $DIR/consider-removing-last-semi.rs:6:11
    |
 LL | fn g() -> String {  //~ ERROR mismatched types
-   |           ^^^^^^ expected struct `std::string::String`, found ()
+   |    -      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     "this won't work".to_string();
 LL |     "removeme".to_string();
    |                           - help: consider removing this semicolon
diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr
index cc97eaf8e1a..82253911316 100644
--- a/src/test/ui/block-result/issue-11714.stderr
+++ b/src/test/ui/block-result/issue-11714.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-11714.rs:1:14
    |
 LL | fn blah() -> i32 { //~ ERROR mismatched types
-   |              ^^^ expected i32, found ()
+   |    ----      ^^^ expected i32, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 ...
 LL |     ;
    |     - help: consider removing this semicolon
diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr
index d3a2b513137..8b8eb825377 100644
--- a/src/test/ui/block-result/issue-13428.stderr
+++ b/src/test/ui/block-result/issue-13428.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-13428.rs:3:13
    |
 LL | fn foo() -> String {  //~ ERROR mismatched types
-   |             ^^^^^^ expected struct `std::string::String`, found ()
+   |    ---      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 ...
 LL |     ;
    |     - help: consider removing this semicolon
@@ -14,7 +16,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-13428.rs:11:13
    |
 LL | fn bar() -> String {  //~ ERROR mismatched types
-   |             ^^^^^^ expected struct `std::string::String`, found ()
+   |    ---      ^^^^^^ expected struct `std::string::String`, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     "foobar".to_string()
 LL |     ;
    |     - help: consider removing this semicolon
diff --git a/src/test/ui/break-while-condition.stderr b/src/test/ui/break-while-condition.stderr
index 1c48ad630d8..6709747b137 100644
--- a/src/test/ui/break-while-condition.stderr
+++ b/src/test/ui/break-while-condition.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/break-while-condition.rs:3:11
    |
 LL | fn main() {
-   |           ^ expected !, found ()
+   |    ----   ^ expected !, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `!`
               found type `()`
diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
index 27f0540e36e..9ace5b8ad3a 100644
--- a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
+++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/coercion-missing-tail-expected-type.rs:3:24
    |
 LL | fn plus_one(x: i32) -> i32 { //~ ERROR mismatched types
-   |                        ^^^ expected i32, found ()
+   |    --------            ^^^ expected i32, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     x + 1;
    |          - help: consider removing this semicolon
    |
@@ -13,7 +15,9 @@ error[E0308]: mismatched types
   --> $DIR/coercion-missing-tail-expected-type.rs:7:13
    |
 LL | fn foo() -> Result<u8, u64> { //~ ERROR mismatched types
-   |             ^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
+   |    ---      ^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     Ok(1);
    |          - help: consider removing this semicolon
    |
diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/issues/issue-10536.stderr
index 71f9a83316c..02008470e63 100644
--- a/src/test/ui/issues/issue-10536.stderr
+++ b/src/test/ui/issues/issue-10536.stderr
@@ -20,7 +20,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-10536.rs:11:15
    |
 LL | pub fn main() {
-   |               ^ expected bool, found ()
+   |        ----   ^ expected bool, found ()
+   |        |
+   |        this function's body doesn't return the expected type
    |
    = note: expected type `bool`
               found type `()`
diff --git a/src/test/ui/issues/issue-32323.stderr b/src/test/ui/issues/issue-32323.stderr
index 6729fdf726a..bef3596103c 100644
--- a/src/test/ui/issues/issue-32323.stderr
+++ b/src/test/ui/issues/issue-32323.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-32323.rs:5:30
    |
 LL | pub fn f<'a, T: Tr<'a>>() -> <T as Tr<'a>>::Out {}
-   |                              ^^^^^^^^^^^^^^^^^^ expected associated type, found ()
+   |        -                     ^^^^^^^^^^^^^^^^^^ expected associated type, found ()
+   |        |
+   |        this function's body doesn't return the expected type
    |
    = note: expected type `<T as Tr<'a>>::Out`
               found type `()`
diff --git a/src/test/ui/issues/issue-43162.stderr b/src/test/ui/issues/issue-43162.stderr
index d679fbb7262..4d2b3549f8e 100644
--- a/src/test/ui/issues/issue-43162.stderr
+++ b/src/test/ui/issues/issue-43162.stderr
@@ -14,7 +14,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-43162.rs:1:13
    |
 LL | fn foo() -> bool {
-   |             ^^^^ expected bool, found ()
+   |    ---      ^^^^ expected bool, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     //~^ ERROR E0308
 LL |     break true; //~ ERROR E0268
    |               - help: consider removing this semicolon
diff --git a/src/test/ui/issues/issue-44023.stderr b/src/test/ui/issues/issue-44023.stderr
index 55757c1eb93..944098a644d 100644
--- a/src/test/ui/issues/issue-44023.stderr
+++ b/src/test/ui/issues/issue-44023.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-44023.rs:5:36
    |
 LL | fn საჭმელად_გემრიელი_სადილი ( ) -> isize { //~ ERROR mismatched types
-   |                                    ^^^^^ expected isize, found ()
+   |    ------------------------        ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `isize`
               found type `()`
diff --git a/src/test/ui/issues/issue-6458-4.stderr b/src/test/ui/issues/issue-6458-4.stderr
index e487e15c16c..f4cdceac172 100644
--- a/src/test/ui/issues/issue-6458-4.stderr
+++ b/src/test/ui/issues/issue-6458-4.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-6458-4.rs:1:20
    |
 LL | fn foo(b: bool) -> Result<bool,String> { //~ ERROR mismatched types
-   |                    ^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
+   |    ---             ^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     Err("bar".to_string());
    |                           - help: consider removing this semicolon
    |
diff --git a/src/test/ui/liveness/liveness-closure-require-ret.stderr b/src/test/ui/liveness/liveness-closure-require-ret.stderr
index 3133efdedd7..d7992704c50 100644
--- a/src/test/ui/liveness/liveness-closure-require-ret.stderr
+++ b/src/test/ui/liveness/liveness-closure-require-ret.stderr
@@ -1,8 +1,10 @@
 error[E0308]: mismatched types
-  --> $DIR/liveness-closure-require-ret.rs:2:37
+  --> $DIR/liveness-closure-require-ret.rs:2:11
    |
 LL | fn main() { println!("{}", force(|| {})); } //~ ERROR mismatched types
-   |                                     ^^ expected isize, found ()
+   |    ----   ^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `isize`
               found type `()`
diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr
index 8d0eeb35fc3..578890f5e62 100644
--- a/src/test/ui/liveness/liveness-forgot-ret.stderr
+++ b/src/test/ui/liveness/liveness-forgot-ret.stderr
@@ -2,7 +2,10 @@ error[E0308]: mismatched types
   --> $DIR/liveness-forgot-ret.rs:3:19
    |
 LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
-   |                   ^^^^^ expected isize, found ()    - expected because of this statement
+   |    -              ^^^^^                             - expected because of this statement
+   |    |              |
+   |    |              expected isize, found ()
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `isize`
               found type `()`
diff --git a/src/test/ui/liveness/liveness-issue-2163.stderr b/src/test/ui/liveness/liveness-issue-2163.stderr
index e91994d9a22..a8a56842076 100644
--- a/src/test/ui/liveness/liveness-issue-2163.stderr
+++ b/src/test/ui/liveness/liveness-issue-2163.stderr
@@ -1,11 +1,10 @@
 error[E0308]: mismatched types
-  --> $DIR/liveness-issue-2163.rs:5:30
+  --> $DIR/liveness-issue-2163.rs:3:11
    |
-LL |       a.iter().all(|_| -> bool {
-   |  ______________________________^
-LL | |         //~^ ERROR mismatched types
-LL | |     });
-   | |_____^ expected bool, found ()
+LL | fn main() {
+   |    ----   ^ expected bool, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `bool`
               found type `()`
diff --git a/src/test/ui/liveness/liveness-missing-ret2.stderr b/src/test/ui/liveness/liveness-missing-ret2.stderr
index 956b71fcfe8..201b3ee6861 100644
--- a/src/test/ui/liveness/liveness-missing-ret2.stderr
+++ b/src/test/ui/liveness/liveness-missing-ret2.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/liveness-missing-ret2.rs:1:11
    |
 LL | fn f() -> isize { //~ ERROR mismatched types
-   |           ^^^^^ expected isize, found ()
+   |    -      ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `isize`
               found type `()`
diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
index bb4ca303aa7..2ee77f30a66 100644
--- a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
+++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
@@ -2,9 +2,10 @@ error[E0308]: mismatched types
   --> $DIR/liveness-return-last-stmt-semi.rs:4:41
    |
 LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } }
-   |                                         ^^^    - help: consider removing this semicolon
-   |                                         |
-   |                                         expected i32, found ()
+   |                                ---      ^^^    - help: consider removing this semicolon
+   |                                |        |
+   |                                |        expected i32, found ()
+   |                                this function's body doesn't return the expected type
 ...
 LL |     test!();
    |     -------- in this macro invocation
@@ -16,7 +17,9 @@ error[E0308]: mismatched types
   --> $DIR/liveness-return-last-stmt-semi.rs:7:19
    |
 LL | fn no_return() -> i32 {} //~ ERROR mismatched types
-   |                   ^^^ expected i32, found ()
+   |    ---------      ^^^ expected i32, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `i32`
               found type `()`
@@ -25,7 +28,9 @@ error[E0308]: mismatched types
   --> $DIR/liveness-return-last-stmt-semi.rs:9:19
    |
 LL | fn bar(x: u32) -> u32 { //~ ERROR mismatched types
-   |                   ^^^ expected u32, found ()
+   |    ---            ^^^ expected u32, found ()
+   |    |
+   |    this function's body doesn't return the expected type
 LL |     x * 2;
    |          - help: consider removing this semicolon
    |
@@ -36,7 +41,9 @@ error[E0308]: mismatched types
   --> $DIR/liveness-return-last-stmt-semi.rs:13:19
    |
 LL | fn baz(x: u64) -> u32 { //~ ERROR mismatched types
-   |                   ^^^ expected u32, found ()
+   |    ---            ^^^ expected u32, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `u32`
               found type `()`
diff --git a/src/test/ui/missing/missing-return.stderr b/src/test/ui/missing/missing-return.stderr
index be86325de00..9e6ffd97312 100644
--- a/src/test/ui/missing/missing-return.stderr
+++ b/src/test/ui/missing/missing-return.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/missing-return.rs:3:11
    |
 LL | fn f() -> isize { }
-   |           ^^^^^ expected isize, found ()
+   |    -      ^^^^^ expected isize, found ()
+   |    |
+   |    this function's body doesn't return the expected type
    |
    = note: expected type `isize`
               found type `()`