diff --git a/src/resolver.ts b/src/resolver.ts index 456aefd6f8..ba10bd0a34 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3063,7 +3063,14 @@ export class Resolver extends DiagnosticEmitter { let boundPrototype = classInstance.getMember(unboundOverridePrototype.name); if (boundPrototype) { // might have errored earlier and wasn't added assert(boundPrototype.kind == ElementKind.FunctionPrototype); - overrideInstance = this.resolveFunction(boundPrototype, instance.typeArguments); + let boundFuncPrototype = boundPrototype; + let overrideTypeParams = boundFuncPrototype.typeParameterNodes; + let numOverrideTypeParams = overrideTypeParams ? overrideTypeParams.length : 0; + let baseTypeArgs = instance.typeArguments; + let numBaseTypeArgs = baseTypeArgs ? baseTypeArgs.length : 0; + if (numOverrideTypeParams == numBaseTypeArgs) { + overrideInstance = this.resolveFunction(boundFuncPrototype, baseTypeArgs); + } } } if (overrideInstance) overrides.add(overrideInstance); @@ -3439,6 +3446,19 @@ export class Resolver extends DiagnosticEmitter { default: assert(false); } if (!member.is(CommonFlags.Abstract)) { + // A generic method cannot implement a non-generic interface method + // because monomorphization requires a concrete type to generate code, + // but virtual dispatch through the interface has no type arguments. + if (unimplemented.has(memberName) + && member.kind == ElementKind.FunctionPrototype + && unimplemented.get(memberName)!.kind == ElementKind.FunctionPrototype + ) { + let memberTypeParams = (member).typeParameterNodes; + let ifaceTypeParams = (unimplemented.get(memberName)).typeParameterNodes; + let numMemberTypeParams = memberTypeParams ? memberTypeParams.length : 0; + let numIfaceTypeParams = ifaceTypeParams ? ifaceTypeParams.length : 0; + if (numMemberTypeParams != numIfaceTypeParams) continue; + } unimplemented.delete(memberName); } } diff --git a/tests/compiler/override-typeparam-mismatch.json b/tests/compiler/override-typeparam-mismatch.json new file mode 100644 index 0000000000..4751c70a92 --- /dev/null +++ b/tests/compiler/override-typeparam-mismatch.json @@ -0,0 +1,9 @@ +{ + "asc_flags": [], + "stderr": [ + "TS2515: Non-abstract class 'override-typeparam-mismatch/CC' does not implement inherited abstract member 'foo' from 'override-typeparam-mismatch/I'.", + "TS2515: Non-abstract class 'override-typeparam-mismatch/DD' does not implement inherited abstract member 'bar' from 'override-typeparam-mismatch/J'.", + "TS2515: Non-abstract class 'override-typeparam-mismatch/C2' does not implement inherited abstract member 'foo' from 'override-typeparam-mismatch/I2'.", + "EOF" + ] +} diff --git a/tests/compiler/override-typeparam-mismatch.ts b/tests/compiler/override-typeparam-mismatch.ts new file mode 100644 index 0000000000..d37bd6d542 --- /dev/null +++ b/tests/compiler/override-typeparam-mismatch.ts @@ -0,0 +1,39 @@ +interface I { + foo(x: i32): i32; +} + +class CC implements I { + foo(x: i32): i32 { + return x; + } +} + +let c:I = new CC(); +c.foo(1); + +interface J { + bar(x: i32): i32; +} + +class DD implements J { + bar(x: i32): i32 { + return x; + } +} + +let dd:DD = new DD(); +dd.bar(1); + +interface I2 { + foo(x: i32): i32; +} + +class C2 implements I2 { + foo(x: i32): i32 { + return x; + } +} + +new C2().foo(1); + +ERROR("EOF");