"can't use type parameters from outer function" - why not?


#1
struct Foo<T>;
fn test<T>() {
    type F = Foo<T>; // type alias for brevity
}

produces: “error: can’t use type parameters from outer function; try using a local type parameter instead [E0401]”.

The --explain output does a good enough job stating the rule: “Items inside functions are basically just like top-level items, except that they can only be used from the function they are in.” But it doesn’t state any reason why this should be the case, and I can’t think of any other than implementation limitations: the semantics of allowing such references would be straightforward. While nested fns can be replaced with closures, that doesn’t work for type aliases and structs, leaving a choice between repeating type parameters (potentially a lot of them) everywhere the type is used, or creating a verbose boilerplate helper function or struct.

Worth creating a RFC over?


#2

I would be very happy to see an RFC about this. I find the current behavior rather annoying when using nested fns because I usually have to repeat many of the (potentially quite large) where clauses.


#3

@comex Did you ever create an RFC about this?


#4

I’m in favor of doing this for type aliases and consts, because they are erased at compile time, but not for other kinds of items which have a compiled representation. I do think it is valuable that they behave just like top level items from a trans perspective.


#5

Having one for structs is also useful for declaring transient objects like Serde-style visitors.


#6

This is extremely annoying.


#7

I thought this was just an implementation limitation to be fixed after the queryfication of the compiler is done…


#8

We might not be able to do it without breaking a lot of code - extra parametrization isn’t free and we can’t even do it for array lengths (e.g. fn foo<T: Trait>() -> [T; T::N]) yet because not even libcore compiles then (cyclical dependencies).

Querification doesn’t fully solve the ordering problem, but rather restates it in terms of dependencies, which must form a DAG.

The solution is believed to be the introduction of even more indirection aka “lazy normalization” - deferring the evaluation of types or values until the result is actually needed.