Skip to content

Unsizing coercions apply in an inconvenient order with respect to constructor calls. #89299

@sfackler

Description

@sfackler
use std::pin::Pin;

trait Trait {}

impl Trait for i32 {}

struct Foo<'a>(Pin<&'a mut (dyn Trait + Send)>);

fn main() {
    let mut a = 1;
    let _x = Foo(Pin::new(&mut a));
}
error[E0277]: `dyn Trait + Send` cannot be unpinned
   --> src/main.rs:11:27
    |
11  |     let _x = Foo(Pin::new(&mut a));
    |                           ^^^^^^ the trait `Unpin` is not implemented for `dyn Trait + Send`
    |
    = note: consider using `Box::pin`
note: required by `Pin::<P>::new`

It looks like it's trying to coerce the i32 to dyn Trait + Send before constructing the Pin rather than constructing the Pin<&mut i32> and then coercing that to Pin<&mut (dyn Trait + Send)>. You can fix this by constructing the Pin in a separate statement, but ideally the compiler would defer the unsizing coercion:

use std::pin::Pin;

trait Trait {}

impl Trait for i32 {}

struct Foo<'a>(Pin<&'a mut (dyn Trait + Send)>);

fn main() {
    let mut a = 1;
    let pin = Pin::new(&mut a);
    let _x = Foo(pin);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-coercionsArea: implicit and explicit `expr as Type` coercionsA-diagnosticsArea: Messages for errors, warnings, and lintsC-bugCategory: This is a bug.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