Skip to content

Commit 55dce72

Browse files
committed
Account for ty::Error when suggesting impl Trait or Box<dyn Trait>
1 parent e0bbe79 commit 55dce72

File tree

3 files changed

+191
-8
lines changed

3 files changed

+191
-8
lines changed

src/librustc/traits/error_reporting/suggestions.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -606,11 +606,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
606606
let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
607607

608608
let mut ret_types = visitor.0.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id));
609-
let (last_ty, all_returns_have_same_type) =
610-
ret_types.clone().fold((None, true), |(last_ty, mut same), returned_ty| {
611-
same &= last_ty.map_or(true, |ty| ty == returned_ty);
612-
(Some(returned_ty), same)
613-
});
609+
let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
610+
(None, true),
611+
|(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
612+
same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
613+
(Some(ty), same)
614+
},
615+
);
614616
let all_returns_conform_to_trait =
615617
if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
616618
match ty_ret_ty.kind {
@@ -625,7 +627,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
625627
})
626628
})
627629
}
628-
_ => true,
630+
_ => false,
629631
}
630632
} else {
631633
true

src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,32 @@ fn bal() -> dyn Trait { //~ ERROR E0746
2222
}
2323
42
2424
}
25+
fn bam() -> Box<dyn Trait> {
26+
if true {
27+
return Struct; //~ ERROR mismatched types
28+
}
29+
42 //~ ERROR mismatched types
30+
}
31+
fn baq() -> Box<dyn Trait> {
32+
if true {
33+
return 0; //~ ERROR mismatched types
34+
}
35+
42 //~ ERROR mismatched types
36+
}
37+
fn baz() -> Box<dyn Trait> {
38+
if true {
39+
Struct //~ ERROR mismatched types
40+
} else {
41+
42 //~ ERROR mismatched types
42+
}
43+
}
44+
fn baw() -> Box<dyn Trait> {
45+
if true {
46+
0 //~ ERROR mismatched types
47+
} else {
48+
42 //~ ERROR mismatched types
49+
}
50+
}
2551

2652
// Suggest using `impl Trait`
2753
fn bat() -> dyn Trait { //~ ERROR E0746
@@ -30,5 +56,12 @@ fn bat() -> dyn Trait { //~ ERROR E0746
3056
}
3157
42
3258
}
59+
fn bay() -> dyn Trait { //~ ERROR E0746
60+
if true {
61+
0u32
62+
} else {
63+
42u32
64+
}
65+
}
3366

3467
fn main() {}

src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,136 @@ LL | }
9595
LL | Box::new(42)
9696
|
9797

98+
error[E0308]: mismatched types
99+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:16
100+
|
101+
LL | fn bam() -> Box<dyn Trait> {
102+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
103+
LL | if true {
104+
LL | return Struct;
105+
| ^^^^^^
106+
| |
107+
| expected struct `std::boxed::Box`, found struct `Struct`
108+
| help: store this in the heap by calling `Box::new`: `Box::new(Struct)`
109+
|
110+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
111+
found struct `Struct`
112+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
113+
114+
error[E0308]: mismatched types
115+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:5
116+
|
117+
LL | fn bam() -> Box<dyn Trait> {
118+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
119+
...
120+
LL | 42
121+
| ^^
122+
| |
123+
| expected struct `std::boxed::Box`, found integer
124+
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
125+
|
126+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
127+
found type `{integer}`
128+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
129+
130+
error[E0308]: mismatched types
131+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:33:16
132+
|
133+
LL | fn baq() -> Box<dyn Trait> {
134+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
135+
LL | if true {
136+
LL | return 0;
137+
| ^
138+
| |
139+
| expected struct `std::boxed::Box`, found integer
140+
| help: store this in the heap by calling `Box::new`: `Box::new(0)`
141+
|
142+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
143+
found type `{integer}`
144+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
145+
146+
error[E0308]: mismatched types
147+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:35:5
148+
|
149+
LL | fn baq() -> Box<dyn Trait> {
150+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
151+
...
152+
LL | 42
153+
| ^^
154+
| |
155+
| expected struct `std::boxed::Box`, found integer
156+
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
157+
|
158+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
159+
found type `{integer}`
160+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
161+
162+
error[E0308]: mismatched types
163+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:39:9
164+
|
165+
LL | fn baz() -> Box<dyn Trait> {
166+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
167+
LL | if true {
168+
LL | Struct
169+
| ^^^^^^
170+
| |
171+
| expected struct `std::boxed::Box`, found struct `Struct`
172+
| help: store this in the heap by calling `Box::new`: `Box::new(Struct)`
173+
|
174+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
175+
found struct `Struct`
176+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
177+
178+
error[E0308]: mismatched types
179+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:9
180+
|
181+
LL | fn baz() -> Box<dyn Trait> {
182+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
183+
...
184+
LL | 42
185+
| ^^
186+
| |
187+
| expected struct `std::boxed::Box`, found integer
188+
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
189+
|
190+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
191+
found type `{integer}`
192+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
193+
194+
error[E0308]: mismatched types
195+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9
196+
|
197+
LL | fn baw() -> Box<dyn Trait> {
198+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
199+
LL | if true {
200+
LL | 0
201+
| ^
202+
| |
203+
| expected struct `std::boxed::Box`, found integer
204+
| help: store this in the heap by calling `Box::new`: `Box::new(0)`
205+
|
206+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
207+
found type `{integer}`
208+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
209+
210+
error[E0308]: mismatched types
211+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9
212+
|
213+
LL | fn baw() -> Box<dyn Trait> {
214+
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
215+
...
216+
LL | 42
217+
| ^^
218+
| |
219+
| expected struct `std::boxed::Box`, found integer
220+
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
221+
|
222+
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
223+
found type `{integer}`
224+
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
225+
98226
error[E0746]: return type cannot have an unboxed trait object
99-
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13
227+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:13
100228
|
101229
LL | fn bat() -> dyn Trait {
102230
| ^^^^^^^^^ doesn't have a size known at compile-time
@@ -107,7 +235,27 @@ help: return `impl Trait` instead, as all return paths are of type `{integer}`,
107235
LL | fn bat() -> impl Trait {
108236
| ^^^^^^^^^^
109237

110-
error: aborting due to 9 previous errors
238+
error[E0746]: return type cannot have an unboxed trait object
239+
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:59:13
240+
|
241+
LL | fn bay() -> dyn Trait {
242+
| ^^^^^^^^^ doesn't have a size known at compile-time
243+
|
244+
= 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>
245+
= note: if all the returned values were of the same type you could use `impl Trait` as the return type
246+
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
247+
= note: you can create a new `enum` with a variant for each returned type
248+
help: return a boxed trait object instead
249+
|
250+
LL | fn bay() -> Box<dyn Trait> {
251+
LL | Box::new(if true {
252+
LL | 0u32
253+
LL | } else {
254+
LL | 42u32
255+
LL | })
256+
|
257+
258+
error: aborting due to 18 previous errors
111259

112260
Some errors have detailed explanations: E0277, E0308, E0746.
113261
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)