mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
go/internal/gcimporter: return error from BExportData
This change adds an error return value to BExportData and replaces the various calls to log.Fatal within that library with panics that propagate the internal error up the call stack to BExportData which recovers and returns the error. Fixes golang/go#25431 Change-Id: Id628c63a04145bb469bd6fbc7fbab1b0fa291b2c Reviewed-on: https://go-review.googlesource.com/113457 Reviewed-by: David Symonds <dsymonds@golang.org> Reviewed-by: Rob Pike <r@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
48418e5732
commit
28aef64757
@ -92,6 +92,10 @@ func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package,
|
||||
// Write writes encoded type information for the specified package to out.
|
||||
// The FileSet provides file position information for named objects.
|
||||
func Write(out io.Writer, fset *token.FileSet, pkg *types.Package) error {
|
||||
_, err := out.Write(gcimporter.BExportData(fset, pkg))
|
||||
b, err := gcimporter.BExportData(fset, pkg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = out.Write(b)
|
||||
return err
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import (
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
@ -76,9 +75,29 @@ type exporter struct {
|
||||
indent int // for trace
|
||||
}
|
||||
|
||||
// internalError represents an error generated inside this package.
|
||||
type internalError string
|
||||
|
||||
func (e internalError) Error() string { return "gcimporter: " + string(e) }
|
||||
|
||||
func internalErrorf(format string, args ...interface{}) error {
|
||||
return internalError(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// BExportData returns binary export data for pkg.
|
||||
// If no file set is provided, position info will be missing.
|
||||
func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
|
||||
func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
if ierr, ok := e.(internalError); ok {
|
||||
err = ierr
|
||||
return
|
||||
}
|
||||
// Not an internal error; panic again.
|
||||
panic(e)
|
||||
}
|
||||
}()
|
||||
|
||||
p := exporter{
|
||||
fset: fset,
|
||||
strIndex: map[string]int{"": 0}, // empty string is mapped to 0
|
||||
@ -107,7 +126,7 @@ func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
|
||||
p.typIndex[typ] = index
|
||||
}
|
||||
if len(p.typIndex) != len(predeclared) {
|
||||
log.Fatalf("gcimporter: duplicate entries in type map?")
|
||||
return nil, internalError("duplicate entries in type map?")
|
||||
}
|
||||
|
||||
// write package data
|
||||
@ -145,12 +164,12 @@ func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
|
||||
|
||||
// --- end of export data ---
|
||||
|
||||
return p.out.Bytes()
|
||||
return p.out.Bytes(), nil
|
||||
}
|
||||
|
||||
func (p *exporter) pkg(pkg *types.Package, emptypath bool) {
|
||||
if pkg == nil {
|
||||
log.Fatalf("gcimporter: unexpected nil pkg")
|
||||
panic(internalError("unexpected nil pkg"))
|
||||
}
|
||||
|
||||
// if we saw the package before, write its index (>= 0)
|
||||
@ -209,7 +228,7 @@ func (p *exporter) obj(obj types.Object) {
|
||||
p.paramList(sig.Results(), false)
|
||||
|
||||
default:
|
||||
log.Fatalf("gcimporter: unexpected object %v (%T)", obj, obj)
|
||||
panic(internalErrorf("unexpected object %v (%T)", obj, obj))
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,7 +292,7 @@ func (p *exporter) qualifiedName(obj types.Object) {
|
||||
|
||||
func (p *exporter) typ(t types.Type) {
|
||||
if t == nil {
|
||||
log.Fatalf("gcimporter: nil type")
|
||||
panic(internalError("nil type"))
|
||||
}
|
||||
|
||||
// Possible optimization: Anonymous pointer types *T where
|
||||
@ -356,7 +375,7 @@ func (p *exporter) typ(t types.Type) {
|
||||
p.typ(t.Elem())
|
||||
|
||||
default:
|
||||
log.Fatalf("gcimporter: unexpected type %T: %s", t, t)
|
||||
panic(internalErrorf("unexpected type %T: %s", t, t))
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,7 +441,7 @@ func (p *exporter) fieldList(t *types.Struct) {
|
||||
|
||||
func (p *exporter) field(f *types.Var) {
|
||||
if !f.IsField() {
|
||||
log.Fatalf("gcimporter: field expected")
|
||||
panic(internalError("field expected"))
|
||||
}
|
||||
|
||||
p.pos(f)
|
||||
@ -452,7 +471,7 @@ func (p *exporter) iface(t *types.Interface) {
|
||||
func (p *exporter) method(m *types.Func) {
|
||||
sig := m.Type().(*types.Signature)
|
||||
if sig.Recv() == nil {
|
||||
log.Fatalf("gcimporter: method expected")
|
||||
panic(internalError("method expected"))
|
||||
}
|
||||
|
||||
p.pos(m)
|
||||
@ -575,13 +594,13 @@ func (p *exporter) value(x constant.Value) {
|
||||
p.tag(unknownTag)
|
||||
|
||||
default:
|
||||
log.Fatalf("gcimporter: unexpected value %v (%T)", x, x)
|
||||
panic(internalErrorf("unexpected value %v (%T)", x, x))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) float(x constant.Value) {
|
||||
if x.Kind() != constant.Float {
|
||||
log.Fatalf("gcimporter: unexpected constant %v, want float", x)
|
||||
panic(internalErrorf("unexpected constant %v, want float", x))
|
||||
}
|
||||
// extract sign (there is no -0)
|
||||
sign := constant.Sign(x)
|
||||
@ -616,7 +635,7 @@ func (p *exporter) float(x constant.Value) {
|
||||
m.SetMantExp(&m, int(m.MinPrec()))
|
||||
mant, acc := m.Int(nil)
|
||||
if acc != big.Exact {
|
||||
log.Fatalf("gcimporter: internal error")
|
||||
panic(internalError("internal error"))
|
||||
}
|
||||
|
||||
p.int(sign)
|
||||
@ -653,7 +672,7 @@ func (p *exporter) bool(b bool) bool {
|
||||
|
||||
func (p *exporter) index(marker byte, index int) {
|
||||
if index < 0 {
|
||||
log.Fatalf("gcimporter: invalid index < 0")
|
||||
panic(internalError("invalid index < 0"))
|
||||
}
|
||||
if debugFormat {
|
||||
p.marker('t')
|
||||
@ -666,7 +685,7 @@ func (p *exporter) index(marker byte, index int) {
|
||||
|
||||
func (p *exporter) tag(tag int) {
|
||||
if tag >= 0 {
|
||||
log.Fatalf("gcimporter: invalid tag >= 0")
|
||||
panic(internalError("invalid tag >= 0"))
|
||||
}
|
||||
if debugFormat {
|
||||
p.marker('t')
|
||||
|
@ -80,7 +80,10 @@ func TestTypeAliases(t *testing.T) {
|
||||
checkPkg(t, pkg1, "export")
|
||||
|
||||
// export
|
||||
exportdata := gcimporter.BExportData(fset1, pkg1)
|
||||
exportdata, err := gcimporter.BExportData(fset1, pkg1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// import
|
||||
imports := make(map[string]*types.Package)
|
||||
|
@ -63,7 +63,10 @@ type UnknownType undefined
|
||||
if info.Files == nil {
|
||||
continue // empty directory
|
||||
}
|
||||
exportdata := gcimporter.BExportData(conf.Fset, pkg)
|
||||
exportdata, err := gcimporter.BExportData(conf.Fset, pkg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
imports := make(map[string]*types.Package)
|
||||
fset2 := token.NewFileSet()
|
||||
@ -306,7 +309,10 @@ func TestVeryLongFile(t *testing.T) {
|
||||
}
|
||||
|
||||
// export
|
||||
exportdata := gcimporter.BExportData(fset1, pkg)
|
||||
exportdata, err := gcimporter.BExportData(fset1, pkg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// import
|
||||
imports := make(map[string]*types.Package)
|
||||
|
Loading…
x
Reference in New Issue
Block a user