o
odinpkg.dev
packages / tool / odin-compiler-bug

odin-compiler-bug

6dbd196tool

No description provided.

No license · updated 1 month ago

Instructions

Running ./build.sh produces the following compiler error:

src/name_canonicalization.cpp(194): Assertion Failure: `!are_types_identical_unique_tuples(key->type, pair.type)`
This is a compiler error. Please report this.

Tried with a locally built (default debug configuration)

Odin:    dev-2026-05:f03ec366c
OS:      macOS Tahoe 26.3.1 (build 25D2128, kernel 25.3.0)
CPU:     Apple M3 Pro
RAM:     18432 MiB
Backend: LLVM 22.1.4

Also tried with a build from Homebrew:

Odin:    dev-2026-05:ea5175d86

App structure

  • Entry point: graphics_api/examples/bindings/main.odin
  • Depends on local packages: graphics_api, webgl (via collection shared that just points to workspace root)
  • Output: public/graphics_api/examples/bindings/main.wasm

Why no minimal example

I tried removing stuff to get the minimal repro, but it looks like it's extremely sensitive to any changes. I tried my best to only include the essential parts of my workspace, but cutting further is very difficult because touching seemingly random things "fixes" the bug.

For example, simply adding a print statement at graphics_api/examples/bindings/main.odin:62 makes the compilation succeed.

My findings

It looks like the bug is most directly related to this type:

// graphics_api/graphics_api.odin:172
TypedUniformBuffer :: struct($T: typeid) {
  buffer: UniformBuffer,
  shape: [0]T,
}

Especially the shape field, which I admit, is hacky. I use [0]T as a phantom type, that allows me to extract T via reflection, but the value of the field does not serve any purpose at runtime.

Nevertheless, I don't see how that little hack should contribute to the observed bug. I experimented with other variants. These are also bugged:

  • [1]T,
  • ^T,
  • proc() -> T,

But these compile fine:

  • [^]T
  • [dynamic]T

Maybe there is some insight in it, or maybe it's just another fragile equilibrium.

This type is used in one place. Removing this usage fixes the bug, which further ties the bug to it:

// graphics_api/examples/bindings/shaders.gen.odin:18
shaders_BindGroup0 :: struct #all_or_none {
	// The single usage of the seemingly offending type (removing this line fixes the bug):
	uniforms: gapi.TypedUniformBuffer(shaders_Uniforms) `@binding(0) @stages(vert)`,

	texture: gapi.Texture `@binding(1) @stages(frag)`,
	textureSampler: gapi.Sampler `@binding(2) @stages(frag)`,
}

One more place that seems important is the invocation of the function that actually does the reflection stuff with the phantom type:

// graphics_api/examples/bindings/main.odin:58
groupLayout0_desc: gapi.BindGroupLayoutDescriptor
// This line seems important. Removing the call to inferBindGroupLayoutDescriptor stops the bug
groupLayout0_desc = gapi.inferBindGroupLayoutDescriptor(shaders_BindGroup0) or_else {}

Debugger dump

Because it's so fragile, my only hope was to try to debug through the compilation. I managed to catch the failing assertion while stepping through the compiler, but I don't know what I was looking at exactly:

> -exec bt
* thread #11, stop reason = EXC_BREAKPOINT (code=1, subcode=0x1001bf8e8)
  * frame #0: 0x00000001001bf8e8 odin`type_set_update_with_mutex(s=0x0000000106b08878, pair=TypeInfoPair @ 0x0000000170371fa8, m=0x0000000106b08870) at name_canonicalization.cpp:194:3
    frame #1: 0x00000001001bf498 odin`type_set_update_with_mutex(s=0x0000000106b08878, ptr=0x00000001071c91c0, m=0x0000000106b08870) at name_canonicalization.cpp:209:9
    frame #2: 0x00000001001bea44 odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x00000001071c91c0) at checker.cpp:2548:6
    frame #3: 0x00000001001bea74 odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x000000010716abb8) at checker.cpp:2555:3
    frame #4: 0x00000001001bec78 odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x0000000107173020) at checker.cpp:2609:3
    frame #5: 0x00000001001bf07c odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x0000000107172798) at checker.cpp:2672:6
    frame #6: 0x00000001001bea74 odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x00000001071726f0) at checker.cpp:2555:3
    frame #7: 0x00000001001bec50 odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x00000001071730f8) at checker.cpp:2601:3
    frame #8: 0x00000001001bf07c odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x0000000107170a00) at checker.cpp:2672:6
    frame #9: 0x00000001001bea74 odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x0000000107170958) at checker.cpp:2555:3
    frame #10: 0x00000001001bec50 odin`add_min_dep_type_info(c=0x0000000106b087b8, t=0x0000000107176d28) at checker.cpp:2601:3
    frame #11: 0x00000001001c0324 odin`add_dependency_to_set_worker(data=0x00000001098d2388) at checker.cpp:2813:3
    frame #12: 0x000000010017e148 odin`thread_pool_thread_proc(thread=0x00000001062bc860) at thread_pool.cpp:239:6
    frame #13: 0x000000010017de9c odin`internal_thread_proc(arg=0x00000001062bc860) at threading.cpp:609:2
    frame #14: 0x0000000195d33c08 libsystem_pthread.dylib`_pthread_start + 136
> -exec f
frame #0: 0x00000001001bf8e8 odin`type_set_update_with_mutex(s=0x0000000106b08878, pair=TypeInfoPair @ 0x0000000170371fa8, m=0x0000000106b08870) at name_canonicalization.cpp:194:3
   191 		GB_ASSERT(hash_index < s->capacity);
   192 		for (usize i = 0; i < s->capacity; i++) {
   193 			TypeInfoPair *key = &s->keys[hash_index];
-> 194 			GB_ASSERT(!are_types_identical_unique_tuples(key->type, pair.type));
    			^
   195 			if (key->hash == TYPE_SET_TOMBSTONE || key->hash == 0) {
   196 				*key = pair;
   197 				s->count++;
> -exec frame var
(TypeSet *) s = 0x0000000106b08878
(TypeInfoPair) pair = {
  type = 0x00000001071c91c0
  hash = 12732292366340213554
}
(RWSpinLock *) m = 0x0000000106b08870
(gbprivDefer<(unnamed class)>) _defer_233 = {
  f = {
    m = 0x0000000170371f98
  }
}
(usize) mask = 63
(usize) hash = 12732292366340213554
(usize) hash_index = 5
(usize) i = 19
(TypeInfoPair *) key = 0x00000007cd0c2450
> key->type->Named->base
0x00000001071c91c0
> pair.type
0x00000001071c91c0
> key->type->Named->name->text
0x000000015571897a "BindGroupLayout :: ^_BindGroupLayout\nBuffer :: be_Buffer\nFragmentShader :: distinct Shader\nFramebuffer :: be_Framebuffer\nIndexBuffer :: distinct Buffer\nPipeline :: be_Pipeline\nPipelineLayout :: be_PipelineLayout\nProgram :: be_Program\nSampler :: be_Sampler\nShader :: be_Shader\nShaderLibrary :: be_ShaderLibrary\nTexture :: be_Texture\nTextureLoader :: be_TextureLoader\nTextureSource :: be_TextureSource\nUniformBuffer :: distinct Buffer\nVertexArray :: be_VertexArray\nVertexBuffer :: distinct Buffer\nVertexShader :: distinct Shader\n\nError :: enum {\n\tNone,\n  Unknown,\n\tNotFound,\n\tMalformed,\n  OutOfMemory,\n\tInvalidValue,\n  InvalidType,\n  InvalidOperation,\n  NilValue,\n}\n\nErrorOrAllocatorError :: union #shared_nil { Error, runtime.Allocator_Error }\n\nAsyncResourceStatus :: enum { Empty, Pending, Ready, Error }\n\nBufferDescriptor :: struct {\n  size: int,\n}\n\nBufferType :: enum u8 { Vertex, Index, Uniform }\n\nShaderType :: enum u8 { Vertex, Fragment }\n\nStepMode :: enum u8 { Vertex = 0, Instance }\n\nTopology :: enum u8 { PointList, "...