Skip to content

Commit

Permalink
Fix higher order inference on indexed access types (microsoft#20165)
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham authored Dec 21, 2017
1 parent 00450f0 commit 7ad0d7b
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11400,7 +11400,7 @@ namespace ts {
return;
}
}
else if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// If source and target are references to the same generic type, infer from type arguments
const sourceTypes = (<TypeReference>source).typeArguments || emptyArray;
const targetTypes = (<TypeReference>target).typeArguments || emptyArray;
Expand Down
21 changes: 21 additions & 0 deletions tests/baselines/reference/indexedAccessCanBeHighOrder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//// [indexedAccessCanBeHighOrder.ts]
declare function get<U, Y extends keyof U>(x: U, y: Y): U[Y];
declare function find<T, K extends keyof T>(o: T[K]): [T, K];

function impl<A, B extends keyof A>(a: A, b: B) {
const item = get(a, b);
return find(item);
}

const o = {x: 42};
const r = impl(o, "x");
r[0][r[1]] = o[r[1]];

//// [indexedAccessCanBeHighOrder.js]
function impl(a, b) {
var item = get(a, b);
return find(item);
}
var o = { x: 42 };
var r = impl(o, "x");
r[0][r[1]] = o[r[1]];
63 changes: 63 additions & 0 deletions tests/baselines/reference/indexedAccessCanBeHighOrder.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
=== tests/cases/compiler/indexedAccessCanBeHighOrder.ts ===
declare function get<U, Y extends keyof U>(x: U, y: Y): U[Y];
>get : Symbol(get, Decl(indexedAccessCanBeHighOrder.ts, 0, 0))
>U : Symbol(U, Decl(indexedAccessCanBeHighOrder.ts, 0, 21))
>Y : Symbol(Y, Decl(indexedAccessCanBeHighOrder.ts, 0, 23))
>U : Symbol(U, Decl(indexedAccessCanBeHighOrder.ts, 0, 21))
>x : Symbol(x, Decl(indexedAccessCanBeHighOrder.ts, 0, 43))
>U : Symbol(U, Decl(indexedAccessCanBeHighOrder.ts, 0, 21))
>y : Symbol(y, Decl(indexedAccessCanBeHighOrder.ts, 0, 48))
>Y : Symbol(Y, Decl(indexedAccessCanBeHighOrder.ts, 0, 23))
>U : Symbol(U, Decl(indexedAccessCanBeHighOrder.ts, 0, 21))
>Y : Symbol(Y, Decl(indexedAccessCanBeHighOrder.ts, 0, 23))

declare function find<T, K extends keyof T>(o: T[K]): [T, K];
>find : Symbol(find, Decl(indexedAccessCanBeHighOrder.ts, 0, 61))
>T : Symbol(T, Decl(indexedAccessCanBeHighOrder.ts, 1, 22))
>K : Symbol(K, Decl(indexedAccessCanBeHighOrder.ts, 1, 24))
>T : Symbol(T, Decl(indexedAccessCanBeHighOrder.ts, 1, 22))
>o : Symbol(o, Decl(indexedAccessCanBeHighOrder.ts, 1, 44))
>T : Symbol(T, Decl(indexedAccessCanBeHighOrder.ts, 1, 22))
>K : Symbol(K, Decl(indexedAccessCanBeHighOrder.ts, 1, 24))
>T : Symbol(T, Decl(indexedAccessCanBeHighOrder.ts, 1, 22))
>K : Symbol(K, Decl(indexedAccessCanBeHighOrder.ts, 1, 24))

function impl<A, B extends keyof A>(a: A, b: B) {
>impl : Symbol(impl, Decl(indexedAccessCanBeHighOrder.ts, 1, 61))
>A : Symbol(A, Decl(indexedAccessCanBeHighOrder.ts, 3, 14))
>B : Symbol(B, Decl(indexedAccessCanBeHighOrder.ts, 3, 16))
>A : Symbol(A, Decl(indexedAccessCanBeHighOrder.ts, 3, 14))
>a : Symbol(a, Decl(indexedAccessCanBeHighOrder.ts, 3, 36))
>A : Symbol(A, Decl(indexedAccessCanBeHighOrder.ts, 3, 14))
>b : Symbol(b, Decl(indexedAccessCanBeHighOrder.ts, 3, 41))
>B : Symbol(B, Decl(indexedAccessCanBeHighOrder.ts, 3, 16))

const item = get(a, b);
>item : Symbol(item, Decl(indexedAccessCanBeHighOrder.ts, 4, 9))
>get : Symbol(get, Decl(indexedAccessCanBeHighOrder.ts, 0, 0))
>a : Symbol(a, Decl(indexedAccessCanBeHighOrder.ts, 3, 36))
>b : Symbol(b, Decl(indexedAccessCanBeHighOrder.ts, 3, 41))

return find(item);
>find : Symbol(find, Decl(indexedAccessCanBeHighOrder.ts, 0, 61))
>item : Symbol(item, Decl(indexedAccessCanBeHighOrder.ts, 4, 9))
}

const o = {x: 42};
>o : Symbol(o, Decl(indexedAccessCanBeHighOrder.ts, 8, 5))
>x : Symbol(x, Decl(indexedAccessCanBeHighOrder.ts, 8, 11))

const r = impl(o, "x");
>r : Symbol(r, Decl(indexedAccessCanBeHighOrder.ts, 9, 5))
>impl : Symbol(impl, Decl(indexedAccessCanBeHighOrder.ts, 1, 61))
>o : Symbol(o, Decl(indexedAccessCanBeHighOrder.ts, 8, 5))

r[0][r[1]] = o[r[1]];
>r : Symbol(r, Decl(indexedAccessCanBeHighOrder.ts, 9, 5))
>0 : Symbol(0)
>r : Symbol(r, Decl(indexedAccessCanBeHighOrder.ts, 9, 5))
>1 : Symbol(1)
>o : Symbol(o, Decl(indexedAccessCanBeHighOrder.ts, 8, 5))
>r : Symbol(r, Decl(indexedAccessCanBeHighOrder.ts, 9, 5))
>1 : Symbol(1)

75 changes: 75 additions & 0 deletions tests/baselines/reference/indexedAccessCanBeHighOrder.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
=== tests/cases/compiler/indexedAccessCanBeHighOrder.ts ===
declare function get<U, Y extends keyof U>(x: U, y: Y): U[Y];
>get : <U, Y extends keyof U>(x: U, y: Y) => U[Y]
>U : U
>Y : Y
>U : U
>x : U
>U : U
>y : Y
>Y : Y
>U : U
>Y : Y

declare function find<T, K extends keyof T>(o: T[K]): [T, K];
>find : <T, K extends keyof T>(o: T[K]) => [T, K]
>T : T
>K : K
>T : T
>o : T[K]
>T : T
>K : K
>T : T
>K : K

function impl<A, B extends keyof A>(a: A, b: B) {
>impl : <A, B extends keyof A>(a: A, b: B) => [A, B]
>A : A
>B : B
>A : A
>a : A
>A : A
>b : B
>B : B

const item = get(a, b);
>item : A[B]
>get(a, b) : A[B]
>get : <U, Y extends keyof U>(x: U, y: Y) => U[Y]
>a : A
>b : B

return find(item);
>find(item) : [A, B]
>find : <T, K extends keyof T>(o: T[K]) => [T, K]
>item : A[B]
}

const o = {x: 42};
>o : { x: number; }
>{x: 42} : { x: number; }
>x : number
>42 : 42

const r = impl(o, "x");
>r : [{ x: number; }, "x"]
>impl(o, "x") : [{ x: number; }, "x"]
>impl : <A, B extends keyof A>(a: A, b: B) => [A, B]
>o : { x: number; }
>"x" : "x"

r[0][r[1]] = o[r[1]];
>r[0][r[1]] = o[r[1]] : number
>r[0][r[1]] : number
>r[0] : { x: number; }
>r : [{ x: number; }, "x"]
>0 : 0
>r[1] : "x"
>r : [{ x: number; }, "x"]
>1 : 1
>o[r[1]] : number
>o : { x: number; }
>r[1] : "x"
>r : [{ x: number; }, "x"]
>1 : 1

11 changes: 11 additions & 0 deletions tests/cases/compiler/indexedAccessCanBeHighOrder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
declare function get<U, Y extends keyof U>(x: U, y: Y): U[Y];
declare function find<T, K extends keyof T>(o: T[K]): [T, K];

function impl<A, B extends keyof A>(a: A, b: B) {
const item = get(a, b);
return find(item);
}

const o = {x: 42};
const r = impl(o, "x");
r[0][r[1]] = o[r[1]];

0 comments on commit 7ad0d7b

Please sign in to comment.