Skip to content

Commit 6443552

Browse files
authored
Merge pull request #25936 from Microsoft/port25913
Port #25913
2 parents e94910f + 2da65c2 commit 6443552

11 files changed

+109
-83
lines changed

src/compiler/checker.ts

Lines changed: 40 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ namespace ts {
250250
getTypeOfSymbol,
251251
getResolvedSymbol,
252252
getIndexTypeOfStructuredType,
253-
getConstraintFromTypeParameter,
253+
getConstraintOfTypeParameter,
254254
getFirstIdentifier,
255255
),
256256
getAmbientModules,
@@ -3715,7 +3715,7 @@ namespace ts {
37153715
return createTypeParameterDeclaration(name, constraintNode, defaultParameterNode);
37163716
}
37173717

3718-
function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintFromTypeParameter(type)): TypeParameterDeclaration {
3718+
function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintOfTypeParameter(type)): TypeParameterDeclaration {
37193719
const constraintNode = constraint && typeToTypeNodeHelper(constraint, context);
37203720
return typeParameterToDeclarationWithConstraint(type, context, constraintNode);
37213721
}
@@ -4363,29 +4363,23 @@ namespace ts {
43634363
return i;
43644364
}
43654365
}
4366-
43674366
return -1;
43684367
}
43694368

43704369
function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
4371-
if (propertyName === TypeSystemPropertyName.Type) {
4372-
return !!getSymbolLinks(<Symbol>target).type;
4373-
}
4374-
if (propertyName === TypeSystemPropertyName.DeclaredType) {
4375-
return !!getSymbolLinks(<Symbol>target).declaredType;
4376-
}
4377-
if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) {
4378-
return !!(<InterfaceType>target).resolvedBaseConstructorType;
4370+
switch (propertyName) {
4371+
case TypeSystemPropertyName.Type:
4372+
return !!getSymbolLinks(<Symbol>target).type;
4373+
case TypeSystemPropertyName.DeclaredType:
4374+
return !!getSymbolLinks(<Symbol>target).declaredType;
4375+
case TypeSystemPropertyName.ResolvedBaseConstructorType:
4376+
return !!(<InterfaceType>target).resolvedBaseConstructorType;
4377+
case TypeSystemPropertyName.ResolvedReturnType:
4378+
return !!(<Signature>target).resolvedReturnType;
4379+
case TypeSystemPropertyName.ImmediateBaseConstraint:
4380+
return !!(<Type>target).immediateBaseConstraint;
43794381
}
4380-
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
4381-
return !!(<Signature>target).resolvedReturnType;
4382-
}
4383-
if (propertyName === TypeSystemPropertyName.ImmediateBaseConstraint) {
4384-
const bc = (<Type>target).immediateBaseConstraint;
4385-
return !!bc && bc !== circularConstraintType;
4386-
}
4387-
4388-
return Debug.fail("Unhandled TypeSystemPropertyName " + propertyName);
4382+
return Debug.assertNever(propertyName);
43894383
}
43904384

43914385
// Pop an entry from the type resolution stack and return its associated result value. The result value will
@@ -6936,21 +6930,12 @@ namespace ts {
69366930
return undefined;
69376931
}
69386932

6939-
function getBaseConstraintOfInstantiableNonPrimitiveUnionOrIntersection(type: Type) {
6933+
function getBaseConstraintOfType(type: Type): Type | undefined {
69406934
if (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection)) {
69416935
const constraint = getResolvedBaseConstraint(<InstantiableType | UnionOrIntersectionType>type);
6942-
if (constraint !== noConstraintType && constraint !== circularConstraintType) {
6943-
return constraint;
6944-
}
6945-
}
6946-
}
6947-
6948-
function getBaseConstraintOfType(type: Type): Type | undefined {
6949-
const constraint = getBaseConstraintOfInstantiableNonPrimitiveUnionOrIntersection(type);
6950-
if (!constraint && type.flags & TypeFlags.Index) {
6951-
return keyofConstraintType;
6936+
return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined;
69526937
}
6953-
return constraint;
6938+
return type.flags & TypeFlags.Index ? keyofConstraintType : undefined;
69546939
}
69556940

69566941
/**
@@ -6971,30 +6956,26 @@ namespace ts {
69716956
* circularly references the type variable.
69726957
*/
69736958
function getResolvedBaseConstraint(type: InstantiableType | UnionOrIntersectionType): Type {
6974-
let circular: boolean | undefined;
6975-
if (!type.resolvedBaseConstraint) {
6976-
const constraint = getBaseConstraint(type);
6977-
type.resolvedBaseConstraint = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type);
6959+
return type.resolvedBaseConstraint ||
6960+
(type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), type));
6961+
6962+
function getImmediateBaseConstraint(t: Type): Type {
6963+
if (!t.immediateBaseConstraint) {
6964+
if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) {
6965+
return circularConstraintType;
6966+
}
6967+
let result = computeBaseConstraint(getSimplifiedType(t));
6968+
if (!popTypeResolution()) {
6969+
result = circularConstraintType;
6970+
}
6971+
t.immediateBaseConstraint = result || noConstraintType;
6972+
}
6973+
return t.immediateBaseConstraint;
69786974
}
6979-
return type.resolvedBaseConstraint;
69806975

69816976
function getBaseConstraint(t: Type): Type | undefined {
6982-
if (t.immediateBaseConstraint) {
6983-
return t.immediateBaseConstraint === noConstraintType ? undefined : t.immediateBaseConstraint;
6984-
}
6985-
if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) {
6986-
circular = true;
6987-
t.immediateBaseConstraint = circularConstraintType;
6988-
return undefined;
6989-
}
6990-
const result = computeBaseConstraint(getSimplifiedType(t));
6991-
if (!popTypeResolution()) {
6992-
circular = true;
6993-
t.immediateBaseConstraint = circularConstraintType;
6994-
return undefined;
6995-
}
6996-
t.immediateBaseConstraint = !result ? noConstraintType : result;
6997-
return result;
6977+
const c = getImmediateBaseConstraint(t);
6978+
return c !== noConstraintType && c !== circularConstraintType ? c : undefined;
69986979
}
69996980

70006981
function computeBaseConstraint(t: Type): Type | undefined {
@@ -7877,6 +7858,7 @@ namespace ts {
78777858
return inferences && getIntersectionType(inferences);
78787859
}
78797860

7861+
/** This is a worker function. Use getConstraintOfTypeParameter which guards against circular constraints. */
78807862
function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type | undefined {
78817863
if (!typeParameter.constraint) {
78827864
if (typeParameter.target) {
@@ -9145,7 +9127,7 @@ namespace ts {
91459127
return type.simplified = substituteIndexedMappedType(objectType, type);
91469128
}
91479129
if (objectType.flags & TypeFlags.TypeParameter) {
9148-
const constraint = getConstraintFromTypeParameter(objectType as TypeParameter);
9130+
const constraint = getConstraintOfTypeParameter(objectType as TypeParameter);
91499131
if (constraint && isGenericMappedType(constraint)) {
91509132
return type.simplified = substituteIndexedMappedType(constraint, type);
91519133
}
@@ -12092,7 +12074,7 @@ namespace ts {
1209212074
}
1209312075

1209412076
function isUnconstrainedTypeParameter(type: Type) {
12095-
return type.flags & TypeFlags.TypeParameter && !getConstraintFromTypeParameter(<TypeParameter>type);
12077+
return type.flags & TypeFlags.TypeParameter && !getConstraintOfTypeParameter(<TypeParameter>type);
1209612078
}
1209712079

1209812080
function isTypeReferenceWithGenericArguments(type: Type): boolean {
@@ -17620,7 +17602,7 @@ namespace ts {
1762017602
}
1762117603

1762217604
const thisType = getTypeFromTypeNode(thisParameter.type);
17623-
enclosingClass = ((thisType.flags & TypeFlags.TypeParameter) ? getConstraintFromTypeParameter(<TypeParameter>thisType) : thisType) as InterfaceType;
17605+
enclosingClass = ((thisType.flags & TypeFlags.TypeParameter) ? getConstraintOfTypeParameter(<TypeParameter>thisType) : thisType) as InterfaceType;
1762417606
}
1762517607
// No further restrictions for static properties
1762617608
if (flags & ModifierFlags.Static) {
@@ -19261,7 +19243,7 @@ namespace ts {
1926119243
typeArguments.pop();
1926219244
}
1926319245
while (typeArguments.length < typeParameters.length) {
19264-
typeArguments.push(getConstraintFromTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node)));
19246+
typeArguments.push(getConstraintOfTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node)));
1926519247
}
1926619248
const instantiated = createSignatureInstantiation(candidate, typeArguments);
1926719249
candidates[bestIndex] = instantiated;
@@ -25164,7 +25146,7 @@ namespace ts {
2516425146
// If the type parameter node does not have an identical constraint as the resolved
2516525147
// type parameter at this position, we report an error.
2516625148
const sourceConstraint = source.constraint && getTypeFromTypeNode(source.constraint);
25167-
const targetConstraint = getConstraintFromTypeParameter(target);
25149+
const targetConstraint = getConstraintOfTypeParameter(target);
2516825150
if (sourceConstraint) {
2516925151
// relax check if later interface augmentation has no constraint
2517025152
if (!targetConstraint || !isTypeIdenticalTo(sourceConstraint, targetConstraint)) {

src/compiler/symbolWalker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace ts {
99
getTypeOfSymbol: (sym: Symbol) => Type,
1010
getResolvedSymbol: (node: Node) => Symbol,
1111
getIndexTypeOfStructuredType: (type: Type, kind: IndexKind) => Type | undefined,
12-
getConstraintFromTypeParameter: (typeParameter: TypeParameter) => Type | undefined,
12+
getConstraintOfTypeParameter: (typeParameter: TypeParameter) => Type | undefined,
1313
getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier) {
1414

1515
return getSymbolWalker;
@@ -93,7 +93,7 @@ namespace ts {
9393
}
9494

9595
function visitTypeParameter(type: TypeParameter): void {
96-
visitType(getConstraintFromTypeParameter(type));
96+
visitType(getConstraintOfTypeParameter(type));
9797
}
9898

9999
function visitUnionOrIntersectionType(type: UnionOrIntersectionType): void {

tests/baselines/reference/circularIndexedAccessErrors.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ interface Foo {
8686
}
8787

8888
function foo<T extends Foo | T["hello"]>() {
89-
>foo : <T extends Foo | T["hello"]>() => void
89+
>foo : <T>() => void
9090
>T : T
9191
>Foo : Foo
9292
>T : T

tests/baselines/reference/incorrectRecursiveMappedTypeConstraint.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
=== tests/cases/compiler/incorrectRecursiveMappedTypeConstraint.ts ===
22
// #17847
33
function sum<T extends { [P in T]: number }, K extends keyof T>(n: number, v: T, k: K) {
4-
>sum : <T extends { [x: string]: number; }, K extends keyof T>(n: number, v: T, k: K) => void
4+
>sum : <T, K extends keyof T>(n: number, v: T, k: K) => void
55
>T : T
66
>P : P
77
>T : T

tests/baselines/reference/typeParameterDirectlyConstrainedToItself.types

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ interface I2<T, U extends U> { }
2424
>U : U
2525

2626
function f<T extends T>() { }
27-
>f : <T extends T>() => void
27+
>f : <T>() => void
2828
>T : T
2929
>T : T
3030

3131
function f2<T, U extends U>() { }
32-
>f2 : <T, U extends U>() => void
32+
>f2 : <T, U>() => void
3333
>T : T
3434
>U : U
3535
>U : U
3636

3737
var a: {
38-
>a : { <T extends T>(): void; <T, U extends U>(): void; }
38+
>a : { <T>(): void; <T, U>(): void; }
3939

4040
<T extends T>(): void;
4141
>T : T
@@ -48,14 +48,14 @@ var a: {
4848
}
4949

5050
var b = <T extends T>() => { }
51-
>b : <T extends T>() => void
52-
><T extends T>() => { } : <T extends T>() => void
51+
>b : <T>() => void
52+
><T extends T>() => { } : <T>() => void
5353
>T : T
5454
>T : T
5555

5656
var b2 = <T, U extends U>() => { }
57-
>b2 : <T, U extends U>() => void
58-
><T, U extends U>() => { } : <T, U extends U>() => void
57+
>b2 : <T, U>() => void
58+
><T, U extends U>() => { } : <T, U>() => void
5959
>T : T
6060
>U : U
6161
>U : U

tests/baselines/reference/typeParameterHasSelfAsConstraint.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/compiler/typeParameterHasSelfAsConstraint.ts ===
22
function foo<T extends T>(x: T): number {
3-
>foo : <T extends T>(x: T) => number
3+
>foo : <T>(x: T) => number
44
>T : T
55
>T : T
66
>x : T

tests/baselines/reference/typeParameterIndirectlyConstrainedToItself.errors.txt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterInd
2323
tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts(16,21): error TS2313: Type parameter 'T' has a circular constraint.
2424
tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts(16,34): error TS2313: Type parameter 'U' has a circular constraint.
2525
tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts(16,47): error TS2313: Type parameter 'V' has a circular constraint.
26-
tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts(18,19): error TS2313: Type parameter 'U' has a circular constraint.
2726
tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts(18,32): error TS2313: Type parameter 'T' has a circular constraint.
2827
tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts(18,45): error TS2313: Type parameter 'V' has a circular constraint.
28+
tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts(23,24): error TS2313: Type parameter 'S' has a circular constraint.
2929

3030

3131
==== tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterIndirectlyConstrainedToItself.ts (28 errors) ====
@@ -97,9 +97,15 @@ tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterInd
9797
!!! error TS2313: Type parameter 'V' has a circular constraint.
9898

9999
class D<U extends T, T extends V, V extends T> { }
100-
~
101-
!!! error TS2313: Type parameter 'U' has a circular constraint.
102100
~
103101
!!! error TS2313: Type parameter 'T' has a circular constraint.
104102
~
105-
!!! error TS2313: Type parameter 'V' has a circular constraint.
103+
!!! error TS2313: Type parameter 'V' has a circular constraint.
104+
105+
// Repro from #25740
106+
107+
type Foo<T> = [T] extends [number] ? {} : {};
108+
function foo<S extends Foo<S>>() {}
109+
~~~~~~
110+
!!! error TS2313: Type parameter 'S' has a circular constraint.
111+

tests/baselines/reference/typeParameterIndirectlyConstrainedToItself.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ var a: {
1616
var b = <U extends T, T extends U>() => { }
1717
var b2 = <T extends U, U extends V, V extends T>() => { }
1818

19-
class D<U extends T, T extends V, V extends T> { }
19+
class D<U extends T, T extends V, V extends T> { }
20+
21+
// Repro from #25740
22+
23+
type Foo<T> = [T] extends [number] ? {} : {};
24+
function foo<S extends Foo<S>>() {}
25+
2026

2127
//// [typeParameterIndirectlyConstrainedToItself.js]
2228
var C = /** @class */ (function () {
@@ -39,3 +45,4 @@ var D = /** @class */ (function () {
3945
}
4046
return D;
4147
}());
48+
function foo() { }

tests/baselines/reference/typeParameterIndirectlyConstrainedToItself.symbols

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,16 @@ class D<U extends T, T extends V, V extends T> { }
9090
>V : Symbol(V, Decl(typeParameterIndirectlyConstrainedToItself.ts, 17, 33))
9191
>T : Symbol(T, Decl(typeParameterIndirectlyConstrainedToItself.ts, 17, 20))
9292

93+
// Repro from #25740
94+
95+
type Foo<T> = [T] extends [number] ? {} : {};
96+
>Foo : Symbol(Foo, Decl(typeParameterIndirectlyConstrainedToItself.ts, 17, 50))
97+
>T : Symbol(T, Decl(typeParameterIndirectlyConstrainedToItself.ts, 21, 9))
98+
>T : Symbol(T, Decl(typeParameterIndirectlyConstrainedToItself.ts, 21, 9))
99+
100+
function foo<S extends Foo<S>>() {}
101+
>foo : Symbol(foo, Decl(typeParameterIndirectlyConstrainedToItself.ts, 21, 45))
102+
>S : Symbol(S, Decl(typeParameterIndirectlyConstrainedToItself.ts, 22, 13))
103+
>Foo : Symbol(Foo, Decl(typeParameterIndirectlyConstrainedToItself.ts, 17, 50))
104+
>S : Symbol(S, Decl(typeParameterIndirectlyConstrainedToItself.ts, 22, 13))
105+

0 commit comments

Comments
 (0)