As a generic parameter T can represent any type. The type parameter T could represent a borrow (T: &U). For instance, binding T to u32 generates a concrete type (in this case value u32). Similarly, binding T to &u32 generates a concrete type (read-borrow of u32).
When lifetimes need to be made explicit, the generic parameter needs to bind both <lifetime, type> in order to generate a concrete type (given that Rust has two "kind types", type and lifetime).
When defining a generic type, will the compiler always reject the use of T when lifetimes need to be made explicit? If so, unless the lifetime and type parameters are qualifying different fields (not the case here) it seems that
// avoid when...
struct Something<'a, T>(&'a T)
should be avoided, and instead use:
// ... the following compiles
struct Something<T>(T)
Seems logical because the latter is just that much more generic allowing for: (i) T or &T and (ii) with and without explicit lifetimes.
Ok. Then what is going on here in what I'm about to describe? (see playground)
The following code compiles, and behaves as expected:
struct A { value: u32 } // move when copied
struct Something<T>(T);
fn go<'a, T>(input: &'a T, _: &T) -> Something<&'a T> {
Something(input);
}
fn main() {
let a1 = A { value: 3 };
let a2 = A { value: 5 };
go(&a1, &a2);
// returns Something(&A)
}
It returns Something(&A)
However, when I introduce a lifetime in the definition of the generic,
//..
struct Something<'a, T>(&'a T);
fn go<'a, T>(input: &'a T, _: &T) -> Something<'a, T> {
Something(input);
}
fn main() {
//..
go(&a1, &a2);
// returns Something(A)
}
... return a value Something(A); what happened to the symbols that indicate that this is a borrow? (a copy/move of the reference, not the value occurred here).
The scope of the difference seems limited to a type cast. But how do the symbols &A and A reconcile?
(The playground lays it out with print-outs of the types)