Skip to content

Commit f142499

Browse files
committed
Auto merge of #43484 - estebank:point-to-return, r=arielb1
Point at return type always when type mismatch against it Before this, the diagnostic errors would only point at the return type when changing it would be a possible solution to a type error. Add a label to the return type without a suggestion to change in order to make the source of the expected type obvious. Follow up to #42850, fixes #25133, fixes #41897.
2 parents 33d7194 + 9bd62a4 commit f142499

File tree

8 files changed

+71
-26
lines changed

8 files changed

+71
-26
lines changed

src/librustc/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ impl<'tcx> TyS<'tcx> {
491491
TypeVariants::TyFnPtr(..) |
492492
TypeVariants::TyDynamic(..) |
493493
TypeVariants::TyClosure(..) |
494+
TypeVariants::TyInfer(..) |
494495
TypeVariants::TyProjection(..) => false,
495496
_ => true,
496497
}

src/librustc_typeck/check/mod.rs

+42-19
Original file line numberDiff line numberDiff line change
@@ -4229,8 +4229,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42294229
ty
42304230
}
42314231

4232-
/// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is
4233-
/// `fn main` if it is a method, `None` otherwise.
4232+
/// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether a
4233+
/// suggetion can be made, `None` otherwise.
42344234
pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
42354235
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
42364236
// `while` before reaching it, as block tail returns are not available in them.
@@ -4241,14 +4241,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42414241
name, node: hir::ItemFn(ref decl, ..), ..
42424242
}) = parent {
42434243
decl.clone().and_then(|decl| {
4244-
// This is less than ideal, it will not present the return type span on any
4245-
// method called `main`, regardless of whether it is actually the entry point.
4246-
Some((decl, name == Symbol::intern("main")))
4244+
// This is less than ideal, it will not suggest a return type span on any
4245+
// method called `main`, regardless of whether it is actually the entry point,
4246+
// but it will still present it as the reason for the expected type.
4247+
Some((decl, name != Symbol::intern("main")))
42474248
})
42484249
} else if let Node::NodeTraitItem(&hir::TraitItem {
42494250
node: hir::TraitItemKind::Method(hir::MethodSig {
42504251
ref decl, ..
42514252
}, ..), ..
4253+
}) = parent {
4254+
decl.clone().and_then(|decl| {
4255+
Some((decl, true))
4256+
})
4257+
} else if let Node::NodeImplItem(&hir::ImplItem {
4258+
node: hir::ImplItemKind::Method(hir::MethodSig {
4259+
ref decl, ..
4260+
}, ..), ..
42524261
}) = parent {
42534262
decl.clone().and_then(|decl| {
42544263
Some((decl, false))
@@ -4275,11 +4284,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42754284
blk_id: ast::NodeId) {
42764285
self.suggest_missing_semicolon(err, expression, expected, cause_span);
42774286

4278-
if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) {
4279-
// `fn main()` must return `()`, do not suggest changing return type
4280-
if !is_main {
4281-
self.suggest_missing_return_type(err, &fn_decl, found);
4282-
}
4287+
if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
4288+
self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
42834289
}
42844290
}
42854291

@@ -4335,20 +4341,37 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
43354341
fn suggest_missing_return_type(&self,
43364342
err: &mut DiagnosticBuilder<'tcx>,
43374343
fn_decl: &hir::FnDecl,
4338-
ty: Ty<'tcx>) {
4339-
4340-
// Only recommend changing the return type for methods that
4344+
expected: Ty<'tcx>,
4345+
found: Ty<'tcx>,
4346+
can_suggest: bool) {
4347+
// Only suggest changing the return type for methods that
43414348
// haven't set a return type at all (and aren't `fn main()` or an impl).
4342-
if let &hir::FnDecl {
4343-
output: hir::FunctionRetTy::DefaultReturn(span), ..
4344-
} = fn_decl {
4345-
if ty.is_suggestable() {
4349+
match (&fn_decl.output, found.is_suggestable(), can_suggest) {
4350+
(&hir::FunctionRetTy::DefaultReturn(span), true, true) => {
43464351
err.span_suggestion(span,
43474352
"try adding a return type",
4348-
format!("-> {} ", ty));
4349-
} else {
4353+
format!("-> {} ", found));
4354+
}
4355+
(&hir::FunctionRetTy::DefaultReturn(span), false, true) => {
43504356
err.span_label(span, "possibly return type missing here?");
43514357
}
4358+
(&hir::FunctionRetTy::DefaultReturn(span), _, _) => {
4359+
// `fn main()` must return `()`, do not suggest changing return type
4360+
err.span_label(span, "expected `()` because of default return type");
4361+
}
4362+
(&hir::FunctionRetTy::Return(ref ty), _, _) => {
4363+
// Only point to return type if the expected type is the return type, as if they
4364+
// are not, the expectation must have been caused by something else.
4365+
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.node);
4366+
let sp = ty.span;
4367+
let ty = AstConv::ast_ty_to_ty(self, ty);
4368+
debug!("suggest_missing_return_type: return type sty {:?}", ty.sty);
4369+
debug!("suggest_missing_return_type: expected type sty {:?}", ty.sty);
4370+
if ty.sty == expected.sty {
4371+
err.span_label(sp, format!("expected `{}` because of return type",
4372+
expected));
4373+
}
4374+
}
43524375
}
43534376
}
43544377

src/test/compile-fail/struct-path-self-type-mismatch.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,15 @@ impl Bar for Foo<i32> {
2020
}
2121

2222
impl<T> Foo<T> {
23-
fn new<U>(u: U) -> Foo<U> {
23+
fn new<U>(u: U) -> Foo<U> { //~ NOTE expected `Foo<U>` because of return type
2424
Self {
2525
//~^ ERROR mismatched types
26-
//~| expected type parameter, found a different type parameter
27-
//~| expected type `Foo<U>`
28-
//~| found type `Foo<T>`
26+
//~| NOTE expected type parameter, found a different type parameter
27+
//~| NOTE expected type `Foo<U>`
2928
inner: u
3029
//~^ ERROR mismatched types
31-
//~| expected type parameter, found a different type parameter
32-
//~| expected type `T`
33-
//~| found type `U`
30+
//~| NOTE expected type parameter, found a different type parameter
31+
//~| NOTE expected type `T`
3432
}
3533
}
3634
}

src/test/ui/block-result/block-must-not-have-result-res.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0308]: mismatched types
22
--> $DIR/block-must-not-have-result-res.rs:15:9
33
|
4+
14 | fn drop(&mut self) {
5+
| - expected `()` because of default return type
46
15 | true //~ ERROR mismatched types
57
| ^^^^ expected (), found bool
68
|

src/test/ui/block-result/issue-13624.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0308]: mismatched types
22
--> $DIR/issue-13624.rs:17:5
33
|
4+
16 | pub fn get_enum_struct_variant() -> () {
5+
| -- expected `()` because of return type
46
17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
57
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
68
|

src/test/ui/block-result/issue-22645.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
1111
error[E0308]: mismatched types
1212
--> $DIR/issue-22645.rs:25:3
1313
|
14+
23 | fn main() {
15+
| - expected `()` because of default return type
16+
24 | let b = Bob + 3.5;
1417
25 | b + 3 //~ ERROR E0277
1518
| ^^^^^ expected (), found struct `Bob`
1619
|

src/test/ui/block-result/issue-5500.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0308]: mismatched types
22
--> $DIR/issue-5500.rs:12:5
33
|
4+
11 | fn main() {
5+
| - expected `()` because of default return type
46
12 | &panic!()
57
| ^^^^^^^^^ expected (), found reference
68
|

src/test/ui/mismatched_types/abridged.stderr

+14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0308]: mismatched types
22
--> $DIR/abridged.rs:26:5
33
|
4+
25 | fn a() -> Foo {
5+
| --- expected `Foo` because of return type
46
26 | Some(Foo { bar: 1 })
57
| ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option`
68
|
@@ -10,6 +12,8 @@ error[E0308]: mismatched types
1012
error[E0308]: mismatched types
1113
--> $DIR/abridged.rs:30:5
1214
|
15+
29 | fn a2() -> Foo {
16+
| --- expected `Foo` because of return type
1317
30 | Ok(Foo { bar: 1})
1418
| ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result`
1519
|
@@ -19,6 +23,8 @@ error[E0308]: mismatched types
1923
error[E0308]: mismatched types
2024
--> $DIR/abridged.rs:34:5
2125
|
26+
33 | fn b() -> Option<Foo> {
27+
| ----------- expected `std::option::Option<Foo>` because of return type
2228
34 | Foo { bar: 1 }
2329
| ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
2430
|
@@ -28,6 +34,8 @@ error[E0308]: mismatched types
2834
error[E0308]: mismatched types
2935
--> $DIR/abridged.rs:38:5
3036
|
37+
37 | fn c() -> Result<Foo, Bar> {
38+
| ---------------- expected `std::result::Result<Foo, Bar>` because of return type
3139
38 | Foo { bar: 1 }
3240
| ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
3341
|
@@ -37,6 +45,9 @@ error[E0308]: mismatched types
3745
error[E0308]: mismatched types
3846
--> $DIR/abridged.rs:49:5
3947
|
48+
41 | fn d() -> X<X<String, String>, String> {
49+
| ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type
50+
...
4051
49 | x
4152
| ^ expected struct `std::string::String`, found integral variable
4253
|
@@ -46,6 +57,9 @@ error[E0308]: mismatched types
4657
error[E0308]: mismatched types
4758
--> $DIR/abridged.rs:60:5
4859
|
60+
52 | fn e() -> X<X<String, String>, String> {
61+
| ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type
62+
...
4963
60 | x
5064
| ^ expected struct `std::string::String`, found integral variable
5165
|

0 commit comments

Comments
 (0)