Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ce9ddf3

Browse files
committedMar 8, 2020
Simplify mapper layout and cache in composite mappers
1 parent 50de2db commit ce9ddf3

File tree

2 files changed

+41
-48
lines changed

2 files changed

+41
-48
lines changed
 

Diff for: ‎src/compiler/checker.ts

+38-46
Original file line numberDiff line numberDiff line change
@@ -9588,8 +9588,7 @@ namespace ts {
95889588
const checkType = (<ConditionalType>type).checkType;
95899589
const constraint = getLowerBoundOfKeyType(checkType);
95909590
if (constraint !== checkType) {
9591-
const mapper = makeUnaryTypeMapper((<ConditionalType>type).root.checkType, constraint);
9592-
return getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers(mapper, (<ConditionalType>type).mapper));
9591+
return getConditionalTypeInstantiation(<ConditionalType>type, prependTypeMapping((<ConditionalType>type).root.checkType, constraint, (<ConditionalType>type).mapper));
95939592
}
95949593
}
95959594
return type;
@@ -9639,7 +9638,7 @@ namespace ts {
96399638
// Create a mapper from T to the current iteration type constituent. Then, if the
96409639
// mapped type is itself an instantiated type, combine the iteration mapper with the
96419640
// instantiation mapper.
9642-
const templateMapper = addTypeMapping(type.mapper, typeParameter, t);
9641+
const templateMapper = appendTypeMapping(type.mapper, typeParameter, t);
96439642
// If the current iteration type constituent is a string literal type, create a property.
96449643
// Otherwise, for type string create a string index signature.
96459644
if (isTypeUsableAsPropertyName(t)) {
@@ -9943,8 +9942,7 @@ namespace ts {
99439942
const simplified = getSimplifiedType(type.checkType, /*writing*/ false);
99449943
const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified;
99459944
if (constraint && constraint !== type.checkType) {
9946-
const mapper = makeUnaryTypeMapper(type.root.checkType, constraint);
9947-
const instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
9945+
const instantiated = getConditionalTypeInstantiation(type, prependTypeMapping(type.root.checkType, constraint, type.mapper));
99489946
if (!(instantiated.flags & TypeFlags.Never)) {
99499947
return instantiated;
99509948
}
@@ -10175,8 +10173,7 @@ namespace ts {
1017510173
if (typeVariable) {
1017610174
const constraint = getConstraintOfTypeParameter(typeVariable);
1017710175
if (constraint && (isArrayType(constraint) || isTupleType(constraint))) {
10178-
const mapper = makeUnaryTypeMapper(typeVariable, constraint);
10179-
return instantiateType(type, combineTypeMappers(mapper, type.mapper));
10176+
return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper));
1018010177
}
1018110178
}
1018210179
return type;
@@ -12903,7 +12900,7 @@ namespace ts {
1290312900
// types rules (i.e. proper contravariance) for inferences.
1290412901
inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
1290512902
}
12906-
combinedMapper = combineTypeMappers(mapper, context.mapper);
12903+
combinedMapper = mergeTypeMappers(mapper, context.mapper);
1290712904
}
1290812905
// Instantiate the extends type including inferences for 'infer T' type parameters
1290912906
const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
@@ -13543,37 +13540,39 @@ namespace ts {
1354313540
}
1354413541

1354513542
function createTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper {
13546-
return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) :
13547-
sources.length === 2 ? makeSimpleTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
13548-
makeArrayTypeMapper(sources, targets);
13543+
return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : makeArrayTypeMapper(sources, targets);
1354913544
}
1355013545

13551-
function getMappedType(type: Type, map: TypeMapper): Type {
13552-
switch (map.kind) {
13546+
function getMappedType(type: Type, mapper: TypeMapper): Type {
13547+
switch (mapper.kind) {
1355313548
case TypeMapKind.Simple:
13554-
return type === map.source1 ? map.target1 : type === map.source2 ? map.target2 : type;
13549+
return type === mapper.source ? mapper.target : type;
1355513550
case TypeMapKind.Array:
13556-
const sources = map.sources;
13557-
const targets = map.targets;
13551+
const sources = mapper.sources;
13552+
const targets = mapper.targets;
1355813553
for (let i = 0; i < sources.length; i++) {
1355913554
if (type === sources[i]) {
1356013555
return targets ? targets[i] : anyType;
1356113556
}
1356213557
}
1356313558
return type;
1356413559
case TypeMapKind.Function:
13565-
return map.func(type);
13560+
return mapper.func(type);
1356613561
case TypeMapKind.Composite:
13567-
return instantiateType(getMappedType(type, map.mapper1), map.mapper2);
13562+
case TypeMapKind.Merged:
13563+
if (type === mapper.cachedSource) return mapper.cachedTarget;
13564+
const t1 = getMappedType(type, mapper.mapper1);
13565+
const t2 = t1 !== type && mapper.kind === TypeMapKind.Composite ? instantiateType(t1, mapper.mapper2) : getMappedType(t1, mapper.mapper2);
13566+
if (t2 !== type) {
13567+
mapper.cachedSource = type;
13568+
mapper.cachedTarget = t2;
13569+
}
13570+
return t2;
1356813571
}
1356913572
}
1357013573

1357113574
function makeUnaryTypeMapper(source: Type, target: Type): TypeMapper {
13572-
return makeSimpleTypeMapper(source, target, anyType, anyType);
13573-
}
13574-
13575-
function makeSimpleTypeMapper(source1: Type, target1: Type, source2: Type, target2: Type): TypeMapper {
13576-
return { kind: TypeMapKind.Simple, source1, target1, source2, target2 };
13575+
return { kind: TypeMapKind.Simple, source, target };
1357713576
}
1357813577

1357913578
function makeArrayTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper {
@@ -13584,8 +13583,8 @@ namespace ts {
1358413583
return { kind: TypeMapKind.Function, func };
1358513584
}
1358613585

13587-
function makeCompositeTypeMapper(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
13588-
return { kind: TypeMapKind.Composite, mapper1, mapper2 };
13586+
function makeCompositeTypeMapper(kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
13587+
return { kind, mapper1, mapper2, cachedSource: undefined!, cachedTarget: undefined! };
1358913588
}
1359013589

1359113590
function createTypeEraser(sources: readonly TypeParameter[]): TypeMapper {
@@ -13600,27 +13599,20 @@ namespace ts {
1360013599
return makeFunctionTypeMapper(t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t);
1360113600
}
1360213601

13603-
function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper;
13604-
function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper | undefined): TypeMapper;
13605-
function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
13606-
return !mapper1 ? mapper2 : !mapper2 ? mapper1 : makeCompositeTypeMapper(mapper1, mapper2);
13602+
function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper {
13603+
return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Composite, mapper1, mapper2) : mapper2;
1360713604
}
1360813605

13609-
function addTypeMapping(mapper: TypeMapper | undefined, source: TypeParameter, target: Type) {
13610-
return mapper && mapper.kind === TypeMapKind.Simple && mapper.source2 === mapper.target2 ?
13611-
makeSimpleTypeMapper(mapper.source1, mapper.target1, source, target) :
13612-
combineTypeMappers(mapper, makeUnaryTypeMapper(source, target));
13606+
function mergeTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper {
13607+
return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Merged, mapper1, mapper2) : mapper2;
1361313608
}
1361413609

13615-
function createReplacementMapper(source: Type, target: Type, baseMapper: TypeMapper): TypeMapper {
13616-
switch (baseMapper.kind) {
13617-
case TypeMapKind.Simple:
13618-
return makeSimpleTypeMapper(baseMapper.source1, baseMapper.source1 === source ? target : baseMapper.target1,
13619-
baseMapper.source2, baseMapper.source2 === source ? target : baseMapper.target2);
13620-
case TypeMapKind.Array:
13621-
return makeArrayTypeMapper(baseMapper.sources, map(baseMapper.targets, (t, i) => baseMapper.sources[i] === source ? target : t));
13622-
}
13623-
return makeFunctionTypeMapper(t => t === source ? target : getMappedType(t, baseMapper));
13610+
function prependTypeMapping(source: Type, target: Type, mapper: TypeMapper | undefined) {
13611+
return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, makeUnaryTypeMapper(source, target), mapper);
13612+
}
13613+
13614+
function appendTypeMapping(mapper: TypeMapper | undefined, source: Type, target: Type) {
13615+
return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, mapper, makeUnaryTypeMapper(source, target));
1362413616
}
1362513617

1362613618
function getRestrictiveTypeParameter(tp: TypeParameter) {
@@ -13815,7 +13807,7 @@ namespace ts {
1381513807
if (typeVariable !== mappedTypeVariable) {
1381613808
return mapType(getReducedType(mappedTypeVariable), t => {
1381713809
if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && t !== errorType) {
13818-
const replacementMapper = createReplacementMapper(typeVariable, t, mapper);
13810+
const replacementMapper = prependTypeMapping(typeVariable, t, mapper);
1381913811
return isArrayType(t) ? instantiateMappedArrayType(t, type, replacementMapper) :
1382013812
isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
1382113813
instantiateAnonymousType(type, replacementMapper);
@@ -13851,7 +13843,7 @@ namespace ts {
1385113843
}
1385213844

1385313845
function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
13854-
const templateMapper = addTypeMapping(mapper, getTypeParameterFromMappedType(type), key);
13846+
const templateMapper = appendTypeMapping(mapper, getTypeParameterFromMappedType(type), key);
1385513847
const propType = instantiateType(getTemplateTypeFromMappedType(<MappedType>type.target || type), templateMapper);
1385613848
const modifiers = getMappedTypeModifiers(type);
1385713849
return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
@@ -13904,7 +13896,7 @@ namespace ts {
1390413896
const checkType = <TypeParameter>root.checkType;
1390513897
const instantiatedType = getMappedType(checkType, mapper);
1390613898
if (checkType !== instantiatedType && instantiatedType.flags & (TypeFlags.Union | TypeFlags.Never)) {
13907-
return mapType(instantiatedType, t => getConditionalType(root, createReplacementMapper(checkType, t, mapper)));
13899+
return mapType(instantiatedType, t => getConditionalType(root, prependTypeMapping(checkType, t, mapper)));
1390813900
}
1390913901
}
1391013902
return getConditionalType(root, mapper);
@@ -18743,7 +18735,7 @@ namespace ts {
1874318735
if (defaultType) {
1874418736
// Instantiate the default type. Any forward reference to a type
1874518737
// parameter should be instantiated to the empty object type.
18746-
inferredType = instantiateType(defaultType, combineTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper));
18738+
inferredType = instantiateType(defaultType, mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper));
1874718739
}
1874818740
}
1874918741
}

Diff for: ‎src/compiler/types.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -4880,14 +4880,15 @@ namespace ts {
48804880
Array,
48814881
Function,
48824882
Composite,
4883+
Merged,
48834884
}
48844885

48854886
/* @internal */
48864887
export type TypeMapper =
4887-
| { kind: TypeMapKind.Simple, source1: Type, target1: Type, source2: Type, target2: Type }
4888+
| { kind: TypeMapKind.Simple, source: Type, target: Type }
48884889
| { kind: TypeMapKind.Array, sources: readonly Type[], targets: readonly Type[] | undefined }
48894890
| { kind: TypeMapKind.Function, func: (t: Type) => Type }
4890-
| { kind: TypeMapKind.Composite, mapper1: TypeMapper, mapper2: TypeMapper };
4891+
| { kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper, cachedSource: Type, cachedTarget: Type };
48914892

48924893
export const enum InferencePriority {
48934894
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type

0 commit comments

Comments
 (0)
Please sign in to comment.