Skip to content

Commit df6f856

Browse files
committed
Persist inference context object throughout the signature, and add isFixed property
1 parent f6de919 commit df6f856

10 files changed

+44
-20
lines changed

src/compiler/checker.ts

+26-20
Original file line numberDiff line numberDiff line change
@@ -3505,6 +3505,7 @@ module ts {
35053505
return t => {
35063506
for (let i = 0; i < context.typeParameters.length; i++) {
35073507
if (t === context.typeParameters[i]) {
3508+
context.inferences[i].isFixed = true;
35083509
return getInferredType(context, i);
35093510
}
35103511
}
@@ -4563,12 +4564,11 @@ module ts {
45634564
function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext {
45644565
let inferences: TypeInferences[] = [];
45654566
for (let unused of typeParameters) {
4566-
inferences.push({ primary: undefined, secondary: undefined });
4567+
inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
45674568
}
45684569
return {
45694570
typeParameters: typeParameters,
45704571
inferUnionTypes: inferUnionTypes,
4571-
inferenceCount: 0,
45724572
inferences: inferences,
45734573
inferredTypes: new Array(typeParameters.length),
45744574
};
@@ -4615,11 +4615,13 @@ module ts {
46154615
for (let i = 0; i < typeParameters.length; i++) {
46164616
if (target === typeParameters[i]) {
46174617
let inferences = context.inferences[i];
4618-
let candidates = inferiority ?
4619-
inferences.secondary || (inferences.secondary = []) :
4620-
inferences.primary || (inferences.primary = []);
4621-
if (!contains(candidates, source)) candidates.push(source);
4622-
break;
4618+
if (!inferences.isFixed) {
4619+
let candidates = inferiority ?
4620+
inferences.secondary || (inferences.secondary = []) :
4621+
inferences.primary || (inferences.primary = []);
4622+
if (!contains(candidates, source)) candidates.push(source);
4623+
}
4624+
return;
46234625
}
46244626
}
46254627
}
@@ -6336,11 +6338,15 @@ module ts {
63366338
return getSignatureInstantiation(signature, getInferredTypes(context));
63376339
}
63386340

6339-
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[]): InferenceContext {
6341+
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
63406342
let typeParameters = signature.typeParameters;
6341-
let context = createInferenceContext(typeParameters, /*inferUnionTypes*/ false);
63426343
let inferenceMapper = createInferenceMapper(context);
63436344

6345+
// Clear out all the inference results from the last time inferTypeArguments was called on this context
6346+
for (let i = 0; i < typeParameters.length; i++) {
6347+
context.inferredTypes[i] = undefined;
6348+
}
6349+
63446350
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
63456351
// wildcards for all context sensitive function expressions.
63466352
for (let i = 0; i < args.length; i++) {
@@ -6385,8 +6391,6 @@ module ts {
63856391
inferredTypes[i] = unknownType;
63866392
}
63876393
}
6388-
6389-
return context;
63906394
}
63916395

63926396
function checkTypeArguments(signature: Signature, typeArguments: TypeNode[], typeArgumentResultTypes: Type[], reportErrors: boolean): boolean {
@@ -6620,15 +6624,17 @@ module ts {
66206624
return resolveErrorCall(node);
66216625

66226626
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
6623-
for (let current of candidates) {
6624-
if (!hasCorrectArity(node, args, current)) {
6627+
for (let originalCandidate of candidates) {
6628+
if (!hasCorrectArity(node, args, originalCandidate)) {
66256629
continue;
66266630
}
6627-
6628-
let originalCandidate = current;
6629-
let inferenceResult: InferenceContext;
6631+
66306632
let candidate: Signature;
66316633
let typeArgumentsAreValid: boolean;
6634+
let inferenceContext = originalCandidate.typeParameters
6635+
? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false)
6636+
: undefined;
6637+
66326638
while (true) {
66336639
candidate = originalCandidate;
66346640
if (candidate.typeParameters) {
@@ -6638,9 +6644,9 @@ module ts {
66386644
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)
66396645
}
66406646
else {
6641-
inferenceResult = inferTypeArguments(candidate, args, excludeArgument);
6642-
typeArgumentsAreValid = inferenceResult.failedTypeParameterIndex < 0;
6643-
typeArgumentTypes = inferenceResult.inferredTypes;
6647+
inferTypeArguments(candidate, args, excludeArgument, inferenceContext);
6648+
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex < 0;
6649+
typeArgumentTypes = inferenceContext.inferredTypes;
66446650
}
66456651
if (!typeArgumentsAreValid) {
66466652
break;
@@ -6670,7 +6676,7 @@ module ts {
66706676
else {
66716677
candidateForTypeArgumentError = originalCandidate;
66726678
if (!typeArguments) {
6673-
resultOfFailedInference = inferenceResult;
6679+
resultOfFailedInference = inferenceContext;
66746680
}
66756681
}
66766682
}

src/compiler/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,8 @@ module ts {
14851485
export interface TypeInferences {
14861486
primary: Type[]; // Inferences made directly to a type parameter
14871487
secondary: Type[]; // Inferences made to a type parameter in a union type
1488+
isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec
1489+
// If a type parameter is fixed, no more inferences can be made for the type parameter
14881490
}
14891491

14901492
export interface InferenceContext {

tests/baselines/reference/APISample_compile.js

+1
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,7 @@ declare module "typescript" {
11751175
interface TypeInferences {
11761176
primary: Type[];
11771177
secondary: Type[];
1178+
isFixed: boolean;
11781179
}
11791180
interface InferenceContext {
11801181
typeParameters: TypeParameter[];

tests/baselines/reference/APISample_compile.types

+3
Original file line numberDiff line numberDiff line change
@@ -3767,6 +3767,9 @@ declare module "typescript" {
37673767
secondary: Type[];
37683768
>secondary : Type[]
37693769
>Type : Type
3770+
3771+
isFixed: boolean;
3772+
>isFixed : boolean
37703773
}
37713774
interface InferenceContext {
37723775
>InferenceContext : InferenceContext

tests/baselines/reference/APISample_linter.js

+1
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,7 @@ declare module "typescript" {
12061206
interface TypeInferences {
12071207
primary: Type[];
12081208
secondary: Type[];
1209+
isFixed: boolean;
12091210
}
12101211
interface InferenceContext {
12111212
typeParameters: TypeParameter[];

tests/baselines/reference/APISample_linter.types

+3
Original file line numberDiff line numberDiff line change
@@ -3913,6 +3913,9 @@ declare module "typescript" {
39133913
secondary: Type[];
39143914
>secondary : Type[]
39153915
>Type : Type
3916+
3917+
isFixed: boolean;
3918+
>isFixed : boolean
39163919
}
39173920
interface InferenceContext {
39183921
>InferenceContext : InferenceContext

tests/baselines/reference/APISample_transform.js

+1
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,7 @@ declare module "typescript" {
12071207
interface TypeInferences {
12081208
primary: Type[];
12091209
secondary: Type[];
1210+
isFixed: boolean;
12101211
}
12111212
interface InferenceContext {
12121213
typeParameters: TypeParameter[];

tests/baselines/reference/APISample_transform.types

+3
Original file line numberDiff line numberDiff line change
@@ -3863,6 +3863,9 @@ declare module "typescript" {
38633863
secondary: Type[];
38643864
>secondary : Type[]
38653865
>Type : Type
3866+
3867+
isFixed: boolean;
3868+
>isFixed : boolean
38663869
}
38673870
interface InferenceContext {
38683871
>InferenceContext : InferenceContext

tests/baselines/reference/APISample_watcher.js

+1
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,7 @@ declare module "typescript" {
12441244
interface TypeInferences {
12451245
primary: Type[];
12461246
secondary: Type[];
1247+
isFixed: boolean;
12471248
}
12481249
interface InferenceContext {
12491250
typeParameters: TypeParameter[];

tests/baselines/reference/APISample_watcher.types

+3
Original file line numberDiff line numberDiff line change
@@ -4036,6 +4036,9 @@ declare module "typescript" {
40364036
secondary: Type[];
40374037
>secondary : Type[]
40384038
>Type : Type
4039+
4040+
isFixed: boolean;
4041+
>isFixed : boolean
40394042
}
40404043
interface InferenceContext {
40414044
>InferenceContext : InferenceContext

0 commit comments

Comments
 (0)