However, this fails to compile saying that T needs to be static. However if I rewrite this using a non-static lifetime rather than a generic parameter, it works fine.
How come when using a struct with a generic field, it needs to be a static type to get the type_id of any method. And how come if I use a struct that has a non-static reference as a field, I am able to get the type_id of the method without any troubles.
It was my understanding that functions/methods are always static since they do not capture any variables from its environment, but this does not seem to hold on this case.
Any help understanding where my gap in knowledge is would be extremely appreciated. Thanks!
My only field is not a static type (it holds a reference, and the lifetime of it is not static) and yet I can get the type_id of the method fine. How come then it requires me to only have static types when I use generics.
Well I’m not an expert in this by any means but I would guess that in your example given with the lifetime as a generic parameter the lifetime bounds of type_id are just requested to be fulfilled by the lifetime ‘a. At compile time without using your Lifetime struct the compiler does not need to check and runs just fine, but as soon as you create an “instance” of the structure Lifetime the lifetime bounds will be checked and complaint by the compiler if the bounds are not met.
That’s at least my understanding. However, I’ve learned that a ‘static lifetime should not be interchanged with variables defined as static.
As I said, I’m also still in the Rust “greenhorn” stage and maybe more lifetime advanced ones can correct me where I’m wrong
You're computing the type id of the type of the function. The difference is that with a generic type, Generic<i32>::foo is a different value than Generic<u32>::foo, but when dealing with a lifetime, there is only one function type. The reason you can call this single function value with any lifetime is that it actually implements the Fn trait multiple times for each different lifetime.
So basically, the generic type is part of the type in the first case, but in the second case, one single value is used for every way it can be called, so the lifetime you called it with is not part of the type of the function.
It works for the same reason that this works:
struct MyFn;
impl MyFn {
// oh no! our function is generic!
pub fn call<T>(t: T) -> T {
t
}
}
fn main() {
// but the type of the function is not
println!("{:?}", MyFn.type_id());
}
So regardless of the lifetime, all the methods will have the same type_id so the lifetime can be effectively ignored and my method signature becomes just Lifetime::foo.type_id hence it being "static". In the generic case, however, it cannot use HRTBs so the signature is Generic<T>::foo.type_id, which then requires T to be static.