Skip to content

fix(compiler): false-positive duplicate-using with file-level (blockless) namespace - #11486

Draft
timotheeguerin with Copilot wants to merge 6 commits into
mainfrom
copilot/fix-using-conflict-issue
Draft

fix(compiler): false-positive duplicate-using with file-level (blockless) namespace#11486
timotheeguerin with Copilot wants to merge 6 commits into
mainfrom
copilot/fix-using-conflict-issue

Conversation

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

using statements placed before a blockless namespace declaration were incorrectly treated as duplicates of the same using appearing inside that namespace. This is inconsistent with block namespace behavior, where using N; outside + using N; inside is explicitly allowed.

// Before fix: incorrectly raised duplicate-using diagnostic
using TypeSpec.Http;
namespace MyService;   // blockless/file-level namespace
using TypeSpec.Http;   // ← false-positive duplicate-using error

Root cause

checkDuplicateUsings groups statements by their parent symbol. All top-level statements in a file share parent = TypeSpecScriptNode, so a using before and after a blockless namespace declaration were indistinguishable — both got the same tracker key, triggering the duplicate check.

Fix

In checkDuplicateUsings, when a file has a blockless namespace (file.inScopeNamespaces[0]), usings that appear after the namespace declaration (by source position) are keyed on the namespace's merged symbol rather than the TypeSpecScript symbol. This creates separate duplicate-detection buckets for pre-namespace and post-namespace usings, matching block namespace behavior.

Changes

  • checker.tscheckDuplicateUsings: use blockless namespace symbol as tracker key for usings positioned after the namespace declaration
  • using.test.ts — two new test cases: using N; namespace Z; using N; → no diagnostic; namespace Z; using N; using N; → duplicate still reported

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI linked an issue Jul 30, 2026 that may be closed by this pull request
…space

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the compiler:core Issues for @typespec/compiler label Jul 30, 2026
Copilot AI changed the title [WIP] Fix using conflict with file namespace fix(compiler): false-positive duplicate-using with file-level (blockless) namespace Jul 30, 2026
Copilot AI requested a review from timotheeguerin July 30, 2026 16:42
Comment thread .chronus/changes/fix-using-blockless-namespace-2026-7-30.md Outdated
Copilot AI and others added 2 commits July 30, 2026 17:07
Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
…less namespace

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
Comment thread packages/compiler/test/checker/namespaces.test.ts
…ssion test

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
@pkg-pr-new

pkg-pr-new Bot commented Jul 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/compiler@11486

commit: 7ab8105

@timotheeguerin

Copy link
Copy Markdown
Member

@copilot lots of failures now

tspd (TypeSpec Library Developer Cli) is experimental and might be BREAKING between versions.
----------------------------------------------------------------------------------------------------
$ tsp compile . --warn-as-error --import @typespec/library-linter --no-emit
TypeSpec compiler v1.14.0

- Compiling...
× Compiling
Diagnostics were reported during compilation:

lib/resource.tsp:63:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 63 | @Private.validateHasKey(Resource)
     |          ^^^^^^^^^^^^^^
lib/resource.tsp:64:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 64 | @Private.validateIsError(Error)
     |          ^^^^^^^^^^^^^^^
lib/resource.tsp:180:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 180 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:181:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 181 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^
lib/resource.tsp:213:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 213 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:214:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 214 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^
lib/resource.tsp:270:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 270 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:271:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 271 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^
lib/resource.tsp:283:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 283 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:284:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 284 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^
lib/resource.tsp:295:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 295 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:296:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 296 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^
lib/resource.tsp:308:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 308 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:309:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 309 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^
lib/resource.tsp:331:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 331 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:332:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 332 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^
lib/resource.tsp:372:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateHasKey
> 372 | @Private.validateHasKey(Resource)
      |          ^^^^^^^^^^^^^^
lib/resource.tsp:373:10 - error invalid-ref: Namespace TypeSpec.Http.Private doesn't have member validateIsError
> 373 | @Private.validateIsError(Error)
      |          ^^^^^^^^^^^^^^^

to note our namespace system is inspired by dotnet and they don't have the same issue

…s in blockless namespace files

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot lots of failures now

...

Fixed in the latest commit. The previous fix was too broad — it changed the resolution order for ALL identifiers at the TypeSpecScript scope, which caused Private in TypeSpec.Rest.Resource to incorrectly resolve to TypeSpec.Http.Private (brought in via using Http) instead of TypeSpec.Rest.Private from the ancestor namespace.

The correct fix is narrower: added a resolveGlobalFirst option to the resolver that's only used when processing using statement targets (setUsingsForFile). In that mode, global scope is checked before inScopeNamespaces, so using TypeSpec.Http in namespace _Specs_.TypeSpec.Bar; correctly finds the global TypeSpec. All other identifier resolution (including inside namespace bodies) is unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler:core Issues for @typespec/compiler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

using is conflicting with file namespace

2 participants