Skip to content

Commit 0617c4a

Browse files
committed
Unification of higher order polymorphic functions - initial version
1 parent f79fca7 commit 0617c4a

File tree

1 file changed

+39
-3
lines changed

1 file changed

+39
-3
lines changed

src/compiler/checker.ts

+39-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ namespace ts {
2727
return symbol.id;
2828
}
2929

30+
declare let gTypeToString: (type: Type) => string;
31+
3032
export function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker {
3133
// Cancellation that controls whether or not we can cancel in the middle of type checking.
3234
// In general cancelling is *not* safe for the type checker. We might be in the middle of
@@ -45,6 +47,8 @@ namespace ts {
4547
const Type = objectAllocator.getTypeConstructor();
4648
const Signature = objectAllocator.getSignatureConstructor();
4749

50+
gTypeToString = typeToString;
51+
4852
let typeCount = 0;
4953
let symbolCount = 0;
5054

@@ -6437,6 +6441,10 @@ namespace ts {
64376441
return context.mapper;
64386442
}
64396443

6444+
function identity<T>(x: T): T {
6445+
return x;
6446+
}
6447+
64406448
function identityMapper(type: Type): Type {
64416449
return type;
64426450
}
@@ -6487,10 +6495,22 @@ namespace ts {
64876495
if (signature.typePredicate) {
64886496
freshTypePredicate = cloneTypePredicate(signature.typePredicate, mapper);
64896497
}
6498+
const returnType = instantiateType(signature.resolvedReturnType, mapper);
6499+
const callSignature = returnType && getSingleCallSignature(returnType);
6500+
if (callSignature && !callSignature.typeParameters && hasFreeTypeVars(callSignature)) {
6501+
// this is an inferred signature
6502+
const paramTypes = map(callSignature.parameters, getTypeOfSymbol);
6503+
if (!contains(paramTypes, callSignature.resolvedReturnType)) {
6504+
paramTypes.push(callSignature.resolvedReturnType);
6505+
}
6506+
const typeParams = <TypeParameter[]>filter(paramTypes, type => !!(type.flags & TypeFlags.TypeParameter));
6507+
Debug.assert(!!typeParams.length);
6508+
callSignature.typeParameters = typeParams;
6509+
}
64906510
const result = createSignature(signature.declaration, freshTypeParameters,
64916511
signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper),
64926512
instantiateList(signature.parameters, mapper, instantiateSymbol),
6493-
instantiateType(signature.resolvedReturnType, mapper),
6513+
returnType,
64946514
freshTypePredicate,
64956515
signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes);
64966516
result.target = signature;
@@ -8750,7 +8770,14 @@ namespace ts {
87508770
const targetLen = targetSignatures.length;
87518771
const len = sourceLen < targetLen ? sourceLen : targetLen;
87528772
for (let i = 0; i < len; i++) {
8753-
inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]));
8773+
const sourceSignature = sourceSignatures[sourceLen - len + i];
8774+
const targetSignature = targetSignatures[targetLen - len + i];
8775+
8776+
const mapper = isPolymorphicSignature(sourceSignature) && isPolymorphicSignature(targetSignature)
8777+
? identity
8778+
: getErasedSignature;
8779+
8780+
inferFromSignature(mapper(sourceSignature), mapper(targetSignature));
87548781
}
87558782
}
87568783

@@ -15043,7 +15070,7 @@ namespace ts {
1504315070
const contextualType = getApparentTypeOfContextualType(<Expression>node);
1504415071
if (contextualType) {
1504515072
const contextualSignature = getSingleCallSignature(contextualType);
15046-
if (contextualSignature && !contextualSignature.typeParameters) {
15073+
if (contextualSignature && !isPolymorphicSignature(contextualSignature)) {
1504715074
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
1504815075
}
1504915076
}
@@ -15053,6 +15080,15 @@ namespace ts {
1505315080
return type;
1505415081
}
1505515082

15083+
function isPolymorphicSignature(signature: Signature | undefined) {
15084+
return signature && (signature.typeParameters || hasFreeTypeVars(signature));
15085+
}
15086+
15087+
function hasFreeTypeVars(signature: Signature) {
15088+
return signature.resolvedReturnType && signature.resolvedReturnType.flags & TypeFlags.TypeParameter
15089+
|| forEach(signature.parameters, (symb) => getTypeOfSymbol(symb).flags & TypeFlags.TypeParameter);
15090+
}
15091+
1505615092
// Returns the type of an expression. Unlike checkExpression, this function is simply concerned
1505715093
// with computing the type and may not fully check all contained sub-expressions for errors.
1505815094
function getTypeOfExpression(node: Expression) {

0 commit comments

Comments
 (0)