Report duplicate [numthreads] attributes as conflicting modifiers#11883
Merged
Conversation
Register NumThreadsAttribute as its own conflict group in getModifierConflictGroupKind() so a second [numthreads] on one entry point trips the existing duplicate-modifier check (error 31202) instead of being silently ignored (previously the compiler kept a single value with no diagnostic). Addresses #11881.
Use the exact three-attribute example from the issue (three [numthreads] on one entry point produce two duplicate-modifier diagnostics) and drop the explanatory comment in favor of the surrounding uncommented self-group style.
- Move the NumThreadsAttribute case into the labeled "Modifiers that are their own exclusive group" block so its membership is self-evident (behavior-identical; still returns modifierType). - Explain in the regression test why the exact four E31202 rows are load-bearing (title vs span messages differ, so both survive dedup), so a future message unification cannot silently break the count.
1fc6717 to
b5f4e43
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
Addresses #11881, which asks for three distinct things. This PR delivers only part (c) as a clean, standalone diagnostic fix:
[numthreads]on one entry point.[numthreads]and alayout(local_size_*)-derived value disagree (see Process report for why).layout(local_size)size is already delivered by open PR Fixes GitHub issue #7894 (makes reflection and SPIR-V agree onlayout(local_size) in) #11715 (NBickford-NV). Not re-implemented.Because (a)/(b) are handled elsewhere/deferred, this uses
Addresses #11881, notFixes, so the issue stays open.Motivation
Multiple
[numthreads]attributes on a single entry point are silently accepted today — the compiler keeps one value and ignores the rest, withrc=0and no diagnostic. Consider the example from the issue:As reported in the issue and reproduced during triage, this compiles cleanly and produces a single group size — one attribute silently wins and the other two are discarded — so the author is never told that two of the three conflicting attributes were dropped.
Proposed solution
Register
NumThreadsAttributeas its own modifier conflict group so the existing duplicate-modifier machinery reports it. IngetModifierConflictGroupKind()(source/slang/slang-check-modifier.cpp), attributes that may legally appear at most once each map to their own node type as their conflict-group key (for example the work-graphNode*attributes just above the added case).NumThreadsAttributewas missing from that switch, so it fell through to thedefault: return ASTNodeType::NodeBasearm. The subsequent duplicate-detection loop only acts on modifiers whose group is notNodeBase, so[numthreads]was never checked. Adding the one case makes a second[numthreads]on the same entry point trip the existing duplicate-modifier error (31202).This reuses one source of truth (the conflict-group classifier + the
DuplicateModifierdiagnostic) rather than adding a parallel numthreads-specific check, and it produces an error, matching the severity the maintainer requested. The"redundant or conflicting"wording of31202already covers both identical and value-conflicting duplicates.Change summary
source/slang/slang-check-modifier.cppcase ASTNodeType::NumThreadsAttribute: return modifierType;togetModifierConflictGroupKind()(its own exclusive group), beside the existing work-graph attribute self-groups.tests/diagnostics/execution-model/duplicate-numthreads.slang[numthreads]entry point now reportsE31202.Concepts and vocabulary
getModifierConflictGroupKind(ASTNodeType)grouping mutually-exclusive modifiers.checkModifiers()walks the checked modifier list and, when it sees a second modifier whose group is already recorded, emitsDiagnostics::DuplicateModifier(code31202). ReturningASTNodeType::NodeBasemeans "not tracked" — the loop skips it.NumThreadsAttribute— for GLSLlayout(local_size_x = N) in;compute/mesh/amp entry points,validateEntryPoint()synthesizes aNumThreadsAttributefrom siblingEmptyDeclGLSLLayoutLocalSizeAttributes, but only when the entry point has no user[numthreads].Process report
Code trace. In
getModifierConflictGroupKind()(source/slang/slang-check-modifier.cpp:1564)NumThreadsAttributehad no case, so it returnedNodeBasevia thedefaultarm (:1672). The duplicate-detection loop readsconflictGroup = getModifierConflictGroupKind(modifier->astNodeType)and only records/compares the modifier whenconflictGroup != ASTNodeType::NodeBase(:2469); so[numthreads]was never diagnosed.validateAttributeforNumThreadsAttribute(:396) validates each attribute's three args but does no duplicate detection. The added case putsNumThreadsAttributein its own group, so the second (and each further) occurrence hitsDiagnostics::DuplicateModifier— theduplicate-modifierdiagnostic, error31202, defined insource/slang/slang-diagnostics.lua:2909.Input-shape / spurious-fire check (the one real risk). The layout-synthesized
NumThreadsAttributeis created and added insidevalidateEntryPoint()(source/slang/slang-check-shader.cpp:1866and:1900), guarded by!entryPointFuncDecl->findModifier<NumThreadsAttribute>()(:1851-1852) — it is synthesized only when the entry point has zero user[numthreads], and exactly one is ever added. The duplicate-modifier loop runs earlier, during the modifier-check pass (checkModifiers()), andaddModifierdoes not re-run it. So the synthesized attribute can never form a duplicate, and this change cannot spuriously fire on the GLSLlayout(local_size)path. Existing tests exercise those paths — the GLSL layout synthesis intests/glsl/compute-shader-layout.slangandtests/glsl/compute-shader-layout-id.slang, and a single[numthreads]intests/hlsl/simple/compute-numthreads.hlslandtests/language-feature/execution-model/compute-numthreads-functional.slang(all must still compile).Why (b) is deferred. A layout-vs-
[numthreads]disagreement warning would live at the same merge site (source/slang/slang-check-shader.cpp:1849-1907), which currently early-outs when a user[numthreads]is present — so (b) needs a new branch there plus a new warning diagnostic and a spec-constant/default-1-aware extent comparison (GLSL defaults unspecified axes to 1; extents may beConstantIntValor spec-constantDeclRef, and a naive compare would emit false warnings). That region is also edited by open PR #11715, so bundling risks a merge conflict with the maintainer's in-flight PR, and (b) is conceptually a follow-up to the precedence #11715 establishes. Keeping (c) standalone lets this land independently; (b) is a clean follow-up.Verification
The change plus the regression test are authored and reviewed by source inspection and by the diagnostic-annotation matcher's documented semantics (
tools/slang-test/diagnostic-annotation-util.cpp). The test asserts the error code: a singleerr()emits two machine-readable rows (a title row and a span row), each carrying the code, and caretless//CHECK: E31202annotations match against theerrorCodefield. Three[numthreads]produce two duplicate diagnostics (four rows), so fourE31202lines are expected under exhaustive mode. The existing teststests/diagnostics/modifier-check.slangandtests/diagnostics/execution-model/non-positive-numthreads.slangshow the same two-rows-per-diagnostic shape. CI is the empirical gate for the build and test run.Labeling
Labeled
pr: non-breaking: this only rejects a malformed construct (conflicting duplicate[numthreads]) that previously compiled by silently discarding all-but-one value. If you'd rather treat "now errors on previously-accepted source" aspr: breaking change, please relabel.Addresses #11881.
🤖 Generated by an automated Slang coworker — may be inaccurate. A human maintainer should verify.