Skip to content

Commit df81147

Browse files
committed
Ensure suggestion correctness
1 parent fcf0ed9 commit df81147

6 files changed

+130
-1
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+10
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
713713
if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
714714
return false;
715715
}
716+
let map = self.tcx.hir();
717+
if let Some(hir::Node::Expr(expr)) = map.find_parent(expr.hir_id)
718+
&& let hir::ExprKind::Ret(_) = expr.kind
719+
{
720+
// `return foo;`
721+
} else if map.get_return_block(expr.hir_id).is_some() {
722+
// Function's tail expression.
723+
} else {
724+
return false;
725+
}
716726
let e = substs_e.type_at(1);
717727
let f = substs_f.type_at(1);
718728
if self
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
struct A;
2+
struct B;
3+
impl From<A> for B {
4+
fn from(_: A) -> Self { B }
5+
}
6+
fn foo4(x: Result<(), A>) -> Result<(), B> {
7+
match true {
8+
true => x, //~ ERROR mismatched types
9+
false => x,
10+
}
11+
}
12+
fn foo5(x: Result<(), A>) -> Result<(), B> {
13+
match true {
14+
true => return x, //~ ERROR mismatched types
15+
false => return x,
16+
}
17+
}
18+
fn main() {
19+
let _ = foo4(Ok(()));
20+
let _ = foo5(Ok(()));
21+
let _: Result<(), B> = { //~ ERROR mismatched types
22+
Err(A);
23+
};
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/coerce-result-return-value-2.rs:8:17
3+
|
4+
LL | fn foo4(x: Result<(), A>) -> Result<(), B> {
5+
| ------------- expected `Result<(), B>` because of return type
6+
LL | match true {
7+
LL | true => x,
8+
| ^ expected struct `B`, found struct `A`
9+
|
10+
= note: expected enum `Result<_, B>`
11+
found enum `Result<_, A>`
12+
help: you can rely on the implicit conversion that `?` does to transform the error type
13+
|
14+
LL | true => Ok(x?),
15+
| +++ ++
16+
17+
error[E0308]: mismatched types
18+
--> $DIR/coerce-result-return-value-2.rs:14:24
19+
|
20+
LL | fn foo5(x: Result<(), A>) -> Result<(), B> {
21+
| ------------- expected `Result<(), B>` because of return type
22+
LL | match true {
23+
LL | true => return x,
24+
| ^ expected struct `B`, found struct `A`
25+
|
26+
= note: expected enum `Result<_, B>`
27+
found enum `Result<_, A>`
28+
help: you can rely on the implicit conversion that `?` does to transform the error type
29+
|
30+
LL | true => return Ok(x?),
31+
| +++ ++
32+
33+
error[E0308]: mismatched types
34+
--> $DIR/coerce-result-return-value-2.rs:21:28
35+
|
36+
LL | let _: Result<(), B> = {
37+
| ____________________________^
38+
LL | | Err(A);
39+
LL | | };
40+
| |_____^ expected enum `Result`, found `()`
41+
|
42+
= note: expected enum `Result<(), B>`
43+
found unit type `()`
44+
45+
error: aborting due to 3 previous errors
46+
47+
For more information about this error, try `rustc --explain E0308`.

tests/ui/type/type-check/coerce-result-return-value.fixed

+8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,15 @@ fn foo1(x: Result<(), A>) -> Result<(), B> {
1010
fn foo2(x: Result<(), A>) -> Result<(), B> {
1111
return Ok(x?); //~ ERROR mismatched types
1212
}
13+
fn foo3(x: Result<(), A>) -> Result<(), B> {
14+
if true {
15+
Ok(x?) //~ ERROR mismatched types
16+
} else {
17+
Ok(x?) //~ ERROR mismatched types
18+
}
19+
}
1320
fn main() {
1421
let _ = foo1(Ok(()));
1522
let _ = foo2(Ok(()));
23+
let _ = foo3(Ok(()));
1624
}

tests/ui/type/type-check/coerce-result-return-value.rs

+8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,15 @@ fn foo1(x: Result<(), A>) -> Result<(), B> {
1010
fn foo2(x: Result<(), A>) -> Result<(), B> {
1111
return x; //~ ERROR mismatched types
1212
}
13+
fn foo3(x: Result<(), A>) -> Result<(), B> {
14+
if true {
15+
x //~ ERROR mismatched types
16+
} else {
17+
x //~ ERROR mismatched types
18+
}
19+
}
1320
fn main() {
1421
let _ = foo1(Ok(()));
1522
let _ = foo2(Ok(()));
23+
let _ = foo3(Ok(()));
1624
}

tests/ui/type/type-check/coerce-result-return-value.stderr

+33-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,38 @@ help: you can rely on the implicit conversion that `?` does to transform the err
2828
LL | return Ok(x?);
2929
| +++ ++
3030

31-
error: aborting due to 2 previous errors
31+
error[E0308]: mismatched types
32+
--> $DIR/coerce-result-return-value.rs:15:9
33+
|
34+
LL | fn foo3(x: Result<(), A>) -> Result<(), B> {
35+
| ------------- expected `Result<(), B>` because of return type
36+
LL | if true {
37+
LL | x
38+
| ^ expected struct `B`, found struct `A`
39+
|
40+
= note: expected enum `Result<_, B>`
41+
found enum `Result<_, A>`
42+
help: you can rely on the implicit conversion that `?` does to transform the error type
43+
|
44+
LL | Ok(x?)
45+
| +++ ++
46+
47+
error[E0308]: mismatched types
48+
--> $DIR/coerce-result-return-value.rs:17:9
49+
|
50+
LL | fn foo3(x: Result<(), A>) -> Result<(), B> {
51+
| ------------- expected `Result<(), B>` because of return type
52+
...
53+
LL | x
54+
| ^ expected struct `B`, found struct `A`
55+
|
56+
= note: expected enum `Result<_, B>`
57+
found enum `Result<_, A>`
58+
help: you can rely on the implicit conversion that `?` does to transform the error type
59+
|
60+
LL | Ok(x?)
61+
| +++ ++
62+
63+
error: aborting due to 4 previous errors
3264

3365
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)