aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/types2/check.go12
-rw-r--r--src/cmd/compile/internal/types2/interface.go46
-rw-r--r--src/cmd/compile/internal/types2/sizeof_test.go2
-rw-r--r--src/cmd/compile/internal/types2/subst.go1
-rw-r--r--src/cmd/compile/internal/types2/type.go10
5 files changed, 28 insertions, 43 deletions
diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go
index 5d3c2c8ad2..071afef058 100644
--- a/src/cmd/compile/internal/types2/check.go
+++ b/src/cmd/compile/internal/types2/check.go
@@ -82,12 +82,11 @@ type Checker struct {
conf *Config
pkg *Package
*Info
- version version // accepted language version
- nextID uint64 // unique Id for type parameters (first valid Id is 1)
- objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
- impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
- posMap map[*Interface][]syntax.Pos // maps interface types to lists of embedded interface positions
- typMap map[string]*Named // maps an instantiated named type hash to a *Named type
+ version version // accepted language version
+ nextID uint64 // unique Id for type parameters (first valid Id is 1)
+ objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
+ impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
+ typMap map[string]*Named // maps an instantiated named type hash to a *Named type
// pkgPathMap maps package names to the set of distinct import paths we've
// seen for that name, anywhere in the import graph. It is used for
@@ -189,7 +188,6 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
version: version,
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
- posMap: make(map[*Interface][]syntax.Pos),
typMap: make(map[string]*Named),
}
}
diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go
index 499b078dc0..e667830db3 100644
--- a/src/cmd/compile/internal/types2/interface.go
+++ b/src/cmd/compile/internal/types2/interface.go
@@ -14,11 +14,18 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
var tlist []syntax.Expr // types collected from all type lists
var tname *syntax.Name // most recent "type" name
+ addEmbedded := func(pos syntax.Pos, typ Type) {
+ ityp.embeddeds = append(ityp.embeddeds, typ)
+ if ityp.embedPos == nil {
+ ityp.embedPos = new([]syntax.Pos)
+ }
+ *ityp.embedPos = append(*ityp.embedPos, pos)
+ }
+
for _, f := range iface.MethodList {
if f.Name == nil {
// We have an embedded type; possibly a union of types.
- ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, flattenUnion(nil, f.Type)))
- check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos())
+ addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type)))
continue
}
// f.Name != nil
@@ -89,10 +96,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
// If we saw a type list, add it like an embedded union.
if tlist != nil {
- ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, tlist))
// Types T in a type list are added as ~T expressions but we don't
// have the position of the '~'. Use the first type position instead.
- check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*syntax.Operation).X.Pos())
+ addEmbedded(tlist[0].(*syntax.Operation).X.Pos(), parseUnion(check, tlist))
}
// All methods and embedded elements for this interface are collected;
@@ -106,8 +112,8 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
}
// sort for API stability
+ // (don't sort embeddeds: they must correspond to *embedPos entries)
sortMethods(ityp.methods)
- sortTypes(ityp.embeddeds)
// Compute type set with a non-nil *Checker as soon as possible
// to report any errors. Subsequent uses of type sets should be
@@ -227,14 +233,13 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet {
// collect embedded elements
var allTypes Type
- var posList []syntax.Pos
- if check != nil {
- posList = check.posMap[ityp]
- }
for i, typ := range ityp.embeddeds {
+ // The embedding position is nil for imported interfaces
+ // and also for interface copies after substitution (but
+ // in that case we don't need to report errors again).
var pos syntax.Pos // embedding position
- if posList != nil {
- pos = posList[i]
+ if ityp.embedPos != nil {
+ pos = (*ityp.embedPos)[i]
}
var types Type
switch t := under(typ).(type) {
@@ -268,6 +273,7 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet {
}
allTypes = intersect(allTypes, types)
}
+ ityp.embedPos = nil // not needed anymore (errors have been reported)
// process todo's (this only happens if check == nil)
for i := 0; i < len(todo); i += 2 {
@@ -287,24 +293,6 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet {
return ityp.tset
}
-func sortTypes(list []Type) {
- sort.Stable(byUniqueTypeName(list))
-}
-
-// byUniqueTypeName named type lists can be sorted by their unique type names.
-type byUniqueTypeName []Type
-
-func (a byUniqueTypeName) Len() int { return len(a) }
-func (a byUniqueTypeName) Less(i, j int) bool { return sortObj(a[i]).less(sortObj(a[j])) }
-func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-
-func sortObj(t Type) *object {
- if named := asNamed(t); named != nil {
- return &named.obj.object
- }
- return nil
-}
-
func sortMethods(list []*Func) {
sort.Sort(byUniqueMethodName(list))
}
diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go
index 0b1f7dacad..82e1221b67 100644
--- a/src/cmd/compile/internal/types2/sizeof_test.go
+++ b/src/cmd/compile/internal/types2/sizeof_test.go
@@ -28,7 +28,7 @@ func TestSizeof(t *testing.T) {
{Tuple{}, 12, 24},
{Signature{}, 44, 88},
{Union{}, 24, 48},
- {Interface{}, 40, 80},
+ {Interface{}, 44, 88},
{Map{}, 16, 32},
{Chan{}, 12, 24},
{Named{}, 84, 160},
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index 38bd07b8a2..db01c36f7a 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -316,7 +316,6 @@ func (subst *subster) typ(typ Type) Type {
if subst.check == nil {
panic("internal error: cannot instantiate interfaces yet")
}
- subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement
return iface
}
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index 122e408ead..2cfcabbdb5 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -264,10 +264,11 @@ func (s *Signature) Variadic() bool { return s.variadic }
// An Interface represents an interface type.
type Interface struct {
- obj Object // type name object defining this interface; or nil (for better error messages)
- methods []*Func // ordered list of explicitly declared methods
- embeddeds []Type // ordered list of explicitly embedded elements
- complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed
+ obj Object // type name object defining this interface; or nil (for better error messages)
+ methods []*Func // ordered list of explicitly declared methods
+ embeddeds []Type // ordered list of explicitly embedded elements
+ embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space
+ complete bool // indicates that all fields (except for tset) are set up
tset *TypeSet // type set described by this interface, computed lazily
}
@@ -322,7 +323,6 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
// sort for API stability
sortMethods(methods)
- sortTypes(embeddeds)
typ.methods = methods
typ.embeddeds = embeddeds