about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-05-14 18:21:59 +0200
committerGitHub <noreply@github.com>2020-05-14 18:21:59 +0200
commit7b5bc61e99ea77ff87233295fc3e789e43dd66f0 (patch)
treeb64230280cd4a445e65ae665e0097b548e9c3989
parentd7f5e56498bffa50813fbdd34623501c8f5b0a5c (diff)
parentf6aa161936887bf4a0aaebbd5cfc743132a1ab0b (diff)
downloadrust-7b5bc61e99ea77ff87233295fc3e789e43dd66f0.tar.gz
rust-7b5bc61e99ea77ff87233295fc3e789e43dd66f0.zip
Rollup merge of #72194 - doctorn:dispatch-from-dyn-ice, r=estebank
Don't ICE on missing `Unsize` impl

Previously code of the form

```rust
#![feature(unsize, dispatch_from_dyn)]

use std::marker::Unsize;
use std::ops::DispatchFromDyn;

pub 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> {}
```

would generate an ICE due to the missing `Unsize` impl being run through the `suggest_change_mut` suggestion. This PR adds an early exit and a pointer to the appropriate docs regarding `Unsize` instead:

```
error[E0277]: the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied
  --> src/test/ui/issues/issue-71036.rs:11:1
   |
11 | 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`.
```

r? @estebank

Resolves #71036
-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 1620bdfa66e..5a63a693652 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`.