From 40a2eb2b4b4147f3dc51f621bf69ae5c3f72bdd8 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 19 Apr 2019 16:01:53 -0700 Subject: [PATCH] Unify couldContainTypeVariables and the similar check done during instantiation (#30969) * Stop symbol based filtering in couldContainTypeVariables * Unify couldContainTypeVariables and the similar check done during instantiation --- src/compiler/checker.ts | 4 +- ...nearbyIdenticalGenericLambdasAssignable.js | 54 +++++++++ ...yIdenticalGenericLambdasAssignable.symbols | 102 ++++++++++++++++ ...rbyIdenticalGenericLambdasAssignable.types | 111 ++++++++++++++++++ ...nearbyIdenticalGenericLambdasAssignable.ts | 28 +++++ 5 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.js create mode 100644 tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.symbols create mode 100644 tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.types create mode 100644 tests/cases/compiler/nearbyIdenticalGenericLambdasAssignable.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f79b04904b1..603d7da5168 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11256,7 +11256,7 @@ namespace ts { // If the anonymous type originates in a declaration of a function, method, class, or // interface, in an object type literal, or in an object literal expression, we may need // to instantiate the type because it might reference a type parameter. - return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ? + return couldContainTypeVariables(type) ? getAnonymousTypeInstantiation(type, mapper) : type; } if (objectFlags & ObjectFlags.Mapped) { @@ -14557,7 +14557,7 @@ namespace ts { const objectFlags = getObjectFlags(type); return !!(type.flags & TypeFlags.Instantiable || objectFlags & ObjectFlags.Reference && forEach((type).typeArguments, couldContainTypeVariables) || - objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) || + objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations || objectFlags & ObjectFlags.Mapped || type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeVariables(type)); } diff --git a/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.js b/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.js new file mode 100644 index 00000000000..34413e8f72b --- /dev/null +++ b/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.js @@ -0,0 +1,54 @@ +//// [nearbyIdenticalGenericLambdasAssignable.ts] +declare const fA: () => { v: T }; +const fB = () => { + return { v: '' as any as T }; +}; +const fC = () => { + return {} as any as { v: T }; +}; + +// Hover display is identical on all of these +type TA = typeof fA; +type TB = typeof fB; +type TC = typeof fC; +type TL = () => { v: T }; + +declare function accA(x: TA): void; +declare function accB(x: TB): void; +declare function accC(x: TC): void; +declare function accL(x: TL): void; + +// These should all be OK, every type is identical +accA(fA); accA(fB); accA(fC); +// ~~ previously an error +accB(fA); accB(fB); accB(fC); +// OK +accC(fA); accC(fB); accC(fC); +// ~~ previously an error +accL(fA); accL(fB); accL(fC); +// ~~ previously an error + +//// [nearbyIdenticalGenericLambdasAssignable.js] +var fB = function () { + return { v: '' }; +}; +var fC = function () { + return {}; +}; +// These should all be OK, every type is identical +accA(fA); +accA(fB); +accA(fC); +// ~~ previously an error +accB(fA); +accB(fB); +accB(fC); +// OK +accC(fA); +accC(fB); +accC(fC); +// ~~ previously an error +accL(fA); +accL(fB); +accL(fC); +// ~~ previously an error diff --git a/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.symbols b/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.symbols new file mode 100644 index 00000000000..b9236cc887d --- /dev/null +++ b/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.symbols @@ -0,0 +1,102 @@ +=== tests/cases/compiler/nearbyIdenticalGenericLambdasAssignable.ts === +declare const fA: () => { v: T }; +>fA : Symbol(fA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 13)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 19)) +>v : Symbol(v, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 28)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 19)) + +const fB = () => { +>fB : Symbol(fB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 5)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 12)) + + return { v: '' as any as T }; +>v : Symbol(v, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 2, 12)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 12)) + +}; +const fC = () => { +>fC : Symbol(fC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 5)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 12)) + + return {} as any as { v: T }; +>v : Symbol(v, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 5, 25)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 12)) + +}; + +// Hover display is identical on all of these +type TA = typeof fA; +>TA : Symbol(TA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 6, 2)) +>fA : Symbol(fA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 13)) + +type TB = typeof fB; +>TB : Symbol(TB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 9, 20)) +>fB : Symbol(fB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 5)) + +type TC = typeof fC; +>TC : Symbol(TC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 10, 20)) +>fC : Symbol(fC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 5)) + +type TL = () => { v: T }; +>TL : Symbol(TL, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 11, 20)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 12, 11)) +>v : Symbol(v, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 12, 20)) +>T : Symbol(T, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 12, 11)) + +declare function accA(x: TA): void; +>accA : Symbol(accA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 12, 28)) +>x : Symbol(x, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 14, 22)) +>TA : Symbol(TA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 6, 2)) + +declare function accB(x: TB): void; +>accB : Symbol(accB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 14, 35)) +>x : Symbol(x, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 15, 22)) +>TB : Symbol(TB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 9, 20)) + +declare function accC(x: TC): void; +>accC : Symbol(accC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 15, 35)) +>x : Symbol(x, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 16, 22)) +>TC : Symbol(TC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 10, 20)) + +declare function accL(x: TL): void; +>accL : Symbol(accL, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 16, 35)) +>x : Symbol(x, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 17, 22)) +>TL : Symbol(TL, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 11, 20)) + +// These should all be OK, every type is identical +accA(fA); accA(fB); accA(fC); +>accA : Symbol(accA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 12, 28)) +>fA : Symbol(fA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 13)) +>accA : Symbol(accA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 12, 28)) +>fB : Symbol(fB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 5)) +>accA : Symbol(accA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 12, 28)) +>fC : Symbol(fC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 5)) + +// ~~ previously an error +accB(fA); accB(fB); accB(fC); +>accB : Symbol(accB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 14, 35)) +>fA : Symbol(fA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 13)) +>accB : Symbol(accB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 14, 35)) +>fB : Symbol(fB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 5)) +>accB : Symbol(accB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 14, 35)) +>fC : Symbol(fC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 5)) + +// OK +accC(fA); accC(fB); accC(fC); +>accC : Symbol(accC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 15, 35)) +>fA : Symbol(fA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 13)) +>accC : Symbol(accC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 15, 35)) +>fB : Symbol(fB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 5)) +>accC : Symbol(accC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 15, 35)) +>fC : Symbol(fC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 5)) + +// ~~ previously an error +accL(fA); accL(fB); accL(fC); +>accL : Symbol(accL, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 16, 35)) +>fA : Symbol(fA, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 0, 13)) +>accL : Symbol(accL, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 16, 35)) +>fB : Symbol(fB, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 1, 5)) +>accL : Symbol(accL, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 16, 35)) +>fC : Symbol(fC, Decl(nearbyIdenticalGenericLambdasAssignable.ts, 4, 5)) + +// ~~ previously an error diff --git a/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.types b/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.types new file mode 100644 index 00000000000..b2f878d548a --- /dev/null +++ b/tests/baselines/reference/nearbyIdenticalGenericLambdasAssignable.types @@ -0,0 +1,111 @@ +=== tests/cases/compiler/nearbyIdenticalGenericLambdasAssignable.ts === +declare const fA: () => { v: T }; +>fA : () => { v: T; } +>v : T + +const fB = () => { +>fB : () => { v: T; } +>() => { return { v: '' as any as T };} : () => { v: T; } + + return { v: '' as any as T }; +>{ v: '' as any as T } : { v: T; } +>v : T +>'' as any as T : T +>'' as any : any +>'' : "" + +}; +const fC = () => { +>fC : () => { v: T; } +>() => { return {} as any as { v: T };} : () => { v: T; } + + return {} as any as { v: T }; +>{} as any as { v: T } : { v: T; } +>{} as any : any +>{} : {} +>v : T + +}; + +// Hover display is identical on all of these +type TA = typeof fA; +>TA : () => { v: T; } +>fA : () => { v: T; } + +type TB = typeof fB; +>TB : () => { v: T; } +>fB : () => { v: T; } + +type TC = typeof fC; +>TC : () => { v: T; } +>fC : () => { v: T; } + +type TL = () => { v: T }; +>TL : TL +>v : T + +declare function accA(x: TA): void; +>accA : (x: () => { v: T; }) => void +>x : () => { v: T; } + +declare function accB(x: TB): void; +>accB : (x: () => { v: T; }) => void +>x : () => { v: T; } + +declare function accC(x: TC): void; +>accC : (x: () => { v: T; }) => void +>x : () => { v: T; } + +declare function accL(x: TL): void; +>accL : (x: TL) => void +>x : TL + +// These should all be OK, every type is identical +accA(fA); accA(fB); accA(fC); +>accA(fA) : void +>accA : (x: () => { v: T; }) => void +>fA : () => { v: T; } +>accA(fB) : void +>accA : (x: () => { v: T; }) => void +>fB : () => { v: T; } +>accA(fC) : void +>accA : (x: () => { v: T; }) => void +>fC : () => { v: T; } + +// ~~ previously an error +accB(fA); accB(fB); accB(fC); +>accB(fA) : void +>accB : (x: () => { v: T; }) => void +>fA : () => { v: T; } +>accB(fB) : void +>accB : (x: () => { v: T; }) => void +>fB : () => { v: T; } +>accB(fC) : void +>accB : (x: () => { v: T; }) => void +>fC : () => { v: T; } + +// OK +accC(fA); accC(fB); accC(fC); +>accC(fA) : void +>accC : (x: () => { v: T; }) => void +>fA : () => { v: T; } +>accC(fB) : void +>accC : (x: () => { v: T; }) => void +>fB : () => { v: T; } +>accC(fC) : void +>accC : (x: () => { v: T; }) => void +>fC : () => { v: T; } + +// ~~ previously an error +accL(fA); accL(fB); accL(fC); +>accL(fA) : void +>accL : (x: TL) => void +>fA : () => { v: T; } +>accL(fB) : void +>accL : (x: TL) => void +>fB : () => { v: T; } +>accL(fC) : void +>accL : (x: TL) => void +>fC : () => { v: T; } + +// ~~ previously an error diff --git a/tests/cases/compiler/nearbyIdenticalGenericLambdasAssignable.ts b/tests/cases/compiler/nearbyIdenticalGenericLambdasAssignable.ts new file mode 100644 index 00000000000..bad3cfb3327 --- /dev/null +++ b/tests/cases/compiler/nearbyIdenticalGenericLambdasAssignable.ts @@ -0,0 +1,28 @@ +declare const fA: () => { v: T }; +const fB = () => { + return { v: '' as any as T }; +}; +const fC = () => { + return {} as any as { v: T }; +}; + +// Hover display is identical on all of these +type TA = typeof fA; +type TB = typeof fB; +type TC = typeof fC; +type TL = () => { v: T }; + +declare function accA(x: TA): void; +declare function accB(x: TB): void; +declare function accC(x: TC): void; +declare function accL(x: TL): void; + +// These should all be OK, every type is identical +accA(fA); accA(fB); accA(fC); +// ~~ previously an error +accB(fA); accB(fB); accB(fC); +// OK +accC(fA); accC(fB); accC(fC); +// ~~ previously an error +accL(fA); accL(fB); accL(fC); +// ~~ previously an error \ No newline at end of file