Skip to content

Commit 9050729

Browse files
committed
Do not give incorrect label for return type mismatch
1 parent daa53a5 commit 9050729

5 files changed

+142
-3
lines changed

src/librustc_typeck/check/coercion.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,9 +1224,31 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
12241224
cause.span,
12251225
blk_id,
12261226
);
1227-
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
1228-
if !sp.overlaps(cause.span) {
1229-
db.span_label(*sp, reason_label);
1227+
// TODO: replace with navigating up the chain until hitting an fn or
1228+
// bailing if no "pass-through" Node is found, in order to provide a
1229+
// suggestion when encountering something like:
1230+
// ```
1231+
// fn foo(a: bool) -> impl Debug {
1232+
// if a {
1233+
// bar()?;
1234+
// }
1235+
// {
1236+
// let x = unsafe { bar() };
1237+
// x
1238+
// }
1239+
// }
1240+
// ```
1241+
//
1242+
// Verify that this is a tail expression of a function, otherwise the
1243+
// label pointing out the cause for the type coercion will be wrong
1244+
// as prior return coercions would not be relevant (#57664).
1245+
let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
1246+
let parent = fcx.tcx.hir().get(fcx.tcx.hir().get_parent_node(parent_id));
1247+
if fcx.get_node_fn_decl(parent).is_some() {
1248+
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
1249+
if !sp.overlaps(cause.span) {
1250+
db.span_label(*sp, reason_label);
1251+
}
12301252
}
12311253
}
12321254
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
fn unrelated() -> Result<(), std::string::ParseError> { // #57664
2+
let x = 0;
3+
4+
match x {
5+
1 => {
6+
let property_value_as_string = "a".parse()?;
7+
}
8+
2 => {
9+
let value: &bool = unsafe { &42 };
10+
//~^ ERROR mismatched types
11+
}
12+
};
13+
14+
Ok(())
15+
}
16+
17+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41
3+
|
4+
LL | let value: &bool = unsafe { &42 };
5+
| ^^^ expected bool, found integer
6+
|
7+
= note: expected type `&bool`
8+
found type `&{integer}`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
fn foo() -> impl std::fmt::Display {
2+
if false {
3+
return 0i32;
4+
}
5+
1u32
6+
//~^ ERROR mismatched types
7+
}
8+
9+
fn bar() -> impl std::fmt::Display {
10+
if false {
11+
return 0i32;
12+
} else {
13+
return 1u32;
14+
//~^ ERROR mismatched types
15+
}
16+
}
17+
18+
fn baz() -> impl std::fmt::Display {
19+
if false {
20+
//~^ ERROR mismatched types
21+
return 0i32;
22+
} else {
23+
1u32
24+
}
25+
}
26+
27+
fn qux() -> impl std::fmt::Display {
28+
if false {
29+
//~^ ERROR if and else have incompatible types
30+
0i32
31+
} else {
32+
1u32
33+
}
34+
}
35+
36+
fn main() {}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
3+
|
4+
LL | return 0i32;
5+
| ---- expected because of this statement
6+
LL | }
7+
LL | 1u32
8+
| ^^^^ expected i32, found u32
9+
|
10+
= note: expected type `i32`
11+
found type `u32`
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
15+
|
16+
LL | return 1u32;
17+
| ^^^^ expected i32, found u32
18+
|
19+
= note: expected type `i32`
20+
found type `u32`
21+
22+
error[E0308]: mismatched types
23+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
24+
|
25+
LL | / if false {
26+
LL | | //~^ ERROR mismatched types
27+
LL | | return 0i32;
28+
LL | | } else {
29+
LL | | 1u32
30+
LL | | }
31+
| |_____^ expected i32, found u32
32+
|
33+
= note: expected type `i32`
34+
found type `u32`
35+
36+
error[E0308]: if and else have incompatible types
37+
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:5
38+
|
39+
LL | / if false {
40+
LL | | //~^ ERROR if and else have incompatible types
41+
LL | | 0i32
42+
LL | | } else {
43+
LL | | 1u32
44+
LL | | }
45+
| |_____^ expected i32, found u32
46+
|
47+
= note: expected type `i32`
48+
found type `u32`
49+
50+
error: aborting due to 4 previous errors
51+
52+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)