]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/noder: write V2 bitstream aliastypeparams=1
authorTim King <taking@google.com>
Mon, 26 Aug 2024 22:49:09 +0000 (15:49 -0700)
committerTim King <taking@google.com>
Wed, 28 Aug 2024 21:03:29 +0000 (21:03 +0000)
Enables V2 unified IR bitstreams when GOEXPERIMENT aliastypeparams
are enabled.

Allows pkgbits.NewPkgEncoder to set the output version.
Reenables support for writing V0 streams.

Updates #68778
Updates #68526

Change-Id: I590c494d81ab7db148232ceaba52229068d1e986
Reviewed-on: https://go-review.googlesource.com/c/go/+/608595
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/noder/unified.go
src/cmd/compile/internal/noder/writer.go
src/internal/pkgbits/decoder.go
src/internal/pkgbits/encoder.go
src/internal/pkgbits/pkgbits_test.go
test/fixedbugs/issue68526.dir/a/a.go
test/fixedbugs/issue68526.dir/main.go

index ead348f0c12b89811143a4a6e530b2184cbb7736..c8dbc43e67ab29d3ad524335bc3bebfc7b47bf82 100644 (file)
@@ -6,6 +6,7 @@ package noder
 
 import (
        "fmt"
+       "internal/buildcfg"
        "internal/pkgbits"
        "internal/types/errors"
        "io"
@@ -462,8 +463,13 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) {
 // writeUnifiedExport writes to `out` the finalized, self-contained
 // Unified IR export data file for the current compilation unit.
 func writeUnifiedExport(out io.Writer) {
+       // Use V2 as the encoded version aliastypeparams GOEXPERIMENT is enabled.
+       version := pkgbits.V1
+       if buildcfg.Experiment.AliasTypeParams {
+               version = pkgbits.V2
+       }
        l := linker{
-               pw: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
+               pw: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
 
                pkgs:   make(map[string]index),
                decls:  make(map[*types.Sym]index),
index 695fdcceea760256f65d521c6d0943f29b50c78d..564087d9123868a3adba485bad2a490ce01c6950 100644 (file)
@@ -96,8 +96,13 @@ type pkgWriter struct {
 // newPkgWriter returns an initialized pkgWriter for the specified
 // package.
 func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
+       // Use V2 as the encoded version aliastypeparams GOEXPERIMENT is enabled.
+       version := pkgbits.V1
+       if buildcfg.Experiment.AliasTypeParams {
+               version = pkgbits.V2
+       }
        return &pkgWriter{
-               PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
+               PkgEncoder: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
 
                m:                     m,
                curpkg:                pkg,
@@ -864,8 +869,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
                        if w.Version().Has(pkgbits.AliasTypeParamNames) {
                                w.typeParamNames(tparams)
                        }
-                       // TODO(taking): enable this assertion once this is not intended to be a nop.
-                       // assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
+                       assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
                        w.typ(rhs)
                        return pkgbits.ObjAlias
                }
index ca66446dbabda1d434bff2ef48a5ffe2640409a5..09f26a84bd4a3f8608911cdeaadcce0cc3fab777 100644 (file)
@@ -82,8 +82,8 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
        assert(binary.Read(r, binary.LittleEndian, &ver) == nil)
        pr.version = Version(ver)
 
-       if pr.version >= V2 { // TODO(taking): Switch to numVersions.
-               panic(fmt.Errorf("cannot decode %q, export data version %d is too new", pkgPath, pr.version))
+       if pr.version >= numVersions {
+               panic(fmt.Errorf("cannot decode %q, export data version %d is greater than maximum supported version %d", pkgPath, pr.version, numVersions-1))
        }
 
        if pr.version.Has(Flags) {
@@ -101,7 +101,9 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
        assert(err == nil)
 
        pr.elemData = input[pos:]
-       assert(len(pr.elemData)-8 == int(pr.elemEnds[len(pr.elemEnds)-1]))
+
+       const fingerprintSize = 8
+       assert(len(pr.elemData)-fingerprintSize == int(pr.elemEnds[len(pr.elemEnds)-1]))
 
        return pr
 }
index b632b58ca016ec45efe54994a4fb7610ce827602..c17a12399d05971e5755124c1fec80a3e8b92ac0 100644 (file)
@@ -15,9 +15,6 @@ import (
        "strings"
 )
 
-// currentVersion is the current version number written.
-const currentVersion = V1
-
 // A PkgEncoder provides methods for encoding a package's Unified IR
 // export data.
 type PkgEncoder struct {
@@ -47,10 +44,9 @@ func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
 // export data files, but can help diagnosing desync errors in
 // higher-level Unified IR reader/writer code. If syncFrames is
 // negative, then sync markers are omitted entirely.
-func NewPkgEncoder(syncFrames int) PkgEncoder {
+func NewPkgEncoder(version Version, syncFrames int) PkgEncoder {
        return PkgEncoder{
-               // TODO(taking): Change NewPkgEncoder to take a version as an argument, and remove currentVersion.
-               version:    currentVersion,
+               version:    version,
                stringsIdx: make(map[string]Index),
                syncFrames: syncFrames,
        }
@@ -68,11 +64,13 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {
 
        writeUint32(uint32(pw.version))
 
-       var flags uint32
-       if pw.SyncMarkers() {
-               flags |= flagSyncMarkers
+       if pw.version.Has(Flags) {
+               var flags uint32
+               if pw.SyncMarkers() {
+                       flags |= flagSyncMarkers
+               }
+               writeUint32(flags)
        }
-       writeUint32(flags)
 
        // Write elemEndsEnds.
        var sum uint32
index f4c3719446f58ec696247ac09691a9231d4e86a7..6f4004741b8d340a8f9200517d24f82b2d80dace 100644 (file)
@@ -11,19 +11,25 @@ import (
 )
 
 func TestRoundTrip(t *testing.T) {
-       pw := pkgbits.NewPkgEncoder(-1)
-       w := pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)
-       w.Flush()
+       for _, version := range []pkgbits.Version{
+               pkgbits.V0,
+               pkgbits.V1,
+               pkgbits.V2,
+       } {
+               pw := pkgbits.NewPkgEncoder(version, -1)
+               w := pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)
+               w.Flush()
 
-       var b strings.Builder
-       _ = pw.DumpTo(&b)
-       input := b.String()
+               var b strings.Builder
+               _ = pw.DumpTo(&b)
+               input := b.String()
 
-       pr := pkgbits.NewPkgDecoder("package_id", input)
-       r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
+               pr := pkgbits.NewPkgDecoder("package_id", input)
+               r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
 
-       if r.Version() != w.Version() {
-               t.Errorf("Expected reader version %q to be the writer version %q", r.Version(), w.Version())
+               if r.Version() != w.Version() {
+                       t.Errorf("Expected reader version %q to be the writer version %q", r.Version(), w.Version())
+               }
        }
 }
 
index 7c2961c28f08010bdf5d5dbc533443f5c4f3977a..83462c7fb99c86d383d2a2915122886dd7ec5ae6 100644 (file)
@@ -6,8 +6,7 @@
 
 package a
 
-// TODO(#68778): enable once type parameterized aliases are allowed in exportdata.
-// type A[T any] = struct{ F T }
+type A[T any] = struct{ F T }
 
 type B = struct{ F int }
 
index 0353ca5daaa181df429dd76787b06cc6681684f8..966efd71900234d8a2eca3ba49215c8aeefda0ea 100644 (file)
@@ -7,12 +7,14 @@
 package main
 
 import (
+       "fmt"
+
        "issue68526.dir/a"
 )
 
 func main() {
        unexported()
-       // exported()
+       exported()
 }
 
 func unexported() {
@@ -23,23 +25,21 @@ func unexported() {
        }
 }
 
-// TODO(#68778): enable once type parameterized aliases are allowed in exportdata.
-
-// func exported() {
-//     var (
-//             astr a.A[string]
-//             aint a.A[int]
-//     )
+func exported() {
+       var (
+               astr a.A[string]
+               aint a.A[int]
+       )
 
-//     if any(astr) != any(struct{ F string }{}) || any(aint) != any(struct{ F int }{}) {
-//             panic("zero value of alias and concrete type not identical")
-//     }
+       if any(astr) != any(struct{ F string }{}) || any(aint) != any(struct{ F int }{}) {
+               panic("zero value of alias and concrete type not identical")
+       }
 
-//     if any(astr) == any(aint) {
-//             panic("zero value of struct{ F string } and struct{ F int } are not distinct")
-//     }
+       if any(astr) == any(aint) {
+               panic("zero value of struct{ F string } and struct{ F int } are not distinct")
+       }
 
-//     if got := fmt.Sprintf("%T", astr); got != "struct { F string }" {
-//             panic(got)
-//     }
-// }
+       if got := fmt.Sprintf("%T", astr); got != "struct { F string }" {
+               panic(got)
+       }
+}