Skip to content

Commit 7b5bc61

Browse files
authored
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
2 parents d7f5e56 + f6aa161 commit 7b5bc61

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

src/librustc_trait_selection/traits/error_reporting/mod.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
283283
.unwrap_or(false);
284284
let is_from = format!("{}", trait_ref.print_only_trait_path())
285285
.starts_with("std::convert::From<");
286+
let is_unsize =
287+
{ Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() };
286288
let (message, note) = if is_try && is_from {
287289
(
288290
Some(format!(
@@ -405,6 +407,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
405407
return;
406408
}
407409

410+
if is_unsize {
411+
// If the obligation failed due to a missing implementation of the
412+
// `Unsize` trait, give a pointer to why that might be the case
413+
err.note(
414+
"all implementations of `Unsize` are provided \
415+
automatically by the compiler, see \
416+
<https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> \
417+
for more information",
418+
);
419+
}
420+
408421
// Try to report a help message
409422
if !trait_ref.has_infer_types_or_consts()
410423
&& self.predicate_can_apply(obligation.param_env, trait_ref)
@@ -427,12 +440,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
427440
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
428441
self.report_similar_impl_candidates(impl_candidates, &mut err);
429442
}
430-
self.suggest_change_mut(
431-
&obligation,
432-
&mut err,
433-
&trait_ref,
434-
points_at_arg,
435-
);
443+
// Changing mutability doesn't make a difference to whether we have
444+
// an `Unsize` impl (Fixes ICE in #71036)
445+
if !is_unsize {
446+
self.suggest_change_mut(
447+
&obligation,
448+
&mut err,
449+
&trait_ref,
450+
points_at_arg,
451+
);
452+
}
436453
}
437454

438455
// If this error is due to `!: Trait` not implemented but `(): Trait` is

src/test/ui/issues/issue-71036.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(unsize, dispatch_from_dyn)]
2+
3+
use std::marker::Unsize;
4+
use std::ops::DispatchFromDyn;
5+
6+
#[allow(unused)]
7+
struct Foo<'a, T: ?Sized> {
8+
_inner: &'a &'a T,
9+
}
10+
11+
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
12+
//~^ ERROR the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied
13+
//~| NOTE the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T`
14+
//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
15+
//~| NOTE required because of the requirements on the impl
16+
17+
fn main() {}

src/test/ui/issues/issue-71036.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0277]: the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied
2+
--> $DIR/issue-71036.rs:11:1
3+
|
4+
LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T`
6+
|
7+
= 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
8+
= note: required because of the requirements on the impl of `std::ops::DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)