From b5a5758169c44060277ee2ac181cadad4c7f9dae Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 16 Jul 2016 07:46:28 -0700 Subject: [PATCH] No subtype reduction in createUnionOrIntersectionProperty for performance --- src/compiler/checker.ts | 14 ++++++++++++-- src/harness/loggedIO.ts | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 996ad2586df..47fa9918d2b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4327,7 +4327,7 @@ namespace ts { result.containingType = containingType; result.declarations = declarations; result.isReadonly = isReadonly; - result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes); + result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes, /*noSubtypeReduction*/ true) : getIntersectionType(propTypes); return result; } @@ -5148,7 +5148,8 @@ namespace ts { if (type.flags & TypeFlags.Null) typeSet.containsNull = true; if (!(type.flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true; } - else if (type !== neverType && !contains(typeSet, type)) { + else if (type !== neverType && !contains(typeSet, type) && + !(type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { typeSet.push(type); } } @@ -5161,6 +5162,15 @@ namespace ts { } } + function containsIdenticalType(types: Type[], type: Type) { + for (const t of types) { + if (isTypeIdenticalTo(t, type)) { + return true; + } + } + return false; + } + function isSubtypeOfAny(candidate: Type, types: Type[]): boolean { for (let i = 0, len = types.length; i < len; i++) { if (candidate !== types[i] && isTypeSubtypeOf(candidate, types[i])) { diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 25e982cf680..33a46450a17 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -209,7 +209,7 @@ namespace Playback { memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( - path => { + (path: string) => { const result = underlying.readFile(path); const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry);