Skip to content

unsizing fails when associated types are involved #50213

Open
@glandium

Description

@glandium

I am trying to implement something very generic, and in the course of doing so, am using trait associated types. That, in turn, apparently doesn't allow the unsizing rules to kick in.

The following compiles fine:

#![crate_type="lib"]
use std::cell::UnsafeCell;

struct Foo<T: ?Sized>(UnsafeCell<T>);

impl<T> Foo<T> {
    fn new(t: T) -> Foo<T> {
        Foo(UnsafeCell::new(t))
    }
}

pub fn foo() {
    let foo: &Foo<[i32]> = &Foo::new([1,2,3]);
}

Now, adding some nesting in the above fails:

#![crate_type="lib"]
use std::cell::UnsafeCell;

trait Wrapper {
    type Type: ?Sized;
}

struct Wrap<T: ?Sized>(T);

impl<T: ?Sized> Wrapper for Wrap<T> {
    type Type = T;
}

struct Foo<T: Wrapper + ?Sized>(UnsafeCell<T::Type>);

impl<T> Foo<Wrap<T>> {
    fn new(t: T) -> Self {
        Foo(UnsafeCell::new(t))
    }
}

pub fn foo() {
    let foo: &Foo<Wrap<[i32]>> = &Foo::new([1,2,3]);
}

That fails with:

error[E0308]: mismatched types
  --> src/lib.rs:23:34
   |
23 |     let foo: &Foo<Wrap<[i32]>> = &Foo::new([1,2,3]);
   |                                  ^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
   |
   = note: expected type `&Foo<Wrap<[i32]>>`
              found type `&Foo<Wrap<[i32; 3]>>`

In fact, it fails similarly with a simplified version that differs even less with the original:

#![crate_type="lib"]
use std::cell::UnsafeCell;

trait Wrapper {
    type Type: ?Sized;
}

impl<T: ?Sized> Wrapper for T {
    type Type = T;
}

struct Foo<T: Wrapper + ?Sized>(UnsafeCell<T::Type>);

impl<T> Foo<T> {
    fn new(t: T) -> Self {
        Foo(UnsafeCell::new(t))
    }
}

pub fn foo() {
    let foo: &Foo<[i32]> = &Foo::new([1,2,3]);
}
error[E0308]: mismatched types
  --> src/lib.rs:21:28
   |
21 |     let foo: &Foo<[i32]> = &Foo::new([1,2,3]);
   |                            ^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
   |
   = note: expected type `&Foo<[i32]>`
              found type `&Foo<[i32; 3]>`

(In fact, the UnsafeCell is irrelevant, and can be removed too)

#![crate_type="lib"]
trait Wrapper {
    type Type: ?Sized;
}

impl<T: ?Sized> Wrapper for T {
    type Type = T;
}

struct Foo<T: Wrapper + ?Sized>(T::Type);

impl<T> Foo<T> {
    fn new(t: T) -> Self {
        Foo(t)
    }
}

pub fn foo() {
    let foo: &Foo<[i32]> = &Foo::new([1,2,3]);
}
error[E0308]: mismatched types
  --> src/lib.rs:19:28
   |
19 |     let foo: &Foo<[i32]> = &Foo::new([1,2,3]);
   |                            ^^^^^^^^^^^^^^^^^^ expected slice, found array of 3 elements
   |
   = note: expected type `&Foo<[i32]>`
              found type `&Foo<[i32; 3]>`

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions