about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Maeda <takoyaki0316@gmail.com>2022-08-01 18:42:16 +0900
committerTakayuki Maeda <takoyaki0316@gmail.com>2022-08-07 16:50:06 +0900
commitfc43bd60c08eed7a714bb4726c8c511c1e6b3332 (patch)
treef4413c34bf183918832be80ca204ec72c8477e39
parent24cf45a591481519cb0116bf2ce111ffb3e1111c (diff)
downloadrust-fc43bd60c08eed7a714bb4726c8c511c1e6b3332.tar.gz
rust-fc43bd60c08eed7a714bb4726c8c511c1e6b3332.zip
revive suggestions for boxed trait objects instead of impl Trait
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs4
-rw-r--r--src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr29
-rw-r--r--src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed21
-rw-r--r--src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs21
-rw-r--r--src/test/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr26
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`.