diff --git a/.chronus/changes/scalar-init-valueof-diagnostic-2026-6-3-18-59-0.md b/.chronus/changes/scalar-init-valueof-diagnostic-2026-6-3-18-59-0.md new file mode 100644 index 00000000000..9a979fdddfd --- /dev/null +++ b/.chronus/changes/scalar-init-valueof-diagnostic-2026-6-3-18-59-0.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/compiler" +--- + +Emit a clear error diagnostic when `valueof` is used in a scalar initializer parameter constraint. Scalar initializer parameters implicitly accept values, so `valueof` is redundant and was previously causing confusing errors. diff --git a/packages/compiler/src/core/checker.ts b/packages/compiler/src/core/checker.ts index de61f2ecd8a..679f4b3458c 100644 --- a/packages/compiler/src/core/checker.ts +++ b/packages/compiler/src/core/checker.ts @@ -7382,6 +7382,17 @@ export function createChecker(program: Program, resolver: NameResolver): Checker return links.declaredType as ScalarConstructor; } + for (const param of node.parameters) { + if (param.type && param.type.kind === SyntaxKind.ValueOfExpression) { + reportCheckerDiagnostic( + createDiagnostic({ + code: "scalar-init-valueof", + target: param.type, + }), + ); + } + } + const member: ScalarConstructor = createType({ kind: "ScalarConstructor", scalar: parentScalar, diff --git a/packages/compiler/src/core/messages.ts b/packages/compiler/src/core/messages.ts index 9008e0f6be6..c65fab39a29 100644 --- a/packages/compiler/src/core/messages.ts +++ b/packages/compiler/src/core/messages.ts @@ -541,6 +541,12 @@ const diagnostics = { default: paramMessage`A constructor already exists with name ${"name"}`, }, }, + "scalar-init-valueof": { + severity: "error", + messages: { + default: `Scalar initializer parameters implicitly accept values. Remove 'valueof' from the parameter type.`, + }, + }, "spread-enum": { severity: "error", messages: { diff --git a/packages/compiler/test/checker/scalar.test.ts b/packages/compiler/test/checker/scalar.test.ts index 0ed431781f5..24cb30b393b 100644 --- a/packages/compiler/test/checker/scalar.test.ts +++ b/packages/compiler/test/checker/scalar.test.ts @@ -157,4 +157,19 @@ describe("compiler: scalars", () => { }); }); }); + + describe("scalar initializer valueof constraint", () => { + it("emit error when scalar init parameter uses valueof", async () => { + const diagnostics = await Tester.diagnose(` + scalar S { + init i(s: valueof string); + } + `); + expectDiagnostics(diagnostics, { + code: "scalar-init-valueof", + message: + "Scalar initializer parameters implicitly accept values. Remove 'valueof' from the parameter type.", + }); + }); + }); });