mirror of
https://github.com/golang/go
synced 2024-11-22 20:40:03 -07:00
[dev.typeparams] cmd/compile/internal/types2: implement package height
This CL extends types2 with package height information, styled after the way it works already in cmd/compile: - A new NewPackageHeight entry point for constructing packages with explicit height information, and a corresponding Height accessor method. - The types2 importer is updated to provide package height for imported packages. - The types2 type checker sets height based on imported packages. - Adds an assertion to irgen to verify that types1 and types2 calculated the same height for the source package. - Func.less's ordering incorporates package height to match types.Sym.less and is generalized to object.less. - sortTypes (used for sorting embedded types) now sorts defined types using object.less as well. Change-Id: Id4dbbb627aef405cc7438d611cbdd5a5bd97fc96 Reviewed-on: https://go-review.googlesource.com/c/go/+/321231 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Trust: Matthew Dempsky <mdempsky@google.com> Trust: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
3f6f12972b
commit
eff66248ea
@ -118,17 +118,22 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) (
|
|||||||
pkgPathOff := r.uint64()
|
pkgPathOff := r.uint64()
|
||||||
pkgPath := p.stringAt(pkgPathOff)
|
pkgPath := p.stringAt(pkgPathOff)
|
||||||
pkgName := p.stringAt(r.uint64())
|
pkgName := p.stringAt(r.uint64())
|
||||||
_ = r.uint64() // package height; unused by go/types
|
pkgHeight := int(r.uint64())
|
||||||
|
|
||||||
if pkgPath == "" {
|
if pkgPath == "" {
|
||||||
pkgPath = path
|
pkgPath = path
|
||||||
}
|
}
|
||||||
pkg := imports[pkgPath]
|
pkg := imports[pkgPath]
|
||||||
if pkg == nil {
|
if pkg == nil {
|
||||||
pkg = types2.NewPackage(pkgPath, pkgName)
|
pkg = types2.NewPackageHeight(pkgPath, pkgName, pkgHeight)
|
||||||
imports[pkgPath] = pkg
|
imports[pkgPath] = pkg
|
||||||
} else if pkg.Name() != pkgName {
|
} else {
|
||||||
errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
|
if pkg.Name() != pkgName {
|
||||||
|
errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
|
||||||
|
}
|
||||||
|
if pkg.Height() != pkgHeight {
|
||||||
|
errorf("conflicting heights %v and %v for package %q", pkg.Height(), pkgHeight, path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.pkgCache[pkgPathOff] = pkg
|
p.pkgCache[pkgPathOff] = pkg
|
||||||
|
@ -132,6 +132,7 @@ Outer:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(myheight == g.self.Height())
|
||||||
types.LocalPkg.Height = myheight
|
types.LocalPkg.Height = myheight
|
||||||
|
|
||||||
// 2. Process all package-block type declarations. As with imports,
|
// 2. Process all package-block type declarations. As with imports,
|
||||||
|
@ -186,6 +186,45 @@ func (obj *object) sameId(pkg *Package, name string) bool {
|
|||||||
return pkg.path == obj.pkg.path
|
return pkg.path == obj.pkg.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// less reports whether object a is ordered before object b.
|
||||||
|
//
|
||||||
|
// Objects are ordered nil before non-nil, exported before
|
||||||
|
// non-exported, then by name, and finally (for non-exported
|
||||||
|
// functions) by package height and path.
|
||||||
|
func (a *object) less(b *object) bool {
|
||||||
|
if a == b {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nil before non-nil.
|
||||||
|
if a == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if b == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exported functions before non-exported.
|
||||||
|
ea := isExported(a.name)
|
||||||
|
eb := isExported(b.name)
|
||||||
|
if ea != eb {
|
||||||
|
return ea
|
||||||
|
}
|
||||||
|
|
||||||
|
// Order by name and then (for non-exported names) by package.
|
||||||
|
if a.name != b.name {
|
||||||
|
return a.name < b.name
|
||||||
|
}
|
||||||
|
if !ea {
|
||||||
|
if a.pkg.height != b.pkg.height {
|
||||||
|
return a.pkg.height < b.pkg.height
|
||||||
|
}
|
||||||
|
return a.pkg.path < b.pkg.path
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// A PkgName represents an imported Go package.
|
// A PkgName represents an imported Go package.
|
||||||
// PkgNames don't have a type.
|
// PkgNames don't have a type.
|
||||||
type PkgName struct {
|
type PkgName struct {
|
||||||
@ -329,36 +368,6 @@ func (obj *Func) FullName() string {
|
|||||||
// Scope returns the scope of the function's body block.
|
// Scope returns the scope of the function's body block.
|
||||||
func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
|
func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
|
||||||
|
|
||||||
// Less reports whether function a is ordered before function b.
|
|
||||||
//
|
|
||||||
// Functions are ordered exported before non-exported, then by name,
|
|
||||||
// and finally (for non-exported functions) by package path.
|
|
||||||
//
|
|
||||||
// TODO(gri) The compiler also sorts by package height before package
|
|
||||||
// path for non-exported names.
|
|
||||||
func (a *Func) less(b *Func) bool {
|
|
||||||
if a == b {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exported functions before non-exported.
|
|
||||||
ea := isExported(a.name)
|
|
||||||
eb := isExported(b.name)
|
|
||||||
if ea != eb {
|
|
||||||
return ea
|
|
||||||
}
|
|
||||||
|
|
||||||
// Order by name and then (for non-exported names) by package.
|
|
||||||
if a.name != b.name {
|
|
||||||
return a.name < b.name
|
|
||||||
}
|
|
||||||
if !ea {
|
|
||||||
return a.pkg.path < b.pkg.path
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Func) isDependency() {} // a function may be a dependency of an initialization expression
|
func (*Func) isDependency() {} // a function may be a dependency of an initialization expression
|
||||||
|
|
||||||
// A Label represents a declared label.
|
// A Label represents a declared label.
|
||||||
|
@ -13,8 +13,9 @@ type Package struct {
|
|||||||
path string
|
path string
|
||||||
name string
|
name string
|
||||||
scope *Scope
|
scope *Scope
|
||||||
complete bool
|
|
||||||
imports []*Package
|
imports []*Package
|
||||||
|
height int
|
||||||
|
complete bool
|
||||||
fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
|
fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
|
||||||
cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
|
cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
|
||||||
}
|
}
|
||||||
@ -22,8 +23,14 @@ type Package struct {
|
|||||||
// NewPackage returns a new Package for the given package path and name.
|
// NewPackage returns a new Package for the given package path and name.
|
||||||
// The package is not complete and contains no explicit imports.
|
// The package is not complete and contains no explicit imports.
|
||||||
func NewPackage(path, name string) *Package {
|
func NewPackage(path, name string) *Package {
|
||||||
|
return NewPackageHeight(path, name, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPackageHeight is like NewPackage, but allows specifying the
|
||||||
|
// package's height.
|
||||||
|
func NewPackageHeight(path, name string, height int) *Package {
|
||||||
scope := NewScope(Universe, nopos, nopos, fmt.Sprintf("package %q", path))
|
scope := NewScope(Universe, nopos, nopos, fmt.Sprintf("package %q", path))
|
||||||
return &Package{path: path, name: name, scope: scope}
|
return &Package{path: path, name: name, scope: scope, height: height}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path returns the package path.
|
// Path returns the package path.
|
||||||
@ -32,6 +39,9 @@ func (pkg *Package) Path() string { return pkg.path }
|
|||||||
// Name returns the package name.
|
// Name returns the package name.
|
||||||
func (pkg *Package) Name() string { return pkg.name }
|
func (pkg *Package) Name() string { return pkg.name }
|
||||||
|
|
||||||
|
// Height returns the package height.
|
||||||
|
func (pkg *Package) Height() int { return pkg.height }
|
||||||
|
|
||||||
// SetName sets the package name.
|
// SetName sets the package name.
|
||||||
func (pkg *Package) SetName(name string) { pkg.name = name }
|
func (pkg *Package) SetName(name string) { pkg.name = name }
|
||||||
|
|
||||||
|
@ -196,6 +196,7 @@ func (check *Checker) importPackage(pos syntax.Pos, path, dir string) *Package {
|
|||||||
// methods with receiver base type names.
|
// methods with receiver base type names.
|
||||||
func (check *Checker) collectObjects() {
|
func (check *Checker) collectObjects() {
|
||||||
pkg := check.pkg
|
pkg := check.pkg
|
||||||
|
pkg.height = 0
|
||||||
|
|
||||||
// pkgImports is the set of packages already imported by any package file seen
|
// pkgImports is the set of packages already imported by any package file seen
|
||||||
// so far. Used to avoid duplicate entries in pkg.imports. Allocate and populate
|
// so far. Used to avoid duplicate entries in pkg.imports. Allocate and populate
|
||||||
@ -253,6 +254,15 @@ func (check *Checker) collectObjects() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if imp == Unsafe {
|
||||||
|
// typecheck ignores imports of package unsafe for
|
||||||
|
// calculating height.
|
||||||
|
// TODO(mdempsky): Revisit this. This seems fine, but I
|
||||||
|
// don't remember explicitly considering this case.
|
||||||
|
} else if h := imp.height + 1; h > pkg.height {
|
||||||
|
pkg.height = h
|
||||||
|
}
|
||||||
|
|
||||||
// local name overrides imported package name
|
// local name overrides imported package name
|
||||||
name := imp.name
|
name := imp.name
|
||||||
if s.LocalPkgName != nil {
|
if s.LocalPkgName != nil {
|
||||||
|
@ -1055,14 +1055,14 @@ func sortTypes(list []Type) {
|
|||||||
type byUniqueTypeName []Type
|
type byUniqueTypeName []Type
|
||||||
|
|
||||||
func (a byUniqueTypeName) Len() int { return len(a) }
|
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) 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 (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
|
||||||
func sortName(t Type) string {
|
func sortObj(t Type) *object {
|
||||||
if named := asNamed(t); named != nil {
|
if named := asNamed(t); named != nil {
|
||||||
return named.obj.Id()
|
return &named.obj.object
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortMethods(list []*Func) {
|
func sortMethods(list []*Func) {
|
||||||
@ -1082,7 +1082,7 @@ func assertSortedMethods(list []*Func) {
|
|||||||
type byUniqueMethodName []*Func
|
type byUniqueMethodName []*Func
|
||||||
|
|
||||||
func (a byUniqueMethodName) Len() int { return len(a) }
|
func (a byUniqueMethodName) Len() int { return len(a) }
|
||||||
func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(a[j]) }
|
func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) }
|
||||||
func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
|
||||||
func (check *Checker) tag(t *syntax.BasicLit) string {
|
func (check *Checker) tag(t *syntax.BasicLit) string {
|
||||||
|
Loading…
Reference in New Issue
Block a user