Conflicting implementation of FromResidual<T> for Option<T>

I am toying around with the unstable try_trait_v2 features, and I found a conflicting implementation error I can't quite wrap my head around. Here's my code; please ignore that the type looks useless :wink:

#![feature(try_trait_v2)]
#![feature(try_trait_v2_residual)]

use std::{convert::Infallible, hint, ops::{ControlFlow, FromResidual, Residual, Try}};

pub struct Surely<T>(pub T);
impl<T> FromResidual<Surely<Infallible>> for Surely<T> {
    fn from_residual(_: Surely<Infallible>) -> Surely<T> {
        unsafe { hint::unreachable_unchecked() }
    }
}
impl<T> Try for Surely<T> {
    type Output = T;
    type Residual = Surely<Infallible>;
    fn branch(self) -> ControlFlow<Surely<Infallible>, T> {
        ControlFlow::Continue(self.0)
    }
    fn from_output(output: T) -> Surely<T> {
        Surely(output)
    }
}
impl<T> Residual<T> for Surely<Infallible> {
    type TryType = Surely<T>;
}

impl<T> FromResidual<Surely<Infallible>> for Option<T> {
    fn from_residual(_: Surely<Infallible>) -> Option<T> {
        unsafe { hint::unreachable_unchecked() }
    }
}

The compiler fails with:

error[E0119]: conflicting implementations of trait `FromResidual<Surely<Infallible>>` for type `Option<_>`
  --> src/main.rs:26:1
   |
26 | impl<T> FromResidual<Surely<Infallible>> for Option<T> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T> FromResidual for Option<T>;

However, there is only one implementation in stdlib of FromResidual<R> for Option<T>, with R = Option<Infallible>.

Why is this an implementation conflict at all? The types Option<Infallible> and Surely<Infallible> are clearly distinct (former is populated, latter is not). Am I missing something about how the compiler unifies type terms, is this a compiler bug or is there an undocumented additional implementation of FromResidual for Option<T> in stdlib?

This is a known issue, unfortunately still open:

1 Like

Ah, a good old nightly bite in the butt :slight_smile: Thanks for the help!

1 Like

Wait, isn't this a fix from 2 weeks ago? I'm on limited connection at the moment, I'll update the compiler and check if it's working now.

1 Like

Jup, looks like the PR merged a temporary fix for FromResidual. Indeed looks like yesterday's nightly compiler can compile your snippet.

1 Like

Hardly; we have something nearly identical in the standard library:

(You'll note that there's no need for unsafe.)

1 Like

Sorry for the blackout, life happened :slight_smile:

Yes, indeed everything works with the latest (nightly) compiler version. Thanks a lot for your help!

1 Like

Ah this is awesome - that was exactly my use case. Not as dumb as idea as I feared then :slight_smile:

Just in case you happen to know: why the move functions in there? I can't figure out what those comments refer to, or what are they trying to avoid.

They're used in iterator adapters in a bunch of places. Having them be separate, rather than inline closures in those places, is done because it avoids needing to monomorphize over as many generic parameters.

Basically, it's a minor compiler-time optimization that I probably wouldn't bother if it wasn't core.

1 Like

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.