Skip to content

Unsizing coercion does not normalize associated types in structs. #75899

Closed
@eddyb

Description

@eddyb
Member

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?

match selcx.select(&obligation.with(trait_pred)) {

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:

let InferOk { value: a_sig, mut obligations } =
self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);

cc @mystor (author of the object-provider crate where this could be useful) @nikomatsakis

Activity

added
A-DSTsArea: Dynamically-sized types (DSTs)
A-associated-itemsArea: Associated items (types, constants & functions)
A-coercionsArea: implicit and explicit `expr as Type` coercions
E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
on Aug 25, 2020
eddyb

eddyb commented on Aug 25, 2020

@eddyb
MemberAuthor

FWIW, this can be worked around with explicit Unsize bounds in the right places but they're nightly-only and entirely unnecessary if we fix this issue.

eddyb

eddyb commented on Aug 25, 2020

@eddyb
MemberAuthor

Not sure if I should nominate this for compiler team or lang team, but let's try compiler team first.

added
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Aug 25, 2020
spastorino

spastorino commented on Sep 3, 2020

@spastorino
Member

This was discussed during today's compiler meeting removing nomination. @eddyb please feel free to keep the discussion going on Zulip or even re-nominating it if you consider a re-discussion important.

WaffleLapkin

WaffleLapkin commented on Apr 8, 2021

@WaffleLapkin
Member

I'd like to work on this. I haven't worked on the compiler yet, so not sure I'll be able to fix this in a reasonable time. But since it's labelled E-easy it's worth giving a try, right? Any advice is appreciated :)

@rustbot claim

nikomatsakis

nikomatsakis commented on Apr 8, 2021

@nikomatsakis
Contributor

@WaffleLapkin I'm not sure if that E-easy label is really accurate! That said, you could try to drop by in #wg-traits on Zulip at some point during one of my morning office hours times, if that works for you (9am-10 US Eastern Time, every day but Tuesday), and we could talk it over.

10 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-DSTsArea: Dynamically-sized types (DSTs)A-associated-itemsArea: Associated items (types, constants & functions)A-coercionsArea: implicit and explicit `expr as Type` coercionsE-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Participants

    @spastorino@eddyb@nikomatsakis@SoniEx2@compiler-errors

    Issue actions

      Unsizing coercion does not normalize associated types in structs. · Issue #75899 · rust-lang/rust