@@ -3519,40 +3519,6 @@ export class Parser extends DiagnosticEmitter {
35193519 return null ;
35203520 }
35213521
3522- private getRecursiveDepthForTypeDeclaration (
3523- identifierName : string ,
3524- type : TypeNode ,
3525- depth : i32 = 0
3526- ) : i32 {
3527- switch ( type . kind ) {
3528- case NodeKind . NamedType : {
3529- let typeArguments = ( < NamedTypeNode > type ) . typeArguments ;
3530- if ( typeArguments ) {
3531- for ( let i = 0 , k = typeArguments . length ; i < k ; i ++ ) {
3532- let res = this . getRecursiveDepthForTypeDeclaration ( identifierName , typeArguments [ i ] , depth + 1 ) ;
3533- if ( res != - 1 ) return res ;
3534- }
3535- }
3536- if ( ( < NamedTypeNode > type ) . name . identifier . text == identifierName ) {
3537- return depth ;
3538- }
3539- break ;
3540- }
3541- case NodeKind . FunctionType : {
3542- let fnType = < FunctionTypeNode > type ;
3543- let res = this . getRecursiveDepthForTypeDeclaration ( identifierName , fnType . returnType , depth + 1 ) ;
3544- if ( res != - 1 ) return res ;
3545- let params = fnType . parameters ;
3546- for ( let i = 0 , k = params . length ; i < k ; i ++ ) {
3547- res = this . getRecursiveDepthForTypeDeclaration ( identifierName , params [ i ] . type , depth + 1 ) ;
3548- if ( res != - 1 ) return res ;
3549- }
3550- break ;
3551- }
3552- }
3553- return - 1 ;
3554- }
3555-
35563522 parseTypeDeclaration (
35573523 tn : Tokenizer ,
35583524 flags : CommonFlags ,
@@ -3574,19 +3540,11 @@ export class Parser extends DiagnosticEmitter {
35743540 tn . skip ( Token . Bar ) ;
35753541 let type = this . parseType ( tn ) ;
35763542 if ( ! type ) return null ;
3577- let depth = this . getRecursiveDepthForTypeDeclaration ( name . text , type ) ;
3578- if ( depth >= 0 ) {
3579- if ( depth == 0 ) {
3580- this . error (
3581- DiagnosticCode . Type_alias_0_circularly_references_itself ,
3582- tn . range ( ) , name . text
3583- ) ;
3584- } else {
3585- this . error (
3586- DiagnosticCode . Not_implemented_0 ,
3587- tn . range ( ) , "Recursion in type aliases"
3588- ) ;
3589- }
3543+ if ( isCircularTypeAlias ( name . text , type ) ) {
3544+ this . error (
3545+ DiagnosticCode . Type_alias_0_circularly_references_itself ,
3546+ name . range , name . text
3547+ ) ;
35903548 return null ;
35913549 }
35923550 let ret = Node . createTypeDeclaration (
@@ -4593,3 +4551,32 @@ function determinePrecedence(kind: Token): Precedence {
45934551 }
45944552 return Precedence . None ;
45954553}
4554+
4555+ /** Checks if the type alias of the given name and type is circular. */
4556+ function isCircularTypeAlias ( name : string , type : TypeNode ) : bool {
4557+ switch ( type . kind ) {
4558+ case NodeKind . NamedType : {
4559+ if ( ( < NamedTypeNode > type ) . name . identifier . text == name ) {
4560+ return true ;
4561+ }
4562+ let typeArguments = ( < NamedTypeNode > type ) . typeArguments ;
4563+ if ( typeArguments ) {
4564+ for ( let i = 0 , k = typeArguments . length ; i < k ; i ++ ) {
4565+ if ( isCircularTypeAlias ( name , typeArguments [ i ] ) ) return true ;
4566+ }
4567+ }
4568+ break ;
4569+ }
4570+ case NodeKind . FunctionType : {
4571+ let functionType = < FunctionTypeNode > type ;
4572+ if ( isCircularTypeAlias ( name , functionType . returnType ) ) return true ;
4573+ let parameters = functionType . parameters ;
4574+ for ( let i = 0 , k = parameters . length ; i < k ; i ++ ) {
4575+ if ( isCircularTypeAlias ( name , parameters [ i ] . type ) ) return true ;
4576+ }
4577+ break ;
4578+ }
4579+ default : assert ( false ) ;
4580+ }
4581+ return false ;
4582+ }
0 commit comments