Mojo change: renaming `alias` to `comptime`

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.

:bullseye: 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)


:light_bulb: Rationale

The Problem with alias

  1. 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.

  2. 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.

  3. 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.

  4. 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?

  1. Honest and accurate: comptime tells you exactly what’s happening—this is a compile-time assignment. The code runs during compilation, not at runtime.

  2. 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.

  3. 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.

  4. Proven in practice: Zig has used comptime successfully for years with similar semantics. This naming has stood the test of time in that community.

  5. 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.


:spiral_calendar: Timeline

  • :white_check_mark: Now (v25.6 nighty releases): Both alias and comptime work

  • :date: v25.7: alias deprecated with warnings

  • :date: v26.1: alias removed

:folded_hands: 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.

— The Mojo Team

14 Likes

I agree here. comptime is way more obvious. I’m guessing alias is an artifact from MLIR / LLVM IR terminology?

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.
3 Likes

Also some of the concerns about “comptime” that we already debated and accepted as non-blockers

  • for the “typedef” use case, comptime is not natural: comptime T = Scalar[DataType] is less intuitive than alias T = Scalar[DataType]

    • comptime is visually on par or better than alias in e.g. alias T, U = Int, Float64 vs comptime T, U = Int, Float64
  • “parametrized comptime value” for comptime Scalar[T] = SIMD[T, 1] is longer than “parmetrized alias”. Would be nice to have a shorter term here.

  • Alias materializaton would become comptime value materialization . I’m ok with this but again, a shorter alternative would be nice.

    • Mixed opinions in the team review, not a show stopper
1 Like

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.

5 Likes

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.

2 Likes

You are spot on Owen!
The debate on “before” and “after” is ongoing :slight_smile:

1 Like

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”.


As usual thanks for opening up the discussion :slight_smile:

1 Like

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)

4 Likes

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.

2 Likes

Nice, agree with the rationale and change.

1 Like

I like that comptime is more expressive and accurate than alias. But it feels too verbose to me as it is such a central part of Mojo.

I saw recent commits to make things less verbose like MutableOriginMutOrigin.

How about an @ct modifier?
Meaning: „at compile time“

@ct Pi = 3.142
@ct T = List[Int]
@ct if …
@ct for …

2 Likes

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.

—Chris

5 Likes

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.

1 Like

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.

1 Like

I agree with Denis that “generator” isn’t a term that should be exposed to users. I think we should talk about “parameterized” declarations.

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.

1 Like

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.

1 Like