Persist inference context object throughout the signature, and add isFixed property

This commit is contained in:
Jason Freeman 2015-03-13 16:41:26 -07:00
parent f6de919407
commit df6f856ad5
10 changed files with 44 additions and 20 deletions

View File

@ -3505,6 +3505,7 @@ module ts {
return t => {
for (let i = 0; i < context.typeParameters.length; i++) {
if (t === context.typeParameters[i]) {
context.inferences[i].isFixed = true;
return getInferredType(context, i);
}
}
@ -4563,12 +4564,11 @@ module ts {
function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext {
let inferences: TypeInferences[] = [];
for (let unused of typeParameters) {
inferences.push({ primary: undefined, secondary: undefined });
inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
}
return {
typeParameters: typeParameters,
inferUnionTypes: inferUnionTypes,
inferenceCount: 0,
inferences: inferences,
inferredTypes: new Array(typeParameters.length),
};
@ -4615,11 +4615,13 @@ module ts {
for (let i = 0; i < typeParameters.length; i++) {
if (target === typeParameters[i]) {
let inferences = context.inferences[i];
let candidates = inferiority ?
inferences.secondary || (inferences.secondary = []) :
inferences.primary || (inferences.primary = []);
if (!contains(candidates, source)) candidates.push(source);
break;
if (!inferences.isFixed) {
let candidates = inferiority ?
inferences.secondary || (inferences.secondary = []) :
inferences.primary || (inferences.primary = []);
if (!contains(candidates, source)) candidates.push(source);
}
return;
}
}
}
@ -6336,11 +6338,15 @@ module ts {
return getSignatureInstantiation(signature, getInferredTypes(context));
}
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[]): InferenceContext {
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
let typeParameters = signature.typeParameters;
let context = createInferenceContext(typeParameters, /*inferUnionTypes*/ false);
let inferenceMapper = createInferenceMapper(context);
// Clear out all the inference results from the last time inferTypeArguments was called on this context
for (let i = 0; i < typeParameters.length; i++) {
context.inferredTypes[i] = undefined;
}
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
// wildcards for all context sensitive function expressions.
for (let i = 0; i < args.length; i++) {
@ -6385,8 +6391,6 @@ module ts {
inferredTypes[i] = unknownType;
}
}
return context;
}
function checkTypeArguments(signature: Signature, typeArguments: TypeNode[], typeArgumentResultTypes: Type[], reportErrors: boolean): boolean {
@ -6620,15 +6624,17 @@ module ts {
return resolveErrorCall(node);
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
for (let current of candidates) {
if (!hasCorrectArity(node, args, current)) {
for (let originalCandidate of candidates) {
if (!hasCorrectArity(node, args, originalCandidate)) {
continue;
}
let originalCandidate = current;
let inferenceResult: InferenceContext;
let candidate: Signature;
let typeArgumentsAreValid: boolean;
let inferenceContext = originalCandidate.typeParameters
? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false)
: undefined;
while (true) {
candidate = originalCandidate;
if (candidate.typeParameters) {
@ -6638,9 +6644,9 @@ module ts {
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)
}
else {
inferenceResult = inferTypeArguments(candidate, args, excludeArgument);
typeArgumentsAreValid = inferenceResult.failedTypeParameterIndex < 0;
typeArgumentTypes = inferenceResult.inferredTypes;
inferTypeArguments(candidate, args, excludeArgument, inferenceContext);
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex < 0;
typeArgumentTypes = inferenceContext.inferredTypes;
}
if (!typeArgumentsAreValid) {
break;
@ -6670,7 +6676,7 @@ module ts {
else {
candidateForTypeArgumentError = originalCandidate;
if (!typeArguments) {
resultOfFailedInference = inferenceResult;
resultOfFailedInference = inferenceContext;
}
}
}

View File

@ -1485,6 +1485,8 @@ module ts {
export interface TypeInferences {
primary: Type[]; // Inferences made directly to a type parameter
secondary: Type[]; // Inferences made to a type parameter in a union type
isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec
// If a type parameter is fixed, no more inferences can be made for the type parameter
}
export interface InferenceContext {

View File

@ -1175,6 +1175,7 @@ declare module "typescript" {
interface TypeInferences {
primary: Type[];
secondary: Type[];
isFixed: boolean;
}
interface InferenceContext {
typeParameters: TypeParameter[];

View File

@ -3767,6 +3767,9 @@ declare module "typescript" {
secondary: Type[];
>secondary : Type[]
>Type : Type
isFixed: boolean;
>isFixed : boolean
}
interface InferenceContext {
>InferenceContext : InferenceContext

View File

@ -1206,6 +1206,7 @@ declare module "typescript" {
interface TypeInferences {
primary: Type[];
secondary: Type[];
isFixed: boolean;
}
interface InferenceContext {
typeParameters: TypeParameter[];

View File

@ -3913,6 +3913,9 @@ declare module "typescript" {
secondary: Type[];
>secondary : Type[]
>Type : Type
isFixed: boolean;
>isFixed : boolean
}
interface InferenceContext {
>InferenceContext : InferenceContext

View File

@ -1207,6 +1207,7 @@ declare module "typescript" {
interface TypeInferences {
primary: Type[];
secondary: Type[];
isFixed: boolean;
}
interface InferenceContext {
typeParameters: TypeParameter[];

View File

@ -3863,6 +3863,9 @@ declare module "typescript" {
secondary: Type[];
>secondary : Type[]
>Type : Type
isFixed: boolean;
>isFixed : boolean
}
interface InferenceContext {
>InferenceContext : InferenceContext

View File

@ -1244,6 +1244,7 @@ declare module "typescript" {
interface TypeInferences {
primary: Type[];
secondary: Type[];
isFixed: boolean;
}
interface InferenceContext {
typeParameters: TypeParameter[];

View File

@ -4036,6 +4036,9 @@ declare module "typescript" {
secondary: Type[];
>secondary : Type[]
>Type : Type
isFixed: boolean;
>isFixed : boolean
}
interface InferenceContext {
>InferenceContext : InferenceContext