]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: implement package height
authorMatthew Dempsky <mdempsky@google.com>
Wed, 19 May 2021 02:03:00 +0000 (19:03 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 19 May 2021 21:53:04 +0000 (21:53 +0000)
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>
src/cmd/compile/internal/importer/iimport.go
src/cmd/compile/internal/noder/irgen.go
src/cmd/compile/internal/types2/object.go
src/cmd/compile/internal/types2/package.go
src/cmd/compile/internal/types2/resolver.go
src/cmd/compile/internal/types2/typexpr.go

index 5c02f837ef441dc0905ff31d682169a42f0ea9e4..b91b209d35ef8764ee4a964778cc08b5c3b3a316 100644 (file)
@@ -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
index 3e0d3285ab916ec0661ba9601149a3209138f02c..2a9f0e99d8a61cb27101dcb59970ce01ca640b9d 100644 (file)
@@ -132,6 +132,7 @@ Outer:
                        }
                }
        }
+       assert(myheight == g.self.Height())
        types.LocalPkg.Height = myheight
 
        // 2. Process all package-block type declarations. As with imports,
index 844bc34b6a3d1e7034880d667b48b1bedcef87f2..8ed55f1dbf9c28d12ecfa3bfea2534e8cbafa61d 100644 (file)
@@ -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.
index 31b1e7178771f5db37264b4886b8b3604e03b4b3..c5804a05adce008469e21128c93db895b3aff519 100644 (file)
@@ -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 }
 
index ef49a8b48dab1e0f3e4716dbc36b0303e496709f..9b1482b14e1b075471e65765f943093e4af8bfd4 100644 (file)
@@ -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 {
index a1663d2aa0c4d70d6e9e9ee1905db319c7eaa556..7fb914cd7ec4a42bbeab0e9ce014bae158c83fef 100644 (file)
@@ -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 {