Skip to content

Commit

Permalink
Rollup merge of #72194 - doctorn:dispatch-from-dyn-ice, r=estebank
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Dylan-DPC authored May 14, 2020
2 parents d7f5e56 + f6aa161 commit 7b5bc61
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
29 changes: 23 additions & 6 deletions src/librustc_trait_selection/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/issues/issue-71036.rs
Original file line number Diff line number Diff line change
@@ -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() {}
12 changes: 12 additions & 0 deletions src/test/ui/issues/issue-71036.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 7b5bc61

Please sign in to comment.