Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursive type references #33050

Merged
merged 29 commits into from Sep 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
643351c
Support deferred resolution of type arguments in type references
ahejlsberg Aug 23, 2019
b24fcd0
Recursive tuple types + fix instantiation of recursive type references
ahejlsberg Aug 24, 2019
52a1a14
Instantiate deferred type references like anonymous types
ahejlsberg Aug 26, 2019
dd47fff
Properly handle recursive array and tuple types in printback
ahejlsberg Aug 26, 2019
7753f7b
Merge branch 'master' into recursiveTypeReferences
ahejlsberg Aug 26, 2019
5310fd0
Minor fixes
ahejlsberg Aug 27, 2019
5c21f43
Accept new baselines
ahejlsberg Aug 27, 2019
bf0debb
Handle missing global array type
ahejlsberg Aug 27, 2019
b18c70f
Fix fourslash test
ahejlsberg Aug 27, 2019
c2d0aa8
Only defer aliased array and tuple types
ahejlsberg Aug 27, 2019
8f3a917
Accept new baselines
ahejlsberg Aug 27, 2019
842c588
Exclude method symbols when relating tuple types
ahejlsberg Aug 28, 2019
fd8f990
Fix instantiation of alias type arguments for deferred type references
ahejlsberg Aug 29, 2019
6270ccc
Accept new baselines
ahejlsberg Aug 29, 2019
2f0ac25
Defer resolution of type arguments in aliased type references
ahejlsberg Aug 30, 2019
81bfa6f
Accept new baselines
ahejlsberg Aug 30, 2019
a92d599
Tweak isAliasedType
ahejlsberg Aug 30, 2019
b9cb3a6
Accept new baselines
ahejlsberg Aug 31, 2019
db7c03d
Merge branch 'master' into recursiveTypeReferences
ahejlsberg Sep 21, 2019
8604d4e
Include type operators in aliased type checks
ahejlsberg Sep 21, 2019
bf08d3b
Fix linting issues
ahejlsberg Sep 23, 2019
e3d23cc
Add tests
ahejlsberg Sep 24, 2019
3aa3326
Accept new baselines
ahejlsberg Sep 24, 2019
5962a5c
Merge branch 'master' into recursiveTypeReferences
ahejlsberg Sep 24, 2019
f0bf72f
Fix linting issue
ahejlsberg Sep 24, 2019
b2f4af4
Fix that works with both LKG and built compilers
ahejlsberg Sep 24, 2019
27752c6
Merge branch 'master' into recursiveTypeReferences
ahejlsberg Sep 24, 2019
3061a41
Add getTypeArguments method to TypeChecker interface
ahejlsberg Sep 24, 2019
7fd93fd
Accept API baseline changes
ahejlsberg Sep 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
334 changes: 201 additions & 133 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/compiler/symbolWalker.ts
Expand Up @@ -10,7 +10,8 @@ namespace ts {
getResolvedSymbol: (node: Node) => Symbol,
getIndexTypeOfStructuredType: (type: Type, kind: IndexKind) => Type | undefined,
getConstraintOfTypeParameter: (typeParameter: TypeParameter) => Type | undefined,
getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier) {
getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier,
getTypeArguments: (type: TypeReference) => readonly Type[]) {

return getSymbolWalker;

Expand Down Expand Up @@ -89,7 +90,7 @@ namespace ts {

function visitTypeReference(type: TypeReference): void {
visitType(type.target);
forEach(type.typeArguments, visitType);
forEach(getTypeArguments(type), visitType);
}

function visitTypeParameter(type: TypeParameter): void {
Expand Down
16 changes: 15 additions & 1 deletion src/compiler/types.ts
Expand Up @@ -3191,6 +3191,7 @@ namespace ts {
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
getNullableType(type: Type, flags: TypeFlags): Type;
getNonNullableType(type: Type): Type;
getTypeArguments(type: TypeReference): readonly Type[];

// TODO: GH#18217 `xToDeclaration` calls are frequently asserted as defined.
/** Note that the resulting nodes cannot be checked. */
Expand Down Expand Up @@ -4025,6 +4026,8 @@ namespace ts {
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
deferredNodes?: Map<Node>; // Set of nodes whose checking has been deferred
capturedBlockScopeBindings?: Symbol[]; // Block-scoped bindings captured beneath this part of an IterationStatement
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
isExhaustive?: boolean; // Is node an exhaustive switch statement
}

Expand Down Expand Up @@ -4272,11 +4275,22 @@ namespace ts {
*/
export interface TypeReference extends ObjectType {
target: GenericType; // Type reference target
typeArguments?: readonly Type[]; // Type reference type arguments (undefined if none)
node?: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
/* @internal */
mapper?: TypeMapper;
/* @internal */
resolvedTypeArguments?: readonly Type[]; // Resolved type reference type arguments
/* @internal */
literalType?: TypeReference; // Clone of type with ObjectFlags.ArrayLiteral set
}

export interface DeferredTypeReference extends TypeReference {
/* @internal */
node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
/* @internal */
mapper?: TypeMapper;
}

/* @internal */
export const enum VarianceFlags {
Invariant = 0, // Neither covariant nor contravariant
Expand Down
4 changes: 2 additions & 2 deletions src/services/codefixes/inferFromUsage.ts
Expand Up @@ -993,8 +993,8 @@ namespace ts.codefix {
}
else if (getObjectFlags(genericType) & ObjectFlags.Reference && getObjectFlags(usageType) & ObjectFlags.Reference) {
// this is wrong because we need a reference to the targetType to, so we can check that it's also a reference
const genericArgs = (genericType as TypeReference).typeArguments;
const usageArgs = (usageType as TypeReference).typeArguments;
const genericArgs = checker.getTypeArguments(genericType as TypeReference);
const usageArgs = checker.getTypeArguments(usageType as TypeReference);
const types = [];
if (genericArgs && usageArgs) {
for (let i = 0; i < genericArgs.length; i++) {
Expand Down
5 changes: 4 additions & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Expand Up @@ -1967,6 +1967,7 @@ declare namespace ts {
getReturnTypeOfSignature(signature: Signature): Type;
getNullableType(type: Type, flags: TypeFlags): Type;
getNonNullableType(type: Type): Type;
getTypeArguments(type: TypeReference): readonly Type[];
/** Note that the resulting nodes cannot be checked. */
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined;
/** Note that the resulting nodes cannot be checked. */
Expand Down Expand Up @@ -2388,7 +2389,9 @@ declare namespace ts {
*/
export interface TypeReference extends ObjectType {
target: GenericType;
typeArguments?: readonly Type[];
node?: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
}
export interface DeferredTypeReference extends TypeReference {
}
export interface GenericType extends InterfaceType, TypeReference {
}
Expand Down
5 changes: 4 additions & 1 deletion tests/baselines/reference/api/typescript.d.ts
Expand Up @@ -1967,6 +1967,7 @@ declare namespace ts {
getReturnTypeOfSignature(signature: Signature): Type;
getNullableType(type: Type, flags: TypeFlags): Type;
getNonNullableType(type: Type): Type;
getTypeArguments(type: TypeReference): readonly Type[];
/** Note that the resulting nodes cannot be checked. */
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined;
/** Note that the resulting nodes cannot be checked. */
Expand Down Expand Up @@ -2388,7 +2389,9 @@ declare namespace ts {
*/
export interface TypeReference extends ObjectType {
target: GenericType;
typeArguments?: readonly Type[];
node?: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
}
export interface DeferredTypeReference extends TypeReference {
}
export interface GenericType extends InterfaceType, TypeReference {
}
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/asyncAliasReturnType_es5.types
@@ -1,7 +1,7 @@
=== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts ===
type PromiseAlias<T> = Promise<T>;
>PromiseAlias : Promise<T>
>PromiseAlias : PromiseAlias<T>

async function f(): PromiseAlias<void> {
>f : () => Promise<void>
>f : () => PromiseAlias<void>
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/asyncAliasReturnType_es6.types
@@ -1,7 +1,7 @@
=== tests/cases/conformance/async/es6/asyncAliasReturnType_es6.ts ===
type PromiseAlias<T> = Promise<T>;
>PromiseAlias : Promise<T>
>PromiseAlias : PromiseAlias<T>

async function f(): PromiseAlias<void> {
>f : () => Promise<void>
>f : () => PromiseAlias<void>
}
32 changes: 16 additions & 16 deletions tests/baselines/reference/asyncAwait_es2017.types
@@ -1,6 +1,6 @@
=== tests/cases/conformance/async/es2017/asyncAwait_es2017.ts ===
type MyPromise<T> = Promise<T>;
>MyPromise : Promise<T>
>MyPromise : MyPromise<T>

declare var MyPromise: typeof Promise;
>MyPromise : PromiseConstructor
Expand All @@ -10,7 +10,7 @@ declare var p: Promise<number>;
>p : Promise<number>

declare var mp: MyPromise<number>;
>mp : Promise<number>
>mp : MyPromise<number>

async function f0() { }
>f0 : () => Promise<void>
Expand All @@ -19,7 +19,7 @@ async function f1(): Promise<void> { }
>f1 : () => Promise<void>

async function f3(): MyPromise<void> { }
>f3 : () => Promise<void>
>f3 : () => MyPromise<void>

let f4 = async function() { }
>f4 : () => Promise<void>
Expand All @@ -30,8 +30,8 @@ let f5 = async function(): Promise<void> { }
>async function(): Promise<void> { } : () => Promise<void>

let f6 = async function(): MyPromise<void> { }
>f6 : () => Promise<void>
>async function(): MyPromise<void> { } : () => Promise<void>
>f6 : () => MyPromise<void>
>async function(): MyPromise<void> { } : () => MyPromise<void>

let f7 = async () => { };
>f7 : () => Promise<void>
Expand All @@ -42,8 +42,8 @@ let f8 = async (): Promise<void> => { };
>async (): Promise<void> => { } : () => Promise<void>

let f9 = async (): MyPromise<void> => { };
>f9 : () => Promise<void>
>async (): MyPromise<void> => { } : () => Promise<void>
>f9 : () => MyPromise<void>
>async (): MyPromise<void> => { } : () => MyPromise<void>

let f10 = async () => p;
>f10 : () => Promise<number>
Expand All @@ -53,21 +53,21 @@ let f10 = async () => p;
let f11 = async () => mp;
>f11 : () => Promise<number>
>async () => mp : () => Promise<number>
>mp : Promise<number>
>mp : MyPromise<number>

let f12 = async (): Promise<number> => mp;
>f12 : () => Promise<number>
>async (): Promise<number> => mp : () => Promise<number>
>mp : Promise<number>
>mp : MyPromise<number>

let f13 = async (): MyPromise<number> => p;
>f13 : () => Promise<number>
>async (): MyPromise<number> => p : () => Promise<number>
>f13 : () => MyPromise<number>
>async (): MyPromise<number> => p : () => MyPromise<number>
>p : Promise<number>

let o = {
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }

async m1() { },
>m1 : () => Promise<void>
Expand All @@ -76,7 +76,7 @@ let o = {
>m2 : () => Promise<void>

async m3(): MyPromise<void> { }
>m3 : () => Promise<void>
>m3 : () => MyPromise<void>

};

Expand All @@ -90,7 +90,7 @@ class C {
>m2 : () => Promise<void>

async m3(): MyPromise<void> { }
>m3 : () => Promise<void>
>m3 : () => MyPromise<void>

static async m4() { }
>m4 : () => Promise<void>
Expand All @@ -99,7 +99,7 @@ class C {
>m5 : () => Promise<void>

static async m6(): MyPromise<void> { }
>m6 : () => Promise<void>
>m6 : () => MyPromise<void>
}

module M {
Expand Down
32 changes: 16 additions & 16 deletions tests/baselines/reference/asyncAwait_es5.types
@@ -1,6 +1,6 @@
=== tests/cases/conformance/async/es5/asyncAwait_es5.ts ===
type MyPromise<T> = Promise<T>;
>MyPromise : Promise<T>
>MyPromise : MyPromise<T>

declare var MyPromise: typeof Promise;
>MyPromise : PromiseConstructor
Expand All @@ -10,7 +10,7 @@ declare var p: Promise<number>;
>p : Promise<number>

declare var mp: MyPromise<number>;
>mp : Promise<number>
>mp : MyPromise<number>

async function f0() { }
>f0 : () => Promise<void>
Expand All @@ -19,7 +19,7 @@ async function f1(): Promise<void> { }
>f1 : () => Promise<void>

async function f3(): MyPromise<void> { }
>f3 : () => Promise<void>
>f3 : () => MyPromise<void>

let f4 = async function() { }
>f4 : () => Promise<void>
Expand All @@ -30,8 +30,8 @@ let f5 = async function(): Promise<void> { }
>async function(): Promise<void> { } : () => Promise<void>

let f6 = async function(): MyPromise<void> { }
>f6 : () => Promise<void>
>async function(): MyPromise<void> { } : () => Promise<void>
>f6 : () => MyPromise<void>
>async function(): MyPromise<void> { } : () => MyPromise<void>

let f7 = async () => { };
>f7 : () => Promise<void>
Expand All @@ -42,8 +42,8 @@ let f8 = async (): Promise<void> => { };
>async (): Promise<void> => { } : () => Promise<void>

let f9 = async (): MyPromise<void> => { };
>f9 : () => Promise<void>
>async (): MyPromise<void> => { } : () => Promise<void>
>f9 : () => MyPromise<void>
>async (): MyPromise<void> => { } : () => MyPromise<void>

let f10 = async () => p;
>f10 : () => Promise<number>
Expand All @@ -53,21 +53,21 @@ let f10 = async () => p;
let f11 = async () => mp;
>f11 : () => Promise<number>
>async () => mp : () => Promise<number>
>mp : Promise<number>
>mp : MyPromise<number>

let f12 = async (): Promise<number> => mp;
>f12 : () => Promise<number>
>async (): Promise<number> => mp : () => Promise<number>
>mp : Promise<number>
>mp : MyPromise<number>

let f13 = async (): MyPromise<number> => p;
>f13 : () => Promise<number>
>async (): MyPromise<number> => p : () => Promise<number>
>f13 : () => MyPromise<number>
>async (): MyPromise<number> => p : () => MyPromise<number>
>p : Promise<number>

let o = {
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }

async m1() { },
>m1 : () => Promise<void>
Expand All @@ -76,7 +76,7 @@ let o = {
>m2 : () => Promise<void>

async m3(): MyPromise<void> { }
>m3 : () => Promise<void>
>m3 : () => MyPromise<void>

};

Expand All @@ -90,7 +90,7 @@ class C {
>m2 : () => Promise<void>

async m3(): MyPromise<void> { }
>m3 : () => Promise<void>
>m3 : () => MyPromise<void>

static async m4() { }
>m4 : () => Promise<void>
Expand All @@ -99,7 +99,7 @@ class C {
>m5 : () => Promise<void>

static async m6(): MyPromise<void> { }
>m6 : () => Promise<void>
>m6 : () => MyPromise<void>
}

module M {
Expand Down