Skip to content

Commit 15232fe

Browse files
committed
Remove circular default check
1 parent fd228a9 commit 15232fe

File tree

10 files changed

+5295
-1211
lines changed

10 files changed

+5295
-1211
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ namespace ts {
375375
ResolvedBaseConstructorType,
376376
DeclaredType,
377377
ResolvedReturnType,
378-
ResolvedDefault
379378
}
380379

381380
const builtinGlobals = createMap<Symbol>();
@@ -2651,7 +2650,7 @@ namespace ts {
26512650
writeSpace(writer);
26522651
buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, symbolStack);
26532652
}
2654-
const defaultType = getDefaultOfTypeParameter(tp);
2653+
const defaultType = getDefaultFromTypeParameter(tp);
26552654
if (defaultType) {
26562655
writeSpace(writer);
26572656
writePunctuation(writer, SyntaxKind.EqualsToken);
@@ -3054,9 +3053,6 @@ namespace ts {
30543053
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
30553054
return (<Signature>target).resolvedReturnType;
30563055
}
3057-
if (propertyName === TypeSystemPropertyName.ResolvedDefault) {
3058-
return (<TypeVariable>target).resolvedDefault;
3059-
}
30603056

30613057
Debug.fail("Unhandled TypeSystemPropertyName " + propertyName);
30623058
}
@@ -4863,69 +4859,6 @@ namespace ts {
48634859
return typeParameter.default === noConstraintOrDefaultType ? undefined : typeParameter.default;
48644860
}
48654861

4866-
/**
4867-
* Gets the default type for a type parameter.
4868-
*
4869-
* If the type parameter is the result of an instantiation, this gets the instantiated
4870-
* default type of its target. If the type parameter has no default type, or if the default
4871-
* type circularly references the type parameter, `undefined` is returned.
4872-
*
4873-
* This function *does* perform a circularity check.
4874-
*/
4875-
function getDefaultOfTypeParameter(typeParameter: TypeParameter): Type | undefined {
4876-
return hasNonCircularDefault(typeParameter) ? getDefaultFromTypeParameter(typeParameter) : undefined;
4877-
}
4878-
4879-
/**
4880-
* Determines whether a type parameter has a non-circular default type.
4881-
*
4882-
* Note that this function also returns `true` if a type parameter *does not* have a
4883-
* default type.
4884-
*/
4885-
function hasNonCircularDefault(typeParameter: TypeParameter): boolean {
4886-
return getResolvedDefault(typeParameter) !== circularConstraintOrDefaultType;
4887-
}
4888-
4889-
/**
4890-
* Resolves the default type of a type parameter.
4891-
*
4892-
* If the type parameter has no default, the `noConstraintOrDefaultType` singleton is
4893-
* returned. If the type parameter has a circular default, the
4894-
* `circularConstraintOrDefaultType` singleton is returned.
4895-
*/
4896-
function getResolvedDefault(typeParameter: TypeParameter): Type {
4897-
if (!typeParameter.resolvedDefault) {
4898-
if (!pushTypeResolution(typeParameter, TypeSystemPropertyName.ResolvedDefault)) {
4899-
return circularConstraintOrDefaultType;
4900-
}
4901-
const defaultType = getDefaultFromTypeParameter(typeParameter);
4902-
const type = defaultType && getResolvedDefaultWorker(defaultType);
4903-
if (!popTypeResolution()) {
4904-
return typeParameter.resolvedDefault = circularConstraintOrDefaultType;
4905-
}
4906-
typeParameter.resolvedDefault = type || noConstraintOrDefaultType;
4907-
}
4908-
return typeParameter.resolvedDefault;
4909-
}
4910-
4911-
/**
4912-
* Recursively resolves the default type for a type.
4913-
*
4914-
* If the type is a union or intersection type and any of its constituents is a circular
4915-
* reference, the `circularConstraintOrDefaultType` singleton is returned.
4916-
*/
4917-
function getResolvedDefaultWorker(type: Type): Type {
4918-
if (type.flags & TypeFlags.TypeParameter) {
4919-
return getResolvedDefault(<TypeParameter>type);
4920-
}
4921-
if (type.flags & TypeFlags.UnionOrIntersection) {
4922-
const types = map((<UnionOrIntersectionType>type).types, getResolvedDefaultWorker);
4923-
return some(types, x => x === circularConstraintOrDefaultType) ? circularConstraintOrDefaultType :
4924-
type.flags & TypeFlags.Union ? getUnionType(types) : getIntersectionType(types);
4925-
}
4926-
return type;
4927-
}
4928-
49294862
/**
49304863
* For a type parameter, return the base constraint of the type parameter. For the string, number,
49314864
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
@@ -5241,20 +5174,23 @@ namespace ts {
52415174
typeArguments = [];
52425175
}
52435176

5244-
// Map an unsatisfied type parameter with a default type to the default type.
5177+
// Map an unsatisfied type parameter with a default type.
52455178
// If a type parameter does not have a default type, or if the default type
5246-
// is a circular reference, the empty object type is used.
5179+
// is a forward reference, the empty object type is used.
52475180
const mapper: TypeMapper = t => {
52485181
const i = indexOf(typeParameters, t);
5249-
return i >= 0
5250-
? typeArguments[i] || (typeArguments[i] =
5251-
instantiateType(getDefaultOfTypeParameter(typeParameters[i]), mapper) ||
5252-
emptyObjectType)
5253-
: t;
5182+
if (i >= typeArguments.length) {
5183+
return emptyObjectType;
5184+
}
5185+
if (i >= 0) {
5186+
return typeArguments[i];
5187+
}
5188+
return t;
52545189
};
52555190

52565191
for (let i = numTypeArguments; i < numTypeParameters; i++) {
5257-
instantiateType(typeParameters[i], mapper);
5192+
const defaultType = getDefaultFromTypeParameter(typeParameters[i]);
5193+
typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : emptyObjectType;
52585194
}
52595195
}
52605196
}
@@ -9181,8 +9117,16 @@ namespace ts {
91819117
// succeeds, meaning there is no error for not having inference candidates. An
91829118
// inference error only occurs when there are *conflicting* candidates, i.e.
91839119
// candidates with no common supertype.
9184-
const defaultType = getDefaultOfTypeParameter(context.signature.typeParameters[index]);
9185-
inferredType = defaultType ? instantiateType(defaultType, getInferenceMapper(context)) : emptyObjectType;
9120+
const defaultType = getDefaultFromTypeParameter(context.signature.typeParameters[index]);
9121+
if (defaultType) {
9122+
const backreferenceMapper: TypeMapper = t => indexOf(context.signature.typeParameters, t) >= index ? emptyObjectType : t;
9123+
const mapper = combineTypeMappers(backreferenceMapper, getInferenceMapper(context));
9124+
inferredType = instantiateType(defaultType, mapper);
9125+
}
9126+
else {
9127+
inferredType = emptyObjectType;
9128+
}
9129+
91869130
inferenceSucceeded = true;
91879131
}
91889132
context.inferredTypes[index] = inferredType;
@@ -15574,11 +15518,8 @@ namespace ts {
1557415518
if (!hasNonCircularBaseConstraint(typeParameter)) {
1557515519
error(node.constraint, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter));
1557615520
}
15577-
if (!hasNonCircularDefault(typeParameter)) {
15578-
error(node.default, Diagnostics.Type_parameter_0_has_a_circular_default, typeToString(typeParameter));
15579-
}
1558015521
const constraintType = getConstraintOfTypeParameter(typeParameter);
15581-
const defaultType = getDefaultOfTypeParameter(typeParameter);
15522+
const defaultType = getDefaultFromTypeParameter(typeParameter);
1558215523
if (constraintType && defaultType) {
1558315524
checkTypeAssignableTo(defaultType, getTypeWithThisArgument(constraintType, defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
1558415525
}

src/compiler/diagnosticMessages.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,11 +2043,7 @@
20432043
"category": "Error",
20442044
"code": 2705
20452045
},
2046-
"Type parameter '{0}' has a circular default.": {
2047-
"category": "Error",
2048-
"code": 2706
2049-
},
2050-
"Generic type '{0}' requires between {1} and {2} type arguments.": {
2046+
"Generic type '{0}' requires between {1} and {2} type arguments.": {
20512047
"category": "Error",
20522048
"code": 2707
20532049
},

src/compiler/types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2990,8 +2990,6 @@ namespace ts {
29902990
/* @internal */
29912991
resolvedBaseConstraint: Type;
29922992
/* @internal */
2993-
resolvedDefault: Type;
2994-
/* @internal */
29952993
resolvedIndexType: IndexType;
29962994
}
29972995

0 commit comments

Comments
 (0)