After a little more thinking, since we’re throwing around silly ideas, here is an unfiltered idea that hasn’t even had the yeast added:
In general, <T, ..> becomes a true path component, which in a lot of situations it’s sorta like that: in my slightly more reasonable proposal, if you have path to module path::to::foo, you need to include type parameters with a turbofish before you can access its contents: path::to::foo<T>, or you can write path::to::foo::<..> to delay application of the arguments further down the chain. What if instead we allow something like
mod foo<T> {
fn bar<U>() {}
}
use self::foo::<..>::*;
// the type parameters are forwarded,
// but now there's two parameter lists!
bar::<T>::<U>();
// or even allow multiple type parameter lists
fn baz<T><U>() {}
baz::<T>::<U>();
// useful for HKTs without type closures!
struct Foo<'a><A>;
fn foo<T<_>>() {}
foo::<Foo<'a>>(); // instead of
foo::<|X| Foo<'a><X>>();
// even more nonsensical:
mod foo<T> {
mod bar<U> {
fn baz<V>();
}
}
use self::foo::<..>::bar::<..>::baz;
baz::<T>::<U>::<V>();
This gives us a vaguely sane way to do inline modules:
mod foo {
mod<T> {
fn bar<U>() {}
}
static BAZ ..;
}
self::foo::<T>::bar::<U>();
self::foo::BAZ = 0;
use self::foo::<..>::bar;
bar::<T>::<U>();
Feel free to take all of this with a grain of salt. I just had this idea and I’m pretty sure most of what I’m suggesting is terrible for readability. Especially the type-currying part.
Edit: Alternative, more reasonable(?) syntax for “forwarding” generic parameters:
use self::foo::<*>::bar;
By analogy with *, we’re importing all possible parameterizations of foo, though I think this makes around as much sense as use foo::*::bar;… but this entire reply is off-the-rails brainstorming.