about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-01-24 16:57:15 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-01-24 16:57:15 +0000
commit796814d91627203444769a680c53ff59a7ff4696 (patch)
tree0371ad13760a659dc616a11b33e9e04a3e63dcba
parentd992d9cd56c21c9fad629f95826895b03bdc7077 (diff)
Account for expected `dyn Trait` found `impl Trait`
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs20
-rw-r--r--tests/ui/impl-trait/dyn-impl-type-mismatch.rs18
-rw-r--r--tests/ui/impl-trait/dyn-impl-type-mismatch.stderr43
3 files changed, 81 insertions, 0 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 662903e30fc..21ea48c6c83 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -294,6 +294,26 @@ impl<T> Trait<T> for X {
                             );
                         }
                     }
+                    (ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias))
+                        if let Some(def_id) = t.principal_def_id()
+                            && tcx.explicit_item_bounds(alias.def_id).skip_binder().iter().any(
+                                |(pred, _span)| match pred.kind().skip_binder() {
+                                    ty::ClauseKind::Trait(trait_predicate)
+                                        if trait_predicate.polarity
+                                            == ty::ImplPolarity::Positive =>
+                                    {
+                                        trait_predicate.def_id() == def_id
+                                    }
+                                    _ => false,
+                                },
+                            ) =>
+                    {
+                        diag.help(format!(
+                            "you can box the `{}` to coerce it to `Box<{}>`, but you'll have to \
+                             change the expected type as well",
+                            values.found, values.expected,
+                        ));
+                    }
                     (ty::Dynamic(t, _, ty::DynKind::Dyn), _)
                         if let Some(def_id) = t.principal_def_id() =>
                     {
diff --git a/tests/ui/impl-trait/dyn-impl-type-mismatch.rs b/tests/ui/impl-trait/dyn-impl-type-mismatch.rs
new file mode 100644
index 00000000000..c6170abb582
--- /dev/null
+++ b/tests/ui/impl-trait/dyn-impl-type-mismatch.rs
@@ -0,0 +1,18 @@
+trait Trait {}
+struct Struct;
+impl Trait for Struct {}
+fn foo() -> impl Trait {
+    Struct
+}
+fn main() {
+    let a: Box<dyn Trait> = if true {
+        Box::new(Struct)
+    } else {
+        foo() //~ ERROR E0308
+    };
+    let a: dyn Trait = if true {
+        Struct //~ ERROR E0308
+    } else {
+        foo() //~ ERROR E0308
+    };
+}
diff --git a/tests/ui/impl-trait/dyn-impl-type-mismatch.stderr b/tests/ui/impl-trait/dyn-impl-type-mismatch.stderr
new file mode 100644
index 00000000000..ddbdaf3eb4b
--- /dev/null
+++ b/tests/ui/impl-trait/dyn-impl-type-mismatch.stderr
@@ -0,0 +1,43 @@
+error[E0308]: mismatched types
+  --> $DIR/dyn-impl-type-mismatch.rs:11:9
+   |
+LL | fn foo() -> impl Trait {
+   |             ---------- the found opaque type
+...
+LL |         foo()
+   |         ^^^^^ expected `Box<dyn Trait>`, found opaque type
+   |
+   = note:   expected struct `Box<dyn Trait>`
+           found opaque type `impl Trait`
+   = 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
+help: store this in the heap by calling `Box::new`
+   |
+LL |         Box::new(foo())
+   |         +++++++++     +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-impl-type-mismatch.rs:14:9
+   |
+LL |         Struct
+   |         ^^^^^^ expected `dyn Trait`, found `Struct`
+   |
+   = note: expected trait object `dyn Trait`
+                    found struct `Struct`
+   = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-impl-type-mismatch.rs:16:9
+   |
+LL | fn foo() -> impl Trait {
+   |             ---------- the found opaque type
+...
+LL |         foo()
+   |         ^^^^^ expected `dyn Trait`, found opaque type
+   |
+   = note: expected trait object `dyn Trait`
+               found opaque type `impl Trait`
+   = help: you can box the `impl Trait` to coerce it to `Box<dyn Trait>`, but you'll have to change the expected type as well
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.