mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00: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()
|
||||
pkgPath := p.stringAt(pkgPathOff)
|
||||
pkgName := p.stringAt(r.uint64())
|
||||
_ = r.uint64() // package height; unused by go/types
|
||||
pkgHeight := int(r.uint64())
|
||||
|
||||
if pkgPath == "" {
|
||||
pkgPath = path
|
||||
}
|
||||
pkg := imports[pkgPath]
|
||||
if pkg == nil {
|
||||
pkg = types2.NewPackage(pkgPath, pkgName)
|
||||
pkg = types2.NewPackageHeight(pkgPath, pkgName, pkgHeight)
|
||||
imports[pkgPath] = pkg
|
||||
} else if pkg.Name() != pkgName {
|
||||
errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
|
||||
} else {
|
||||
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
|
||||
|
|
|
@ -132,6 +132,7 @@ Outer:
|
|||
}
|
||||
}
|
||||
}
|
||||
assert(myheight == g.self.Height())
|
||||
types.LocalPkg.Height = myheight
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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.
|
||||
// PkgNames don't have a type.
|
||||
type PkgName struct {
|
||||
|
@ -329,36 +368,6 @@ func (obj *Func) FullName() string {
|
|||
// Scope returns the scope of the function's body block.
|
||||
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
|
||||
|
||||
// A Label represents a declared label.
|
||||
|
|
|
@ -13,8 +13,9 @@ type Package struct {
|
|||
path string
|
||||
name string
|
||||
scope *Scope
|
||||
complete bool
|
||||
imports []*Package
|
||||
height int
|
||||
complete bool
|
||||
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
|
||||
}
|
||||
|
@ -22,8 +23,14 @@ type Package struct {
|
|||
// NewPackage returns a new Package for the given package path and name.
|
||||
// The package is not complete and contains no explicit imports.
|
||||
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))
|
||||
return &Package{path: path, name: name, scope: scope}
|
||||
return &Package{path: path, name: name, scope: scope, height: height}
|
||||
}
|
||||
|
||||
// Path returns the package path.
|
||||
|
@ -32,6 +39,9 @@ func (pkg *Package) Path() string { return pkg.path }
|
|||
// Name returns the package 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.
|
||||
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.
|
||||
func (check *Checker) collectObjects() {
|
||||
pkg := check.pkg
|
||||
pkg.height = 0
|
||||
|
||||
// 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
|
||||
|
@ -253,6 +254,15 @@ func (check *Checker) collectObjects() {
|
|||
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
|
||||
name := imp.name
|
||||
if s.LocalPkgName != nil {
|
||||
|
|
|
@ -1055,14 +1055,14 @@ func sortTypes(list []Type) {
|
|||
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) 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 sortName(t Type) string {
|
||||
func sortObj(t Type) *object {
|
||||
if named := asNamed(t); named != nil {
|
||||
return named.obj.Id()
|
||||
return &named.obj.object
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortMethods(list []*Func) {
|
||||
|
@ -1082,7 +1082,7 @@ func assertSortedMethods(list []*Func) {
|
|||
type byUniqueMethodName []*Func
|
||||
|
||||
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 (check *Checker) tag(t *syntax.BasicLit) string {
|
||||
|
|
Loading…
Reference in a new issue