Repository navigation
The Mojo compiler hang
A Bool variable that is set to True inside a nested for loop and read after the loop hangs mojo build. The coverage instrumenter emits an Int counter instead. Two reproducers are in docs/mojo-compiler-issue/.
Mojo 1.0.0 (ed45d567), installed with uv pip install mojo, on macOS 25.6 with an Apple M4 Max. Not yet checked on other platforms, and not re-checked on Mojo 1.1.0.
The two reproducers keep the spelling they were written in, @no_inline included. They are evidence of what one toolchain did, so modernizing them would make them evidence of something else. coverage/runtime.mojo, which is live code, uses the current @inline(.never).
Type-checking is unaffected. mojo doc completes in under a second on the hanging file. Codegen is what hangs.
var ran = False # hangs the compiler when nested
for i in range(n):
ran = True
...
_ = observe("loop", ran)
var ran = 0 # builds in about a second
for i in range(n):
ran += 1
...
_ = observe("loop", ran > 0)The coverage tool reports whether a for loop ever ran zero times. It emitted exactly the first pattern: a flag raised in the body and read after the loop. Every module with nested loops then took minutes to build under instrumentation. For a while the Makefile carried a growing exclusion list and blamed "statement-dense arithmetic". That diagnosis was wrong.
Bisecting the instrumented geometries/sphere.mojo by removing one kind of emitted code at a time, with each build capped at 25 seconds:
| Removed from the instrumented file | Build |
|---|---|
| Nothing, the plain file | 1 s |
| Every line probe | Hangs |
| Every branch probe | 2 s |
| The loop flag machinery | 1 s |
| Only the per-iteration probe inside loops | Hangs |
| Only the after-loop read of the flag | 2 s |
Candidate fixes on the full instrumented file:
| Change | Build |
|---|---|
Bool flag to Int counter |
2 s |
| Copy the flag to a fresh local before the read | Hangs |
| Track only the outermost loop of each nest | 2 s |
Two earlier hypotheses were wrong, and are recorded so nobody tests them again. @no_inline on the probe functions does not help. Passing StaticString instead of String does not help. Both changes were kept as improvements.
A struct value that is built again in two nested loops, and read after them, also hangs codegen. This was on Mojo 1.1.0 in WSL. postprocessing/ssr_node.mojo hit it: its box blur summed its taps into a FloatColor. The fix was to sum four Float32 values and build the color after the loops. A copy of the function with four floats built in 7 seconds. The same function with the FloatColor did not build in 200 seconds.
Four nested loops in one function hang codegen too, as render/target.mojo notes. Keep at most two loops in a function, and call a function for the inner two.
Two files, identical except for the flag type. Do not add repro_bool.mojo to any build target. Time-box it:
perl -e 'alarm 25; exec @ARGV' .venv/bin/mojo build -o /tmp/b docs/mojo-compiler-issue/repro_bool.mojo
echo "exit $?" # 142 when SIGALRM killed it after 25 s
.venv/bin/mojo build -o /tmp/i docs/mojo-compiler-issue/repro_int.mojo # about 1 sThe report belongs on modular/modular. A search of that tracker found no existing report of this pattern. The report text is the section above, with repro_bool.mojo and repro_int.mojo attached.
Tutorials
How-to
Reference
- Scene graph
- Rotations
- Cameras
- Geometry
- Geometry addons
- Lofts and clipping groups
- Sculptor
- Procedural generators
- Meshes and assets
- Lines
- Points and sprites
- Helpers
- Scene objects
- Animated objects
- Raycasting
- Curves and paths
- Animation
- Skinning
- Materials
- Node materials
- TSL functions
- Lights
- Lighting addons
- Fog
- Textures
- Renderer
- Renderer hooks and material flags
- Rasterization
- GPU backend
- Render target
- Post-processing
- GPU computation
- Compute nodes
- Progressive light map
- Gaussian splats
- Voxel global illumination
- SVG renderer
- Image files
- Image decode queue
- Model files
- More model files
- Exporters
- Scene JSON
- Windowing and controls
- Math
- Norm consumers
- Math addons
- Units
- Coverage tool
- Commands
- Examples
- Benchmarks
- Extensions
- Shared physics
- Physics query snapshots
- Continuous collision
- Tick force restoration
- Water
- Animals
- Buildings
- CARLA
- Femur
- Tibia
- Fibula
- Patella
- Knee
- Muscles
- Vessels
- Lymph
- Nerves
- Integument
- Leg
- Foot
- Pelvis
- Torso
- Arm
- Hand
- Head
- Genome
- Game humanoid
- Humanoid fidelity
- Audio-aligned game faces
- Converted assets
- Mesh quality
- Segment inertia
Explanation
- Software rasterizer
- Scene graph as an array
- Linear color
- Normals are not colors
- Perspective correction
- Fixed-point coverage
- Per-fragment shading
- Mipmaps
- Sorted transparency
- Types and checks
- Render hooks as a trait
- Shared CPU and GPU code
- Bands and threads
- PNG structure
- Extensions beside the port
- CUDA teardown hang
- Mojo compiler hang