Skip to content

Commit 75eabb1

Browse files
committed
Account for diverging types in return impl Trait
1 parent 6fd5641 commit 75eabb1

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

src/librustc_typeck/check/coercion.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,34 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
13481348
"...is found to be `{}` here",
13491349
fcx.resolve_vars_with_obligations(expected),
13501350
));
1351+
err.note(
1352+
"`impl Trait` as a return type requires that all the returned values must have \
1353+
the same type",
1354+
);
1355+
let snippet = fcx
1356+
.tcx
1357+
.sess
1358+
.source_map()
1359+
.span_to_snippet(return_sp)
1360+
.unwrap_or_else(|_| "dyn Trait".to_string());
1361+
let mut snippet_iter = snippet.split_whitespace();
1362+
let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
1363+
if has_impl {
1364+
err.help(&format!(
1365+
"you can instead return a trait object using `Box<dyn {}>`",
1366+
&snippet[5..]
1367+
));
1368+
}
1369+
let impl_trait_msg = "for information on `impl Trait`, see \
1370+
<https://doc.rust-lang.org/book/ch10-02-traits.html\
1371+
#returning-types-that-implement-traits>";
1372+
let trait_obj_msg = "for information on trait objects, see \
1373+
<https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
1374+
#using-trait-objects-that-allow-for-values-of-different-types>";
1375+
err.note(impl_trait_msg);
1376+
if has_impl {
1377+
err.note(trait_obj_msg);
1378+
}
13511379
}
13521380
err
13531381
}

src/test/ui/impl-trait/equality.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ LL | return 1_i32;
99
LL | }
1010
LL | 0_u32
1111
| ^^^^^ expected `i32`, found `u32`
12+
|
13+
= note: `impl Trait` as a return type requires that all the returned values must have the same type
14+
= help: you can instead return a trait object using `Box<dyn Foo>`
15+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
16+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
1217

1318
error[E0277]: cannot add `impl Foo` to `u32`
1419
--> $DIR/equality.rs:24:11

src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ LL | return 0i32;
99
LL | }
1010
LL | 1u32
1111
| ^^^^ expected `i32`, found `u32`
12+
|
13+
= note: `impl Trait` as a return type requires that all the returned values must have the same type
14+
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
15+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
16+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
1217

1318
error[E0308]: mismatched types
1419
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
@@ -21,6 +26,11 @@ LL | return 0i32;
2126
LL | } else {
2227
LL | return 1u32;
2328
| ^^^^ expected `i32`, found `u32`
29+
|
30+
= note: `impl Trait` as a return type requires that all the returned values must have the same type
31+
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
32+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
33+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
2434

2535
error[E0308]: mismatched types
2636
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
@@ -33,6 +43,11 @@ LL | return 0i32;
3343
LL | } else {
3444
LL | 1u32
3545
| ^^^^ expected `i32`, found `u32`
46+
|
47+
= note: `impl Trait` as a return type requires that all the returned values must have the same type
48+
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
49+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
50+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
3651

3752
error[E0308]: `if` and `else` have incompatible types
3853
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
@@ -57,6 +72,11 @@ LL | 0 => return 0i32,
5772
| ---- ...is found to be `i32` here
5873
LL | _ => 1u32,
5974
| ^^^^ expected `i32`, found `u32`
75+
|
76+
= note: `impl Trait` as a return type requires that all the returned values must have the same type
77+
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
78+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
79+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
6080

6181
error[E0308]: mismatched types
6282
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
@@ -71,6 +91,11 @@ LL | | 1 => 1u32,
7191
LL | | _ => 2u32,
7292
LL | | }
7393
| |_____^ expected `i32`, found `u32`
94+
|
95+
= note: `impl Trait` as a return type requires that all the returned values must have the same type
96+
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
97+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
98+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
7499

75100
error[E0308]: mismatched types
76101
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
@@ -83,6 +108,11 @@ LL | return 0i32;
83108
...
84109
LL | 1u32
85110
| ^^^^ expected `i32`, found `u32`
111+
|
112+
= note: `impl Trait` as a return type requires that all the returned values must have the same type
113+
= help: you can instead return a trait object using `Box<dyn std::fmt::Display>`
114+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
115+
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
86116

87117
error: aborting due to 7 previous errors
88118

0 commit comments

Comments
 (0)