Account for ty::Error when suggesting impl Trait or Box<dyn Trait>

This commit is contained in:
Esteban Küber 2020-01-23 15:21:15 -08:00
parent e0bbe7915e
commit 55dce720b2
3 changed files with 191 additions and 8 deletions

View File

@ -606,11 +606,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
let mut ret_types = visitor.0.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id));
let (last_ty, all_returns_have_same_type) =
ret_types.clone().fold((None, true), |(last_ty, mut same), returned_ty| {
same &= last_ty.map_or(true, |ty| ty == returned_ty);
(Some(returned_ty), same)
});
let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
(None, true),
|(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
(Some(ty), same)
},
);
let all_returns_conform_to_trait =
if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
match ty_ret_ty.kind {
@ -625,7 +627,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
})
})
}
_ => true,
_ => false,
}
} else {
true

View File

@ -22,6 +22,32 @@ fn bal() -> dyn Trait { //~ ERROR E0746
}
42
}
fn bam() -> Box<dyn Trait> {
if true {
return Struct; //~ ERROR mismatched types
}
42 //~ ERROR mismatched types
}
fn baq() -> Box<dyn Trait> {
if true {
return 0; //~ ERROR mismatched types
}
42 //~ ERROR mismatched types
}
fn baz() -> Box<dyn Trait> {
if true {
Struct //~ ERROR mismatched types
} else {
42 //~ ERROR mismatched types
}
}
fn baw() -> Box<dyn Trait> {
if true {
0 //~ ERROR mismatched types
} else {
42 //~ ERROR mismatched types
}
}
// Suggest using `impl Trait`
fn bat() -> dyn Trait { //~ ERROR E0746
@ -30,5 +56,12 @@ fn bat() -> dyn Trait { //~ ERROR E0746
}
42
}
fn bay() -> dyn Trait { //~ ERROR E0746
if true {
0u32
} else {
42u32
}
}
fn main() {}

View File

@ -95,8 +95,136 @@ LL | }
LL | Box::new(42)
|
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:16
|
LL | fn bam() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | return Struct;
| ^^^^^^
| |
| expected struct `std::boxed::Box`, found struct `Struct`
| help: store this in the heap by calling `Box::new`: `Box::new(Struct)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found struct `Struct`
= 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
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:5
|
LL | fn bam() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
| ^^
| |
| expected struct `std::boxed::Box`, found integer
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found type `{integer}`
= 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
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:33:16
|
LL | fn baq() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | return 0;
| ^
| |
| expected struct `std::boxed::Box`, found integer
| help: store this in the heap by calling `Box::new`: `Box::new(0)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found type `{integer}`
= 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
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:35:5
|
LL | fn baq() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
| ^^
| |
| expected struct `std::boxed::Box`, found integer
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found type `{integer}`
= 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
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:39:9
|
LL | fn baz() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | Struct
| ^^^^^^
| |
| expected struct `std::boxed::Box`, found struct `Struct`
| help: store this in the heap by calling `Box::new`: `Box::new(Struct)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found struct `Struct`
= 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
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:9
|
LL | fn baz() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
| ^^
| |
| expected struct `std::boxed::Box`, found integer
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found type `{integer}`
= 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
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9
|
LL | fn baw() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | 0
| ^
| |
| expected struct `std::boxed::Box`, found integer
| help: store this in the heap by calling `Box::new`: `Box::new(0)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found type `{integer}`
= 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
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9
|
LL | fn baw() -> Box<dyn Trait> {
| -------------- expected `std::boxed::Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
| ^^
| |
| expected struct `std::boxed::Box`, found integer
| help: store this in the heap by calling `Box::new`: `Box::new(42)`
|
= note: expected struct `std::boxed::Box<(dyn Trait + 'static)>`
found type `{integer}`
= 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
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:13
|
LL | fn bat() -> dyn Trait {
| ^^^^^^^^^ 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}`,
LL | fn bat() -> impl Trait {
| ^^^^^^^^^^
error: aborting due to 9 previous errors
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:59:13
|
LL | fn bay() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= 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>
= note: if all the returned values were of the same type you could use `impl Trait` as the return type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= note: you can create a new `enum` with a variant for each returned type
help: return a boxed trait object instead
|
LL | fn bay() -> Box<dyn Trait> {
LL | Box::new(if true {
LL | 0u32
LL | } else {
LL | 42u32
LL | })
|
error: aborting due to 18 previous errors
Some errors have detailed explanations: E0277, E0308, E0746.
For more information about an error, try `rustc --explain E0277`.