Skip to content

Unexpected interactions with async blocks, auto traits, and trait objects #67036

Closed
@syntacticsugarglider

Description

@syntacticsugarglider

The source below does not compile, where the expected behavior is for it to compile as far as I can tell. Removing the Send bound on drop_send causes it to compile. Removing the async {}.await no-op causes it to compile. This seems likely related to #64552, with the same sort of leakage of regions that should not be user-visible occurring. However, the error message is quite opaque in this case.

note: `Bound` would have to be implemented for the type `(dyn Object + '0)`, for any lifetime `'0`...
   = note: ...but `Bound` is actually implemented for the type `(dyn Object + '1)`, for some specific lifetime `'1`

My presumption is therefore that the auto trait is being correctly satisfied in the generator for some lifetime, the implementation of Bound is implicitly constrained on Send by Object where the async block is required to be Send, so #64552 is occurring in a lifetime-dependent fashion resulting in an altogether surprising error message. I'm not as familiar with borrow checker internals as I'd like so this may be barking up the wrong tree.

I am, however, unclear as to why the associated type parametrization over T::Type as opposed to simply T is necessary to reproduce.

use std::marker::PhantomData;

// remove this Send bound and it compiles
fn drop_send<F: Send>(_: F) {}

trait Object: Send {}

pub trait Bound {
    type Type;
}

impl Bound for dyn Object {
    type Type = ();
}

trait Contains<T> {}

struct IsBound<T: Bound + ?Sized>(PhantomData<dyn Contains<T::Type> + Send>);

impl<T: Bound + ?Sized> IsBound<T> {
    pub fn new() -> Self {
        IsBound(PhantomData)
    }
}

fn fails() {
    drop_send(async {
        let collection: IsBound<dyn Object> = IsBound::new();

        // comment out this no-op and it builds:
        async {}.await;
    })
}

Finally, here is a playground demonstrating this issue to show independence from any local state of my own system

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsA-trait-systemArea: Trait systemT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.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