@@ -9,6 +9,7 @@ package types2
99import (
1010 "bytes"
1111 "cmd/compile/internal/syntax"
12+ "fmt"
1213)
1314
1415const useConstraintTypeInference = true
@@ -409,6 +410,34 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t
409410 }
410411 }
411412
413+ // The data structure of each (provided or inferred) type represents a graph, where
414+ // each node corresponds to a type and each (directed) vertice points to a component
415+ // type. The substitution process described above repeatedly replaces type parameter
416+ // nodes in these graphs with the graphs of the types the type parameters stand for,
417+ // which creates a new (possibly bigger) graph for each type.
418+ // The substitution process will not stop if the replacement graph for a type parameter
419+ // also contains that type parameter.
420+ // For instance, for [A interface{ *A }], without any type argument provided for A,
421+ // unification produces the type list [*A]. Substituting A in *A with the value for
422+ // A will lead to infinite expansion by producing [**A], [****A], [********A], etc.,
423+ // because the graph A -> *A has a cycle through A.
424+ // Generally, cycles may occur across multiple type parameters and inferred types
425+ // (for instance, consider [P interface{ *Q }, Q interface{ func(P) }]).
426+ // We eliminate cycles by walking the graphs for all type parameters. If a cycle
427+ // through a type parameter is detected, cycleFinder nils out the respectice type
428+ // which kills the cycle; this also means that the respective type could not be
429+ // inferred.
430+ //
431+ // TODO(gri) If useful, we could report the respective cycle as an error. We don't
432+ // do this now because type inference will fail anyway, and furthermore,
433+ // constraints with cycles of this kind cannot currently be satisfied by
434+ // any user-suplied type. But should that change, reporting an error
435+ // would be wrong.
436+ w := cycleFinder {tparams , types , make (map [Type ]bool )}
437+ for _ , t := range tparams {
438+ w .typ (t ) // t != nil
439+ }
440+
412441 // dirty tracks the indices of all types that may still contain type parameters.
413442 // We know that nil type entries and entries corresponding to provided (non-nil)
414443 // type arguments are clean, so exclude them from the start.
@@ -457,3 +486,98 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t
457486
458487 return
459488}
489+
490+ type cycleFinder struct {
491+ tparams []* TypeParam
492+ types []Type
493+ seen map [Type ]bool
494+ }
495+
496+ func (w * cycleFinder ) typ (typ Type ) {
497+ if w .seen [typ ] {
498+ // We have seen typ before. If it is one of the type parameters
499+ // in tparams, iterative substitution will lead to infinite expansion.
500+ // Nil out the corresponding type which effectively kills the cycle.
501+ if tpar , _ := typ .(* TypeParam ); tpar != nil {
502+ if i := tparamIndex (w .tparams , tpar ); i >= 0 {
503+ // cycle through tpar
504+ w .types [i ] = nil
505+ }
506+ }
507+ // If we don't have one of our type parameters, the cycle is due
508+ // to an ordinary recursive type and we can just stop walking it.
509+ return
510+ }
511+ w .seen [typ ] = true
512+ defer delete (w .seen , typ )
513+
514+ switch t := typ .(type ) {
515+ case * Basic , * top :
516+ // nothing to do
517+
518+ case * Array :
519+ w .typ (t .elem )
520+
521+ case * Slice :
522+ w .typ (t .elem )
523+
524+ case * Struct :
525+ w .varList (t .fields )
526+
527+ case * Pointer :
528+ w .typ (t .base )
529+
530+ // case *Tuple:
531+ // This case should not occur because tuples only appear
532+ // in signatures where they are handled explicitly.
533+
534+ case * Signature :
535+ // There are no "method types" so we should never see a recv.
536+ assert (t .recv == nil )
537+ if t .params != nil {
538+ w .varList (t .params .vars )
539+ }
540+ if t .results != nil {
541+ w .varList (t .results .vars )
542+ }
543+
544+ case * Union :
545+ for _ , t := range t .terms {
546+ w .typ (t .typ )
547+ }
548+
549+ case * Interface :
550+ for _ , m := range t .methods {
551+ w .typ (m .typ )
552+ }
553+ for _ , t := range t .embeddeds {
554+ w .typ (t )
555+ }
556+
557+ case * Map :
558+ w .typ (t .key )
559+ w .typ (t .elem )
560+
561+ case * Chan :
562+ w .typ (t .elem )
563+
564+ case * Named :
565+ for _ , tpar := range t .TArgs ().list () {
566+ w .typ (tpar )
567+ }
568+
569+ case * TypeParam :
570+ if i := tparamIndex (w .tparams , t ); i >= 0 && w .types [i ] != nil {
571+ w .typ (w .types [i ])
572+ }
573+
574+ default :
575+ panic (fmt .Sprintf ("unexpected %T" , typ ))
576+ }
577+ }
578+
579+ func (w * cycleFinder ) varList (list []* Var ) {
580+ for _ , v := range list {
581+ w .typ (v .typ )
582+ }
583+ }
0 commit comments