Skip to content

Commit 91c880c

Browse files
committed
go/internal/gcimporter: add support for exporting the 1.18 export format
This CL adds support for the Go 1.18 export format to iexport.go. This support is based on cmd/compile/internal/typecheck/iexport.go, though with a different types API and adjusted to build at Go versions below 1.18. Specifically, this CL adds support for both column details in positions, and generic types and functions. Along the way, some minor adjustments are made to aid in debugging and testing. Notably, after this CL the export data version produced by go/gcexportdata will depend on the Go version used to build. As part of this change, TestIExportData_stdlib is unskipped for Go 1.18. Fixes golang/go#48392 Change-Id: I1b218e0acd4864de5c7b89706192273bc7850ffa Reviewed-on: https://go-review.googlesource.com/c/tools/+/351029 Trust: Robert Findley <[email protected]> Run-TryBot: Robert Findley <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
1 parent d2417d5 commit 91c880c

10 files changed

+390
-72
lines changed

go/internal/gcimporter/bexport.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,18 @@ func internalErrorf(format string, args ...interface{}) error {
9292
// BExportData returns binary export data for pkg.
9393
// If no file set is provided, position info will be missing.
9494
func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
95-
defer func() {
96-
if e := recover(); e != nil {
97-
if ierr, ok := e.(internalError); ok {
98-
err = ierr
99-
return
95+
if !debug {
96+
defer func() {
97+
if e := recover(); e != nil {
98+
if ierr, ok := e.(internalError); ok {
99+
err = ierr
100+
return
101+
}
102+
// Not an internal error; panic again.
103+
panic(e)
100104
}
101-
// Not an internal error; panic again.
102-
panic(e)
103-
}
104-
}()
105+
}()
106+
}
105107

106108
p := exporter{
107109
fset: fset,

go/internal/gcimporter/bexport_test.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"golang.org/x/tools/go/buildutil"
2222
"golang.org/x/tools/go/internal/gcimporter"
2323
"golang.org/x/tools/go/loader"
24+
"golang.org/x/tools/internal/typeparams"
2425
)
2526

2627
var isRace = false
@@ -230,9 +231,14 @@ func equalType(x, y types.Type) error {
230231
}
231232
case *types.Named:
232233
y := y.(*types.Named)
233-
if x.String() != y.String() {
234+
xOrig := typeparams.NamedTypeOrigin(x)
235+
yOrig := typeparams.NamedTypeOrigin(y)
236+
if sanitizeName(xOrig.String()) != sanitizeName(yOrig.String()) {
234237
return fmt.Errorf("unequal named types: %s vs %s", x, y)
235238
}
239+
if err := equalTypeArgs(typeparams.NamedTypeArgs(x), typeparams.NamedTypeArgs(y)); err != nil {
240+
return fmt.Errorf("type arguments: %s", err)
241+
}
236242
case *types.Pointer:
237243
y := y.(*types.Pointer)
238244
if err := equalType(x.Elem(), y.Elem()); err != nil {
@@ -262,6 +268,12 @@ func equalType(x, y types.Type) error {
262268
// return fmt.Errorf("receiver: %s", err)
263269
// }
264270
}
271+
if err := equalTypeParams(typeparams.ForSignature(x), typeparams.ForSignature(y)); err != nil {
272+
return fmt.Errorf("type params: %s", err)
273+
}
274+
if err := equalTypeParams(typeparams.RecvTypeParams(x), typeparams.RecvTypeParams(y)); err != nil {
275+
return fmt.Errorf("recv type params: %s", err)
276+
}
265277
case *types.Slice:
266278
y := y.(*types.Slice)
267279
if err := equalType(x.Elem(), y.Elem()); err != nil {
@@ -297,10 +309,63 @@ func equalType(x, y types.Type) error {
297309
return fmt.Errorf("tuple element %d: %s", i, err)
298310
}
299311
}
312+
case *typeparams.TypeParam:
313+
y := y.(*typeparams.TypeParam)
314+
if sanitizeName(x.String()) != sanitizeName(y.String()) {
315+
return fmt.Errorf("unequal named types: %s vs %s", x, y)
316+
}
317+
// For now, just compare constraints by type string to short-circuit
318+
// cycles.
319+
xc := sanitizeName(x.Constraint().String())
320+
yc := sanitizeName(y.Constraint().String())
321+
if xc != yc {
322+
return fmt.Errorf("unequal constraints: %s vs %s", xc, yc)
323+
}
324+
325+
default:
326+
panic(fmt.Sprintf("unexpected %T type", x))
327+
}
328+
return nil
329+
}
330+
331+
func equalTypeArgs(x, y *typeparams.TypeList) error {
332+
if x.Len() != y.Len() {
333+
return fmt.Errorf("unequal lengths: %d vs %d", x.Len(), y.Len())
334+
}
335+
for i := 0; i < x.Len(); i++ {
336+
if err := equalType(x.At(i), y.At(i)); err != nil {
337+
return fmt.Errorf("type %d: %s", i, err)
338+
}
339+
}
340+
return nil
341+
}
342+
343+
func equalTypeParams(x, y *typeparams.TypeParamList) error {
344+
if x.Len() != y.Len() {
345+
return fmt.Errorf("unequal lengths: %d vs %d", x.Len(), y.Len())
346+
}
347+
for i := 0; i < x.Len(); i++ {
348+
if err := equalType(x.At(i), y.At(i)); err != nil {
349+
return fmt.Errorf("type parameter %d: %s", i, err)
350+
}
300351
}
301352
return nil
302353
}
303354

355+
// sanitizeName removes type parameter debugging markers from an object
356+
// or type string, to normalize it for comparison.
357+
// TODO(rfindley): remove once this is no longer necessary.
358+
func sanitizeName(name string) string {
359+
var runes []rune
360+
for _, r := range name {
361+
if '₀' <= r && r < '₀'+10 {
362+
continue // trim type parameter subscripts
363+
}
364+
runes = append(runes, r)
365+
}
366+
return string(runes)
367+
}
368+
304369
// TestVeryLongFile tests the position of an import object declared in
305370
// a very long input file. Line numbers greater than maxlines are
306371
// reported as line 1, not garbage or token.NoPos.

0 commit comments

Comments
 (0)