mirror of
https://github.com/golang/go
synced 2024-11-23 00:30:07 -07:00
go/types, types2: factor out inference cycle detector (cleanup)
Change-Id: If3c6724497dfbe8611ffffb4735e47ddc53a742c Reviewed-on: https://go-review.googlesource.com/c/go/+/484158 Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com> Run-TryBot: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
f05c1941dd
commit
45c0a7f27e
@ -334,19 +334,16 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
||||
// Generally, cycles may occur across multiple type parameters and inferred types
|
||||
// (for instance, consider [P interface{ *Q }, Q interface{ func(P) }]).
|
||||
// We eliminate cycles by walking the graphs for all type parameters. If a cycle
|
||||
// through a type parameter is detected, cycleFinder nils out the respective type
|
||||
// which kills the cycle; this also means that the respective type could not be
|
||||
// inferred.
|
||||
// through a type parameter is detected, killCycles nils out the respective type
|
||||
// (in the inferred list) which kills the cycle, and marks the corresponding type
|
||||
// parameter as not inferred.
|
||||
//
|
||||
// TODO(gri) If useful, we could report the respective cycle as an error. We don't
|
||||
// do this now because type inference will fail anyway, and furthermore,
|
||||
// constraints with cycles of this kind cannot currently be satisfied by
|
||||
// any user-supplied type. But should that change, reporting an error
|
||||
// would be wrong.
|
||||
w := cycleFinder{tparams, inferred, make(map[Type]bool)}
|
||||
for _, t := range tparams {
|
||||
w.typ(t) // t != nil
|
||||
}
|
||||
killCycles(tparams, inferred)
|
||||
|
||||
// dirty tracks the indices of all types that may still contain type parameters.
|
||||
// We know that nil type entries and entries corresponding to provided (non-nil)
|
||||
@ -601,6 +598,20 @@ func coreTerm(tpar *TypeParam) (*term, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// killCycles walks through the given type parameters and looks for cycles
|
||||
// created by type parameters whose inferred types refer back to that type
|
||||
// parameter, either directly or indirectly. If such a cycle is detected,
|
||||
// it is killed by setting the corresponding inferred type to nil.
|
||||
//
|
||||
// TODO(gri) Determine if we can simply abort inference as soon as we have
|
||||
// found a single cycle.
|
||||
func killCycles(tparams []*TypeParam, inferred []Type) {
|
||||
w := cycleFinder{tparams, inferred, make(map[Type]bool)}
|
||||
for _, t := range tparams {
|
||||
w.typ(t) // t != nil
|
||||
}
|
||||
}
|
||||
|
||||
type cycleFinder struct {
|
||||
tparams []*TypeParam
|
||||
types []Type
|
||||
@ -610,7 +621,7 @@ type cycleFinder struct {
|
||||
func (w *cycleFinder) typ(typ Type) {
|
||||
if w.seen[typ] {
|
||||
// We have seen typ before. If it is one of the type parameters
|
||||
// in tparams, iterative substitution will lead to infinite expansion.
|
||||
// in w.tparams, iterative substitution will lead to infinite expansion.
|
||||
// Nil out the corresponding type which effectively kills the cycle.
|
||||
if tpar, _ := typ.(*TypeParam); tpar != nil {
|
||||
if i := tparamIndex(w.tparams, tpar); i >= 0 {
|
||||
|
@ -336,19 +336,16 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
|
||||
// Generally, cycles may occur across multiple type parameters and inferred types
|
||||
// (for instance, consider [P interface{ *Q }, Q interface{ func(P) }]).
|
||||
// We eliminate cycles by walking the graphs for all type parameters. If a cycle
|
||||
// through a type parameter is detected, cycleFinder nils out the respective type
|
||||
// which kills the cycle; this also means that the respective type could not be
|
||||
// inferred.
|
||||
// through a type parameter is detected, killCycles nils out the respective type
|
||||
// (in the inferred list) which kills the cycle, and marks the corresponding type
|
||||
// parameter as not inferred.
|
||||
//
|
||||
// TODO(gri) If useful, we could report the respective cycle as an error. We don't
|
||||
// do this now because type inference will fail anyway, and furthermore,
|
||||
// constraints with cycles of this kind cannot currently be satisfied by
|
||||
// any user-supplied type. But should that change, reporting an error
|
||||
// would be wrong.
|
||||
w := cycleFinder{tparams, inferred, make(map[Type]bool)}
|
||||
for _, t := range tparams {
|
||||
w.typ(t) // t != nil
|
||||
}
|
||||
killCycles(tparams, inferred)
|
||||
|
||||
// dirty tracks the indices of all types that may still contain type parameters.
|
||||
// We know that nil type entries and entries corresponding to provided (non-nil)
|
||||
@ -603,6 +600,20 @@ func coreTerm(tpar *TypeParam) (*term, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// killCycles walks through the given type parameters and looks for cycles
|
||||
// created by type parameters whose inferred types refer back to that type
|
||||
// parameter, either directly or indirectly. If such a cycle is detected,
|
||||
// it is killed by setting the corresponding inferred type to nil.
|
||||
//
|
||||
// TODO(gri) Determine if we can simply abort inference as soon as we have
|
||||
// found a single cycle.
|
||||
func killCycles(tparams []*TypeParam, inferred []Type) {
|
||||
w := cycleFinder{tparams, inferred, make(map[Type]bool)}
|
||||
for _, t := range tparams {
|
||||
w.typ(t) // t != nil
|
||||
}
|
||||
}
|
||||
|
||||
type cycleFinder struct {
|
||||
tparams []*TypeParam
|
||||
types []Type
|
||||
@ -612,7 +623,7 @@ type cycleFinder struct {
|
||||
func (w *cycleFinder) typ(typ Type) {
|
||||
if w.seen[typ] {
|
||||
// We have seen typ before. If it is one of the type parameters
|
||||
// in tparams, iterative substitution will lead to infinite expansion.
|
||||
// in w.tparams, iterative substitution will lead to infinite expansion.
|
||||
// Nil out the corresponding type which effectively kills the cycle.
|
||||
if tpar, _ := typ.(*TypeParam); tpar != nil {
|
||||
if i := tparamIndex(w.tparams, tpar); i >= 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user