Conflicting impl of trait `std::convert::From<...>`

I'm really confused by this error :thinking:

conflicting implementations of trait `std::convert::From<representations::script::ScriptNew>` for type `representations::script::ScriptNew` conflicting implementation in crate `core`: - impl<T> From<T> for T;

I've got this code:

pub struct Script {
    id: Id,
    name: Name,
    source: Source,
    description: Description,
    is_active: bool,
    owner_id: Option<i32>,
    output_id: Option<i32>,
}

pub trait Tuple {
    type Tuple;

    fn to_tuple(&self) -> Self::Tuple;
}

impl Tuple for Script {
    type Tuple = (
        Option<i32>,
        String,
        String,
        Option<String>,
        bool,
        Option<i32>,
        Option<i32>,
    );

    fn to_tuple(&self) -> <Self as Tuple>::Tuple {
        (
            self.id.0.clone(),
            self.name.0.clone(),
            self.source.0.clone(),
            self.description.0.clone(),
            self.is_active,
            self.owner_id,
            self.output_id,
        )
    }
}

pub struct ScriptNew {
    pub name: String,
    pub source: String,
    pub description: Option<String>,
    pub is_active: bool,
    pub owner_id: Option<i32>,
    pub output_id: Option<i32>,
}

impl From<<Script as Tuple>::Tuple> for ScriptNew {
    fn from(script: <Script as Tuple>::Tuple) -> Self {
        !unimplemented!()
    }
}

As far as I can understand - the trait is in fact not implemented, since I can't do:

let script_new: ScriptNew = script.to_tuple().into()

What am I missing? I need to be able to convert from <Script as Tuple>::Tuple to ScriptNew

What's ScriptEntity here? Its not declared anywhere, so we can't get the same error.

sorry, it's just an alias for Script , i copied the snippets from several files.. will adjust

No error for me - playground. The error seems to suggest that <Script as Tuple>::Tuple is ScriptNew and not the tuple you've written here, is this what your real code does?

hmm, so strange.

Script is defined in another crate than ScriptNew, but I guess that should be fine as long as the trait Im implementing it on is in scope?

The wierdest thing.
If i replace <ScriptEntity as Tuple>::Tuple with another identical tuple in From<T> it doesnt throw an error, very grateful for any clues what's going on here, I find it very obscure.

This change to my code makes it compile (but is ugly and brittle)

impl
    From<(
        Option<i32>,
        String,
        String,
        Option<String>,
        bool,
        Option<i32>,
        Option<i32>,
    )> for ScriptNew
{
    fn from(script: <Script as Tuple>::Tuple) -> Self {
        !unimplemented!()
    }
}

What does this mean?

also... if I instead expose the tulpe by pub type ScriptTuple = (...); in the same file where Script is defined, then it also works :thinking:

Like so:

// entities.rs

pub type ScriptTuple = (
    Option<i32>,
    String,
    String,
    Option<String>,
    bool,
    Option<i32>,
    Option<i32>,
);

impl Tuple for Script {
    type Tuple = ScriptTuple;

    fn to_tuple(&self) -> <Self as Tuple>::Tuple {
        (
            self.id.0.clone(),
            self.name.0.clone(),
            self.source.0.clone(),
            self.description.0.clone(),
            self.is_active,
            self.owner_id,
            self.output_id,
        )
    }
}

Then i can use it:

// repository.rs

pub struct ScriptNew {
    pub name: String,
    pub source: String,
    pub description: Option<String>,
    pub is_active: bool,
    pub owner_id: Option<i32>,
    pub output_id: Option<i32>,
}

impl From<ScriptTuple> for ScriptNew {
    fn from(script: <ScriptEntity as Tuple>::Tuple) -> Self {
        !unimplemented!()
    }
}

Alright, I think the mystery is solved (and known):

you cannot implement a trait with a generic trait not from this crate

This is also the reason it works when it's all in one file. I think I'll go with the workaround in my previous post, altough I realize it's not ideal :confused:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.