Howdy folks. I have this code here:
trait Input {}
impl Input for &usize {}
trait System {}
impl<A: Input,> System for fn(A) {}
fn test_system(_: &usize) {}
fn is_system<T>(_: T) where T: System {
println!("{} is a system", type_name::<T>());
}
fn main() {
is_system(test_system as fn(&usize)); // implementation of `System` is not general enough
}
But I'm having trouble understanding the error it generates. Would anyone be able to explain it to me, please?
link to the playground
impl<A: Input> System for fn(A) {}
Generic parameters like A
represent a single type, so the implementation only applies to fn(_)
that take a single type. fn(&usize)
-- aka for<'a> fn(&'a usize)
-- is not such a function pointer. It's a subtype of all fn(&'a usize)
-- fn(_)
that take a reference with one specific lifetime.
The implementation does apply to fn(&'a usize)
(which take one specific lifetime).
To attempt to put it another way, there's nothing you can replace A
with in fn(A)
to get a for<'a> fn(&'a usize)
, so the implementation cannot apply.
If you replace A
with something like &usize
, it actually has to be &'a usize
for one specific lifetime 'a
, because A
can only represent a single type. There is no for<'a> &'a usize
type.
1 Like
Thank you, that makes a lot of sense. Might I also ask how I could work around this problem?
It depends and there's not always a full solution. For this particular case you can add:
impl<A> System for fn(&A) where for<'a> &'a A: Input {}
You'll get a future compatibility warning. Last I knew the plan is to keep accepting this case, but they haven't committed to it yet, so you'll have to decide if you want to accept the risk of future breakage.