aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2022-08-18 11:04:21 -0700
committerMatthew Dempsky <mdempsky@google.com>2022-12-07 03:44:27 +0000
commitdddc1ba847467524c397eda22b69862773e9f21a (patch)
treecb98bef266b51e6ecde8ed1a3a32f8640c84e42e
parent8cd931ff0d4652b333996299d63603c659dbcc6c (diff)
downloadgo-dddc1ba847467524c397eda22b69862773e9f21a.tar.gz
go-dddc1ba847467524c397eda22b69862773e9f21a.zip
cmd/compile: restore test/nested.go test cases
[Re-land of CL 424854, which was reverted as CL 425214.] When handling a type declaration like: ``` type B A ``` unified IR has been writing out that B's underlying type is A, rather than the underlying type of A. This is a bit awkward to implement and adds complexity to importers, who need to handle resolving the underlying type themselves. But it was necessary to handle when A was declared like: ``` //go:notinheap type A int ``` Because we expected A's not-in-heap'ness to be conferred to B, which required knowing that A was on the path from B to its actual underlying type int. However, since #46731 was accepted, we no longer need to support this case. Instead we can write out B's actual underlying type. One stumbling point though is the existing code for exporting interfaces doesn't work for the underlying type of `comparable`, which is now needed to implement `type C comparable`. As a bit of a hack, we we instead export its underlying type as `interface{ comparable }`. Fixes #54512. Change-Id: I9aa087e0a277527003195ebc7f4fbba6922e788c Reviewed-on: https://go-review.googlesource.com/c/go/+/455279 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com>
-rw-r--r--src/cmd/compile/internal/noder/writer.go39
1 files changed, 23 insertions, 16 deletions
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 262e2020c8..da5c1e910d 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -442,8 +442,9 @@ func (pw *pkgWriter) pkgIdx(pkg *types2.Package) pkgbits.Index {
// @@@ Types
var (
- anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName)
- runeTypeName = types2.Universe.Lookup("rune").(*types2.TypeName)
+ anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName)
+ comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName)
+ runeTypeName = types2.Universe.Lookup("rune").(*types2.TypeName)
)
// typ writes a use of the given type into the bitstream.
@@ -495,7 +496,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
w.Len(int(kind))
default:
- // Handle "byte" and "rune" as references to their TypeName.
+ // Handle "byte" and "rune" as references to their TypeNames.
obj := types2.Universe.Lookup(typ.Name())
assert(obj.Type() == typ)
@@ -553,6 +554,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
w.structType(typ)
case *types2.Interface:
+ // Handle "any" as reference to its TypeName.
if typ == anyTypeName.Type() {
w.Code(pkgbits.TypeNamed)
w.obj(anyTypeName, nil)
@@ -600,6 +602,23 @@ func (w *writer) unionType(typ *types2.Union) {
}
func (w *writer) interfaceType(typ *types2.Interface) {
+ // If typ has no embedded types but it's not a basic interface, then
+ // the natural description we write out below will fail to
+ // reconstruct it.
+ if typ.NumEmbeddeds() == 0 && !typ.IsMethodSet() {
+ // Currently, this can only happen for the underlying Interface of
+ // "comparable", which is needed to handle type declarations like
+ // "type C comparable".
+ assert(typ == comparableTypeName.Type().(*types2.Named).Underlying())
+
+ // Export as "interface{ comparable }".
+ w.Len(0) // NumExplicitMethods
+ w.Len(1) // NumEmbeddeds
+ w.Bool(false) // IsImplicit
+ w.typ(comparableTypeName.Type()) // EmbeddedType(0)
+ return
+ }
+
w.Len(typ.NumExplicitMethods())
w.Len(typ.NumEmbeddeds())
@@ -785,9 +804,6 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
return pkgbits.ObjFunc
case *types2.TypeName:
- decl, ok := w.p.typDecls[obj]
- assert(ok)
-
if obj.IsAlias() {
w.pos(obj)
w.typ(obj.Type())
@@ -800,7 +816,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
w.pos(obj)
w.typeParamNames(named.TypeParams())
wext.typeExt(obj)
- w.typExpr(decl.Type)
+ w.typ(named.Underlying())
w.Len(named.NumMethods())
for i := 0; i < named.NumMethods(); i++ {
@@ -817,15 +833,6 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
}
}
-// typExpr writes the type represented by the given expression.
-//
-// TODO(mdempsky): Document how this differs from exprType.
-func (w *writer) typExpr(expr syntax.Expr) {
- tv := w.p.typeAndValue(expr)
- assert(tv.IsType())
- w.typ(tv.Type)
-}
-
// objDict writes the dictionary needed for reading the given object.
func (w *writer) objDict(obj types2.Object, dict *writerDict) {
// TODO(mdempsky): Split objDict into multiple entries? reader.go