aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/unify.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/go/types/unify.go')
-rw-r--r--src/go/types/unify.go52
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