Skip to content

Rustc coerces smart pointer to unsized too eagerly #36007

Closed
@plietar

Description

@plietar

Full code: https://is.gd/hZ9nqK

Given a smart pointer, which only works on types implementing the trait Bar or on Bar trait objects, such that Pointer<T> is allowed to coerce to Pointer<Bar>, and the corresponding PartialEq implementation :

trait Bar {}
struct Foo;
impl Bar for Foo {}

struct Pointer<T: ?Sized>
        where T: Bar + Unsize<Bar> {

    value: *mut T,
}

impl <T: ?Sized> CoerceUnsized<Pointer<Bar>> for Pointer<T>
        where T: Bar + Unsize<Bar> {}

impl <T: ?Sized, U: ?Sized> PartialEq<Pointer<U>> for Pointer<T>
        where T: Bar + Unsize<Bar>,
              U: Bar + Unsize<Bar> {

    fn eq(&self, _other: &Pointer<U>) -> bool {
        true
    }
}

Applying the == operator on two Pointer<Foo> will try to coerce them to Pointer<Bar>, even though this isn't needed. This is an issue since coercion moves the original pointer.

fn cmp(x: Pointer<Foo>, y: Pointer<Foo>) {
    x == y;
    x == y; // use of moved value: `y`
}

Removing the CoerceUnsized implementation lets the code build, which means that the coercion is not needed.

As @Diggsey pointed out on reddit, if the PartialEq is restricted to pointers with identical types (PartialEq for Pointer<T>), then no coercion occurs.

Metadata

Metadata

Assignees

Labels

A-type-systemArea: Type systemC-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.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

Development

No branches or pull requests

Issue actions