Unsizing coercion does not normalize associated types in structs. #75899
Description
Example code I'd expect to work (playground):
// NOTE: this is only needed for coerce_tuple, you can remove both for a stable version.
#![feature(unsized_tuple_coercion)]
trait Trait {}
impl<T> Trait for T {}
trait Noop {
type Assoc: ?Sized;
}
impl<T: ?Sized> Noop for T {
type Assoc = T;
}
// Both of these work:
fn coerce<T: Trait>(x: &<T as Noop>::Assoc) -> &<dyn Trait as Noop>::Assoc { x }
fn coerce_tuple<T: Trait>(x: &(String, <T as Noop>::Assoc)) -> &(String, <dyn Trait as Noop>::Assoc) { x }
// But this doesn't:
struct NoopNewtype<T: ?Sized + Noop>(T::Assoc);
fn coerce_newtype<T: Trait>(x: &NoopNewtype<T>) -> &NoopNewtype<dyn Trait> { x }
(in case the example above seems artificial, the realistic one I've reduced this from involves using an associated trait to add Option
around sized types, but not dyn Trait
, since Option<dyn Trait>
wouldn't itself work)
I'd expect coerce_newtype
to work because <T as Noop>::Assoc: Unsize<<dyn Trait as Noop>::Assoc>
should hold, after normalization to T: Unsize<dyn Trait>
(which holds here because T: Trait
), but nothing performs that normalization before coercion gives up entirely.
Unlike CoerceUnsized
(where I've been wary of associated types in the past), there should be no weird interactions here, we should be able to largely treat the struct
as a tuple (and we already ensure the type parameter being changed doesn't show up anywhere else in the struct
, anyway).
The coerce
and coerce_tuple
examples get to normalize before asking the trait system about any CoerceUnsized
or Unsized
obligations - I wonder if we could just normalize trait_pred
here?
rust/src/librustc_typeck/check/coercion.rs
Line 603 in 3d6a3ed
But we would have to be careful, because we are in a speculative operation, so we would have to use normalize_associated_types_in_as_infer_ok
, like this other piece of coercion logic:
rust/src/librustc_typeck/check/coercion.rs
Lines 732 to 733 in 3d6a3ed
cc @mystor (author of the object-provider
crate where this could be useful) @nikomatsakis
Activity