Skip to content

Commit

Permalink
bug fix 2727: class member function type is assigned to a normal func…
Browse files Browse the repository at this point in the history
…tion type
  • Loading branch information
Changqing-JING committed Jul 31, 2023
1 parent 382aabe commit 0055da6
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 14 deletions.
4 changes: 3 additions & 1 deletion src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6611,7 +6611,9 @@ export class Compiler extends DiagnosticEmitter {
if (!overrideInstance.is(CommonFlags.Compiled)) continue; // errored
let overrideType = overrideInstance.type;
let originalType = instance.type;
if (!overrideType.isAssignableTo(originalType)) {

assert(originalType.getSignature() != null && overrideType.getSignature() != null);
if (!(overrideType.getSignature() as Signature).isAssignableTo(originalType.getSignature() as Signature, true)) {
this.error(
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
overrideInstance.identifierNode.range, overrideType.toString(), originalType.toString()
Expand Down
28 changes: 15 additions & 13 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1051,21 +1051,23 @@ export class Signature {
isAssignableTo(target: Signature, checkCompatibleOverride: bool = false): bool {
let thisThisType = this.thisType;
let targetThisType = target.thisType;
if (checkCompatibleOverride) {
// check kind of `this` type
if (thisThisType) {
if (!targetThisType || !thisThisType.canExtendOrImplement(targetThisType)) {

if (
(thisThisType == null && targetThisType != null) ||
(thisThisType != null && targetThisType == null)
) {
return false;
}else if(thisThisType != null && targetThisType != null){
if(checkCompatibleOverride){
// check kind of `this` type
if(!thisThisType.canExtendOrImplement(targetThisType)){
return false;
}
}else{
// check `this` type (invariant)
if(!targetThisType.isAssignableTo(thisThisType)){
return false;
}
} else if (targetThisType) {
return false;
}
} else {
// check `this` type (invariant)
if (thisThisType) {
if (targetThisType != targetThisType) return false;
} else if (targetThisType) {
return false;
}
}

Expand Down
8 changes: 8 additions & 0 deletions tests/compiler/class-member-function-as-parameter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"asc_flags": [],
"stderr": [
"TS2322: Type '(this: class-member-function-as-parameter/C, i32) => i32' is not assignable to type '(i32) => i32'.",
"TS2322: Type '() => void' is not assignable to type '(this: class-member-function-as-parameter/B) => void'.",
"EOF"
]
}
52 changes: 52 additions & 0 deletions tests/compiler/class-member-function-as-parameter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class C {
aa: i32 = 1;
callback(a: i32): i32 {
return this.aa + a + 3;
}
}

function expectCallback(c1: (arg0: i32) => i32): i32 {
return c1(4);
}

export function fut(): i32 {
const c1 = new C();
return expectCallback(c1.callback);
}

fut();

class A {
foo(): void {
console.log("A");
}
}

class B extends A {
foo(): void {
console.log("B");
}
}

function foo(): void {
console.log("nothing");
}

function consume(callback: (this: B) => void): void {
const b = new B();
callback.call(b);
}

export function testNull(): void {
consume(foo); // This should (and does) error; this is fine.
}

export function testA(): void {
const a = new A();
consume(a.foo); // This shouldn't error
}

testNull();
testA();

ERROR("EOF");

0 comments on commit 0055da6

Please sign in to comment.