revive suggestions for boxed trait objects instead of impl Trait

This commit is contained in:
Takayuki Maeda 2022-08-01 18:42:16 +09:00
parent 24cf45a591
commit fc43bd60c0
5 changed files with 99 additions and 2 deletions

View File

@ -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();

View File

@ -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

View File

@ -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() {}

View File

@ -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() {}

View File

@ -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`.