Type parameters always represent a single type [1], and there is no general way to do that. You can approximate it with a trait and higher-ranked bounds:
trait MakeSomething<'a> {
type Something: 'a;
fn make(x: &'a u32) -> Self::Something;
}
trait MakeAnyOfThem: for<'any> MakeSomething<'any> {}
impl<T: for<'any> MakeSomething<'any>> MakeAnyOfThem for T {}
Your solution with a 'static lifetime reminds me of my idea here (note that I didn't apply that idea to mmtkvdb yet, so the links to mmtkvdb below do not incorporate that idea):
As said in that post, I wasn't sure whether this idea is feasible because of the complex syntax.
I was also worried about issues regarding variance, i.e. the compiler doesn't know that for a generic type T: MakeAnyOfThem the type T::Something<'a> is a supertype of T::Something<'static>. That is, if I understand it right, the compiler doesn't know that values of T::Something<'static> can always be stored in variables of T::Something<'a> unless the compiler knows what T::Something<'lt> actually is in a particular scenario for a particular T. See also: Discussion on IRLO regarding GATs and variance.
So far I have been refraining from using this "'static trick" because I didn't really overlook all the consequences yet, but maybe it works well in your case. (And maybe it would work well in my case too; I might consider using it as well.)
I'm not fully understand how 'static works there but I think it is less important in this case, as it is only for method resolution, never get involved into any computation. The worst thing I can imagine is that explicitly type that 'static every time when calling like make<Foo<'static>>(...).
But thanks for the heads up, it was interesting to learn this topic
When you write make::<Foo>(&value) without a lifetime for Foo, then the compiler will try to infer that lifetime (i.e. use a lifetime that fits). The only fitting lifetime here would be 'static, so that's what the compiler chooses (I think).
So basically the compiler turns it automatically into make::<Foo<'static>>(&value) for you.
Using Foo<'static> as a type constructor seems a bit like a "hack" (or dirty trick) to me (even though I had the same idea for my use case). Maybe the cleaner way would be something like the following:
Here FooMaker is a data type that has no value (not even a single one like ()), and such a data type is called zero variant enum. It solely exists to be passed as a type argument at compile-time.
Sometimes it is better to use unit-like structs (i.e. "struct FooMaker;") instead, but I think in the above case a zero variant enum is a good choice.
Edit: Maybe a unit-like struct is better. See also this thread if you're interested in that.
Edit #2: Also, I'm unsure if any of this actually makes sense for your use case. Perhaps there exists an easier way for whatever you want/need to achieve.