Skip to content

Commit b822def

Browse files
committed
Minor cleanup plus more comments
1 parent 203fd9f commit b822def

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

src/compiler/checker.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15463,7 +15463,7 @@ namespace ts {
1546315463
let bivariant = false;
1546415464
let propagationType: Type;
1546515465
let inferenceCount = 0;
15466-
let inferenceBlocked = false;
15466+
let inferenceIncomplete = false;
1546715467
let allowComplexConstraintInference = true;
1546815468
inferFromTypes(originalSource, originalTarget);
1546915469

@@ -15710,14 +15710,16 @@ namespace ts {
1571015710
function inferToMultipleTypes(source: Type, targets: Type[], targetFlags: TypeFlags) {
1571115711
let typeVariableCount = 0;
1571215712
if (targetFlags & TypeFlags.Union) {
15713+
let nakedTypeVariable: Type | undefined;
1571315714
const sources = source.flags & TypeFlags.Union ? (<UnionType>source).types : [source];
1571415715
const matched = new Array<boolean>(sources.length);
15715-
const saveInferenceBlocked = inferenceBlocked;
15716-
inferenceBlocked = false;
15716+
const saveInferenceIncomplete = inferenceIncomplete;
15717+
inferenceIncomplete = false;
1571715718
// First infer to types that are not naked type variables. For each source type we
1571815719
// track whether inferences were made from that particular type to some target.
1571915720
for (const t of targets) {
1572015721
if (getInferenceInfoForType(t)) {
15722+
nakedTypeVariable = t;
1572115723
typeVariableCount++;
1572215724
}
1572315725
else {
@@ -15728,21 +15730,18 @@ namespace ts {
1572815730
}
1572915731
}
1573015732
}
15731-
// If the target has a single naked type variable and inference wasn't blocked (meaning
15732-
// we explored the types fully), create a union of the source types from which no inferences
15733+
const inferenceComplete = !inferenceIncomplete;
15734+
inferenceIncomplete = inferenceIncomplete || saveInferenceIncomplete;
15735+
// If the target has a single naked type variable and inference completed (meaning we
15736+
// explored the types fully), create a union of the source types from which no inferences
1573315737
// have been made so far and infer from that union to the naked type variable.
15734-
if (typeVariableCount === 1 && !inferenceBlocked) {
15738+
if (typeVariableCount === 1 && inferenceComplete) {
1573515739
const unmatched = flatMap(sources, (s, i) => matched[i] ? undefined : s);
1573615740
if (unmatched.length) {
15737-
const s = getUnionType(unmatched);
15738-
for (const t of targets) {
15739-
if (getInferenceInfoForType(t)) {
15740-
inferFromTypes(s, t);
15741-
}
15742-
}
15741+
inferFromTypes(getUnionType(unmatched), nakedTypeVariable!);
15742+
return;
1574315743
}
1574415744
}
15745-
inferenceBlocked = inferenceBlocked || saveInferenceBlocked;
1574615745
}
1574715746
else {
1574815747
// We infer from types that are not naked type variables first so that inferences we
@@ -15839,7 +15838,7 @@ namespace ts {
1583915838
const symbol = isNonConstructorObject ? target.symbol : undefined;
1584015839
if (symbol) {
1584115840
if (contains(symbolStack, symbol)) {
15842-
inferenceBlocked = true;
15841+
inferenceIncomplete = true;
1584315842
return;
1584415843
}
1584515844
(symbolStack || (symbolStack = [])).push(symbol);
@@ -15955,10 +15954,13 @@ namespace ts {
1595515954
}
1595615955

1595715956
function isMatchableType(type: Type) {
15957+
// We exclude non-anonymous object types because some frameworks (e.g. Ember) rely on the ability to
15958+
// infer between types that don't witness their type variables. Such types would otherwise be eliminated
15959+
// because they appear identical.
1595815960
return !(type.flags & TypeFlags.Object) || !!(getObjectFlags(type) & ObjectFlags.Anonymous);
1595915961
}
1596015962

15961-
function typeIdenticalToSomeType(type: Type, types: Type[]): boolean {
15963+
function typeMatchedBySomeType(type: Type, types: Type[]): boolean {
1596215964
for (const t of types) {
1596315965
if (t === type || isMatchableType(t) && isMatchableType(type) && isTypeIdenticalTo(t, type)) {
1596415966
return true;
@@ -15968,12 +15970,12 @@ namespace ts {
1596815970
}
1596915971

1597015972
function findMatchedType(type: Type, target: UnionOrIntersectionType) {
15971-
if (typeIdenticalToSomeType(type, target.types)) {
15973+
if (typeMatchedBySomeType(type, target.types)) {
1597215974
return type;
1597315975
}
1597415976
if (type.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral) && target.flags & TypeFlags.Union) {
1597515977
const base = getBaseTypeOfLiteralType(type);
15976-
if (typeIdenticalToSomeType(base, target.types)) {
15978+
if (typeMatchedBySomeType(base, target.types)) {
1597715979
return base;
1597815980
}
1597915981
}
@@ -15987,7 +15989,7 @@ namespace ts {
1598715989
function removeTypesFromUnionOrIntersection(type: UnionOrIntersectionType, typesToRemove: Type[]) {
1598815990
const reducedTypes: Type[] = [];
1598915991
for (const t of type.types) {
15990-
if (!typeIdenticalToSomeType(t, typesToRemove)) {
15992+
if (!typeMatchedBySomeType(t, typesToRemove)) {
1599115993
reducedTypes.push(t);
1599215994
}
1599315995
}

0 commit comments

Comments
 (0)