Skip to content

Commit 070ad50

Browse files
committed
cache relationships, needs work on preserving diagnostic output
Error caching is a losing game Only safe caches Carve out a few more safe cache uses Lifted cache from recursiveTypeRelatedTo, shows need for elaboration cache Cache more outputs, accept elaboration-omitting baselines Remove whitespace
1 parent 49676c5 commit 070ad50

14 files changed

+39
-76
lines changed

src/compiler/checker.ts

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8925,6 +8925,16 @@ namespace ts {
89258925
return false;
89268926
}
89278927

8928+
function reportElaboratedRelationError(headMessage: DiagnosticMessage | undefined, source: Type, target: Type) {
8929+
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) {
8930+
tryElaborateErrorsForPrimitivesAndObjects(source, target);
8931+
}
8932+
else if (source.symbol && source.flags & TypeFlags.Object && globalObjectType === source) {
8933+
reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead);
8934+
}
8935+
reportRelationError(headMessage, source, target);
8936+
}
8937+
89288938
/**
89298939
* Compare two types and return
89308940
* * Ternary.True if they are related with no assumptions,
@@ -8941,8 +8951,24 @@ namespace ts {
89418951
// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
89428952
if (source === target) return Ternary.True;
89438953

8954+
const comparisonId = getRelationKey(source, target, relation);
8955+
if (relation.has(comparisonId)) {
8956+
const result = relation.get(comparisonId);
8957+
// If we need to report errors, and the result is RelationComparisonResult.Failed, then we need
8958+
// to redo our work to generate an error message. Otherwise, we can just return the cached result.
8959+
if (!reportErrors || result !== RelationComparisonResult.Failed) {
8960+
if (reportErrors && result !== RelationComparisonResult.Succeeded) {
8961+
reportElaboratedRelationError(headMessage, source, target);
8962+
}
8963+
return result === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
8964+
}
8965+
if (reportErrors && result === RelationComparisonResult.Failed) {
8966+
relation.set(comparisonId, RelationComparisonResult.FailedAndReported);
8967+
}
8968+
}
8969+
89448970
if (relation === identityRelation) {
8945-
return isIdenticalTo(source, target);
8971+
return cacheResult(isIdenticalTo(source, target), comparisonId, /*reportErrors*/ false);
89468972
}
89478973

89488974
if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
@@ -8952,7 +8978,7 @@ namespace ts {
89528978
if (reportErrors) {
89538979
reportRelationError(headMessage, source, target);
89548980
}
8955-
return Ternary.False;
8981+
return cacheResult(Ternary.False, comparisonId, reportErrors);
89568982
}
89578983
// Above we check for excess properties with respect to the entire target type. When union
89588984
// and intersection types are further deconstructed on the target side, we don't want to
@@ -8984,6 +9010,7 @@ namespace ts {
89849010
reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target));
89859011
}
89869012
}
9013+
// Intentionally not cached, so common property errors are repeated
89879014
return Ternary.False;
89889015
}
89899016

@@ -9034,13 +9061,15 @@ namespace ts {
90349061
isIntersectionConstituent = saveIsIntersectionConstituent;
90359062

90369063
if (!result && reportErrors) {
9037-
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) {
9038-
tryElaborateErrorsForPrimitivesAndObjects(source, target);
9039-
}
9040-
else if (source.symbol && source.flags & TypeFlags.Object && globalObjectType === source) {
9041-
reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead);
9042-
}
9043-
reportRelationError(headMessage, source, target);
9064+
reportElaboratedRelationError(headMessage, source, target);
9065+
}
9066+
9067+
return cacheResult(result, comparisonId, reportErrors);
9068+
}
9069+
9070+
function cacheResult(result: Ternary, comparisonId: string, reportErrors?: boolean) {
9071+
if (!relation.has(comparisonId) && result !== Ternary.Maybe) {
9072+
relation.set(comparisonId, result ? RelationComparisonResult.Succeeded : reportErrors ? RelationComparisonResult.FailedAndReported : RelationComparisonResult.Failed);
90449073
}
90459074
return result;
90469075
}
@@ -9214,17 +9243,6 @@ namespace ts {
92149243
return Ternary.False;
92159244
}
92169245
const id = getRelationKey(source, target, relation);
9217-
const related = relation.get(id);
9218-
if (related !== undefined) {
9219-
if (reportErrors && related === RelationComparisonResult.Failed) {
9220-
// We are elaborating errors and the cached result is an unreported failure. Record the result as a reported
9221-
// failure and continue computing the relation such that errors get reported.
9222-
relation.set(id, RelationComparisonResult.FailedAndReported);
9223-
}
9224-
else {
9225-
return related === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
9226-
}
9227-
}
92289246
if (!maybeKeys) {
92299247
maybeKeys = [];
92309248
sourceStack = [];
@@ -9264,9 +9282,6 @@ namespace ts {
92649282
}
92659283
}
92669284
else {
9267-
// A false result goes straight into global cache (when something is false under
9268-
// assumptions it will also be false without assumptions)
9269-
relation.set(id, reportErrors ? RelationComparisonResult.FailedAndReported : RelationComparisonResult.Failed);
92709285
maybeCount = maybeStart;
92719286
}
92729287
return result;

tests/baselines/reference/arityAndOrderCompatibility01.errors.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(26,5): error
3535
Types of property 'pop' are incompatible.
3636
Type '() => string | number' is not assignable to type '() => string'.
3737
Type 'string | number' is not assignable to type 'string'.
38-
Type 'number' is not assignable to type 'string'.
3938
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(27,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string]'.
4039
Property 'length' is missing in type '{ 0: string; 1: number; }'.
4140
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(28,5): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'.
@@ -127,7 +126,6 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error
127126
!!! error TS2322: Types of property 'pop' are incompatible.
128127
!!! error TS2322: Type '() => string | number' is not assignable to type '() => string'.
129128
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
130-
!!! error TS2322: Type 'number' is not assignable to type 'string'.
131129
var m3: [string] = z;
132130
~~
133131
!!! error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string]'.

tests/baselines/reference/callWithSpread2.errors.txt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(30,5): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
22
Type 'string' is not assignable to type 'number'.
33
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(31,5): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
4-
Type 'string' is not assignable to type 'number'.
54
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(32,13): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
6-
Type 'string' is not assignable to type 'number'.
75
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(33,13): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
8-
Type 'string' is not assignable to type 'number'.
96
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(34,11): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
10-
Type 'string' is not assignable to type 'number'.
117
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(35,11): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
12-
Type 'string' is not assignable to type 'number'.
138
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,1): error TS2556: Expected 1-3 arguments, but got a minimum of 0.
149
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(37,1): error TS2556: Expected 1-3 arguments, but got a minimum of 0.
1510
tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(38,1): error TS2556: Expected 1-3 arguments, but got a minimum of 0.
@@ -52,23 +47,18 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(38,1): erro
5247
all(...tuple)
5348
~~~~~~~~
5449
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
55-
!!! error TS2345: Type 'string' is not assignable to type 'number'.
5650
prefix("b", ...mixed)
5751
~~~~~~~~
5852
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
59-
!!! error TS2345: Type 'string' is not assignable to type 'number'.
6053
prefix("c", ...tuple)
6154
~~~~~~~~
6255
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
63-
!!! error TS2345: Type 'string' is not assignable to type 'number'.
6456
rest("e", ...mixed)
6557
~~~~~~~~
6658
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
67-
!!! error TS2345: Type 'string' is not assignable to type 'number'.
6859
rest("f", ...tuple)
6960
~~~~~~~~
7061
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
71-
!!! error TS2345: Type 'string' is not assignable to type 'number'.
7262
prefix(...ns) // required parameters are required
7363
~~~~~~~~~~~~~
7464
!!! error TS2556: Expected 1-3 arguments, but got a minimum of 0.

tests/baselines/reference/checkJsxChildrenProperty7.errors.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@ tests/cases/conformance/jsx/file.tsx(25,16): error TS2322: Type '{ a: 10; b: "hi
99
Type '{ a: 10; b: "hi"; children: (string | Element)[]; }' is not assignable to type 'Prop'.
1010
Types of property 'children' are incompatible.
1111
Type '(string | Element)[]' is not assignable to type 'Element | Element[]'.
12-
Type '(string | Element)[]' is not assignable to type 'Element[]'.
1312
tests/cases/conformance/jsx/file.tsx(27,16): error TS2322: Type '{ a: 10; b: "hi"; children: (string | Element)[]; }' is not assignable to type 'IntrinsicAttributes & Prop'.
1413
Type '{ a: 10; b: "hi"; children: (string | Element)[]; }' is not assignable to type 'Prop'.
1514
Types of property 'children' are incompatible.
1615
Type '(string | Element)[]' is not assignable to type 'Element | Element[]'.
17-
Type '(string | Element)[]' is not assignable to type 'Element[]'.
1816

1917

2018
==== tests/cases/conformance/jsx/file.tsx (3 errors) ====
@@ -56,13 +54,11 @@ tests/cases/conformance/jsx/file.tsx(27,16): error TS2322: Type '{ a: 10; b: "hi
5654
!!! error TS2322: Type '{ a: 10; b: "hi"; children: (string | Element)[]; }' is not assignable to type 'Prop'.
5755
!!! error TS2322: Types of property 'children' are incompatible.
5856
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'Element | Element[]'.
59-
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'Element[]'.
6057
<AnotherButton /> </Comp>;
6158
let k3 = <Comp a={10} b="hi"> <Button />
6259
~~~~~~~~~~~~~
6360
!!! error TS2322: Type '{ a: 10; b: "hi"; children: (string | Element)[]; }' is not assignable to type 'IntrinsicAttributes & Prop'.
6461
!!! error TS2322: Type '{ a: 10; b: "hi"; children: (string | Element)[]; }' is not assignable to type 'Prop'.
6562
!!! error TS2322: Types of property 'children' are incompatible.
6663
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'Element | Element[]'.
67-
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'Element[]'.
6864
<AnotherButton /></Comp>;

tests/baselines/reference/contextualTypeWithTuple.errors.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(24,1): error TS23
1818
Property '2' is missing in type '[C, string | number]'.
1919
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'.
2020
Type 'string | number' is not assignable to type 'string'.
21-
Type 'number' is not assignable to type 'string'.
2221

2322

2423
==== tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts (7 errors) ====
@@ -73,5 +72,4 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23
7372
numStrTuple = unionTuple3;
7473
~~~~~~~~~~~
7574
!!! error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'.
76-
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
77-
!!! error TS2322: Type 'number' is not assignable to type 'string'.
75+
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.

tests/baselines/reference/contextualTypeWithUnionTypeObjectLiteral.errors.txt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,23 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(
77
Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'.
88
Types of property 'prop' are incompatible.
99
Type 'string | number' is not assignable to type 'number'.
10-
Type 'string' is not assignable to type 'number'.
1110
tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(21,5): error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'.
1211
Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; }'.
1312
Types of property 'prop' are incompatible.
1413
Type 'string | number' is not assignable to type 'number'.
15-
Type 'string' is not assignable to type 'number'.
1614
tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(25,5): error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'.
1715
Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; anotherP1: number; }'.
1816
Types of property 'prop' are incompatible.
1917
Type 'string | number' is not assignable to type 'number'.
20-
Type 'string' is not assignable to type 'number'.
2118
tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(29,5): error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; anotherP1: number; }'.
2219
Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: number; anotherP1: number; }'.
2320
Types of property 'prop' are incompatible.
2421
Type 'string | number' is not assignable to type 'number'.
25-
Type 'string' is not assignable to type 'number'.
2622
tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(57,5): error TS2322: Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I11 | I21'.
2723
Type '{ commonMethodDifferentReturnType: (a: string, b: number) => string | number; }' is not assignable to type 'I21'.
2824
Types of property 'commonMethodDifferentReturnType' are incompatible.
2925
Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'.
3026
Type 'string | number' is not assignable to type 'number'.
31-
Type 'string' is not assignable to type 'number'.
3227

3328

3429
==== tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts (6 errors) ====
@@ -63,14 +58,12 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(
6358
!!! error TS2322: Type '{ prop: string | number; }' is not assignable to type '{ prop: number; }'.
6459
!!! error TS2322: Types of property 'prop' are incompatible.
6560
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
66-
!!! error TS2322: Type 'string' is not assignable to type 'number'.
6761
var objStrOrNum6: { prop: string; anotherP: string; } | { prop: number } = {
6862
~~~~~~~~~~~~
6963
!!! error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: string; anotherP: string; } | { prop: number; }'.
7064
!!! error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; }'.
7165
!!! error TS2322: Types of property 'prop' are incompatible.
7266
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
73-
!!! error TS2322: Type 'string' is not assignable to type 'number'.
7467
prop: strOrNumber,
7568
anotherP: str
7669
};
@@ -80,7 +73,6 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(
8073
!!! error TS2322: Type '{ prop: string | number; anotherP: string; }' is not assignable to type '{ prop: number; anotherP1: number; }'.
8174
!!! error TS2322: Types of property 'prop' are incompatible.
8275
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
83-
!!! error TS2322: Type 'string' is not assignable to type 'number'.
8476
prop: strOrNumber,
8577
anotherP: str
8678
};
@@ -90,7 +82,6 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(
9082
!!! error TS2322: Type '{ prop: string | number; anotherP: string; anotherP1: number; }' is not assignable to type '{ prop: number; anotherP1: number; }'.
9183
!!! error TS2322: Types of property 'prop' are incompatible.
9284
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
93-
!!! error TS2322: Type 'string' is not assignable to type 'number'.
9485
prop: strOrNumber,
9586
anotherP: str,
9687
anotherP1: num
@@ -125,6 +116,5 @@ tests/cases/conformance/types/union/contextualTypeWithUnionTypeObjectLiteral.ts(
125116
!!! error TS2322: Types of property 'commonMethodDifferentReturnType' are incompatible.
126117
!!! error TS2322: Type '(a: string, b: number) => string | number' is not assignable to type '(a: string, b: number) => number'.
127118
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
128-
!!! error TS2322: Type 'string' is not assignable to type 'number'.
129119
commonMethodDifferentReturnType: (a, b) => strOrNumber,
130120
};

0 commit comments

Comments
 (0)