Description
Has been alluded to in code comments but still opening an issue to track it
Using a structural generic type before its declaration doesn't work (common in cases like NodeObj[T] = ...; Node[T] = ref NodeObj[T]
):
type
Foo[T] = object
x: Bar[T]
Bar[T] = T
The reason is that in the SemcheckTopLevelSyms
phase, typevars are not declared yet and they are not referenced in the preliminal AST of the type. Guessing the solution is:
- typevars are declared in
SemcheckTopLevelSyms
- an untyped prepass or something similar captures the typevar symbols in the type AST in
SemcheckTopLevelSyms
rather than just taking the raw AST
Then since instantiating the type compiles the type expression, it will work even though the type AST is not originally fully typed. Though it depends on the untyped prepass outside of compat mode.
Another option might be to allow invocation types to have structural type implementations for cases like this but this is too niche of a case for invoke types to always have to consider. Also this would have to account for cases like Foo = Bar[int]
where it has to resolve immediately and isn't delayed until generic instantiations.
Everything beyond this point is not necessary to fix to close this issue as they are not really encountered in Nim code but is context for choosing a solution.
Another case is that using a concrete nominal generic type before its declaration doesn't work:
type
Foo = object
x: Bar[int]
Bar[T] = object
Again, the issue is that typevars are not declared yet, but I am not sure if attempting to compile untyped AST of nominal types is sound, though I don't see why it wouldn't be.
An edge case for untyped AST of nominal types (that was not possible in Nim code up to this point) would be:
type Foo[T] = object
x: Bar[T]
proc foo[U](y: Foo[U]) =
let a: U = y.x.field
type Bar[T] = object
field: T
where foo
has to know that Bar.field
has type U
. Even this case would probably be fine, since field expressions mostly use identifiers and not symbols in generic contexts, and we freshly instantiate generic field types since #592 so untyped field type expressions would be handled.