diff --git a/go/packages/packages.go b/go/packages/packages.go index 92fce758..f40720d0 100644 --- a/go/packages/packages.go +++ b/go/packages/packages.go @@ -15,13 +15,14 @@ import ( "go/scanner" "go/token" "go/types" + "io/ioutil" "log" "os" + "path/filepath" + "runtime" "sync" "golang.org/x/tools/go/gcexportdata" - "io/ioutil" - "path/filepath" ) // A LoadMode specifies the amount of detail to return when loading. @@ -681,6 +682,14 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { panic("unreachable") }) + // This is only an approximation. + // TODO(adonovan): derive Sizes from the underlying build system. + goarch := runtime.GOARCH + if x, ok := os.LookupEnv("GOARCH"); ok { + goarch = x + } + sizes := types.SizesFor("gc", goarch) + // type-check tc := &types.Config{ Importer: importer, @@ -691,9 +700,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { IgnoreFuncBodies: ld.Mode < LoadAllSyntax && !lpkg.initial, Error: appendError, - - // TODO(adonovan): derive Sizes from the underlying - // build system. + Sizes: sizes, } types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go index 555a4908..f5e99ba8 100644 --- a/go/packages/packages_test.go +++ b/go/packages/packages_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "fmt" "go/ast" + constantpkg "go/constant" "go/parser" "go/token" "go/types" @@ -1041,6 +1042,41 @@ func TestContains(t *testing.T) { } } +// This test ensures that the effective GOARCH variable in the +// application determines the Sizes function used by the type checker. +// This behavior is a stop-gap until we make the build system's query +// too report the correct sizes function for the actual configuration. +func TestSizes(t *testing.T) { + tmp, cleanup := makeTree(t, map[string]string{ + "src/a/a.go": `package a; import "unsafe"; const WordSize = 8*unsafe.Sizeof(int(0))`, + }) + defer cleanup() + + savedGOARCH := os.Getenv("GOARCH") + defer os.Setenv("GOARCH", savedGOARCH) + + for arch, wantWordSize := range map[string]int64{"386": 32, "amd64": 64} { + os.Setenv("GOARCH", arch) + cfg := &packages.Config{ + Mode: packages.LoadSyntax, + Dir: tmp, + Env: append(os.Environ(), "GOPATH="+tmp, "GO111MODULE=off"), + } + initial, err := packages.Load(cfg, "a") + if err != nil { + t.Fatal(err) + } + if packages.PrintErrors(initial) > 0 { + t.Fatal("there were errors") + } + gotWordSize, _ := constantpkg.Int64Val(constant(initial[0], "WordSize").Val()) + if gotWordSize != wantWordSize { + t.Errorf("for GOARCH=%s, got word size %d, want %d", arch, gotWordSize, wantWordSize) + } + } + +} + // TestContains_FallbackSticks ensures that when there are both contains and non-contains queries // the decision whether to fallback to the pre-1.11 go list sticks across both sets of calls to // go list.