While experimenting with the decorator design pattern in Rust, I came across what I believe may be a compiler error, but I am too new to the language to be confident.
I think that the following example code should not generate a recursive trait E0275 error.
A simple type that can be converted to an i64:
enum MyNumbers {
Zero,
One,
Two,
}
impl From<MyNumbers> for i64 {
fn from(n: MyNumbers) -> Self {
match n {
MyNumbers::Zero => 0,
MyNumbers::One => 1,
MyNumbers::Two => 2,
}
}
}
And here, a struct that might be used in a decorator:
struct MyWrapper<N> {
n: N,
}
MyWrapper<N> can be converted to an i64 if N can be converted to i64.
impl<N> From<MyWrapper<N>> for i64
where
N: Into<i64>,
{
fn from(wrapper: MyWrapper<N>) -> Self {
wrapper.n.into()
}
}
This works as I expect.
Now I want to be able to construct an i64 from MyWrapper without consuming it. I change my From trait implementations to operate on references:
impl From<&MyNumbers> for i64 {
fn from(n: &MyNumbers) -> Self {
match n {
MyNumbers::Zero => 0,
MyNumbers::One => 1,
MyNumbers::Two => 2,
}
}
}
impl<'a, N> From<&'a MyWrapper<N>> for i64
where
&'a N: Into<i64>,
{
fn from(wrapper: &'a MyWrapper<N>) -> Self {
(&wrapper.n).into()
}
}
But now...
error[E0275]: overflow evaluating the requirement `i64: From<&MyWrapper<_>>`
--> src/main.rs:34:13
|
34 | let i = i64::from(&w);
| ^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
= note: required because of the requirements on the impl of `Into<i64>` for `&MyWrapper<_>`
= note: required because of the requirements on the impl of `From<&MyWrapper<MyWrapper<_>>>` for `i64`
= note: 126 redundant requirements hidden
= note: required because of the requirements on the impl of `From<&MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` for `i64`
Why was this fine for owned types, but not references?
Also, this really confuses me -
No calls to i64::from() is fine - Playground
Call to different i64::from errors - but should not be evaluating my code!? Playground
fn main() {
i64::from(32i32);
}