Skip to content

Fix ICE when interpolating a function call in a template declaration#11056

Open
timotheeguerin wants to merge 1 commit into
microsoft:mainfrom
timotheeguerin:fix-string-template-fn-call-template-decl
Open

Fix ICE when interpolating a function call in a template declaration#11056
timotheeguerin wants to merge 1 commit into
microsoft:mainfrom
timotheeguerin:fix-string-template-fn-call-template-decl

Conversation

@timotheeguerin

Copy link
Copy Markdown
Member

Fixes #11054

Problem

Compiling a string template that interpolates a function call referencing a template parameter on a template declaration crashed with an internal compiler error:

extern fn fn(type: unknown): valueof string;

@doc("${fn(T)}")
model Crud<T extends Reflection.Model> {}
Error: Expected type.
    at checkStringTemplateExpresion (packages/compiler/src/core/checker.ts)

Root cause

In a template declaration the function call can't be evaluated yet, so checkFunctionCallgetDefaultFunctionResult returns null for a value-returning function (the same behavior already used for a direct decorator arg like @doc(fn(T))). null is the value-world equivalent of errorType.

checkStringTemplateExpresion didn't handle a null span: both hasValue/hasType stayed false, execution fell into the type branch, and compilerAssert(typeOrValue !== null && !isValue(typeOrValue), "Expected type.") fired.

Fix

If any span resolves to null, the whole string template resolves to null — propagating the error sentinel up exactly like checkArrayValue/checkObjectValue do for value aggregates, rather than fabricating a partial string. The value is re-evaluated against the real argument when the template is instantiated. This also let the now-redundant per-branch null checks be removed.

Tests

Added regression tests in string-template.test.ts:

  • A function call interpolated in a string template on a template declaration no longer crashes and reports no diagnostics.
  • The instantiation path still resolves the function call (Crud<Foo> produces the expected doc value).

…late declaration

A string template interpolating a value-returning function call that
references a template parameter (e.g. `@doc("${fn(T)}")`) crashed with
"Expected type.". The function call returns null (the value-world
equivalent of errorType) in a template declaration; the template now
propagates that null instead of asserting, consistent with
checkArrayValue/checkObjectValue. The value is resolved at instantiation.

Fixes microsoft#11054
@microsoft-github-policy-service microsoft-github-policy-service Bot added the compiler:core Issues for @typespec/compiler label Jun 23, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jun 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 2260527

@github-actions

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/compiler
Show changes

@typespec/compiler - fix ✏️

Fix Expected type. internal compiler error when a string template interpolates a function call that references a template parameter on a template declaration (e.g. @doc("${myFn(T)}") model Crud<T extends Reflection.Model> {}). The deferred function call now defers the whole template, which is evaluated at instantiation.

@azure-sdk-automation

azure-sdk-automation Bot commented Jun 23, 2026

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

@timotheeguerin timotheeguerin marked this pull request as ready for review June 23, 2026 18:41
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.

[Bug]: function-based interpolation conditionally dumps the generator

1 participant