Skip to content

Commit 50417ae

Browse files
WIP
1 parent 2180c8c commit 50417ae

File tree

5 files changed

+62
-9
lines changed

5 files changed

+62
-9
lines changed

src/diagnosticMessages.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"Definitive assignment has no effect on local variables.": 239,
5454
"Ambiguous operator overload '{0}' (conflicting overloads '{1}' and '{2}').": 240,
5555
"An interface or abstract method '{0}' cannot have type parameters.": 241,
56+
"Cannot override generic method '{0}' with a non-generic method or vice versa.": 242,
5657

5758
"Importing the table disables some indirect call optimizations.": 901,
5859
"Exporting the table disables some indirect call optimizations.": 902,

src/program.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,16 @@ export class Program extends DiagnosticEmitter {
15571557
) {
15581558
let thisMethod = <FunctionPrototype>thisMember;
15591559
let baseMethod = <FunctionPrototype>baseMember;
1560+
let thisIsGeneric = thisMethod.is(CommonFlags.Generic);
1561+
let baseIsGeneric = baseMethod.is(CommonFlags.Generic);
1562+
if (thisIsGeneric != baseIsGeneric) {
1563+
this.errorRelated(
1564+
DiagnosticCode.Cannot_override_generic_method_0_with_a_non_generic_method_or_vice_versa,
1565+
thisMethod.identifierNode.range, baseMethod.identifierNode.range,
1566+
thisMethod.name
1567+
);
1568+
return;
1569+
}
15601570
if (!thisMethod.visibilityEquals(baseMethod)) {
15611571
this.errorRelated(
15621572
DiagnosticCode.Overload_signatures_must_all_be_public_private_or_protected,

src/resolver.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2933,11 +2933,23 @@ export class Resolver extends DiagnosticEmitter {
29332933
incompatibleOverride = false;
29342934
} else {
29352935
if (baseMember.kind == ElementKind.FunctionPrototype) {
2936-
// Possibly generic. Resolve with same type arguments to obtain the correct one.
29372936
let basePrototype = <FunctionPrototype>baseMember;
2938-
let baseFunction = this.resolveFunction(basePrototype, typeArguments, new Map(), ReportMode.Swallow);
2939-
if (baseFunction && instance.signature.isAssignableTo(baseFunction.signature, true)) {
2940-
incompatibleOverride = false;
2937+
let baseIsGeneric = basePrototype.typeParameterNodes != null && basePrototype.typeParameterNodes.length > 0;
2938+
let instanceIsGeneric = typeArguments != null && typeArguments.length > 0;
2939+
if (baseIsGeneric != instanceIsGeneric) {
2940+
// Cannot mix generic and non-generic functions in an override chain
2941+
this.errorRelated(
2942+
DiagnosticCode.Cannot_override_generic_method_0_with_a_non_generic_method_or_vice_versa,
2943+
instance.identifierAndSignatureRange, baseMember.identifierAndSignatureRange,
2944+
methodOrPropertyName
2945+
);
2946+
incompatibleOverride = false; // already reported
2947+
} else {
2948+
// Possibly generic. Resolve with same type arguments to obtain the correct one.
2949+
let baseFunction = this.resolveFunction(basePrototype, typeArguments, new Map(), ReportMode.Swallow);
2950+
if (baseFunction && instance.signature.isAssignableTo(baseFunction.signature, true)) {
2951+
incompatibleOverride = false;
2952+
}
29412953
}
29422954
}
29432955
}
@@ -3069,11 +3081,8 @@ export class Resolver extends DiagnosticEmitter {
30693081
// arguments to forward to the monomorphized child.
30703082
// - generic child → generic base: OK; type args come from the base call site.
30713083
// - non-generic child → non-generic base: OK; plain vtable override.
3072-
// FIXME: non-generic child → generic base is also mismatched (resolveFunction
3073-
// would assert on typeArguments/typeParameterNodes length mismatch) but that
3074-
// case is not yet guarded here. The correct fix is to replace this condition
3075-
// with `boundFuncPrototype.is(Generic) == instance.is(Generic)`.
3076-
if (!boundFuncPrototype.is(CommonFlags.Generic) || instance.is(CommonFlags.Generic)) {
3084+
// - non-generic child → generic base: skip; mismatched generic-ness.
3085+
if (boundFuncPrototype.is(CommonFlags.Generic) == instance.is(CommonFlags.Generic)) {
30773086
overrideInstance = this.resolveFunction(boundFuncPrototype, instance.typeArguments);
30783087
}
30793088
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"asc_flags": [],
3+
"stderr": [
4+
"AS242: Cannot override generic method 'foo' with a non-generic method or vice versa.",
5+
"AS242: Cannot override generic method 'bar' with a non-generic method or vice versa.",
6+
"EOF"
7+
]
8+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Non-generic method overriding generic method
2+
class A {
3+
foo<T>(x: T): void {}
4+
}
5+
6+
class B extends A {
7+
foo(x: i32): void {}
8+
}
9+
10+
let a:A = new B();
11+
a.foo<i32>(1);
12+
13+
// Generic method overriding non-generic method
14+
class C {
15+
bar(x: i32): void {}
16+
}
17+
18+
class D extends C {
19+
bar<T>(x: T): void {}
20+
}
21+
22+
let c:C = new D();
23+
c.bar(1);
24+
25+
ERROR("EOF");

0 commit comments

Comments
 (0)