@@ -2761,10 +2761,24 @@ export class Resolver extends DiagnosticEmitter {
27612761 assert ( ! ( typeParameterNodes && typeParameterNodes . length ) ) ;
27622762 }
27632763
2764+ // There shouldn't be an instance before resolving the base class
2765+ assert ( ! prototype . getResolvedInstance ( instanceKey ) ) ;
2766+
27642767 // Resolve base class if applicable
27652768 var basePrototype = prototype . basePrototype ;
27662769 var baseClass : Class | null = null ;
27672770 if ( basePrototype ) {
2771+ let current : ClassPrototype | null = basePrototype ;
2772+ do {
2773+ if ( current == prototype ) {
2774+ this . error (
2775+ DiagnosticCode . _0_is_referenced_directly_or_indirectly_in_its_own_base_expression ,
2776+ prototype . identifierNode . range ,
2777+ prototype . internalName
2778+ ) ;
2779+ return null ;
2780+ }
2781+ } while ( current = current . basePrototype ) ;
27682782 let extendsNode = assert ( prototype . extendsNode ) ; // must be present if it has a base prototype
27692783 baseClass = this . resolveClassInclTypeArguments (
27702784 basePrototype ,
@@ -2778,11 +2792,17 @@ export class Resolver extends DiagnosticEmitter {
27782792 }
27792793
27802794 // Construct the instance and remember that it has been resolved already
2781- var nameInclTypeParamters = prototype . name ;
2782- if ( instanceKey . length ) nameInclTypeParamters += "<" + instanceKey + ">" ;
2783- instance = new Class ( nameInclTypeParamters , prototype , typeArguments , baseClass ) ;
2784- instance . contextualTypeArguments = ctxTypes ;
2785- prototype . setResolvedInstance ( instanceKey , instance ) ;
2795+ var recursiveInstanceFromResolvingBase = prototype . getResolvedInstance ( instanceKey ) ;
2796+ if ( recursiveInstanceFromResolvingBase ) {
2797+ // Happens if the base class already triggers resolving this class
2798+ instance = recursiveInstanceFromResolvingBase ;
2799+ } else {
2800+ let nameInclTypeParamters = prototype . name ;
2801+ if ( instanceKey . length ) nameInclTypeParamters += "<" + instanceKey + ">" ;
2802+ instance = new Class ( nameInclTypeParamters , prototype , typeArguments , baseClass ) ;
2803+ prototype . setResolvedInstance ( instanceKey , instance ) ;
2804+ }
2805+ instance . contextualTypeArguments = ctxTypes ; // unique (as specified by the caller)
27862806
27872807 // Inherit base class members and set up the initial memory offset for own fields
27882808 var memoryOffset : u32 = 0 ;
0 commit comments