about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs29
-rw-r--r--src/test/ui/issues/issue-71036.rs17
-rw-r--r--src/test/ui/issues/issue-71036.stderr12
3 files changed, 52 insertions, 6 deletions
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index 405c656bad5..784fc36e67e 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -283,6 +283,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             .unwrap_or(false);
                         let is_from = format!("{}", trait_ref.print_only_trait_path())
                             .starts_with("std::convert::From<");
+                        let is_unsize =
+                            { Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() };
                         let (message, note) = if is_try && is_from {
                             (
                                 Some(format!(
@@ -405,6 +407,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             return;
                         }
 
+                        if is_unsize {
+                            // If the obligation failed due to a missing implementation of the
+                            // `Unsize` trait, give a pointer to why that might be the case
+                            err.note(
+                                "all implementations of `Unsize` are provided \
+                                automatically by the compiler, see \
+                                <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> \
+                                for more information",
+                            );
+                        }
+
                         // Try to report a help message
                         if !trait_ref.has_infer_types_or_consts()
                             && self.predicate_can_apply(obligation.param_env, trait_ref)
@@ -427,12 +440,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                 let impl_candidates = self.find_similar_impl_candidates(trait_ref);
                                 self.report_similar_impl_candidates(impl_candidates, &mut err);
                             }
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                &trait_ref,
-                                points_at_arg,
-                            );
+                            // Changing mutability doesn't make a difference to whether we have
+                            // an `Unsize` impl (Fixes ICE in #71036)
+                            if !is_unsize {
+                                self.suggest_change_mut(
+                                    &obligation,
+                                    &mut err,
+                                    &trait_ref,
+                                    points_at_arg,
+                                );
+                            }
                         }
 
                         // If this error is due to `!: Trait` not implemented but `(): Trait` is
diff --git a/src/test/ui/issues/issue-71036.rs b/src/test/ui/issues/issue-71036.rs
new file mode 100644
index 00000000000..01d1cff42e4
--- /dev/null
+++ b/src/test/ui/issues/issue-71036.rs
@@ -0,0 +1,17 @@
+#![feature(unsize, dispatch_from_dyn)]
+
+use std::marker::Unsize;
+use std::ops::DispatchFromDyn;
+
+#[allow(unused)]
+struct Foo<'a, T: ?Sized> {
+    _inner: &'a &'a T,
+}
+
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+//~^ ERROR the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied
+//~| NOTE the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T`
+//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
+//~| NOTE required because of the requirements on the impl
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-71036.stderr b/src/test/ui/issues/issue-71036.stderr
new file mode 100644
index 00000000000..57cf2468945
--- /dev/null
+++ b/src/test/ui/issues/issue-71036.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied
+  --> $DIR/issue-71036.rs:11:1
+   |
+LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T`
+   |
+   = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
+   = note: required because of the requirements on the impl of `std::ops::DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.