We’re making a significant change to Mojo’s syntax before completing Phase 1 of the Mojo roadmap: renaming the alias keyword to comptimefor accuracy and consistency.
Quick Summary
alias was chosen early in Mojo’s development, but as the language has evolved, we’ve realized it doesn’t accurately describe what this feature does. It’s not just creating aliases—it’s performing compile-time computation and meta-programming.
Before:
alias storage_size = eval[layout.size()] * size_of[dtype]() * num_tiles
alias a, b = divmod(j, N)
After:
comptime storage_size = eval[layout.size()] * size_of[dtype]() * num_tiles
comptime a, b = divmod(j, N)
Rationale
The Problem with alias
Misleading for meta-programming: When you’re doing complex compile-time computation like alias a, b = divmod(j, N), calling it an “alias” doesn’t help anyone understand what’s happening. It’s not aliasing anything—it’s computing values at compile time.
Not self-explanatory: What can be on the right-hand side of an alias? What can you do with an alias? Both require explanation because the keyword doesn’t communicate its true nature.
Creates terminology fragmentation: We use alias for compile-time values but @parameter for related constructs like @parameter if and @parameter for. This obscures that they’re all part of the same compile-time system.
Only fits one use case well: While alias makes sense for type definitions (alias MyType = SomeType[T]), it actively confuses for constants (alias SOLAR_MASS = 4 * PI * PI) and computed values.
Why comptime?
Honest and accurate:comptime tells you exactly what’s happening—this is a compile-time assignment. The code runs during compilation, not at runtime.
Works as a statement modifier: This construct is really a compile-time assignment, not just a declaration. You can see this from syntax like comptime x, y = foo()—the comptime modifies the assignment to x and y.
Unifies the language: Using comptime lets us rally behind one term across Mojo’s compile-time features. We are looking to rename @parameter if and for statements and this is an important stepping stone.
Proven in practice: Zig has used comptime successfully for years with similar semantics. This naming has stood the test of time in that community.
Improved learning experience: When teaching Mojo, explaining “compile-time assignment” with the keyword comptime is straightforward. With alias, we constantly have to explain “it’s not just for aliases, it’s actually for…”
Why Now?
Phase 1 window: We need to make this decision at some point but also “sooner is better than later” as Mojo adoption grows.
Foundation for future features: This sets up consistent terminology for upcoming compile-time features.
Community-driven insight: Real-world code has shown us that meta-programming is central to Mojo, not edge-case usage.
Timeline
Now (v25.6 nighty releases): Both alias and comptime work
v25.7:alias deprecated with warnings
v26.1:alias removed
Thank You
We know breaking changes are disruptive. We’re making this change now specifically because getting the fundamentals right is worth short-term migration pain. Your feedback helps us make this transition as smooth as possible.
We had quite a bit of debate about this change in the team, and I want to share some of the alternatives that were considered.
parameter
parameter requires an explanation, but we already have “parameter domain” and new users have to understand this, no matter what.
This would be confusing because we already have “parameters” to functions and structs. This construct is a different thing, so should get a different name.
Not considering parameter because it would be confusing as a statement modifier.
Two keywords
Embrace two keywords for the typedef and const use cases: type and const, or constexpr and alias
Decided that the boundary between type and const use cases is too fluid in Mojo
const or constexpr or consteval(good old PL/C++ terms)
People would immediately think of C++ meanings
Conflicts with immutable variables? var x vs const x
var v: comptime = or var v: const =
does not work because mojo doesn’t require the use of var to declare a new variable.
It also does not solve the “alias as a typedef” use case.
I think this is a good change. “alias-time” doesn’t really roll off the tongue very well
The only question I have is whether it might be better to have comptime be more of a modifier and do comptime var x = ..., which helps make what it does more clear. if and for are currently macros so I’m not sure we’d want to do that there.
I agree that two keywords is not a good idea. We keep blurring types vs compile-time values more and more, and a “type type” and/or Zig-style static reflection will only blur that more. I think leaning in to types as comptime values makes sense. I also agree on it being best to reserve const for a later conversation around immutable variables.
Not needing var to declare a new variable is something I’m still not thrilled about (I think a lot of linters will forbid it in the future), but it existing right now is a reasonable argument for not doing comptime var.
On “typedef” usecases, as I said before, I think we can lean in to types as values to help users understand this.
“parametrized comptime value” for comptime Scalar[T] = SIMD[T, 1] is longer than “parmetrized alias”. Would be nice to have a shorter term here.
Could we lift “type generator” out of the compiler realm and surface that, or do you think that’s going to be confusing to users?
Alias materializaton would become comptime value materialization . I’m ok with this but again, a shorter alternative would be nice.
I think in many contexts it could be shortened to “materialization” since I don’t think there’s anything else that uses “materialization” in Mojo.
Could you also take the opportunity to discuss trying to unify parameter if and for ?
“parametrized comptime value” for comptime Scalar[T] = SIMD[T, 1] is longer than “parmetrized alias”. Would be nice to have a shorter term here.
I think we should lean towards treating comptime as a modifier like Owen mentioned. So something like comptime const Scalar[T] = SIMD[T, 1] (const could be elided by syntax sugar like it currently is) would be a comptime parametrized constant.
An alternative would be to just use parameter as the keyword. We are already using it so much in every other place and it takes 1 letter more than comptime to write. We would also be unifying the terminology and IMO avoid many unnecessary differences.
I’m not a compiler person but my mental model is that a parameter is the same thing when being passed to a function than being passed to an alias (the implementation is certainly different and non-trivial given it took long to get there). But from a programmer’s perspective IMO we should encourage parameter Scalar[T] = SIMD[T, 1] (optionally adding const) to be considered a parametrized constant. Also cases like parameter const UInt8 = Scalar[DType.uint8] seems easy to explain like “this is a parameter constant of the type SIMD with the parameters set to DType.uint8 and of width 1”.
I like comptime more than alias. What about param for everything?
E.g. param a, b = divmod(c, d)
E.g.
@param
if condition:
Param is short, it matches with the […] parameters, it’s consistent with the docs, as parameters are semantically connected with metaprogramming and comptime
Also, if used as modifier, the shorter the better
meta for everything is another option I like, e.g. meta a, b = divmod(c, d)
I really hate comptime. Contrary to the belief most hold here, I think alias provides the perfect amount of terminological strangeness to capture the semantical depth (since e.g. we model things like heap effects in the comptime evaluator) of what we call an alias today. Sadly, that ship has sailed.
To add/emphasize a bit to the rationale, one of the biggest considerations, in my opinion, is the Mojo documentation. We talk extensively about doing things at compile time, and want to align the syntax with that. Today we find ourselves saying things like “alias declares one or more compile-time values,” whereas in the future we’ll be able to say something like “comptime is a modifier that can be applied to assignments, if statements, for loops that move their behavior to compile time.”
It does effectively work as a modifier. Remember that var isn’t required; you can just use x, y = foo to declare new runtime variables x and y. comptime moves that computation, declaration, and assignment to compile time.
Re @parameter, we would like to rename compile-time for/if, so this syntax is not something we want to unify behind. We haven’t nailed down the naming of these statements, but would like to unify the terminology (e.g. comptime if x: or something similar). This goal guided the name toward comptime (which can support this sort of unification) instead of variants of typedef, which aren’t as general.
I personally still find ‘type generators’ and ‘function generators’ unnatural, after being exposed to these terms for 6 months. I think the rest of the world speaks generics, templates, parmetrized functions / types, but not generators, so we’d be sailing against the wind trying to use 'generator’ as a user-visible term.
Sora, thank you for capturing this so well and so elegantly. Many people share this sentiment to some degree. Alias is indeed strange enough so that it can be accepted as a separate term, but not too alien. This is a quality that comptime may or may not have, time will tell.
I would strongly recommend considering static. Per @denis’s post, it doesn’t even seem to have been considered.
Benefits:
In the PL community the word “static” is usually a synonym for “compile time”. For example, programmers talk about “static typing” and “static dispatch”. In everyday English, the word means “not moving or changing”.
As a keyword, static more succinct than comptime, and also more established.
Yes—I’m aware that in C++ static variables are mutable at runtime, and therefore the use of static in Mojo would mean something slightly different to C++. I am not worried about that though. If you just consider Mojo’s static variables to be immutable by default, the difference mostly goes away. At some point in the future, Mojo could also offer static var, which would give you the equivalent of C++ static. The most notable prior art is “static” in Rust, which offers both static x: T (immutable) and static mut x: T (mutable).
There’s also the weirdness of static in C/C++ having implications for access control. That’s a bizarre quirk of C/C++ and the static keyword doesn’t work this way in any other language, e.g. Java, C#, or Rust. Mojo is not a C++ compiler, so it doesn’t need to strive for consistency with the idiosyncrasies of C++. I think it would be fine to tell people who care about these kinds of discrepancies that we’re using a model closer to that of Rust.
If we take Rust as a reference scale, its immutable static has the semantics of global_constant[...](), not quite that of alias. The latter sits somewhere between const and static: it lacks storage like the former yet supports memory types like the latter. There’s a fair bit of subtlety (the semantic depth I mentioned earlier) hidden in that distinction. CC @denis since we discussed this offline before.
alias sits somewhere between [Rust’s] const and static: it lacks storage like the former yet supports memory types like the latter.
It could make sense for the compiler to give non-trivial aliases dedicated storage, to prevent expensive copying. There’s even an open issue about this.
I think that comptime var, comptime if and comptime for go together nicely, and I agree that comptime is probably a better name. I wasn’t sure if the goal was to eventually push parameter for and parameter if into library code once mlir reflection is more finished, since I had assumed that construct would take the place of decorators.
ack on not needing var, although I don’t like some of the ambiguity that brings.
I agree with you and @denis that “type generator” isn’t a great name. However, it gets surfaced a decent amount when things start getting near the limits of what the type system is capable of dealing with so I wanted to float it as an option.