mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Add circularity checking during deferred type argument creation (#34791)
This commit is contained in:
parent
8b7664ae15
commit
5e0fbc677a
@ -163,6 +163,7 @@ namespace ts {
|
||||
ImmediateBaseConstraint,
|
||||
EnumTagType,
|
||||
JSDocTypeReference,
|
||||
ResolvedTypeArguments,
|
||||
}
|
||||
|
||||
const enum CheckMode {
|
||||
@ -6560,6 +6561,8 @@ namespace ts {
|
||||
return !!(<Type>target).immediateBaseConstraint;
|
||||
case TypeSystemPropertyName.JSDocTypeReference:
|
||||
return !!getSymbolLinks(target as Symbol).resolvedJSDocType;
|
||||
case TypeSystemPropertyName.ResolvedTypeArguments:
|
||||
return !!(target as TypeReference).resolvedTypeArguments;
|
||||
}
|
||||
return Debug.assertNever(propertyName);
|
||||
}
|
||||
@ -10650,12 +10653,28 @@ namespace ts {
|
||||
|
||||
function getTypeArguments(type: TypeReference): readonly Type[] {
|
||||
if (!type.resolvedTypeArguments) {
|
||||
if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedTypeArguments)) {
|
||||
return type.target.localTypeParameters?.map(() => errorType) || emptyArray;
|
||||
}
|
||||
const node = type.node;
|
||||
const typeArguments = !node ? emptyArray :
|
||||
node.kind === SyntaxKind.TypeReference ? concatenate(type.target.outerTypeParameters, getEffectiveTypeArguments(node, type.target.localTypeParameters!)) :
|
||||
node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] :
|
||||
map(node.elementTypes, getTypeFromTypeNode);
|
||||
type.resolvedTypeArguments = type.mapper ? instantiateTypes(typeArguments, type.mapper) : typeArguments;
|
||||
if (popTypeResolution()) {
|
||||
type.resolvedTypeArguments = type.mapper ? instantiateTypes(typeArguments, type.mapper) : typeArguments;
|
||||
}
|
||||
else {
|
||||
type.resolvedTypeArguments = type.target.localTypeParameters?.map(() => errorType) || emptyArray;
|
||||
error(
|
||||
type.node || currentNode,
|
||||
type.target.symbol
|
||||
? Diagnostics.Type_arguments_for_0_circularly_reference_themselves
|
||||
: Diagnostics.Tuple_type_arguments_circularly_reference_themselves
|
||||
,
|
||||
type.target.symbol && symbolToString(type.target.symbol)
|
||||
);
|
||||
}
|
||||
}
|
||||
return type.resolvedTypeArguments;
|
||||
}
|
||||
|
||||
@ -3136,6 +3136,14 @@
|
||||
"category": "Error",
|
||||
"code": 4108
|
||||
},
|
||||
"Type arguments for '{0}' circularly reference themselves.": {
|
||||
"category": "Error",
|
||||
"code": 4109
|
||||
},
|
||||
"Tuple type arguments circularly reference themselves.": {
|
||||
"category": "Error",
|
||||
"code": 4110
|
||||
},
|
||||
|
||||
"The current host does not support the '{0}' option.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
tests/cases/compiler/circularlyReferentialInterfaceAccessNoCrash.ts(1,12): error TS4109: Type arguments for 'Mx' circularly reference themselves.
|
||||
tests/cases/compiler/circularlyReferentialInterfaceAccessNoCrash.ts(8,16): error TS4109: Type arguments for 'Array' circularly reference themselves.
|
||||
tests/cases/compiler/circularlyReferentialInterfaceAccessNoCrash.ts(10,18): error TS4110: Tuple type arguments circularly reference themselves.
|
||||
|
||||
|
||||
==== tests/cases/compiler/circularlyReferentialInterfaceAccessNoCrash.ts (3 errors) ====
|
||||
type Mxs = Mx<'list', Mxs['p1']>;
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS4109: Type arguments for 'Mx' circularly reference themselves.
|
||||
|
||||
interface Mx<T, K> {
|
||||
p1: T;
|
||||
p2: K;
|
||||
}
|
||||
|
||||
type ArrElem = ['list', ArrElem[number][0]][];
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS4109: Type arguments for 'Array' circularly reference themselves.
|
||||
|
||||
type TupleElem = [['list', TupleElem[0][0]]];
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS4110: Tuple type arguments circularly reference themselves.
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
//// [circularlyReferentialInterfaceAccessNoCrash.ts]
|
||||
type Mxs = Mx<'list', Mxs['p1']>;
|
||||
|
||||
interface Mx<T, K> {
|
||||
p1: T;
|
||||
p2: K;
|
||||
}
|
||||
|
||||
type ArrElem = ['list', ArrElem[number][0]][];
|
||||
|
||||
type TupleElem = [['list', TupleElem[0][0]]];
|
||||
|
||||
|
||||
//// [circularlyReferentialInterfaceAccessNoCrash.js]
|
||||
@ -0,0 +1,28 @@
|
||||
=== tests/cases/compiler/circularlyReferentialInterfaceAccessNoCrash.ts ===
|
||||
type Mxs = Mx<'list', Mxs['p1']>;
|
||||
>Mxs : Symbol(Mxs, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 0, 0))
|
||||
>Mx : Symbol(Mx, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 0, 33))
|
||||
>Mxs : Symbol(Mxs, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 0, 0))
|
||||
|
||||
interface Mx<T, K> {
|
||||
>Mx : Symbol(Mx, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 0, 33))
|
||||
>T : Symbol(T, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 2, 13))
|
||||
>K : Symbol(K, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 2, 15))
|
||||
|
||||
p1: T;
|
||||
>p1 : Symbol(Mx.p1, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 2, 20))
|
||||
>T : Symbol(T, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 2, 13))
|
||||
|
||||
p2: K;
|
||||
>p2 : Symbol(Mx.p2, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 3, 8))
|
||||
>K : Symbol(K, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 2, 15))
|
||||
}
|
||||
|
||||
type ArrElem = ['list', ArrElem[number][0]][];
|
||||
>ArrElem : Symbol(ArrElem, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 5, 1))
|
||||
>ArrElem : Symbol(ArrElem, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 5, 1))
|
||||
|
||||
type TupleElem = [['list', TupleElem[0][0]]];
|
||||
>TupleElem : Symbol(TupleElem, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 7, 46))
|
||||
>TupleElem : Symbol(TupleElem, Decl(circularlyReferentialInterfaceAccessNoCrash.ts, 7, 46))
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
=== tests/cases/compiler/circularlyReferentialInterfaceAccessNoCrash.ts ===
|
||||
type Mxs = Mx<'list', Mxs['p1']>;
|
||||
>Mxs : Mxs
|
||||
|
||||
interface Mx<T, K> {
|
||||
p1: T;
|
||||
>p1 : T
|
||||
|
||||
p2: K;
|
||||
>p2 : K
|
||||
}
|
||||
|
||||
type ArrElem = ['list', ArrElem[number][0]][];
|
||||
>ArrElem : ArrElem
|
||||
|
||||
type TupleElem = [['list', TupleElem[0][0]]];
|
||||
>TupleElem : TupleElem
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
type Mxs = Mx<'list', Mxs['p1']>;
|
||||
|
||||
interface Mx<T, K> {
|
||||
p1: T;
|
||||
p2: K;
|
||||
}
|
||||
|
||||
type ArrElem = ['list', ArrElem[number][0]][];
|
||||
|
||||
type TupleElem = [['list', TupleElem[0][0]]];
|
||||
Loading…
x
Reference in New Issue
Block a user