diff options
Diffstat (limited to 'src/go/types/unify.go')
-rw-r--r-- | src/go/types/unify.go | 52 |
1 files changed, 25 insertions, 27 deletions
diff --git a/src/go/types/unify.go b/src/go/types/unify.go index db06e21cf7..90a5cf7c72 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -8,7 +8,7 @@ package types import ( "bytes" - "go/token" + "fmt" "sort" ) @@ -38,7 +38,6 @@ import ( // and the respective types inferred for each type parameter. // A unifier is created by calling newUnifier. type unifier struct { - check *Checker exact bool x, y tparamsList // x and y must initialized via tparamsList.init types []Type // inferred types, shared by x and y @@ -49,8 +48,8 @@ type unifier struct { // exactly. If exact is not set, a named type's underlying type // is considered if unification would fail otherwise, and the // direction of channels is ignored. -func newUnifier(check *Checker, exact bool) *unifier { - u := &unifier{check: check, exact: exact} +func newUnifier(exact bool) *unifier { + u := &unifier{exact: exact} u.x.unifier = u u.y.unifier = u return u @@ -100,7 +99,7 @@ func (d *tparamsList) init(tparams []*TypeName) { } if debug { for i, tpar := range tparams { - assert(i == tpar.typ.(*_TypeParam).index) + assert(i == tpar.typ.(*TypeParam).index) } } d.tparams = tparams @@ -148,10 +147,17 @@ func (u *unifier) join(i, j int) bool { // If typ is a type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { - if t, ok := typ.(*_TypeParam); ok { - if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t { - return i - } + if tpar, ok := typ.(*TypeParam); ok { + return tparamIndex(d.tparams, tpar) + } + return -1 +} + +// If tpar is a type parameter in list, tparamIndex returns the type parameter index. +// Otherwise, the result is < 0. tpar must not be nil. +func tparamIndex(list []*TypeName, tpar *TypeParam) int { + if i := tpar.index; i < len(list) && list[i].typ == tpar { + return i } return -1 } @@ -352,25 +358,21 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { u.nify(x.results, y.results, p) } - case *_Sum: - // This should not happen with the current internal use of sum types. - panic("type inference across sum types not implemented") + case *Union: + panic("unimplemented: unification with type sets described by types") case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from // different packages are always different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - // If identical0 is called (indirectly) via an external API entry point - // (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in - // that case, interfaces are expected to be complete and lazy completion - // here is not needed. - if u.check != nil { - u.check.completeInterface(token.NoPos, x) - u.check.completeInterface(token.NoPos, y) + xset := x.typeSet() + yset := y.typeSet() + if !Identical(xset.types, yset.types) { + return false } - a := x.allMethods - b := y.allMethods + a := xset.methods + b := yset.methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles @@ -448,21 +450,17 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } } - case *_TypeParam: + case *TypeParam: // Two type parameters (which are not part of the type parameters of the // enclosing type as those are handled in the beginning of this function) // are identical if they originate in the same declaration. return x == y - // case *instance: - // unreachable since types are expanded - case nil: // avoid a crash in case of nil type default: - u.check.dump("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams) - unreachable() + panic(fmt.Sprintf("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams)) } return false |