---
generated: true
model: claude-opus-4-7
generated_at: 2026-05-22T00:00:00+00:00
source_commit: 6e923e2c0fe3cae4e7cf40e25a96569df5b9f009
watched_paths_digest: 4cd2b0ab91da080eb6a16ece95070e661cf2096b991cd6d164bfccb383236671
source_doc: docs/generated/design/ir-reference/types.md
source_doc_digest: 1c525783aca7f77dc841cbd36fd6911b8ec56b1fee8cffc96d4938b604220a84
warning: "Auto-generated. May drift from source. Do not edit by hand."
---

# Tests for ir-reference/types

## Intent
Tests verify the per-opcode catalog of the IR `Type` family
described in
[`docs/generated/design/ir-reference/types.md`](../../../design/ir-reference/types.md):
that each documented IR type opcode (basic scalars
`Bool`/`Int*`/`UInt*`/`Half`/`Float`/`Double`/`Void`,
`Vec(elementType, elementCount)`,
`Mat(elementType, rowCount, columnCount, layout)`,
`Array(elementType, elementCount)` and `UnsizedArray(elementType)`,
`Func(resultType, paramTypes...)`,
`Ptr(valueType, ...)` and rate-qualified pointer types
(`RateQualified(GroupShared, Ptr(<T>))`),
`struct`, `interface` with `interface_req_entry`/`this_type`,
`witness_table_t` with `witness_table_entry`,
`Optional`, `tuple_type`, `type_t`, and the resource family
(`RWStructuredBuffer`, `StructuredBuffer`, `ConstantBuffer`,
`ByteAddressBuffer`, `RWByteAddressBuffer`, `SamplerState`,
`Texture2D` via `TextureType`)) appears in `-dump-ir` output for the
obvious surface construct that produces it, and that target-divergent
type lowerings (vector spelling, matrix wrapper, struct names) emit
the documented per-target text on the text-emit backends (HLSL,
GLSL, Metal, WGSL, CPP).

The primary observation mechanism is
`-target spirv-asm -dump-ir -o /dev/null` followed by a FileCheck
against the IR dump. Anchors are user-named functions, user structs,
and user `global_param`s — the IR dump's preamble is large and any
unanchored pattern risks false positives. For target-divergent
lowerings (vectors, matrices, struct-field wrappers, buffer-type
wrappers) the test carries one SIMPLE directive per feasible
text-emit target with a distinct CHECK prefix, because the doc's
notable-opcodes section does not claim cross-target uniformity for
type spellings.

Cross-cutting type observations that the `cross-cutting/ir-instructions`
bundle already covers at a sample level (`Vec`, `Array`, `Ptr` from a
local `var`) are not duplicated here; this bundle drills into the
rest of the catalog without repeating those.


## Functional coverage
| Claim | Intent | Anchor | Tests |
| --- | --- | --- | --- |
| An unsized array (runtime extent) is typed UnsizedArray(elementType) in the IR dump. | functional | [#array-vs-unsizedarray](../../../design/ir-reference/types.md#array-vs-unsizedarray) | [`array-unsized.slang`](array-unsized.slang) |
| A fixed-size array field appears as Array(elementType, elementCount) in the IR dump. | functional | [#arrays](../../../design/ir-reference/types.md#arrays) | [`array-fixed-size.slang`](array-fixed-size.slang) |
| Boundary: minimum non-trivial array size (1) appears as Array(Int, 1 : Int) in the IR. | boundary | [#arrays](../../../design/ir-reference/types.md#arrays) | [`array-size-one.slang`](array-size-one.slang) |
| Expansion: Array composes with the narrow Int8 element type, surfacing Array(Int8, N : Int). | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`int8-array-element.slang`](int8-array-element.slang) |
| Expansion: Array of Double elements surfaces Array(Double, N : Int) in the IR dump. | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`double-array-element.slang`](double-array-element.slang) |
| Expansion: Array of Half elements surfaces Array(Half, N : Int) in the IR dump. | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`half-array-element.slang`](half-array-element.slang) |
| Expansion: Array of Int16 elements surfaces Array(Int16, N : Int) in the IR dump. | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`int16-array-element.slang`](int16-array-element.slang) |
| Expansion: Array of Int64 elements surfaces Array(Int64, N : Int) in the IR dump. | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`int64-array-element.slang`](int64-array-element.slang) |
| Expansion: Array of UInt16 elements surfaces Array(UInt16, N : Int) in the IR dump. | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`uint16-array-element.slang`](uint16-array-element.slang) |
| Expansion: Array of UInt64 elements surfaces Array(UInt64, N : Int) in the IR dump. | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`uint64-array-element.slang`](uint64-array-element.slang) |
| Expansion: Array of UInt8 elements surfaces Array(UInt8, N : Int) in the IR dump. | expansion | [#arrays](../../../design/ir-reference/types.md#arrays) | [`uint8-array-element.slang`](uint8-array-element.slang) |
| Negative: assigning an int[3] to an int[4] is rejected because Array types with different elementCount are distinct. | negative | [#arrays](../../../design/ir-reference/types.md#arrays) | [`array-size-mismatch-negative.slang`](array-size-mismatch-negative.slang) |
| Stress: Array composes with a user-struct element; the element-type operand names the struct IR identity. | stress | [#arrays](../../../design/ir-reference/types.md#arrays) | [`array-of-struct-stress.slang`](array-of-struct-stress.slang) |
| Stress: a large `static const`-bounded array surfaces the full extent as Array(Float, 256 : Int). | stress | [#arrays](../../../design/ir-reference/types.md#arrays) | [`array-static-const-bound-256.slang`](array-static-const-bound-256.slang) |
| Stress: array-of-array nests Array operands; int[3][4] surfaces as Array(Array(Int, 4 : Int), 3 : Int). | stress | [#arrays](../../../design/ir-reference/types.md#arrays) | [`array-of-array-nesting.slang`](array-of-array-nesting.slang) |
| Boundary: largest floating-point scalar (Double, 64-bit) appears alone on a global_param's IR type. | boundary | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`scalar-double-largest.slang`](scalar-double-largest.slang) |
| Boundary: largest signed-integer scalar (Int64) appears alone on a global_param's IR type. | boundary | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`scalar-int64-largest.slang`](scalar-int64-largest.slang) |
| Boundary: largest unsigned-integer scalar (UInt64) appears alone on a global_param's IR type. | boundary | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`scalar-uint64-largest.slang`](scalar-uint64-largest.slang) |
| Boundary: smallest documented scalar (Bool, single bit) appears as a global_param's IR type. | boundary | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`scalar-bool-boundary.slang`](scalar-bool-boundary.slang) |
| Boundary: smallest floating-point scalar (Half, 16-bit) appears alone on a global_param's IR type. | boundary | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`scalar-half-smallest-float.slang`](scalar-half-smallest-float.slang) |
| Boundary: smallest signed-integer scalar (Int8) appears alone on a global_param's IR type. | boundary | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`scalar-int8-smallest.slang`](scalar-int8-smallest.slang) |
| Expansion: a scalar Int16 surfaces as the IR type of a uniform int16_t global_param. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`int16-global-param.slang`](int16-global-param.slang) |
| Expansion: a scalar UInt16 surfaces as the IR type of a uniform uint16_t global_param. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`uint16-global-param.slang`](uint16-global-param.slang) |
| Expansion: arithmetic add on Int8 operands produces an Int8-typed IR value, not auto-widened. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`int8-arithmetic-add.slang`](int8-arithmetic-add.slang) |
| Expansion: equality compare on two UInt8 operands yields a Bool-typed cmpEQ on Int8 inputs. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`uint8-comparison-eq.slang`](uint8-comparison-eq.slang) |
| Expansion: less-than compare on Int16 operands yields a Bool-typed cmpLT preserving the narrow operand type. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`int16-comparison-lt.slang`](int16-comparison-lt.slang) |
| Expansion: less-than compare on two Int64 operands yields a cmpLT with Int64 inputs and Bool result. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`int64-comparison-lt.slang`](int64-comparison-lt.slang) |
| Expansion: narrowing conversion from Double to Half yields a Half-typed floatCast value. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`double-to-half-narrow.slang`](double-to-half-narrow.slang) |
| Expansion: narrowing conversion from Int to Int8 yields a value typed Int8 in the dump. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`int32-to-int8-narrow.slang`](int32-to-int8-narrow.slang) |
| Expansion: narrowing from UInt64 to UInt16 yields a UInt16-typed cast value, distinguishing the two unsigned widths. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`uint64-to-uint16-narrow.slang`](uint64-to-uint16-narrow.slang) |
| Expansion: widening conversion from Half to Float yields a Float-typed floatCast value, complementing the narrow-to-wide direction. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`half-to-float-widen.slang`](half-to-float-widen.slang) |
| Expansion: widening conversion from UInt8 to UInt yields a UInt-typed intCast value. | expansion | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`uint8-to-uint-widen.slang`](uint8-to-uint-widen.slang) |
| The Bool scalar opcode encodes `bool`; a `void` function uses the Void opcode as its Func result-type operand. | functional | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`basic-bool-and-void.slang`](basic-bool-and-void.slang) |
| The floating-point scalar opcodes Half, Float, Double appear as struct-field types in the IR dump. | functional | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`basic-scalars-float-family.slang`](basic-scalars-float-family.slang) |
| The signed-integer scalar opcodes Int8, Int16, Int, Int64 appear as struct-field types in the IR dump. | functional | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`basic-scalars-int-family.slang`](basic-scalars-int-family.slang) |
| The unsigned-integer scalar opcodes UInt8, UInt16, UInt, UInt64 appear as struct-field types in the IR dump. | functional | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | [`basic-scalars-uint-family.slang`](basic-scalars-uint-family.slang) |
| An interface declaration produces interface_req_entry instructions whose method-types use this_type. | functional | [#existentials-and-interfaces](../../../design/ir-reference/types.md#existentials-and-interfaces) | [`interface-and-this-type.slang`](interface-and-this-type.slang) |
| Boundary: Func operands preserve param type heterogeneity (mixed scalar/vector/array params). | boundary | [#func](../../../design/ir-reference/types.md#func) | [`func-mixed-vector-params.slang`](func-mixed-vector-params.slang) |
| Boundary: a function returning a user struct names that struct as the Func result-type operand. | boundary | [#func](../../../design/ir-reference/types.md#func) | [`func-struct-result.slang`](func-struct-result.slang) |
| Boundary: a zero-parameter void function is typed Func(Void) with no parameter operands. | boundary | [#func](../../../design/ir-reference/types.md#func) | [`func-zero-params-void-return.slang`](func-zero-params-void-return.slang) |
| Stress: eight-parameter function preserves all parameter types as positional operands of Func. | stress | [#func](../../../design/ir-reference/types.md#func) | [`func-eight-params-stress.slang`](func-eight-params-stress.slang) |
| The Func type opcode places the result type first, then parameter types in declaration order. | functional | [#func](../../../design/ir-reference/types.md#func) | [`func-result-then-params.slang`](func-result-then-params.slang) |
| A local var of struct type produces a value whose IR type is Ptr<T>. | functional | [#ptr-and-the-access-qualifier-address-space-operands](../../../design/ir-reference/types.md#ptr-and-the-access-qualifier-address-space-operands) | [`ptr-from-struct-var.slang`](ptr-from-struct-var.slang) |
| Boundary: a get_field_addr through a nested struct field yields a value of type Ptr(<InnerStruct>). | boundary | [#ptr-and-the-access-qualifier-address-space-operands](../../../design/ir-reference/types.md#ptr-and-the-access-qualifier-address-space-operands) | [`ptr-to-nested-struct-field.slang`](ptr-to-nested-struct-field.slang) |
| Boundary: a local var of fixed-array type produces a value of IR type Ptr(Array(<T>, <N>)). | boundary | [#ptr-and-the-access-qualifier-address-space-operands](../../../design/ir-reference/types.md#ptr-and-the-access-qualifier-address-space-operands) | [`ptr-from-array-var.slang`](ptr-from-array-var.slang) |
| A groupshared declaration is typed RateQualified(GroupShared, Ptr(<T>)) in the IR. | functional | [#rates-and-rate-qualified-types](../../../design/ir-reference/types.md#rates-and-rate-qualified-types) | [`ptr-groupshared-rate-qualified.slang`](ptr-groupshared-rate-qualified.slang) |
| A ConstantBuffer<T> uniform lowers to a global_param of IR type ConstantBuffer(<T>, <layout>, ...). | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`constantbuffer-type.slang`](constantbuffer-type.slang) |
| A LineStream<T> geometry-shader output parameter surfaces the LineStream opcode parameterised by its element type in the IR dump. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`linestream-type.slang`](linestream-type.slang) |
| A PointStream<T> geometry-shader output parameter surfaces the PointStream opcode parameterised by its element type in the IR dump. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`pointstream-type.slang`](pointstream-type.slang) |
| A RWStructuredBuffer<T> uniform lowers to a global_param of IR type RWStructuredBuffer(<T>, <layout>, ...). | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`rwstructuredbuffer-type.slang`](rwstructuredbuffer-type.slang) |
| A RayQuery<flags> local variable surfaces the RayQuery opcode in the IR dump. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`rayquery-type.slang`](rayquery-type.slang) |
| A SubpassInput<T> uniform declared in a fragment entry point surfaces the SubpassInputType opcode parameterised by its element type in the IR dump. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`subpassinput-type.slang`](subpassinput-type.slang) |
| A TriangleStream<T> geometry-shader output parameter surfaces the TriangleStream opcode parameterised by its element type in the IR dump. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`trianglestream-type.slang`](trianglestream-type.slang) |
| A read-only StructuredBuffer<T> uniform lowers to a global_param of IR type StructuredBuffer(<T>, <layout>, ...). | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`structuredbuffer-type.slang`](structuredbuffer-type.slang) |
| A uniform RaytracingAccelerationStructure declaration lowers to a global_param of IR type RaytracingAccelerationStructure. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`raytracingaccelerationstructure-type.slang`](raytracingaccelerationstructure-type.slang) |
| A uniform SamplerState declaration lowers to a global_param of IR type SamplerState. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`samplerstate-type.slang`](samplerstate-type.slang) |
| A uniform Texture2D<float4> declaration lowers to a global_param of IR type TextureType with element-type and TextureShape2DType operands. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`texture-type.slang`](texture-type.slang) |
| An InputPatch<T,N> hull-shader parameter surfaces the InputPatch opcode parameterised by element type and elementCount in the IR dump. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`inputpatch-type.slang`](inputpatch-type.slang) |
| An OutputPatch<T,N> domain-shader parameter surfaces the OutputPatch opcode parameterised by element type and elementCount in the IR dump. | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`outputpatch-type.slang`](outputpatch-type.slang) |
| Boundary: RWStructuredBuffer parameterised by a user struct names that struct as its first operand. | boundary | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`rwbuf-struct-element.slang`](rwbuf-struct-element.slang) |
| Boundary: RWStructuredBuffer parameterised by a vector element type names the Vec(...) form as its first operand. | boundary | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`rwbuf-vector-element.slang`](rwbuf-vector-element.slang) |
| ByteAddressBuffer and RWByteAddressBuffer uniforms lower to global_params of the same-spelled IR types (no element-type operand). | functional | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`byteaddressbuffer-type.slang`](byteaddressbuffer-type.slang) |
| Expansion: RWStructuredBuffer parameterised by Int8 names the narrow scalar as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`int8-rwstructuredbuffer-element.slang`](int8-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer parameterised by UInt8 names the narrow scalar as its first operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`uint8-rwstructuredbuffer-element.slang`](uint8-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer parameterised by a double4 vector exposes Vec(Double, 4 : Int) as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`double4-rwstructuredbuffer-element.slang`](double4-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer parameterised by a half4 vector exposes Vec(Half, 4 : Int) as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`half4-rwstructuredbuffer-element.slang`](half4-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer<double> names Double as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`double-rwstructuredbuffer-element.slang`](double-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer<half> names Half as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`half-rwstructuredbuffer-element.slang`](half-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer<int16_t> names Int16 as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`int16-rwstructuredbuffer-element.slang`](int16-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer<int64_t> names Int64 as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`int64-rwstructuredbuffer-element.slang`](int64-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer<uint16_t> names UInt16 as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`uint16-rwstructuredbuffer-element.slang`](uint16-rwstructuredbuffer-element.slang) |
| Expansion: RWStructuredBuffer<uint64_t> names UInt64 as its element-type operand. | expansion | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`uint64-rwstructuredbuffer-element.slang`](uint64-rwstructuredbuffer-element.slang) |
| Stress: RWStructuredBuffer parameterised by a struct of three vector fields preserves all field rows and the struct identity in the IR type. | stress | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | [`rwbuf-struct-of-vectors-stress.slang`](rwbuf-struct-of-vectors-stress.slang) |
| A generic type-parameter is typed type_t in the IR dump. | functional | [#spir-v-literals-and-kinds](../../../design/ir-reference/types.md#spir-v-literals-and-kinds) | [`type-t-generic-param.slang`](type-t-generic-param.slang) |
| Stress: an instantiation of a generic with a Vec type-argument still surfaces the type_t kind on the generic param. | stress | [#spir-v-literals-and-kinds](../../../design/ir-reference/types.md#spir-v-literals-and-kinds) | [`generic-on-vector-element.slang`](generic-on-vector-element.slang) |
| A string literal in a printf call produces an operand of IR type String in the dump. | functional | [#strings-and-dynamic-types](../../../design/ir-reference/types.md#strings-and-dynamic-types) | [`string-literal-type.slang`](string-literal-type.slang) |
| A user struct lowers to a parent `struct %Name` opcode containing `field(%key, <T>)` rows. | functional | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`struct-with-fields.slang`](struct-with-fields.slang) |
| Boundary: a single-field struct surfaces exactly one `field` row under the parent. | boundary | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`struct-single-field-boundary.slang`](struct-single-field-boundary.slang) |
| Boundary: a struct field of vector type composes; the field row carries the full Vec(...) operand. | boundary | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`struct-with-vector-field.slang`](struct-with-vector-field.slang) |
| Boundary: an empty struct still surfaces a parent `struct %Name` opcode (no field children). | boundary | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`struct-empty-boundary.slang`](struct-empty-boundary.slang) |
| Expansion: a struct field of Double lowers to a field(...) row carrying Double. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`double-struct-field.slang`](double-struct-field.slang) |
| Expansion: a struct field of Half lowers to a field(...) row carrying Half. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`half-struct-field.slang`](half-struct-field.slang) |
| Expansion: a struct field of Int16 lowers to a field(...) row whose type operand is Int16. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`int16-struct-field.slang`](int16-struct-field.slang) |
| Expansion: a struct field of Int64 lowers to a field(...) row carrying Int64. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`int64-struct-field.slang`](int64-struct-field.slang) |
| Expansion: a struct field of Int8 type lowers to a field(...) row carrying Int8 as its type operand. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`int8-struct-field.slang`](int8-struct-field.slang) |
| Expansion: a struct field of UInt16 lowers to a field(...) row carrying UInt16. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`uint16-struct-field.slang`](uint16-struct-field.slang) |
| Expansion: a struct field of UInt64 lowers to a field(...) row carrying UInt64. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`uint64-struct-field.slang`](uint64-struct-field.slang) |
| Expansion: struct field of UInt8 surfaces a field(...) row carrying UInt8. | expansion | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`uint8-struct-field.slang`](uint8-struct-field.slang) |
| Stress: five-deep struct nesting produces five distinct `struct %Name` parent opcodes. | stress | [#struct-and-class-containers](../../../design/ir-reference/types.md#struct-and-class-containers) | [`struct-nested-five-deep.slang`](struct-nested-five-deep.slang) |
| A makeTuple call yields a value of IR type tuple_type(<T1>, <T2>, ...). | functional | [#tuples-packs-and-target-tuples](../../../design/ir-reference/types.md#tuples-packs-and-target-tuples) | [`tuple-type.slang`](tuple-type.slang) |
| Stress: a three-element heterogeneous tuple surfaces tuple_type(Float, Int, Bool) with all operands. | stress | [#tuples-packs-and-target-tuples](../../../design/ir-reference/types.md#tuples-packs-and-target-tuples) | [`tuple-three-element-stress.slang`](tuple-three-element-stress.slang) |
| A float3 vector type lowers to target-specific spellings on each text-emit backend. | functional | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vec-emit-multi-target.slang`](vec-emit-multi-target.slang) |
| A float4x4 matrix type lowers to target-specific spellings (float4x4 on HLSL, mat4x4 on GLSL, mat4x4<f32> on WGSL). | functional | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`mat-emit-multi-target.slang`](mat-emit-multi-target.slang) |
| A matrix value is typed Mat(elementType, rowCount, columnCount, layout) in the IR dump. | functional | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`mat-shape-operands.slang`](mat-shape-operands.slang) |
| A vector value is typed Vec(elementType, elementCount) in the IR dump. | functional | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vec-elementtype-elementcount.slang`](vec-elementtype-elementcount.slang) |
| A vector<int,3>-to-vector<int,4> assignment is rejected; Vec types with different elementCount are not interchangeable. | negative | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vector-size-mismatch-negative.slang`](vector-size-mismatch-negative.slang) |
| Boundary: a int3 vector type combines the signed-int scalar with elementCount 3 in the Vec opcode. | boundary | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vec-int3-explicit-uintcount.slang`](vec-int3-explicit-uintcount.slang) |
| Boundary: largest-element vector (double4) is typed Vec(Double, 4 : Int) in the IR. | boundary | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vec-double4-largest-element.slang`](vec-double4-largest-element.slang) |
| Boundary: minimum-dimension vector (vector<float,1>) is typed Vec(Float, 1 : Int) in the IR. | boundary | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vec1-minimum-dimension.slang`](vec1-minimum-dimension.slang) |
| Boundary: minimum-shape matrix (matrix<float,1,1>) is typed Mat(Float, 1 : Int, 1 : Int, layout) in the IR. | boundary | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`mat1x1-minimum-shape.slang`](mat1x1-minimum-shape.slang) |
| Boundary: rectangular (non-square) matrix surfaces both shape operands distinctly as Mat(Float, 2 : Int, 3 : Int, layout). | boundary | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`mat-rectangular-2x3.slang`](mat-rectangular-2x3.slang) |
| Boundary: smallest multi-element vector (float2) is typed Vec(Float, 2 : Int) in the IR. | boundary | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vec2-minimum-multi-element.slang`](vec2-minimum-multi-element.slang) |
| Expansion: Vec composes with Double at the standard upper element count to form Vec(Double, 4 : Int) on a global_param. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`double-vector4-global-param.slang`](double-vector4-global-param.slang) |
| Expansion: Vec composes with Double to form Vec(Double, 3 : Int) on a global_param. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`double-vector3-global-param.slang`](double-vector3-global-param.slang) |
| Expansion: Vec composes with Half to form Vec(Half, 3 : Int) on a global_param. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`half-vector3-global-param.slang`](half-vector3-global-param.slang) |
| Expansion: Vec composes with Half to form Vec(Half, 4 : Int) at the standard upper element count. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`half-vector4-global-param.slang`](half-vector4-global-param.slang) |
| Expansion: Vec composes with Int16 to form Vec(Int16, 2 : Int) on a global_param. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`int16-vector2-global-param.slang`](int16-vector2-global-param.slang) |
| Expansion: Vec composes with UInt16 to form Vec(UInt16, 3 : Int) on a global_param. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`uint16-vector3-global-param.slang`](uint16-vector3-global-param.slang) |
| Expansion: Vec composes with UInt64 to form Vec(UInt64, 2 : Int). | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`uint64-vector2-global-param.slang`](uint64-vector2-global-param.slang) |
| Expansion: Vec composes with UInt8 to form Vec(UInt8, 4 : Int) as a global_param. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`uint8-vector4-global-param.slang`](uint8-vector4-global-param.slang) |
| Expansion: Vec composes with the narrow Half float scalar to form Vec(Half, 2 : Int). | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`half-vector2-global-param.slang`](half-vector2-global-param.slang) |
| Expansion: Vec composes with the narrow Int8 scalar to form Vec(Int8, 3 : Int) as a global_param. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`int8-vector3-global-param.slang`](int8-vector3-global-param.slang) |
| Expansion: Vec composes with the wide Double scalar to form Vec(Double, 2 : Int). | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`double-vector2-global-param.slang`](double-vector2-global-param.slang) |
| Expansion: Vec composes with the wide Int64 scalar to form Vec(Int64, 2 : Int). | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`int64-vector2-global-param.slang`](int64-vector2-global-param.slang) |
| Expansion: narrowing conversion from a Vec(Double, 4) to a Vec(Float, 4) yields a floatCast whose result is the narrower-element vector. | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`double4-narrow-to-float4.slang`](double4-narrow-to-float4.slang) |
| Expansion: vector add on Vec(Double, 3 : Int) operands produces an add whose result type stays Vec(Double, 3 : Int). | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`double-vector3-arithmetic.slang`](double-vector3-arithmetic.slang) |
| Expansion: vector add on Vec(Half, 2 : Int) operands yields an add whose result type stays Vec(Half, 2 : Int). | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`half2-arithmetic.slang`](half2-arithmetic.slang) |
| Expansion: vector add on Vec(Half, 3 : Int) operands produces an add whose result type stays Vec(Half, 3 : Int). | expansion | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`half-vector3-arithmetic.slang`](half-vector3-arithmetic.slang) |
| Negative: assigning a float2x2 to a float3x3 is rejected because Mat types with different rowCount/columnCount are distinct. | negative | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`matrix-shape-mismatch-negative.slang`](matrix-shape-mismatch-negative.slang) |
| Negative: assigning a vector<int,4> to a vector<int,2> (narrowing) is rejected by the type checker. | negative | [#vec-and-mat](../../../design/ir-reference/types.md#vec-and-mat) | [`vector-size-narrowing-negative.slang`](vector-size-narrowing-negative.slang) |
| An Atomic<T> field surfaces the Atomic opcode parameterised by its element type in the IR dump. | functional | [#vectors-matrices-and-composite](../../../design/ir-reference/types.md#vectors-matrices-and-composite) | [`atomic-type.slang`](atomic-type.slang) |
| Boundary: Optional<T> composes with a Vec<T> payload; the Optional operand is the Vec(...) IR type. | boundary | [#vectors-matrices-and-composite](../../../design/ir-reference/types.md#vectors-matrices-and-composite) | [`optional-vector-payload.slang`](optional-vector-payload.slang) |
| The Optional(valueType) IR type is produced for an Optional<T> return value. | functional | [#vectors-matrices-and-composite](../../../design/ir-reference/types.md#vectors-matrices-and-composite) | [`optional-type.slang`](optional-type.slang) |
| A conformance produces a witness_table value whose IR type is witness_table_t(<interface>) with witness_table_entry rows. | functional | [#witness-table-types](../../../design/ir-reference/types.md#witness-table-types) | [`witness-table-type.slang`](witness-table-type.slang) |
| Stress: two distinct conformances to the same interface produce two distinct witness_table values parameterised by the same interface. | stress | [#witness-table-types](../../../design/ir-reference/types.md#witness-table-types) | [`witness-table-two-conformances.slang`](witness-table-two-conformances.slang) |


## Untested claims
| Claim | Reason | Anchor | Why untested |
| --- | --- | --- | --- |
| **Storage-only floats** (`FloatE4M3Type`, `FloatE5M2Type`, `BFloat16Type`) — surface support varies by target and core module; the doc does not name a portable surface for them. | (unclassified) | [#floate4m3type](../../../design/ir-reference/types.md#floate4m3type) | Reason and explanation to be refined by the next regeneration. |
| **Buffer-layout marker family** as individual opcodes (`Std140Layout`, `Std430Layout`, `D3DConstantBufferLayout`, `MetalParameterBlockLayout`, `CUDALayout`, `LLVMLayout`, `CLayout`, `ScalarLayout`, `DefaultPushConstantLayout`) — they appear as operands inside the typed-buffer family IR shapes; the doc lists them but does not provide a per-marker surface trigger. `DefaultLayout` is covered through the typed-buffer tests; per- marker tests are not warranted from the doc claims. | (unclassified) | [#std140layout](../../../design/ir-reference/types.md#std140layout) | Reason and explanation to be refined by the next regeneration. |
| **Tensor and torch-tensor types** (`TensorView`, `TorchTensor`, `ArrayListVector`, `TensorAddressingTensorLayoutType`, `TensorAddressingTensorViewType`, `MakeTensorAddressingTensor*`) — Python-binding lowering, no shader-language surface. | (unclassified) | [#tensorview](../../../design/ir-reference/types.md#tensorview) | Reason and explanation to be refined by the next regeneration. |
| The **kinds** (`Type`, `TypeParameterPack`, `Rate`, `Generic`) beyond `type_t` — the doc lists them as kinds but does not name a `-dump-ir` observation that surfaces them directly. | (unclassified) | [#type](../../../design/ir-reference/types.md#type) | Reason and explanation to be refined by the next regeneration. |
| **Set-theoretic types** (`UntaggedUnionType`, `ElementOfSetType`, `SetTagType`, `TaggedUnionType`, `OptionalNoneType`) — also pass-produced; not anchored to a surface in the source doc. | (unclassified) | [#untaggeduniontype](../../../design/ir-reference/types.md#untaggeduniontype) | Reason and explanation to be refined by the next regeneration. |
| The **C++ wrapper struct** identity for each opcode (e.g. that `Vec` is a `VectorType` in C++, `Func` is a `FuncType`) — internal API, not surface-visible. | (unclassified) | [#vec](../../../design/ir-reference/types.md#vec) | Reason and explanation to be refined by the next regeneration. |
| **Host-side pointer types** (`ComPtr`, `NativePtr`, `DescriptorHandle`) — host-side API types, not exercisable from a shader. | needs-unit-test | [#comptr](../../../design/ir-reference/types.md#comptr) | No slangc CLI surface reaches this. A C++ unit test in `tools/slang-unit-test/` could exercise the relevant compiler internals directly. |
| **`Char`** — listed as the element type of a string literal in the basic-scalar table, but Slang has no portable shader-side surface that declares a `Char`-typed value; only the `String` literal whose element type is `Char` is observable, and that is covered through `string-literal-type.slang`. | internal-source-fact | [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | Implementation detail (C++ class hierarchy, field names, parser-callback names) with no user-observable consequence. |
| **`NativeString`** — the table describes it as an "Unowned raw C-style string", reachable only through host-side / native APIs; no portable shader surface produces a `NativeString`-typed IR value. | internal-source-fact | [#strings-and-dynamic-types](../../../design/ir-reference/types.md#strings-and-dynamic-types) | Implementation detail (C++ class hierarchy, field names, parser-callback names) with no user-observable consequence. |
| **`HitObject`, `TextureFootprintType`, `DynamicResource`, `CoopVector`, `CoopMatrix`** — DXR shader-execution-reordering / cooperative / footprint surfaces; coverage belongs to `ir-reference/resources-and-atomics` (DXR + cooperative-matrix sibling bundles). | out-of-bundle | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | Covered by a sibling bundle; see the appropriate `docs/generated/tests/<sibling>/` directory. |
| **Mesh-shader output types** (`Vertices`, `Indices`, `Primitives`, `metal::mesh`, `mesh_grid_properties`) — mesh-shader pipeline stages; coverage belongs to a future `ir-reference/mesh-shader` sibling bundle when the doc gives a portable mesh-shader entry-point example. | out-of-bundle | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | Covered by a sibling bundle; see the appropriate `docs/generated/tests/<sibling>/` directory. |
| **`GLSLInputAttachment`** — GLSL-specific input attachment opcode; the SPIR-V/Vulkan surface is `SubpassInput<T>` which lowers to `SubpassInputType`, covered by `subpassinput-type.slang`. Coverage of the GLSL-only opcode belongs to a GLSL-input-only sibling bundle. | out-of-bundle | [#resource-and-texture-types](../../../design/ir-reference/types.md#resource-and-texture-types) | Covered by a sibling bundle; see the appropriate `docs/generated/tests/<sibling>/` directory. |
| **Hoistability flags** (`H` in the doc's tables) — the dump shows the post-hoist result, not the decision. Two textually identical `Vec(Float, 3 : Int)` types appearing once is observable; the *reason* (hoisting) is not. | implementation-detail | (unspecified) | Internal compiler choice (pass ordering, hoistability decisions, deduplication) with no test-directive that reveals it. |
| The IR's structural type-equality-by-pointer (the `IRInst*`-compare optimisation enabled by hoistable types). This is a runtime property of `IRBuilder` deduplication, not visible in the dump. | implementation-detail | [#irbuilder](../../../design/ir-reference/types.md#irbuilder) | Internal compiler choice (pass ordering, hoistability decisions, deduplication) with no test-directive that reveals it. |
| **Differentiation context types** (`BackwardDiffIntermediateContextType`, `TrivialBackwardDiffIntermediateContextType`, the `*Minimal*` variants, the legacy-bridge variants, `ForwardDiffFuncType`, `BackwardDiffFuncType`, `ApplyForBwdFuncType`, `BwdCallableFuncType`, `RematFuncType`) — only produced by the autodiff pass with `[Differentiable]` annotations; coverage belongs to `ir-reference/differentiation`. | link-stage-only | [#backwarddiffintermediatecontexttype](../../../design/ir-reference/types.md#backwarddiffintermediatecontexttype) | Synthesized at a later IR pass than this bundle's `pipeline_stage` observes; the test belongs in the bundle whose pipeline stage matches. |
| **Existential / RTTI types** (`BindExistentials`, `BoundInterface`, `AnyValueType`, `DynamicType`, `rtti_type`, `rtti_handle_type`, `RTTIPointerType`, `RTTIHandleType`) — produced by the existential-elimination IR pass; coverage belongs to `ir-reference/generics-and-existentials`. | link-stage-only | [#bindexistentials](../../../design/ir-reference/types.md#bindexistentials) | Synthesized at a later IR pass than this bundle's `pipeline_stage` observes; the test belongs in the bundle whose pipeline stage matches. |


## Doc gaps observed
| Anchor | Kind | Gap | Suggested addition |
| --- | --- | --- | --- |
| [#basic-scalar-types](../../../design/ir-reference/types.md#basic-scalar-types) | missing-surface | The doc's "Basic scalar types" table lists `IntPtr` and `UIntPtr` ("Signed/Unsigned integer with pointer-equivalent width") but does not name a Slang surface construct that produces them. The user-level type names (if any — typically host-side only) are not reachable from a shader, so a `.slang` test cannot anchor here. |  |
| [#storage-only-floating-point](../../../design/ir-reference/types.md#storage-only-floating-point) | missing-surface | "Storage-only floating-point" (`FloatE4M3Type`, `FloatE5M2Type`, `BFloat16Type`) lists three opcodes but does not state a portable surface construct that reliably produces them on the no-GPU runner. A user-level surface example (`_E4M3 x;`, `BFloat16 y;`) per row would let the agent anchor a test. |  |
| [#differentiation-types](../../../design/ir-reference/types.md#differentiation-types) | undocumented-behavior | "Differentiation types" (`DiffPair`, `DiffRefPair`, `ForwardDiffFuncType`, `BackwardDiffFuncType`, and the seven context-channel types) are produced by the autodiff pass when `[Differentiable]` is in play. The catalog rows do not name the user-level construct that triggers each context-type variant (`Minimal` vs ordinary vs `Trivial`); a one-line "surface" column would let the agent test them. |  |
| [#existentials-and-interfaces](../../../design/ir-reference/types.md#existentials-and-interfaces) | undocumented-behavior | "Existentials and interfaces" lists `BindExistentials`, `BoundInterface`, `AnyValueType`, `DynamicType`, and `rtti_type` / `rtti_handle_type` as opcodes but tags most as "(synthesized)" — they are produced by the existential-elimination IR pass, not by lowering. The doc does not state which `-dump-ir` stage to inspect to observe them; without that hint the doc reader cannot anchor a test in this bundle. Coverage belongs to `ir-reference/generics-and-existentials`. |  |
| [#pointer-types](../../../design/ir-reference/types.md#pointer-types) | undocumented-behavior | "Pointer types" lists `RefParam`, `BorrowInParam`, `BorrowInOutParam`, `OutParam`, `ComPtr`, `NativePtr`, `DescriptorHandle`, and `PseudoPtr`. The doc gives AST origin rows (`RefType`, `BorrowInType`, etc.) but does not name a user-language keyword for each (Slang's surface for borrow / ref parameters is documented elsewhere). A cross-reference to `docs/generated/design/ast-reference/types.md` row by row would let the agent anchor tests for each pointer kind. |  |
| [#sampler-and-buffer-layout-types](../../../design/ir-reference/types.md#sampler-and-buffer-layout-types) | undocumented-behavior | "Sampler and buffer-layout types" — `Std140Layout`, `Std430Layout`, `D3DConstantBufferLayout`, `MetalParameterBlockLayout`, `CUDALayout`, `LLVMLayout`, `CLayout`, `ScalarLayout`, `DefaultLayout`, `DefaultPushConstantLayout` — the doc names each marker but does not state where in the IR they appear (they appear as the third operand of a `RWStructuredBuffer(...)` IR type, for example). | A one-line "where to observe" note would let the agent test each marker individually; the current bundle uses one test (`rwstructuredbuffer-type.slang`) to cover the family. |
| [#set-theoretic-types](../../../design/ir-reference/types.md#set-theoretic-types) | undocumented-behavior | "Set-theoretic types" (`UntaggedUnionType`, `ElementOfSetType`, `SetTagType`, `TaggedUnionType`, `OptionalNoneType`) are listed with "(synthesized)" AST origin. The doc does not state a language surface that triggers each; they appear to be produced by the existential-elimination pass. | Without a documented surface, no `.slang` test in this bundle can anchor here. |
| [#tensor-and-torch-tensor-types](../../../design/ir-reference/types.md#tensor-and-torch-tensor-types) | undocumented-behavior | "Tensor and torch-tensor types" — Python-binding lowering only; no shader-language surface reaches it. |  |
| [#spir-v-literals-and-kinds](../../../design/ir-reference/types.md#spir-v-literals-and-kinds) | undocumented-behavior | "SPIR-V literals and kinds" — the `Type` (TypeKind), `TypeParameterPack`, `Rate`, `Generic` kind opcodes are listed but their observation requires inspecting the type of a generic-parameter's type (`type_t`'s type is `Type`). The doc does not name a `-dump-ir` line that displays the kind directly; one test (`type-t-generic-param.slang`) covers `type_t` only. |  |
| [#layout-int-literal-selecting-row-major-column-major](../../../design/ir-reference/types.md#layout-int-literal-selecting-row-major-column-major) | undocumented-behavior | The doc's `Mat` row says the fourth operand is a "layout int literal selecting row-major / column-major" but does not name which integer value selects which layout. The current bundle uses a wildcard pattern in the matrix test rather than asserting a specific value. |  |
