Bakcxoj
September 4, 2025, 9:31pm
1
Let's say I have the following enum.
enum MaybeFnOrVal<T> {
Val(T),
Fn(Box<Fn() -> T>),
}
I’d like to be able to impl From for both of these cases.
impl<T> From<T> for MaybeFnOrVal<T> {
fn from(v: T) -> Self {
Self::Val(v)
}
}
impl<F, T> From<F> for MaybeFnOrVal<T>
where
F: Fn() -> T,
{
fn from(f: F) -> Self {
Self::Fn(Box::new(f))
}
}
let x: MaybeFnOrVal<i32> = MaybeFnOrVal::from(5);
let y: MaybeFnOrVal<i32> = MaybeFnOrVal::from(|| 5);
assert!(matches!(x, MaybeFnOrVal::Val(_));
assert!(matches!(y, MaybeFnOrVal::Fn(_));
I understand these conflict with each other because T might impl Fn() → Self, but that seems like a nonsensical case.
Edit: I misread the OP a bit, and don't have time to try to correct it this instant, so I'll just hide the contents.
Probably irrelevant original reply
Not without specialization, or negative bounds in coherence.
fn() meets the bounds on your second implementation and creates a MaybeFnOrVal::<()>::Fn(_).
But it also meets the bounds on your first implementation and creates a MaybeFnOrVal::<fn()>::Val(_).
Both are completely sensible from a types POV.
Or in other words: Every F: Fn() -> _ is also a T: (with no bounds besides the implied Sized).
This is not a problem though? impl From<fn()> for MaybeFnOrVal<()> and impl From<fn()> for MaybeFnOrVal<fn()> are not conflicting, since, well, they are implementations on a distinct types. Problem is with blanket implementations only.
It might be a nonsensical, but it's possible now on nightly (upd: there was a link here, but I re-read the code and understood that it is not relevant here), so there have to be some mechanism to explicitly exclude this case.
1 Like
Ah yeah, I misread things, thanks.
It's technically allowed by the type system and you can create a type that satisfies this condition in nightly though.
system
Closed
December 4, 2025, 5:40am
6
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.