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

Max call stack size exceeded for class expression with extends clause in static method #20695

Closed
FabianLauer opened this issue Dec 14, 2017 · 4 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@FabianLauer
Copy link

TypeScript Version: 2.7.0-dev.201xxxxx

Code

// test.ts
export class Test {
	public static createSubclass() {
		return class extends Test { };
	}
}

Expected behavior:
TSC should not fail to compile with --declaration.

Actual behavior:
TSC fails with Maximum call stack size exceeded:

> tsc --declaration test.ts                                                                                                                                                                                                                 

/usr/local/lib/node_modules/typescript/lib/tsc.js:59538
                throw e;
                ^

RangeError: Maximum call stack size exceeded
    at writeKeyword (/usr/local/lib/node_modules/typescript/lib/tsc.js:21320:30)
    at buildSignatureDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22591:21)
    at writeObjectLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:22366:25)
    at writeLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:22352:21)
    at writeAnonymousType (/usr/local/lib/node_modules/typescript/lib/tsc.js:22246:33)
    at writeType (/usr/local/lib/node_modules/typescript/lib/tsc.js:22098:25)
    at buildTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22061:24)
    at buildReturnTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22586:21)
    at buildSignatureDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22601:17)
    at writeObjectLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:22388:33)

More Details:

Seems like the error is not caused by extending the specific class that owns the static method, but it also fails with other bases:

// fails too:

export class Foo { }

export class Test {
	public static createSubclass() {
		return class extends Foo { };
	}
}

When the class expression is returned by an instance method though, TSC does not fail:

// works:
export class Test {
	public createSubclass() {
		return class extends Test { };
	}
}

// result:
export declare class Test {
    createSubclass(): {
        new (): {
            createSubclass(): any;
        };
    };
}
@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Dec 14, 2017
@mhegazy mhegazy added this to the TypeScript 2.8 milestone Jan 10, 2018
@FabianLauer
Copy link
Author

Just noticed that my first example also fails with TSC version 2.6.2, both with --declaration and --watch.

tsc --declaration test.ts

/usr/local/lib/node_modules/typescript/lib/tsc.js:58192
                throw e;
                ^

RangeError: Maximum call stack size exceeded
    at writeTypeReference (/usr/local/lib/node_modules/typescript/lib/tsc.js:21698:44)
    at writeType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21617:25)
    at buildTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:21602:24)
    at buildReturnTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22109:21)
    at buildSignatureDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22124:17)
    at writeObjectLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21890:25)
    at writeLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21876:21)
    at writeAnonymousType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21777:33)
    at writeType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21639:25)
    at buildTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:21602:24)

tsc -w test.ts

/usr/local/lib/node_modules/typescript/lib/tsc.js:58192
                throw e;
                ^

RangeError: Maximum call stack size exceeded
    at writeKeyword (/usr/local/lib/node_modules/typescript/lib/tsc.js:20867:30)
    at buildSignatureDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22114:21)
    at writeObjectLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21890:25)
    at writeLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21876:21)
    at writeAnonymousType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21777:33)
    at writeType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21639:25)
    at buildTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:21602:24)
    at buildReturnTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22109:21)
    at buildSignatureDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22124:17)
    at writeObjectLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21912:33)

tsc -w --declaration test.ts

/usr/local/lib/node_modules/typescript/lib/tsc.js:58192
                throw e;
                ^

RangeError: Maximum call stack size exceeded
    at getIndentString (/usr/local/lib/node_modules/typescript/lib/tsc.js:7546:29)
    at Object.write (/usr/local/lib/node_modules/typescript/lib/tsc.js:7566:31)
    at writeKeyword (/usr/local/lib/node_modules/typescript/lib/tsc.js:20868:20)
    at buildSignatureDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22114:21)
    at writeObjectLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21890:25)
    at writeLiteralType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21876:21)
    at writeAnonymousType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21777:33)
    at writeType (/usr/local/lib/node_modules/typescript/lib/tsc.js:21639:25)
    at buildTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:21602:24)
    at buildReturnTypeDisplay (/usr/local/lib/node_modules/typescript/lib/tsc.js:22109:21)

@sandersn
Copy link
Member

sandersn commented May 8, 2018

The loop happens when trying to turn the static type of class extends C {} into a type node that can be printed. typeToTypeNode should probably cut off the return type with any:

class C 
{ 
    make(): { 
        new(): { }; 
        make(): any 
    }
}

But it doesn't. I'll need to investigate further to find out how similar cutoffs work; it's a while since I looked at this code. @weswigham have you touched this recently? If so, can you point me in the right direction?

@weswigham
Copy link
Member

@sandersn we have a flag that causes us to attempt to write the structure of the class (for handling, eg, mixins (like this)), and the second example isn't even self-referential, so in theory it should print structurally just fine.

@mhegazy mhegazy assigned weswigham and unassigned sandersn May 8, 2018
@mhegazy
Copy link
Contributor

mhegazy commented May 22, 2018

Should be fixed by #24225

@mhegazy mhegazy closed this as completed May 22, 2018
@mhegazy mhegazy added the Fixed A PR has been merged for this issue label May 22, 2018
@microsoft microsoft locked and limited conversation to collaborators Jul 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

5 participants