diff --git a/go/internal/gcimporter/gcimporter_test.go b/go/internal/gcimporter/gcimporter_test.go index b517bf1250..cfafbbf1c4 100644 --- a/go/internal/gcimporter/gcimporter_test.go +++ b/go/internal/gcimporter/gcimporter_test.go @@ -10,6 +10,7 @@ package gcimporter import ( "bytes" "fmt" + "go/constant" "go/types" "io/ioutil" "os" @@ -320,26 +321,11 @@ func TestImportedTypes(t *testing.T) { } for _, test := range importedObjectTests { - s := strings.Split(test.name, ".") - if len(s) != 2 { - t.Fatal("inconsistent test data") - } - importPath := s[0] - objName := s[1] - - pkg, err := Import(make(map[string]*types.Package), importPath, ".", nil) - if err != nil { - t.Error(err) - continue - } - - obj := pkg.Scope().Lookup(objName) + obj := importObject(t, test.name) if obj == nil { - t.Errorf("%s: object not found", test.name) - continue + continue // error reported elsewhere } - - got := types.ObjectString(obj, types.RelativeTo(pkg)) + got := types.ObjectString(obj, types.RelativeTo(obj.Pkg())) if got != test.want { t.Errorf("%s: got %q; want %q", test.name, got, test.want) } @@ -350,6 +336,54 @@ func TestImportedTypes(t *testing.T) { } } +func TestImportedConsts(t *testing.T) { + testenv.NeedsGo1Point(t, 11) + skipSpecialPlatforms(t) + + tests := []struct { + name string + want constant.Kind + }{ + {"math.Pi", constant.Float}, + {"math.MaxFloat64", constant.Float}, + {"math.MaxInt64", constant.Int}, + } + + for _, test := range tests { + obj := importObject(t, test.name) + if got := obj.(*types.Const).Val().Kind(); got != test.want { + t.Errorf("%s: imported as constant.Kind(%v), want constant.Kind(%v)", test.name, got, test.want) + } + } +} + +// importObject imports the object specified by a name of the form +// ., e.g. go/types.Type. +// +// If any errors occur they are reported via t and the resulting object will +// be nil. +func importObject(t *testing.T, name string) types.Object { + s := strings.Split(name, ".") + if len(s) != 2 { + t.Fatal("inconsistent test data") + } + importPath := s[0] + objName := s[1] + + pkg, err := Import(make(map[string]*types.Package), importPath, ".", nil) + if err != nil { + t.Error(err) + return nil + } + + obj := pkg.Scope().Lookup(objName) + if obj == nil { + t.Errorf("%s: object not found", name) + return nil + } + return obj +} + // verifyInterfaceMethodRecvs verifies that method receiver types // are named if the methods belong to a named interface type. func verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) { diff --git a/go/internal/gcimporter/iimport.go b/go/internal/gcimporter/iimport.go index b236debad1..8ed8bc62d6 100644 --- a/go/internal/gcimporter/iimport.go +++ b/go/internal/gcimporter/iimport.go @@ -473,6 +473,14 @@ func (r *importReader) mpfloat(b *types.Basic) constant.Value { switch { case exp > 0: x = constant.Shift(x, token.SHL, uint(exp)) + // Ensure that the imported Kind is Float, else this constant may run into + // bitsize limits on overlarge integers. Eventually we can instead adopt + // the approach of CL 288632, but that CL relies on go/constant APIs that + // were introduced in go1.13. + // + // TODO(rFindley): sync the logic here with tip Go once we no longer + // support go1.12. + x = constant.ToFloat(x) case exp < 0: d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) x = constant.BinaryOp(x, token.QUO, d)