`untyped` parameters must not be followed by non-untyped parameters
saem opened this issue · comments
Semantically analysing the AST results in comptime (compile time) effects.
Paired with conditional compilation via when
, we can even vary types, e.g.:
var val {.compileTime.} = 1
proc p[T](x: T) = discard
p:
static:
val += 1
when val == 1:
"string"
else:
true # boolean
Although typed
AST can for the most part be sanitized into untyped
, the
comptime effects can't be undone. Long story short, the entire idea of untyped
as a "fallback" choice during overload resolution is broken by design.
As a first step in making things sane once more, implement a rule where
untyped
arguments must not be followed by any non-untyped arguments.
template foo(a: untyped) = # legal
# ...
template foo(a: untyped, b: untyped) = # legal
# ...
template foo(a: int, b: untyped) = # legal
# ...
template foo(a: int, b: varargs[untyped]) = # legal
# ...
template foo(a: untyped, b: int) = # illegal
# ...
template foo(a: untyped, b: typed) = # illegal
# ...
template foo[T](a: untyped, b: T) = # illegal
# ...
The net effect is that untyped parameter matching can now reliably disqualify
untyped
matches using little more than arity information. The way this works
is also in keeping with semantic information is only ever available
top-to-bottom and left-to-right.
Future Considerations
Once this is in place we can consider promoting untyped
parameters to match
eagerly, ensuring no unintended comptime effects happen during semantic analysis
of call arguments.
Hints for Implementer(s)
Parameter type analysis is implemented in semtypes.semProcTypeNode
, which is
the first place to start understanding how to implement the first step.