mirror of
https://github.com/golang/go
synced 2024-11-02 08:01:26 +00:00
[dev.typeparams] go/types: move embedding positions from Checker to Interface
This is a straightforward port of CL 331514 to go/types, with minor adjustments for the different position API. Change-Id: I714b3f1cd5a0e8d249912bb589d456885a87e167 Reviewed-on: https://go-review.googlesource.com/c/go/+/335030 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
b98b8b9b5b
commit
fe4f13404d
5 changed files with 30 additions and 45 deletions
|
@ -89,7 +89,6 @@ type Checker struct {
|
||||||
nextID uint64 // unique Id for type parameters (first valid Id is 1)
|
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
|
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
|
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
|
||||||
posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
|
|
||||||
typMap map[string]*Named // maps an instantiated named type hash to a *Named type
|
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
|
// pkgPathMap maps package names to the set of distinct import paths we've
|
||||||
|
@ -193,7 +192,6 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
|
||||||
version: version,
|
version: version,
|
||||||
objMap: make(map[Object]*declInfo),
|
objMap: make(map[Object]*declInfo),
|
||||||
impMap: make(map[importKey]*Package),
|
impMap: make(map[importKey]*Package),
|
||||||
posMap: make(map[*Interface][]token.Pos),
|
|
||||||
typMap: make(map[string]*Named),
|
typMap: make(map[string]*Named),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,18 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||||
var tlist []ast.Expr
|
var tlist []ast.Expr
|
||||||
var tname *ast.Ident // "type" name of first entry in a type list declaration
|
var tname *ast.Ident // "type" name of first entry in a type list declaration
|
||||||
|
|
||||||
|
addEmbedded := func(pos token.Pos, typ Type) {
|
||||||
|
ityp.embeddeds = append(ityp.embeddeds, typ)
|
||||||
|
if ityp.embedPos == nil {
|
||||||
|
ityp.embedPos = new([]token.Pos)
|
||||||
|
}
|
||||||
|
*ityp.embedPos = append(*ityp.embedPos, pos)
|
||||||
|
}
|
||||||
|
|
||||||
for _, f := range iface.Methods.List {
|
for _, f := range iface.Methods.List {
|
||||||
if len(f.Names) == 0 {
|
if len(f.Names) == 0 {
|
||||||
// We have an embedded type; possibly a union of types.
|
// We have an embedded type; possibly a union of types.
|
||||||
ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, flattenUnion(nil, f.Type)))
|
addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type)))
|
||||||
check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos())
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,10 +99,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||||
|
|
||||||
// type constraints
|
// type constraints
|
||||||
if tlist != nil {
|
if tlist != nil {
|
||||||
ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, tlist))
|
// TODO(rfindley): this differs from types2 due to the use of Pos() below,
|
||||||
// Types T in a type list are added as ~T expressions but we don't
|
// which should actually be on the ~. Confirm that this position is correct.
|
||||||
// have the position of the '~'. Use the first type position instead.
|
addEmbedded(tlist[0].Pos(), parseUnion(check, tlist))
|
||||||
check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*ast.UnaryExpr).X.Pos())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All methods and embedded elements for this interface are collected;
|
// All methods and embedded elements for this interface are collected;
|
||||||
|
@ -110,7 +116,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||||
|
|
||||||
// sort for API stability
|
// sort for API stability
|
||||||
sortMethods(ityp.methods)
|
sortMethods(ityp.methods)
|
||||||
sortTypes(ityp.embeddeds)
|
// (don't sort embeddeds: they must correspond to *embedPos entries)
|
||||||
|
|
||||||
// Compute type set with a non-nil *Checker as soon as possible
|
// Compute type set with a non-nil *Checker as soon as possible
|
||||||
// to report any errors. Subsequent uses of type sets should be
|
// to report any errors. Subsequent uses of type sets should be
|
||||||
|
@ -226,14 +232,13 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet {
|
||||||
|
|
||||||
// collect embedded elements
|
// collect embedded elements
|
||||||
var allTypes Type
|
var allTypes Type
|
||||||
var posList []token.Pos
|
|
||||||
if check != nil {
|
|
||||||
posList = check.posMap[ityp]
|
|
||||||
}
|
|
||||||
for i, typ := range ityp.embeddeds {
|
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 token.Pos // embedding position
|
var pos token.Pos // embedding position
|
||||||
if posList != nil {
|
if ityp.embedPos != nil {
|
||||||
pos = posList[i]
|
pos = (*ityp.embedPos)[i]
|
||||||
}
|
}
|
||||||
var types Type
|
var types Type
|
||||||
switch t := under(typ).(type) {
|
switch t := under(typ).(type) {
|
||||||
|
@ -268,6 +273,7 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet {
|
||||||
}
|
}
|
||||||
allTypes = intersect(allTypes, types)
|
allTypes = intersect(allTypes, types)
|
||||||
}
|
}
|
||||||
|
ityp.embedPos = nil // not needed anymore (errors have been reported)
|
||||||
|
|
||||||
// process todo's (this only happens if check == nil)
|
// process todo's (this only happens if check == nil)
|
||||||
for i := 0; i < len(todo); i += 2 {
|
for i := 0; i < len(todo); i += 2 {
|
||||||
|
@ -287,24 +293,6 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet {
|
||||||
return ityp.tset
|
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 sortName(a[i]) < sortName(a[j]) }
|
|
||||||
func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
||||||
|
|
||||||
func sortName(t Type) string {
|
|
||||||
if named := asNamed(t); named != nil {
|
|
||||||
return named.obj.Id()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func sortMethods(list []*Func) {
|
func sortMethods(list []*Func) {
|
||||||
sort.Sort(byUniqueMethodName(list))
|
sort.Sort(byUniqueMethodName(list))
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) {
|
||||||
{Tuple{}, 12, 24},
|
{Tuple{}, 12, 24},
|
||||||
{Signature{}, 44, 88},
|
{Signature{}, 44, 88},
|
||||||
{Union{}, 24, 48},
|
{Union{}, 24, 48},
|
||||||
{Interface{}, 40, 80},
|
{Interface{}, 44, 88},
|
||||||
{Map{}, 16, 32},
|
{Map{}, 16, 32},
|
||||||
{Chan{}, 12, 24},
|
{Chan{}, 12, 24},
|
||||||
{Named{}, 84, 160},
|
{Named{}, 84, 160},
|
||||||
|
|
|
@ -320,7 +320,6 @@ func (subst *subster) typ(typ Type) Type {
|
||||||
if subst.check == nil {
|
if subst.check == nil {
|
||||||
panic("internal error: cannot instantiate interfaces yet")
|
panic("internal error: cannot instantiate interfaces yet")
|
||||||
}
|
}
|
||||||
subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement
|
|
||||||
return iface
|
return iface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,7 @@ type Interface struct {
|
||||||
obj Object // type name object defining this interface; or nil (for better error messages)
|
obj Object // type name object defining this interface; or nil (for better error messages)
|
||||||
methods []*Func // ordered list of explicitly declared methods
|
methods []*Func // ordered list of explicitly declared methods
|
||||||
embeddeds []Type // ordered list of explicitly embedded elements
|
embeddeds []Type // ordered list of explicitly embedded elements
|
||||||
|
embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space
|
||||||
complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed
|
complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed
|
||||||
|
|
||||||
tset *TypeSet // type set described by this interface, computed lazily
|
tset *TypeSet // type set described by this interface, computed lazily
|
||||||
|
@ -326,7 +327,6 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
|
||||||
|
|
||||||
// sort for API stability
|
// sort for API stability
|
||||||
sortMethods(methods)
|
sortMethods(methods)
|
||||||
sortTypes(embeddeds)
|
|
||||||
|
|
||||||
typ.methods = methods
|
typ.methods = methods
|
||||||
typ.embeddeds = embeddeds
|
typ.embeddeds = embeddeds
|
||||||
|
|
Loading…
Reference in a new issue