diff --git a/src/compiler.ts b/src/compiler.ts index 36f09ab8aa..af751d336c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -7186,6 +7186,21 @@ export class Compiler extends DiagnosticEmitter { let sourceFunction = flow.sourceFunction; let isNamed = declaration.name.text.length > 0; let isSemanticallyAnonymous = !isNamed || contextualType != Type.void; + + // Check for duplicate named function declarations before creating the + // prototype, since registering a concrete element with a duplicate + // internalName would trigger an assertion error. + if (!isSemanticallyAnonymous) { + let existingLocal = flow.getScopedLocal(declaration.name.text); + if (existingLocal) { + this.error( + DiagnosticCode.Duplicate_identifier_0, + declaration.name.range, declaration.name.text + ); + return this.module.unreachable(); + } + } + let prototype = new FunctionPrototype( isSemanticallyAnonymous ? `${isNamed ? declaration.name.text : "anonymous"}|${sourceFunction.nextAnonymousId++}` diff --git a/tests/compiler/duplicate-function-in-scope.json b/tests/compiler/duplicate-function-in-scope.json new file mode 100644 index 0000000000..05cb143081 --- /dev/null +++ b/tests/compiler/duplicate-function-in-scope.json @@ -0,0 +1,7 @@ +{ + "asc_flags": [], + "stderr": [ + "EOF", + "TS2300: Duplicate identifier 'inner'." + ] +} diff --git a/tests/compiler/duplicate-function-in-scope.ts b/tests/compiler/duplicate-function-in-scope.ts new file mode 100644 index 0000000000..62c2e68a00 --- /dev/null +++ b/tests/compiler/duplicate-function-in-scope.ts @@ -0,0 +1,16 @@ +// Duplicate named function declarations in the same scope should +// produce a diagnostic instead of crashing the compiler. + +export function test(): void { + function inner(): i32 { + let x: i32 = 0; + return x; + } + function inner(): i32 { + let x: i32 = 0; + return x + 1; + } + inner(); +} + +ERROR("EOF");