Point at function name span

This commit is contained in:
Esteban Küber 2018-12-30 15:41:19 -08:00
parent 1f65dc0770
commit f62f540b4e
17 changed files with 132 additions and 77 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 `()`

View File

@ -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
|

View File

@ -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 `()`

View File

@ -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 `()`

View File

@ -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

View File

@ -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 `()`

View File

@ -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
|

View File

@ -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 `()`

View File

@ -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 `()`

View File

@ -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 `()`

View File

@ -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 `()`

View File

@ -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 `()`

View File

@ -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 `()`