---
gap_intake_report: true
intake_model: claude-opus-5[1m]
intake_at: 2026-08-11T16:38:40Z
target_doc: name-resolution/visibility.md
target_doc_source_commit_before: 53b76e6d3009b8e6434d41573524c7ce5c499d23
target_doc_source_commit_after: ec47ea72b6aa5fefc3b36f8a780dbd3ecf5b1f6e
gap_count: 8
actions:
  fixed: 8
  rejected_bogus: 0
  rejected_out_of_scope: 0
  deferred: 0
  escalated_to_finding: 0
---

# Gap-intake report for name-resolution/visibility.md

## Summary

No gap was escalated: every observation in the queue is what the
watched sources say, so all eight are documentation defects. Three of
them (`0c9178b9df46`, `583a43f2ddbc`, `a0476bc4c2a8`) are one
underlying rule — `checkVisibility`'s `PrivateModifier` arm tests
`isGlobalDecl` first and returns
(`source/slang/slang-check-modifier.cpp:2188-2216`), and `isGlobalDecl`
is true for anything whose parent is a `NamespaceDeclBase` or
`FileDecl` (`source/slang/slang-check-decl.cpp:1567-1575`) — so
`private` requires membership in a *type*, not merely a container, and
`private namespace X` never reaches the 36005 path. That rule is now
stated once in `### Per-keyword semantics` and once in the two
rewritten failure-mode bullets. The remaining five gaps were fixed
individually: function-local visibility classification, the `extern`
lookup-mask example, the `ExpectedANamespace` code and example, the
`FuncAliasDecl` surface syntax, and the extension target-type
asymmetry. All eight are `fixed`; there are no rejections, deferrals,
or escalations, and no unwatched-source blockers.

## Actions

| Gap ID | Action | Evidence | Fix summary |
| --- | --- | --- | --- |
| 0c9178b9df46 | fixed | `source/slang/slang-check-modifier.cpp:2188-2197` diagnoses `InvalidUseOfPrivateVisibility` when `isGlobalDecl(decl)` and returns; `source/slang/slang-check-decl.cpp:1567-1575` shows `isGlobalDecl` is true when the parent is a `NamespaceDeclBase`, so a namespace member is never accepted as `private`. Printed form pinned by `private-inside-namespace-rejected.slang` (`E30603`, "cannot have private visibility because it is not a member of a type"). Source agrees with the observation, so the doc was wrong, not the compiler | Rewrote the `private` bullet in `### Per-keyword semantics` to say "declaring aggregate type" and to name the `isGlobalDecl` rejection; consolidated with a0476bc4c2a8 and 583a43f2ddbc, which state the same rule in the failure-mode list |
| a0476bc4c2a8 | fixed | Two producers of `InvalidUseOfPrivateVisibility` in `source/slang/slang-check-modifier.cpp`: `:2192` (`isGlobalDecl`, covering module/file scope and namespace members) and `:2210` (`isInterfaceRequirement`, defined `source/slang/slang-ast-decl.cpp:66`). All three shapes pinned by `private-on-top-level-decl-rejected.slang`, `private-inside-namespace-rejected.slang`, `private-interface-requirement-rejected.slang`, each `E30603` | Retitled the bullet to "`private` on a decl that is not a member of a type" and enumerated the three reaching shapes with the `slang-check-modifier.cpp:2188-2216` citation; consolidated with 583a43f2ddbc in the same list |
| 583a43f2ddbc | fixed | Ordering is explicit in `source/slang/slang-check-modifier.cpp:2188-2205`: under `PrivateModifier` the `isGlobalDecl` branch diagnoses and `return`s at `:2197` before the `as<NamespaceDeclBase>` branch at `:2199` is reached; a namespace at any depth has a `NamespaceDeclBase` parent and is therefore `isGlobalDecl`. The 36005 path is live only for `InternalModifier` (`:2217-2225`), pinned by `namespace-internal-modifier-rejected.slang` (`E36005`) | Narrowed the 36005 example to `internal` on a namespace and added the note that `private namespace X` is reported as 30603 instead, because the `isGlobalDecl` test runs first |
| 23b139a02fb5 | fixed | `checkVisibility` is called unconditionally at the end of `SemanticsDeclHeaderVisitor::checkVarDeclCommon` (`source/slang/slang-check-decl.cpp:2953`, function starts `:2651`, no early return in between), and a function-local decl reaches it through `ensureDeclBase(stmt->decl, DeclCheckState::DefinitionChecked, this)` in `source/slang/slang-check-stmt.cpp:58-70`. `getDeclVisibility` (`source/slang/slang-check-decl.cpp:21269-21333`) has no local-decl carve-out, so an unmodified local falls through to `parentModule->defaultVisibility`, which `public module` flips to `Public` (`:5143-5146`, pinned by `public-module-default-makes-unannotated-decl-public.slang`); `checkVisibility` then compares it against the type via `getTypeVisibility` and emits `UseOfLessVisibleType` (`source/slang/slang-check-modifier.cpp:2361-2372`, code 30604 at `source/slang/slang-diagnostics.lua:2376-2381`) | Added a paragraph plus a three-line example to `### Defaults by language version` stating that the fall-back chain is not conditioned on membership, so a function-local `VarDecl` takes the module default and is subject to the less-visible-type rule |
| c232cde0a9d3 | fixed | `source/slang/slang-check-expr.cpp:1247-1251`: the `applyExtensionToType` relaxation is inside `if (auto parentExtensionDecl = as<ExtensionDecl>(parentAggTypeDecl))`, i.e. it runs only when the *candidate's* container is an extension. When the private member lives in the generic type's own body, `getTargetTypeForContainer` returns `DeclRefType::create(..., getDefaultDeclRef(containerDecl))` (`:1226`), so `G<T>` is compared by `equals` against the requesting extension's `G<int>` (or the extension's own `T`) at `:1244` and fails. Source agrees with the observation; the working direction is pinned by `private-in-generic-extension-callable-from-sibling-extension.slang` | Added a qualifying paragraph to `### Where visibility is filtered` and rewrote the "`extension` on a generic type" failure-mode bullet so both state that the alignment requires the candidate to live in an `ExtensionDecl` |
| 60a07e74b886 | fixed | `source/slang/slang-lookup.cpp:41-54` drops an `ExternModifier` member whose `parentDecl` is an `ExtensionDecl` before any visibility filtering; codes from `source/slang/slang-diagnostics.lua:2841-2846` (`missing-original-defintion-of-extern-decl`, 31143) and `:1309-1314` (`no-member-of-name-in-type`, 30027, "member not found"). Both printed forms pinned by `extern-member-of-extension-hidden-from-lookup.slang` | Added the `extension S { extern int extra; }` example plus a use site to the `DeclPassesLookupMask` bullet, naming 31143 at the decl and 30027 at the use, and contrasting with 30600 |
| 52dec1764244 | fixed | `ExpectedANamespace` is `expected-a-namespace`, code 30061 (`source/slang/slang-diagnostics.lua:1421-1426`); `SemanticsDeclScopeWiringVisitor::visitUsingDecl` (`source/slang/slang-check-decl.cpp:17338-17400`) emits it at `:17397` when neither the `DeclRefExpr` nor the `OverloadedExpr` arm resolves the argument to a `NamespaceDeclBase`, which is exactly what a struct name produces | Added the 30061 code and the `using SomeStruct;` example to the "Re-exporting a non-exported decl through an alias" bullet, and refreshed the stale `visitUsingDecl` line range; consolidated with 89af3143b615 in the same bullet |
| 89af3143b615 | fixed | The only `FuncAliasDecl` construction site is `source/slang/slang-check-decl.cpp:19185`, inside `translateFwdDerivativeAttributeToAD2` (`:19139`), reached from `checkDerivativeAttribute(..., ForwardDerivativeAttribute*)` at `:19340`; the backward twin is `translateBwdDerivativeAttributeToAD2` (`:19210`, reached at `:19374`). The alias branch of `validatePublicCallableOperandVisibility` is `:9211-9223` (function starts `:9198`). The rejected two-module shape is pinned by the repo test `tests/diagnostics/autodiff-custom-diff-non-exported-import.slang` against `tests/autodiff/autodiff-custom-diff-exported-import-deriv.slang` | Named `[ForwardDerivative(...)]` / `[BackwardDerivative(...)]` as the producers of a `FuncAliasDecl` and added a minimal rejected example (plain `import` plus a `public` primal); refreshed the stale `validatePublicCallableOperandVisibility` line ranges |
