Interested in thinking about how the type system could be extended to support raising functions in type parameter computations. Also curious about the relationship between comptime parameter expressions and other static systems within the compiler (and external tooling like LSPs).
Below, an example where raising within a parameter expression might be useful.
Example: array broadcasting with compile time checking
Suppose one wanted to define a array broadcasting system which checked shape compatibility at comptime. One might try the following:
alias Shape = List[Int]
@value
struct Rep[dtype: DType, shape: Shape]:
pass
# Broadcasting of arrays may fail statically!
fn broadcast(s1: Shape, s2: Shape) raises -> Shape:
# imagine we check for compatibility here ...
# if compatibility check fails, we'd like to raise
return s1
# Now, say we wanted to add arrays with broadcasting turned on.
# The output shape depends on the input shapes (it will be 1 of the input shapes)
# but broadcasting may fail due to shape incompatibility.
fn add[
D1: DType, D2: DType, S1: Shape, S2: Shape
](self: Rep[D1, S1], v: Rep[D2, S2],) -> Rep[D1, broadcast(S1, S2)]: # problem! raising in parameter expression
return Rep[D1, broadcast(S1, S2)]()
def main():
var r1 = Rep[DType.float32, [1, 2]]()
var r2 = Rep[DType.float32, [1, 2, 3]]()
var c = add(r1, r2)
The general idea here being that one might want to compute and check static information as part of the computation of a parameter expression, and possibly fail.
Above: broadcasting (following NumPy rules: Broadcasting — NumPy v2.2 Manual) is something that one could check at comptime.
Interaction with existing proposals
It’s not clear to me yet how this feature interacts with other proposed features like modular/mojo/proposals/requires-clause.md at main · modular/modular · GitHub (and likely, discussing that proposal should be another topic). If we could all have our language design utopias, I’m of the opinion that a comptime system which allows evaluation of the full language via the comptime interpreter would be an ideal to strive for! Then one doesn’t introduce feature biformity between comptime and runtime. This is obviously an ideal (!) and may have to be tarnished for e.g. fast compilation.
It is also not clear to me how compile time parameter expression evaluation should interact with useful tooling like LSPs. For instance, it seems beneficial if an LSP could surface a violation of broadcasting in a system such as the one above! But it’s not clear to me how this works in the Mojo compiler today (parser vs. elaborator vs. comptime vs. runtime) – or how to usefully think about this.