Skip to content

Commit 564c7b4

Browse files
committed
Merge pull request #5921 from Microsoft/revert-5919-port_union_reduction_to_1.7
Revert "Port union reduction to 1.7"
2 parents 2fb9f9b + 8c085fc commit 564c7b4

17 files changed

+41
-1167
lines changed

src/compiler/checker.ts

+41-60
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ namespace ts {
4343
let emptyArray: any[] = [];
4444
let emptySymbols: SymbolTable = {};
4545

46-
let jsxElementClassType: Type = undefined;
47-
4846
let compilerOptions = host.getCompilerOptions();
4947
let languageVersion = compilerOptions.target || ScriptTarget.ES3;
5048
let modulekind = compilerOptions.module ? compilerOptions.module : languageVersion === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.None;
@@ -4940,6 +4938,9 @@ namespace ts {
49404938
}
49414939
return objectTypeRelatedTo(<ObjectType>source, <ObjectType>target, /*reportErrors*/ false);
49424940
}
4941+
if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
4942+
return typeParameterIdenticalTo(<TypeParameter>source, <TypeParameter>target);
4943+
}
49434944
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
49444945
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
49454946
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
@@ -5070,6 +5071,20 @@ namespace ts {
50705071
return result;
50715072
}
50725073

5074+
function typeParameterIdenticalTo(source: TypeParameter, target: TypeParameter): Ternary {
5075+
if (source.symbol.name !== target.symbol.name) {
5076+
return Ternary.False;
5077+
}
5078+
// covers case when both type parameters does not have constraint (both equal to noConstraintType)
5079+
if (source.constraint === target.constraint) {
5080+
return Ternary.True;
5081+
}
5082+
if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
5083+
return Ternary.False;
5084+
}
5085+
return isIdenticalTo(source.constraint, target.constraint);
5086+
}
5087+
50735088
// Determine if two object types are related by structure. First, check if the result is already available in the global cache.
50745089
// Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
50755090
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
@@ -5592,20 +5607,27 @@ namespace ts {
55925607
return Ternary.False;
55935608
}
55945609
}
5595-
// Check that the two signatures have the same number of type parameters. We might consider
5596-
// also checking that any type parameter constraints match, but that would require instantiating
5597-
// the constraints with a common set of type arguments to get relatable entities in places where
5598-
// type parameters occur in the constraints. The complexity of doing that doesn't seem worthwhile,
5599-
// particularly as we're comparing erased versions of the signatures below.
5600-
if ((source.typeParameters ? source.typeParameters.length : 0) !== (target.typeParameters ? target.typeParameters.length : 0)) {
5610+
let result = Ternary.True;
5611+
if (source.typeParameters && target.typeParameters) {
5612+
if (source.typeParameters.length !== target.typeParameters.length) {
5613+
return Ternary.False;
5614+
}
5615+
for (let i = 0, len = source.typeParameters.length; i < len; ++i) {
5616+
let related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
5617+
if (!related) {
5618+
return Ternary.False;
5619+
}
5620+
result &= related;
5621+
}
5622+
}
5623+
else if (source.typeParameters || target.typeParameters) {
56015624
return Ternary.False;
56025625
}
56035626
// Spec 1.0 Section 3.8.3 & 3.8.4:
56045627
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
56055628
source = getErasedSignature(source);
56065629
target = getErasedSignature(target);
5607-
let result = Ternary.True;
5608-
const targetLen = target.parameters.length;
5630+
let targetLen = target.parameters.length;
56095631
for (let i = 0; i < targetLen; i++) {
56105632
let s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
56115633
let t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
@@ -5906,17 +5928,6 @@ namespace ts {
59065928
}
59075929

59085930
function inferFromTypes(source: Type, target: Type) {
5909-
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
5910-
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
5911-
// Source and target are both unions or both intersections. To improve the quality of
5912-
// inferences we first reduce the types by removing constituents that are identically
5913-
// matched by a constituent in the other type. For example, when inferring from
5914-
// 'string | string[]' to 'string | T', we reduce the types to 'string[]' and 'T'.
5915-
const reducedSource = reduceUnionOrIntersectionType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
5916-
const reducedTarget = reduceUnionOrIntersectionType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
5917-
source = reducedSource;
5918-
target = reducedTarget;
5919-
}
59205931
if (target.flags & TypeFlags.TypeParameter) {
59215932
// If target is a type parameter, make an inference, unless the source type contains
59225933
// the anyFunctionType (the wildcard type that's used to avoid contextually typing functions).
@@ -5927,7 +5938,8 @@ namespace ts {
59275938
if (source.flags & TypeFlags.ContainsAnyFunctionType) {
59285939
return;
59295940
}
5930-
const typeParameters = context.typeParameters;
5941+
5942+
let typeParameters = context.typeParameters;
59315943
for (let i = 0; i < typeParameters.length; i++) {
59325944
if (target === typeParameters[i]) {
59335945
let inferences = context.inferences[i];
@@ -5999,9 +6011,12 @@ namespace ts {
59996011
}
60006012
else {
60016013
source = getApparentType(source);
6002-
if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
6003-
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
6004-
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
6014+
if (source.flags & TypeFlags.ObjectType && (
6015+
target.flags & TypeFlags.Reference && (<TypeReference>target).typeArguments ||
6016+
target.flags & TypeFlags.Tuple ||
6017+
target.flags & TypeFlags.Anonymous && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
6018+
// If source is an object type, and target is a type reference with type arguments, a tuple type,
6019+
// the type of a method, or a type literal, infer from members
60056020
if (isInProcess(source, target)) {
60066021
return;
60076022
}
@@ -6074,41 +6089,6 @@ namespace ts {
60746089
}
60756090
}
60766091

6077-
function typeIdenticalToSomeType(source: Type, target: UnionOrIntersectionType): boolean {
6078-
for (const t of target.types) {
6079-
if (isTypeIdenticalTo(source, t)) {
6080-
return true;
6081-
}
6082-
}
6083-
return false;
6084-
}
6085-
6086-
/**
6087-
* Return the reduced form of the source type. This type is computed by by removing all source
6088-
* constituents that have an identical match in the target type.
6089-
*/
6090-
function reduceUnionOrIntersectionType(source: UnionOrIntersectionType, target: UnionOrIntersectionType) {
6091-
let sourceTypes = source.types;
6092-
let sourceIndex = 0;
6093-
let modified = false;
6094-
while (sourceIndex < sourceTypes.length) {
6095-
if (typeIdenticalToSomeType(sourceTypes[sourceIndex], target)) {
6096-
if (!modified) {
6097-
sourceTypes = sourceTypes.slice(0);
6098-
modified = true;
6099-
}
6100-
sourceTypes.splice(sourceIndex, 1);
6101-
}
6102-
else {
6103-
sourceIndex++;
6104-
}
6105-
}
6106-
if (modified) {
6107-
return source.flags & TypeFlags.Union ? getUnionType(sourceTypes, /*noSubtypeReduction*/ true) : getIntersectionType(sourceTypes);
6108-
}
6109-
return source;
6110-
}
6111-
61126092
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
61136093
let inferences = context.inferences[index];
61146094
return inferences.primary || inferences.secondary || emptyArray;
@@ -7882,6 +7862,7 @@ namespace ts {
78827862
return prop || unknownSymbol;
78837863
}
78847864

7865+
let jsxElementClassType: Type = undefined;
78857866
function getJsxGlobalElementClassType(): Type {
78867867
if (!jsxElementClassType) {
78877868
jsxElementClassType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.ElementClass);

tests/baselines/reference/genericSignatureIdentity.js

-32
This file was deleted.

tests/baselines/reference/genericSignatureIdentity.symbols

-49
This file was deleted.

tests/baselines/reference/genericSignatureIdentity.types

-49
This file was deleted.

0 commit comments

Comments
 (0)