about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs69
-rw-r--r--tests/ui/dst/dst-bad-assign-3.stderr1
-rw-r--r--tests/ui/dst/dst-bad-assign.stderr1
-rw-r--r--tests/ui/dyn-star/no-implicit-dyn-star.stderr1
-rw-r--r--tests/ui/generic-associated-types/issue-79422.extended.stderr1
-rw-r--r--tests/ui/impl-trait/dyn-impl-type-mismatch.rs18
-rw-r--r--tests/ui/impl-trait/dyn-impl-type-mismatch.stderr43
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr2
-rw-r--r--tests/ui/methods/issues/issue-61525.stderr1
9 files changed, 137 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 01cd3c57925..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,75 @@ 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() =>
+                    {
+                        let mut impl_def_ids = vec![];
+                        tcx.for_each_relevant_impl(def_id, values.found, |did| {
+                            impl_def_ids.push(did)
+                        });
+                        if let [_] = &impl_def_ids[..] {
+                            let trait_name = tcx.item_name(def_id);
+                            diag.help(format!(
+                                "`{}` implements `{trait_name}` so you could box the found value \
+                                 and coerce it to the trait object `Box<dyn {trait_name}>`, you \
+                                 will have to change the expected type as well",
+                                values.found,
+                            ));
+                        }
+                    }
+                    (_, ty::Dynamic(t, _, ty::DynKind::Dyn))
+                        if let Some(def_id) = t.principal_def_id() =>
+                    {
+                        let mut impl_def_ids = vec![];
+                        tcx.for_each_relevant_impl(def_id, values.expected, |did| {
+                            impl_def_ids.push(did)
+                        });
+                        if let [_] = &impl_def_ids[..] {
+                            let trait_name = tcx.item_name(def_id);
+                            diag.help(format!(
+                                "`{}` implements `{trait_name}` so you could change the expected \
+                                 type to `Box<dyn {trait_name}>`",
+                                values.expected,
+                            ));
+                        }
+                    }
+                    (ty::Dynamic(t, _, ty::DynKind::DynStar), _)
+                        if let Some(def_id) = t.principal_def_id() =>
+                    {
+                        let mut impl_def_ids = vec![];
+                        tcx.for_each_relevant_impl(def_id, values.found, |did| {
+                            impl_def_ids.push(did)
+                        });
+                        if let [_] = &impl_def_ids[..] {
+                            let trait_name = tcx.item_name(def_id);
+                            diag.help(format!(
+                                "`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \
+                                 not enabled; that feature it is currently incomplete",
+                                values.found,
+                            ));
+                        }
+                    }
                     (_, ty::Alias(ty::Opaque, opaque_ty))
                     | (ty::Alias(ty::Opaque, opaque_ty), _) => {
                         if opaque_ty.def_id.is_local()
diff --git a/tests/ui/dst/dst-bad-assign-3.stderr b/tests/ui/dst/dst-bad-assign-3.stderr
index 6dd3434fd21..007f6b898be 100644
--- a/tests/ui/dst/dst-bad-assign-3.stderr
+++ b/tests/ui/dst/dst-bad-assign-3.stderr
@@ -8,6 +8,7 @@ LL |     f5.2 = Bar1 {f: 36};
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
+   = help: `Bar1` implements `ToBar` so you could box the found value and coerce it to the trait object `Box<dyn ToBar>`, you will have to change the expected type as well
 
 error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
   --> $DIR/dst-bad-assign-3.rs:33:5
diff --git a/tests/ui/dst/dst-bad-assign.stderr b/tests/ui/dst/dst-bad-assign.stderr
index d8d1057876f..f935d27e96e 100644
--- a/tests/ui/dst/dst-bad-assign.stderr
+++ b/tests/ui/dst/dst-bad-assign.stderr
@@ -8,6 +8,7 @@ LL |     f5.ptr = Bar1 {f: 36};
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
+   = help: `Bar1` implements `ToBar` so you could box the found value and coerce it to the trait object `Box<dyn ToBar>`, you will have to change the expected type as well
 
 error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
   --> $DIR/dst-bad-assign.rs:35:5
diff --git a/tests/ui/dyn-star/no-implicit-dyn-star.stderr b/tests/ui/dyn-star/no-implicit-dyn-star.stderr
index 06c7bcc5748..bea334a8a69 100644
--- a/tests/ui/dyn-star/no-implicit-dyn-star.stderr
+++ b/tests/ui/dyn-star/no-implicit-dyn-star.stderr
@@ -8,6 +8,7 @@ LL |     dyn_star_foreign::require_dyn_star_display(1usize);
    |
    = note: expected trait object `(dyn* std::fmt::Display + 'static)`
                       found type `usize`
+   = help: `usize` implements `Display`, `#[feature(dyn_star)]` is likely not enabled; that feature it is currently incomplete
 note: function defined here
   --> $DIR/auxiliary/dyn-star-foreign.rs:6:8
    |
diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr
index 14492266cda..ae1526296a7 100644
--- a/tests/ui/generic-associated-types/issue-79422.extended.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr
@@ -27,6 +27,7 @@ LL |     type VRefCont<'a> = &'a V where Self: 'a;
    |                         ^^^^^
    = note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
                  found reference `&u8`
+   = help: `&u8` implements `RefCont` so you could box the found value and coerce it to the trait object `Box<dyn RefCont>`, you will have to change the expected type as well
    = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 2 previous errors
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`.
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
index 4a52f82540d..9cc199d1e0e 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -6,6 +6,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    |
    = note: expected trait object `(dyn Trait + 'static)`
                     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[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
@@ -27,6 +28,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    |
    = note: expected trait object `(dyn Trait + 'static)`
                     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[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr
index a329b52e373..2670a3e4755 100644
--- a/tests/ui/methods/issues/issue-61525.stderr
+++ b/tests/ui/methods/issues/issue-61525.stderr
@@ -27,6 +27,7 @@ LL |         1.query::<dyn ToString>("")
    |
    = note: expected trait object `dyn ToString`
                  found reference `&'static str`
+   = help: `&'static str` implements `ToString` so you could box the found value and coerce it to the trait object `Box<dyn ToString>`, you will have to change the expected type as well
 note: method defined here
   --> $DIR/issue-61525.rs:2:8
    |