diff options
| author | Takayuki Maeda <takoyaki0316@gmail.com> | 2022-08-01 18:42:16 +0900 |
|---|---|---|
| committer | Takayuki Maeda <takoyaki0316@gmail.com> | 2022-08-07 16:50:06 +0900 |
| commit | fc43bd60c08eed7a714bb4726c8c511c1e6b3332 (patch) | |
| tree | f4413c34bf183918832be80ca204ec72c8477e39 | |
| parent | 24cf45a591481519cb0116bf2ce111ffb3e1111c (diff) | |
| download | rust-fc43bd60c08eed7a714bb4726c8c511c1e6b3332.tar.gz rust-fc43bd60c08eed7a714bb4726c8c511c1e6b3332.zip | |
revive suggestions for boxed trait objects instead of impl Trait
5 files changed, 99 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 1b13c98e4c3..9c6896dbad7 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -4,7 +4,7 @@ use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable}; +use rustc_middle::ty::{self, ToPredicate, Ty}; use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ @@ -479,7 +479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match orig_expected { Expectation::ExpectHasType(expected) if self.in_tail_expr - && self.ret_coercion.as_ref()?.borrow().merged_ty().has_opaque_types() + && self.return_type_has_opaque && self.can_coerce(outer_ty, expected) => { let obligations = self.fulfillment_cx.borrow().pending_obligations(); diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index 11c1072f02c..3c65fd998c5 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -52,6 +52,16 @@ LL | | 1u32 LL | | } | |_____- `if` and `else` have incompatible types | +help: you could change the return type to be a boxed trait object + | +LL | fn qux() -> Box<dyn std::fmt::Display> { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ Box::new(0i32) +LL | } else { +LL ~ Box::new(1u32) + | help: change the type of the numeric literal from `u32` to `i32` | LL | 1i32 @@ -114,6 +124,15 @@ LL | | _ => 2u32, LL | | } | |_____- `match` arms have incompatible types | +help: you could change the return type to be a boxed trait object + | +LL | fn dog() -> Box<dyn std::fmt::Display> { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ 0 => Box::new(0i32), +LL ~ 1 => Box::new(1u32), + | help: change the type of the numeric literal from `u32` to `i32` | LL | 1 => 1i32, @@ -131,6 +150,16 @@ LL | | 1u32 LL | | } | |_____- `if` and `else` have incompatible types | +help: you could change the return type to be a boxed trait object + | +LL | fn apt() -> Box<dyn std::fmt::Display> { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ Box::new(0i32) +LL | } else { +LL ~ Box::new(1u32) + | help: change the type of the numeric literal from `u32` to `i32` | LL | 1i32 diff --git a/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed b/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed new file mode 100644 index 00000000000..bc4ccbf503c --- /dev/null +++ b/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed @@ -0,0 +1,21 @@ +// run-rustfix + +#![allow(dead_code)] + +struct S; +struct Y; + +trait Trait {} + +impl Trait for S {} +impl Trait for Y {} + +fn baz() -> Box<dyn Trait> { + if true { + Box::new(S) + } else { + Box::new(Y) //~ ERROR `if` and `else` have incompatible types + } +} + +fn main() {} diff --git a/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs b/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs new file mode 100644 index 00000000000..0f609665005 --- /dev/null +++ b/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs @@ -0,0 +1,21 @@ +// run-rustfix + +#![allow(dead_code)] + +struct S; +struct Y; + +trait Trait {} + +impl Trait for S {} +impl Trait for Y {} + +fn baz() -> impl Trait { + if true { + S + } else { + Y //~ ERROR `if` and `else` have incompatible types + } +} + +fn main() {} diff --git a/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr b/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr new file mode 100644 index 00000000000..72b5e25ea46 --- /dev/null +++ b/src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr @@ -0,0 +1,26 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/suggest-boxed-trait-objects-instead-of-impl-trait.rs:17:9 + | +LL | / if true { +LL | | S + | | - expected because of this +LL | | } else { +LL | | Y + | | ^ expected struct `S`, found struct `Y` +LL | | } + | |_____- `if` and `else` have incompatible types + | +help: you could change the return type to be a boxed trait object + | +LL | fn baz() -> Box<dyn Trait> { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ Box::new(S) +LL | } else { +LL ~ Box::new(Y) + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. |
