Which Mojo keywords can be used as package names without escaping?

I was trying to understand how Mojo treats package path segments that overlap

with language keywords, especially for generated code where package names may

come from an external schema.

I wrote a small standalone probe that creates a temporary package for each

candidate name, then asks Mojo to compile imports of both forms:

from keyword import keyword_package_probe_value

from probe_root.keyword import keyword_package_probe_value


The probe is here:

pixi run bash issues/mojo_keyword_package_names.sh

Tested with:

Mojo 1.0.0b2.dev2026051506 (795a5e20)

# Result

These names were accepted without escaping, both as a top-level package name and

as a dotted package segment:

AnyType Bool _mlir_op borrowed capturing constrained deinit inout let mut out owned raises read take

These names were rejected without escaping:

False None Self True alias and as async await break class comptime continue def elif else except finally fn for from global if import in lambda nonlocal not or pass raise ref return struct trait try var while with yield

The top-level and dotted-segment results were identical in this test.

# Why I am asking

Some of the accepted names surprised me. For example, `mut`, `out`, `read`,

`deinit`, and `take` are treated as reserved in other syntactic positions, but

they are accepted as unescaped package path segments:

from mut import keyword_package_probe_value

from probe_root.mut import keyword_package_probe_value


Meanwhile, names like `ref`, `var`, `def`, and `struct` are rejected.

Is this split intentional and stable, or is it an implementation detail of the current parser/import grammar?

In particular:

1. Should generated Mojo code conservatively escape all package segments that overlap with contextual or reserved keywords?

2. Is there an official list of words that are illegal as unescaped package path segments?

3. Should package path segments follow the same identifier rules as ordinary local names, or is the import grammar intentionally more permissive?

Thanks! I can share the full probe script if helpful; it just creates temporary `_init_.mojo` files and compiles one generated import file per candidate.

I assume that argument convention, at the very least, act as “soft” keywords and can be used not only in package paths but also for example as the names of struct parameters. But I don’t know if there is a complete list of soft keywords anywhere.