Skip to content

fix(compiler): error when $functions implementation has no corresponding extern fn declaration#10765

Draft
Copilot wants to merge 4 commits into
mainfrom
copilot/add-error-check-function-implementation
Draft

fix(compiler): error when $functions implementation has no corresponding extern fn declaration#10765
Copilot wants to merge 4 commits into
mainfrom
copilot/add-error-check-function-implementation

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 21, 2026

Defining a function in $functions without a matching extern fn declaration in TypeSpec silently had no effect — the implementation was simply ignored, leading to confusing behavior where calling the function would use a default no-op implementation.

Changes

  • New diagnostic implementation-without-extern: Reported during checkProgram() for any function in a JS $functions map that has no corresponding extern fn declaration in TypeSpec.

    error implementation-without-extern: Function "testFn" is declared in `$functions`
    but does not have a corresponding `extern fn` declaration in TypeSpec.
    Add an `extern fn` declaration.
    
  • Documentation: Added url and description fields to the diagnostic and created a dedicated markdown documentation page at website/src/content/docs/docs/standard-library/diags/implementation-without-extern.md (following the same pattern as other diagnostics like triple-quote).

  • Checker: Added checkJsImplementations() (called from checkProgram()) that walks all JS source file symbol tables and checks each Function | Implementation symbol for a paired FunctionDeclarationStatement in the merged symbol's declarations.

  • Test helpers: expectFunctionDiagnosticsEmpty / expectFunctionDiagnostics only filter the existing experimental-feature warning. Tests are now correctly structured so that every $functions entry has a corresponding extern fn declaration, eliminating the need to suppress implementation-without-extern in test helpers.

  • Test fixes: Corrected semantic-walker.test.ts (removed shared $functions fixture, scoped it to the one test that needs it) and functions.test.ts (replaced shared multi-function testers with per-function testers so each test only registers the exact implementations it declares with extern fn).

  • 4 new tests covering the error for both root-namespace and namespaced $functions entries, with and without a matching extern fn.

Example

// lib.js — BAD: implementation is silently ignored, no error previously
export const $functions = {
  "TestFn": {
    testFn: (context, target) => target,
  },
};
// lib.tsp — no `namespace TestFn { extern fn testFn(...); }` → now emits error

The fix surfaces implementation-without-extern pointing at the JS source file, making namespace mismatches and missing declarations immediately diagnosable.

…declaration

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/ee46de1b-9e2a-4264-8477-662cf80b09ae

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 May 21, 2026
… tester pollution

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/ee46de1b-9e2a-4264-8477-662cf80b09ae

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
Copilot AI changed the title [WIP] Add error handling for undefined function implementation fix(compiler): error when $functions implementation has no corresponding extern fn declaration May 21, 2026
Copilot AI requested a review from timotheeguerin May 21, 2026 22:32
default: "Extern declaration must have an implementation in JS file.",
},
},
"implementation-without-extern": {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot lets add a documentation url and a markdown document for it like for triple-quote error

expectDiagnosticEmpty(diagnostics.filter((d) => d.code !== "experimental-feature"));
expectDiagnosticEmpty(
diagnostics.filter(
(d) => d.code !== "experimental-feature" && d.code !== "implementation-without-extern",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot why do we need to filter this, shouldn't the test not testing for this error hjave an extern dec?

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 22, 2026

Open in StackBlitz

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

commit: 181cebc

…thout-extern, remove filter from helpers, fix tests to use per-function testers

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/e622bfe1-d9ab-4d99-b9a7-aaa7bb298665

Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the meta:website TypeSpec.io updates label May 22, 2026
Copilot AI requested a review from timotheeguerin May 22, 2026 12:54
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 meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Defining function in js with $functions without extern fn silently does nothing

2 participants