Skip to content

Traits are resolved incorrectly when dyn trait is used in a struct. #104174

Open
@wdanilo

Description

@wdanilo

Consider the following code:

#![feature(auto_traits)]
#![feature(negative_impls)]

use core::any::TypeId;

auto trait NotSame {}
impl<T> ! NotSame for (T, T) {}


#[derive(Debug)]
pub struct EventData {
    pub id:  TypeId,
    payload: Box<dyn std::any::Any>,
}

impl EventData {
    pub fn new<T: 'static>(payload: T) -> Self {
        let id = TypeId::of::<T>();
        let payload = Box::new(payload);
        Self { id, payload }
    }
}

impl<T: 'static> From<T> for EventData
where (T, EventData): NotSame
{
    fn from(t: T) -> Self {
        Self::new(t)
    }
}

fn main() {
    let v: EventData = ().into();
}

It does not compile:

error[[E0277]](https://doc.rust-lang.org/nightly/error-index.html#E0277): the trait bound `(dyn Any + 'static): NotSame` is not satisfied in `((), EventData)`
  --> src/main.rs:34:24
   |
34 |     let v: EventData = ().into();
   |                        ^^ ---- required by a bound introduced by this call
   |                        |
   |                        within `((), EventData)`, the trait `NotSame` is not implemented for `(dyn Any + 'static)`
   |
   = note: required because it appears within the type `PhantomData<(dyn Any + 'static)>`
   = note: required because it appears within the type `Unique<(dyn Any + 'static)>`
   = note: required because it appears within the type `Box<(dyn Any + 'static)>`
note: required because it appears within the type `EventData`

However, if we remove the field containing std::any::Any, it compiles fine:

#![feature(auto_traits)]
#![feature(negative_impls)]

use core::any::TypeId;

auto trait NotSame {}
impl<T> ! NotSame for (T, T) {}


#[derive(Debug)]
pub struct EventData {
}

impl EventData {
    pub fn new<T: 'static>(payload: T) -> Self {
        Self {}
    }
}

impl<T: 'static> From<T> for EventData
where (T, EventData): NotSame
{
    fn from(t: T) -> Self {
        Self::new(t)
    }
}

fn main() {
    let v: EventData = ().into();
}

Another strange thing is that if we change ().into() to EventData::from(()), then none of these codes compiles.

Please note that no types were changed. Click here to see live demo

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.F-auto_traits`#![feature(auto_traits)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions