---
generated: true
model: claude-opus-4-8
generated_at: 2026-07-02T00:00:00+00:00
source_commit: 8e2a63cbf22c85332796702fd02a875466486a23
watched_paths_digest: 46d02a2bd8b7c35ba5960c3109455d40e100dd1525ab1a1e912e382d83b9943c
source_doc: docs/generated/design/pipeline/03-semantic-check.md
source_doc_digest: 6d8666ce84da327589c421d02bf9ec5b19ae43b68ed61932a0ba48045a900b99
warning: "Auto-generated. May drift from source. Do not edit by hand."
---

# Tests for design/pipeline/03-semantic-check

## Intent

Tests exercise the semantic-checking stage described in
[`docs/generated/design/pipeline/03-semantic-check.md`](../../../design/pipeline/03-semantic-check.md):
turning a raw AST into a fully resolved, type-checked AST. The doc is
largely architectural (it names which `slang-check-*.cpp` file owns
which concern) but commits to several concrete, user-observable
behaviors — the "Failure modes", "Generic specialization",
"Synthesizing implicit code", "Modifier validation", and
"Shader-specific checks" sections make claims about what is accepted,
what is rejected (and with which diagnostic), and what is
synthesized. Each such claim is decomposed into a positive
(`INTERPRET`) test and/or a negative (`DIAGNOSTIC_TEST`) test.

The doc hands off the lookup / overload-resolution algorithm to the
[`name-resolution/`](../../../design/name-resolution/) subtree
(which the primary doc explicitly references from its "Name lookup
and `DeclRef`" section and its overload-resolution discussion), so a
handful of tests anchor to `lookup.md` and `overload-resolution.md`
as secondary docs the per-section prompt permits.

Every claim here is target-independent — semantic checking resolves
names, types, conformances, and diagnostics before any back-end
codegen. Positive observations therefore use `//TEST:INTERPRET`
(the lightest runner that actually executes checked code at runtime);
rejection claims use `//DIAGNOSTIC_TEST:SIMPLE` citing the exact
diagnostic code and message text. No per-target fan-out is warranted
and none is added.

## Functional coverage

| Claim                                                                                                                                                                                            | Intent     | Anchor                                                                                                                                            | Tests                                                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Block-local shadowing hides a local from lookup until its DeclStmt is reached; using `x` before its declaration produces an undefined-identifier diagnostic.                                       | negative   | [#block-local-shadowing](../../../design/name-resolution/lookup.md#block-local-shadowing)                                                         | [`forward-reference-in-block-rejected.slang`](forward-reference-in-block-rejected.slang)                       |
| Same-named functions in one container accumulate into an overload set; overload resolution picks each by argument type at the call site.                                                          | functional | [#container-level-overload-accumulation](../../../design/name-resolution/lookup.md#container-level-overload-accumulation)                         | [`overload-accumulation-by-arg-type.slang`](overload-accumulation-by-arg-type.slang)                           |
| Member lookup walks the inheritance chain so a method declared on an interface is callable through a generic constrained on that interface.                                                        | functional | [#member-lookup](../../../design/name-resolution/lookup.md#member-lookup)                                                                         | [`inheritance-walk-finds-base-member.slang`](inheritance-walk-finds-base-member.slang)                         |
| When a non-overloadable lookup resolves to multiple decls (two types of the same name reachable via different namespace imports), the checker reports ambiguous-reference.                          | negative   | [#edge-cases-and-failure-modes](../../../design/name-resolution/lookup.md#edge-cases-and-failure-modes)                                           | [`ambiguous-reference-diagnostic.slang`](ambiguous-reference-diagnostic.slang)                                 |
| Overload checking accepts a function taking 8 positional arguments and resolves at the call site; each argument flows through to the body.                                                        | boundary   | [#conversion-costs](../../../design/name-resolution/overload-resolution.md#conversion-costs)                                                       | [`many-args-positional.slang`](many-args-positional.slang)                                                     |
| Overload checking accepts a zero-argument call to a function with a default argument; the default-value expression is filled in at check time.                                                    | boundary   | [#conversion-costs](../../../design/name-resolution/overload-resolution.md#conversion-costs)                                                       | [`default-argument-with-zero-args.slang`](default-argument-with-zero-args.slang)                               |
| Overload resolution prefers the candidate that requires no implicit conversion (lowest conversion cost) over one that requires a numeric widening.                                                | functional | [#conversion-costs](../../../design/name-resolution/overload-resolution.md#conversion-costs)                                                       | [`overload-prefer-exact-type.slang`](overload-prefer-exact-type.slang)                                         |
| Overload resolution selects the exact-type `int` candidate over the `uint` candidate for an `int`-typed argument because no signedness conversion is needed.                                       | boundary   | [#conversion-costs](../../../design/name-resolution/overload-resolution.md#conversion-costs)                                                       | [`overload-prefer-int-over-uint.slang`](overload-prefer-int-over-uint.slang)                                   |
| A call with zero applicable candidates among multiple overloads is rejected with "no overload applicable" naming the call name.                                                                    | negative   | [#edge-cases-and-failure-modes](../../../design/name-resolution/overload-resolution.md#edge-cases-and-failure-modes)                               | [`no-applicable-overload-zero-candidate-rejected.slang`](no-applicable-overload-zero-candidate-rejected.slang) |
| Overload resolution rejects a call passing too many arguments with the "too many arguments to call" diagnostic, counterpart of "not enough arguments".                                            | negative   | [#edge-cases-and-failure-modes](../../../design/name-resolution/overload-resolution.md#edge-cases-and-failure-modes)                               | [`too-many-arguments-rejected.slang`](too-many-arguments-rejected.slang)                                       |
| Two equally-applicable overloads to the same call site are rejected with the "ambiguous call" diagnostic naming the function and arg types.                                                        | negative   | [#edge-cases-and-failure-modes](../../../design/name-resolution/overload-resolution.md#edge-cases-and-failure-modes)                               | [`ambiguous-overload-rejected.slang`](ambiguous-overload-rejected.slang)                                       |
| When no candidate in the overload set matches the call's argument count and types, the call is rejected with a diagnostic.                                                                         | negative   | [#edge-cases-and-failure-modes](../../../design/name-resolution/overload-resolution.md#edge-cases-and-failure-modes)                               | [`no-applicable-overload-diagnostic.slang`](no-applicable-overload-diagnostic.slang)                           |
| Operator overloading: a user-defined `operator+` on a struct is found by overload resolution at a `+` expression with that struct's argument types.                                                | functional | [#operator-overloading](../../../design/name-resolution/overload-resolution.md#operator-overloading)                                               | [`operator-overload-on-struct.slang`](operator-overload-on-struct.slang)                                       |
| Inheritance checking rejects a struct that names itself as its base ("cyclic reference in inheritance graph").                                                                                     | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`cyclic-inheritance-rejected.slang`](cyclic-inheritance-rejected.slang)                                       |
| Declaring the same function name twice with different return types is rejected with the function-return-type-mismatch diagnostic (E30202).                                                         | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`function-return-type-mismatch-rejected.slang`](function-return-type-mismatch-rejected.slang)                 |
| Defining the same function twice is rejected (function-redefinition, 30201) with a note pointing at the previous definition.                                                                       | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`function-redefinition-diagnostic.slang`](function-redefinition-diagnostic.slang)                             |
| Discarding the result of a call to a `[NoDiscard]`-marked function is rejected with the discarded-no-discard-result diagnostic (E30059).                                                           | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`discarded-no-discard-result-rejected.slang`](discarded-no-discard-result-rejected.slang)                     |
| Member lookup that finds no match is rejected with diagnostic 30027 naming the missing member and the host type.                                                                                   | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`member-lookup-no-match.slang`](member-lookup-no-match.slang)                                                 |
| Member lookup on a struct without the requested name produces E30027 with the requested member and host type cited verbatim.                                                                       | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`member-not-found-on-struct-rejected.slang`](member-not-found-on-struct-rejected.slang) |
| A type mismatch at a coercion site is rejected with the type-mismatch (30019) diagnostic citing the expected and actual types.                                                                     | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`type-mismatch-rejected.slang`](type-mismatch-rejected.slang)                                                 |
| An unresolved name produces a diagnostic; the checker recovers by treating the reference as ErrorType so the failure does not cascade.                                                             | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`undefined-identifier-becomes-error.slang`](undefined-identifier-becomes-error.slang)                         |
| Check-level recovery is "continue with a placeholder type" so one error does not cascade; an undefined identifier in one statement does not erase the diagnostic for an unrelated error in the next. | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`recovery-after-error-does-not-cascade.slang`](recovery-after-error-does-not-cascade.slang)                   |
| Decl checking rejects a variable whose initializer depends on the variable itself ("used in its own definition").                                                                                 | negative   | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                                     | [`variable-used-in-own-definition-rejected.slang`](variable-used-in-own-definition-rejected.slang)             |
| Decl checking rejects a bit-field whose declared width exceeds the type's width (E31300).                                                                                                          | boundary   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`bit-field-too-wide-rejected.slang`](bit-field-too-wide-rejected.slang)                                       |
| Decl checking rejects a bit-field whose underlying type is not integral (E31301).                                                                                                                  | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`bit-field-non-integral-rejected.slang`](bit-field-non-integral-rejected.slang)                               |
| Decl checking rejects an unsized member that is not the last member of a struct (E30070).                                                                                                          | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`unsized-member-must-be-last-rejected.slang`](unsized-member-must-be-last-rejected.slang)                     |
| Decl checking rejects two struct types declared with the same name as a conflicting declaration (E30200) at the type-decl shape.                                                                   | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`conflicting-struct-redeclaration-rejected.slang`](conflicting-struct-redeclaration-rejected.slang)           |
| Declaration checking rejects two locals with the same name in the same block as a conflicting declaration.                                                                                         | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`local-redeclaration-rejected.slang`](local-redeclaration-rejected.slang)                                     |
| Expression checking detects a literal divide-by-zero in a constant expression and emits diagnostic 30002.                                                                                          | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`divide-by-zero-rejected.slang`](divide-by-zero-rejected.slang)                                               |
| Expression checking enforces lvalue-ness; assigning to a non-lvalue expression is rejected with diagnostic 30011.                                                                                  | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`assign-to-non-lvalue-rejected.slang`](assign-to-non-lvalue-rejected.slang)                                   |
| Expression checking rejects `new T` when T is a struct (E30065): `new` is only valid on classes.                                                                                                   | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`new-on-non-class-rejected.slang`](new-on-non-class-rejected.slang)                                           |
| Expression checking rejects a `try` clause applied to a non-call expression (E30090).                                                                                                              | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`try-on-non-call-rejected.slang`](try-on-non-call-rejected.slang)                                             |
| Expression checking rejects a bare assignment used as the predicate of an `if` statement (E30057).                                                                                                 | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`assignment-in-predicate-rejected.slang`](assignment-in-predicate-rejected.slang)                             |
| Expression checking rejects a call expression whose callee resolves to a non-callable type with diagnostic 30016.                                                                                  | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`call-on-non-callable-rejected.slang`](call-on-non-callable-rejected.slang)                                   |
| Expression checking rejects constructor-style initialization of a class without `new` (E30066): classes must be initialized with `new`.                                                            | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`class-without-new-rejected.slang`](class-without-new-rejected.slang)                                         |
| Expression checking rejects passing a non-lvalue argument to an `out` parameter (E30047).                                                                                                          | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`argument-must-be-lvalue-rejected.slang`](argument-must-be-lvalue-rejected.slang)                             |
| Expression checking rejects subscripting a non-array, non-subscriptable type (E30013).                                                                                                             | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`subscript-on-non-array-rejected.slang`](subscript-on-non-array-rejected.slang)                               |
| Implicit-conversion ranking inserts an int-to-float coercion at a typed initialization site so the value preserves the source value as float.                                                      | functional | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`implicit-int-to-float-conversion.slang`](implicit-int-to-float-conversion.slang)                             |
| Slang's inheritance checker rejects a struct attempting to inherit from a built-in non-interface (sealed) type, naming the offending base type (E30831).                                            | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`inheritance-from-non-interface-rejected.slang`](inheritance-from-non-interface-rejected.slang)               |
| Statement checking detects duplicate `case` values inside a switch and rejects with E30605.                                                                                                        | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`switch-duplicate-cases-rejected.slang`](switch-duplicate-cases-rejected.slang)                               |
| Statement checking detects functions that fall off the end without returning and emits the missing-return warning (41010).                                                                         | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`missing-return-warning.slang`](missing-return-warning.slang)                                                 |
| Statement checking rejects `break` inside a `defer` block (E30108).                                                                                                                                | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`break-inside-defer-rejected.slang`](break-inside-defer-rejected.slang)                                       |
| Statement checking rejects `case` outside a `switch` statement.                                                                                                                                    | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`case-outside-switch-rejected.slang`](case-outside-switch-rejected.slang)                                     |
| Statement checking rejects `continue` inside a `defer` block (E30109).                                                                                                                             | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`continue-inside-defer-rejected.slang`](continue-inside-defer-rejected.slang)                                 |
| Statement checking rejects `continue` outside a loop with diagnostic 30004.                                                                                                                        | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`continue-outside-loop-rejected.slang`](continue-outside-loop-rejected.slang)                                 |
| Statement checking rejects `return` inside a `defer` block (E30110).                                                                                                                               | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`return-inside-defer-rejected.slang`](return-inside-defer-rejected.slang)                                     |
| Statement checking rejects an uncaught `try` inside a function not declared `throws` (E30093).                                                                                                     | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`uncaught-try-in-non-throw-rejected.slang`](uncaught-try-in-non-throw-rejected.slang)                         |
| Statement checking rejects more than one `default:` inside a single switch (E30602).                                                                                                               | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`switch-multiple-default-rejected.slang`](switch-multiple-default-rejected.slang)                             |
| Statement checking validates `return` against the function's return type; a bare `return` in a non-void function is rejected.                                                                       | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`return-needs-expression-rejected.slang`](return-needs-expression-rejected.slang)                             |
| Statement checking validates control-flow scope rules; `break` outside a loop or switch is rejected with diagnostic 30003.                                                                          | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`break-outside-loop-rejected.slang`](break-outside-loop-rejected.slang)                                       |
| Type checking rejects `void` as a variable type with diagnostic 30009.                                                                                                                             | negative   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`invalid-type-void-rejected.slang`](invalid-type-void-rejected.slang)                                         |
| Type checking rejects an array declared with a negative size literal (E30025).                                                                                                                     | boundary   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`array-negative-size-rejected.slang`](array-negative-size-rejected.slang)                                     |
| Type checking resolves a typedef'd name to its base type so an operation on the alias is the same as on the underlying type.                                                                        | functional | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`typedef-resolves-to-base-type.slang`](typedef-resolves-to-base-type.slang)                                   |
| Type resolution follows a chain of `typealias` declarations and resolves all the way to the underlying primitive type.                                                                              | boundary   | [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)                                           | [`typedef-chain-resolves.slang`](typedef-chain-resolves.slang)                                                 |
| A generic type used without specifying its arguments is rejected with a diagnostic explaining a generic argument is required.                                                                       | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`generic-without-args-rejected.slang`](generic-without-args-rejected.slang)                                   |
| A generic applied with the wrong number of type arguments is rejected; the constraint solver's arity-mismatch inference failure surfaces as E30441 "wrong number of generic arguments".             | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`generic-arity-mismatch-rejected.slang`](generic-arity-mismatch-rejected.slang)                               |
| A struct declared as conforming to an interface but missing a required member is rejected with a diagnostic naming the missing member.                                                              | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`missing-conformance-rejected.slang`](missing-conformance-rejected.slang)                                     |
| Conformance checking rejects a member that overrides an interface default without the `override` keyword (E30853).                                                                                 | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`missing-override-rejected.slang`](missing-override-rejected.slang)                                           |
| Constraint checking rejects a generic value parameter whose type is not an integer or enum (E30624).                                                                                               | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`generic-value-parameter-type-rejected.slang`](generic-value-parameter-type-rejected.slang)                   |
| Constraint solving rejects a non-interface type used as a generic constraint (E30401).                                                                                                             | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`invalid-type-for-constraint-rejected.slang`](invalid-type-for-constraint-rejected.slang)                     |
| Decl checking rejects a generic parameter declared after a variadic pack parameter (E30522).                                                                                                       | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`pack-param-must-be-last-rejected.slang`](pack-param-must-be-last-rejected.slang)                             |
| Generic functions are specialized at the call site; the constraint solver infers the type argument from the actual argument.                                                                        | functional | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`generic-argument-inferred-from-call.slang`](generic-argument-inferred-from-call.slang)                       |
| Inheritance checking rejects an `extension` directly on an interface type (E30852).                                                                                                                | negative   | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`invalid-extension-on-interface-rejected.slang`](invalid-extension-on-interface-rejected.slang)               |
| The checker finds a witness that a type satisfies an interface required by a constraint, so a generic constrained on the interface accepts conforming types.                                        | functional | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints)                   | [`interface-conformance-checked.slang`](interface-conformance-checked.slang)                                   |
| After checking, a DeclRef-bearing node points at the canonical decl; a name used after its declaration resolves to that decl and the call returns the expected value.                               | functional | [#inputs-and-outputs](../../../design/pipeline/03-semantic-check.md#inputs-and-outputs)                                                           | [`declref-points-at-canonical-decl.slang`](declref-points-at-canonical-decl.slang)                             |
| The checker attaches a Type to every Expr; arithmetic between int and float coerces to float and the result type matches that.                                                                      | functional | [#inputs-and-outputs](../../../design/pipeline/03-semantic-check.md#inputs-and-outputs)                                                           | [`expr-gets-type-attached.slang`](expr-gets-type-attached.slang)                                               |
| A [mutating] method cannot be invoked on an immutable receiver; the checker rejects the call with diagnostic 30050.                                                                                 | negative   | [#modifier-validation](../../../design/pipeline/03-semantic-check.md#modifier-validation)                                                         | [`mutating-method-on-immutable-rejected.slang`](mutating-method-on-immutable-rejected.slang)                   |
| Decl checking rejects a `static` global variable with an opaque (resource) type (E30076).                                                                                                          | negative   | [#modifier-validation](../../../design/pipeline/03-semantic-check.md#modifier-validation)                                                         | [`global-var-opaque-type-rejected.slang`](global-var-opaque-type-rejected.slang)                               |
| Modifier validation enforces the immutability of `let`-bound locals; assigning to one is rejected as a non-lvalue.                                                                                  | negative   | [#modifier-validation](../../../design/pipeline/03-semantic-check.md#modifier-validation)                                                         | [`assign-to-let-is-rejected.slang`](assign-to-let-is-rejected.slang)                                           |
| Modifier validation rejects a `[SpecializationConstant]` on a non-scalar/non-enum value (E31218).                                                                                                  | negative   | [#modifier-validation](../../../design/pipeline/03-semantic-check.md#modifier-validation)                                                         | [`spec-constant-must-be-scalar-rejected.slang`](spec-constant-must-be-scalar-rejected.slang)                   |
| Modifier validation rejects a redundant repetition of the same modifier (E31202) on one declaration.                                                                                               | negative   | [#modifier-validation](../../../design/pipeline/03-semantic-check.md#modifier-validation)                                                         | [`duplicate-modifier-rejected.slang`](duplicate-modifier-rejected.slang)                                       |
| Modifier validation rejects an attribute placed on a target where it is not allowed (E31002).                                                                                                       | negative   | [#modifier-validation](../../../design/pipeline/03-semantic-check.md#modifier-validation)                                                         | [`attribute-not-applicable-rejected.slang`](attribute-not-applicable-rejected.slang)                           |
| Attribute argument checking rejects a non-string-literal argument to `[shader(...)]` (E33071).                                                                                                     | negative   | [#shader-specific-checks](../../../design/pipeline/03-semantic-check.md#shader-specific-checks)                                                   | [`expected-string-literal-attr-rejected.slang`](expected-string-literal-attr-rejected.slang)                   |
| Attribute-value checking rejects a non-positive integer in `[numthreads]` (E31102).                                                                                                                | boundary   | [#shader-specific-checks](../../../design/pipeline/03-semantic-check.md#shader-specific-checks)                                                   | [`numthreads-non-positive-rejected.slang`](numthreads-non-positive-rejected.slang)                             |
| Entry-point checks require a stage attribute on the function or a -stage command-line option; without either the checker emits diagnostic 38007.                                                    | negative   | [#shader-specific-checks](../../../design/pipeline/03-semantic-check.md#shader-specific-checks)                                                   | [`entry-point-needs-stage-rejected.slang`](entry-point-needs-stage-rejected.slang)                             |
| Initializer-list checking rejects more initializers than the synthesized constructor accepts (E30523).                                                                                             | boundary   | [#synthesizing-implicit-code](../../../design/pipeline/03-semantic-check.md#synthesizing-implicit-code)                                           | [`too-many-initializers-rejected.slang`](too-many-initializers-rejected.slang)                                 |
| The checker synthesizes implicit construction code (e.g. an initializer-list constructor) so a struct can be built from a brace-enclosed value list without an explicit `__init`.                   | functional | [#synthesizing-implicit-code](../../../design/pipeline/03-semantic-check.md#synthesizing-implicit-code)                                           | [`synthesized-positional-constructor.slang`](synthesized-positional-constructor.slang)                         |
| The checker synthesizes nested initializer-list construction so a struct containing another struct can be initialized by a brace-enclosed list of brace-enclosed lists.                             | boundary   | [#synthesizing-implicit-code](../../../design/pipeline/03-semantic-check.md#synthesizing-implicit-code)                                           | [`synthesized-positional-constructor-nested.slang`](synthesized-positional-constructor-nested.slang)           |
| Function bodies are left as UnparsedStmt by the parser and checked on demand; a well-formed body parses and runs.                                                                                   | functional | [#two-pass-interaction-with-the-parser](../../../design/pipeline/03-semantic-check.md#two-pass-interaction-with-the-parser)                       | [`function-body-checked-after-parser-handoff.slang`](function-body-checked-after-parser-handoff.slang)         |

## Untested claims

| Claim                                                                                                                                                                                                                                                       | Reason          | Anchor                                                                                                                         | Why untested                                                                                                                                                                                                             |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| When a name fails to resolve, the checker attaches a conservative "did you mean '<name>'?" suggestion (via Levenshtein distance) to the `UndefinedIdentifier` diagnostic.                                                                                     | needs-cli-test  | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                 | The suggestion note is emitted only along the AOT (`slangc`) diagnostic path and depends on edit-distance/length gating; the byte-code interpreter (`slangi`, the only runner usable locally here) does not render it. A `slangc`-driven `DIAGNOSTIC_TEST` would verify it, but the local `slangc` binary segfaults at process shutdown (see Doc gaps below), so the note text/columns could not be pinned. |
| When a call matches no overload, each candidate signature note also carries the specific argument index that rejected it (`OverloadCandidateArgumentTypeMismatch`, E40018: "argument N does not match: expected …, got …").                                     | needs-cli-test  | [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                                 | The per-argument note is part of the `slangc` overload-failure rendering; `slangi` emits the top-level "no overload applicable" error and the `candidate:` notes but not the E40018 per-argument note. Verifying it needs a `slangc`-driven `DIAGNOSTIC_TEST`, which the shutdown-crashing local `slangc` prevented pinning here. |
| A constraint on an associated type (`associatedtype A : IBar`, `associatedtype A where A : IBar`, `__constraint A : IBar`) is recorded uniformly as a `GenericTypeConstraintDecl` on the enclosing interface and honored by `findWitnessForInterfaceRequirement`. | needs-unit-test | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints) | The claim is about the internal representation of the constraint (which decl carries it) and the witness-lookup early-out. The user-visible consequence (a generic body may call the associated type's interface methods) is exercised by `interface-conformance-checked.slang` for a direct interface constraint, but the associated-type value has no directly printable form under `slangi` (the value has type `C.Element`, not `int`), so the representation-level claim is best verified by a C++ unit test over the checker types. |
| A bare-`This` subject on an interface `__constraint` (expressing inheritance rather than a checked predicate) is rejected during checking in `visitGenericTypeConstraintDecl`.                                                                                  | needs-cli-test  | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints) | The `__constraint` syntax and the exact diagnostic for a bare-`This` subject could not be pinned: the local `slangc` (the AOT path a `DIAGNOSTIC_TEST` uses) segfaults at shutdown without flushing diagnostics, so neither the diagnostic code nor its message/columns could be observed for a stable CHECK. |
| An enum's synthesized `__Tag : __BuiltinIntegerType` witness (including the `bool`-tagged `NoneWitness` case) satisfies the interface-level constraint requirement via the witness-table early-out.                                                             | needs-unit-test | [#generic-specialization-and-constraints](../../../design/pipeline/03-semantic-check.md#generic-specialization-and-constraints) | The claim is about which witness is installed by conformance synthesis and how the early-out honors it — internal witness-table state with no distinct user-visible surface beyond "the enum compiles". A C++ unit test inspecting the synthesized witness table is the appropriate harness. |
| Generic-struct capability requirements: `collectGenericStructTypeUses` recurses an entry point's signature to validate each user-defined generic struct's `[require(...)]` against the target.                                                                   | gpu-other       | [#shader-specific-checks](../../../design/pipeline/03-semantic-check.md#shader-specific-checks)                               | The check fires against a specific target's capability set; observing the accept/reject boundary needs a target compile with a known capability profile, which the shutdown-crashing local `slangc` could not run to produce stable diagnostic output. CI with a provisioned target validates it. |
| An unspecialized generic entry point (`void main<T>(...)`) is diagnosed rather than crashing at link time (`createSpecializedGlobalAndEntryPointsComponentType` uses `Linkage::isSpecialized` + specialization-argument strings).                                | needs-cli-test  | [#shader-specific-checks](../../../design/pipeline/03-semantic-check.md#shader-specific-checks)                               | The claim is about how the entry point is compiled (the specialization decision and its diagnostic vs. an `IRGeneric` link crash); pinning the diagnostic needs a `slangc -entry` invocation, which the local `slangc` shutdown crash prevented observing. |

## Doc gaps observed

| Anchor                                                                                                          | Kind                  | Gap                                                                                                                                                                                                                                                                                                                                                                                                       | Suggested addition                                                                                                                                                                                            |
| --------------------------------------------------------------------------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [#files-and-responsibilities](../../../design/pipeline/03-semantic-check.md#files-and-responsibilities)         | missing-example       | The `### Files and responsibilities` table assigns each `slang-check-*.cpp` file a one-word "concern" (e.g. "control flow, scope rules"), but gives no user-visible example or diagnostic for any of them. The bundle anchors 30+ negative tests to this table by treating each concern as a testable claim, which is a stretch of the doc's actual text.                                                    | For each row, add a one-line "example rejection" naming a concrete diagnostic the file owns (e.g. slang-check-stmt.cpp → "E30003 `break` outside loop"), so tests can anchor to a stated behavior, not a concern label. |
| [#modifier-validation](../../../design/pipeline/03-semantic-check.md#modifier-validation)                       | ambiguous-claim       | The `## Modifier validation` section says the file validates "mutually exclusive combinations" but names no specific exclusive pair. A test for any individual combination (e.g. `static` + `[mutating]`) would be anchoring to unstated behavior.                                                                                                                                                          | Enumerate at least one concrete mutually-exclusive modifier pair and its diagnostic code, so a boundary test can anchor to a stated exclusion.                                                                 |
| [#shader-specific-checks](../../../design/pipeline/03-semantic-check.md#shader-specific-checks)                 | missing-surface       | The section describes `collectGenericStructTypeUses` (generic-struct `[require(...)]` validation) and the unspecialized-generic-entry-point diagnostic in terms of internal functions, but does not state the user-visible diagnostic code / message for either, nor a minimal example shader. Tests can only reach these via a target compile with a specific capability profile.                            | Add a minimal example and the emitted diagnostic code for (a) a generic struct whose `[require(...)]` is unmet on a target, and (b) a truly-unspecialized generic entry point, so tests can pin the message.   |
| [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                   | missing-surface       | The section names three "point the user at the fix" diagnostics — per-candidate argument mismatch, the "did you mean …?" undefined-identifier suggestion, and `[NoDiscard]` discard — but does not give the diagnostic codes (E40018, the `UndefinedIdentifier` suggestion note, E30059) or a minimal example for each. Only the `[NoDiscard]` claim had enough detail to anchor a diagnostic test here.       | Add the diagnostic code and a one-line example for the per-candidate argument-mismatch note and the "did you mean" suggestion, matching the detail level now implied for `[NoDiscard]`.                          |
| [#failure-modes](../../../design/pipeline/03-semantic-check.md#failure-modes)                                   | undocumented-behavior | Not a doc claim, but an environment note for triage: the local `slangc` and `slang-test` binaries at this `source_commit` segfault at process shutdown (exit 139) and flush no diagnostic output, so no `DIAGNOSTIC_TEST`/`SIMPLE -target` test in this bundle could be executed locally; only `slangi` (`INTERPRET`) tests were runnable. The 17 INTERPRET tests were verified locally; the diagnostic tests were validated by matching each cited E-code and message against `slangi` output where the diagnostic is stmt/expr/decl-level, and against `source/slang/slang-diagnostics.lua`. | The nightly CI runner (with a working `slangc`) must be treated as the authoritative verifier for the `DIAGNOSTIC_TEST` and stage-gated tests in this bundle until the local shutdown crash is diagnosed.       |
