mirror of
https://github.com/golang/go
synced 2024-11-26 04:07:59 -07:00
[dev.typeparams] cmd/compile/internal/types2: move embedding positions from Checker to Interface
This change moves the position information to the place where it is actually used. It also simplifies getting rid of it after use. In the process, fixed a latent bug: Before this CL, embedded types were sorted, but the corresponding embedding positions were not. Removed the sorting altogether as it is not needed for type-checking. Change-Id: I48003f317196d814326424430336b6cb222fdee6 Reviewed-on: https://go-review.googlesource.com/c/go/+/331514 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
1ff43d1b17
commit
f0206e3df2
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user