Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/go/packages: gotypesalias=1 does not seem to get used correctly for deps on Go 1.23 #70394

Open
mvdan opened this issue Nov 16, 2024 · 15 comments
Assignees
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Tools This label describes issues relating to any tools in the x/tools repository.
Milestone

Comments

@mvdan
Copy link
Member

mvdan commented Nov 16, 2024

$ go version
go version go1.23.3 linux/amd64
$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/mvdan/.cache/go-build'
GOENV='/home/mvdan/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/mvdan/go/pkg/mod'
GONOPROXY='github.com/cue-unity'
GONOSUMDB='github.com/cue-unity'
GOOS='linux'
GOPATH='/home/mvdan/go'
GOPRIVATE='github.com/cue-unity'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.23.3'
GODEBUG=''
GOTELEMETRY='on'
GOTELEMETRYDIR='/home/mvdan/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build977617588=/tmp/go-build -gno-record-gcc-switches'

Take the testscript below:

go run .

go run . -godebug

go run . -godebug -needsyntax

go run . -needsyntax
-- go.mod --
module test

go 1.23

require golang.org/x/tools v0.27.0

require (
	golang.org/x/mod v0.22.0 // indirect
	golang.org/x/sync v0.9.0 // indirect
)
-- go.sum --
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
-- main.go --
package main

import (
	"flag"
	"fmt"
	"os"

	"golang.org/x/tools/go/packages"
)

var (
	godebug    = flag.Bool("godebug", false, "")
	needsyntax = flag.Bool("needsyntax", false, "")
)

func main() {
	flag.Parse()
	if *godebug {
		os.Setenv("GODEBUG", "gotypesalias=1")
	}
	mode := packages.NeedTypes
	if *needsyntax {
		mode |= packages.NeedSyntax
	}
	cfg := &packages.Config{Mode: mode}
	pkgs, err := packages.Load(cfg, "./pkg1")
	if err != nil {
		panic(err)
	}
	if packages.PrintErrors(pkgs) > 0 {
		os.Exit(1)
	}

	pkg := pkgs[0]
	scope := pkg.Types.Scope()
	fmt.Println(scope.Lookup("Var1"))
	fmt.Println(scope.Lookup("Var2"))
}
-- pkg1/pkg1.go --
package pkg1

import "test/pkg2"

type Alias1 = int32

var Var1 Alias1

var Var2 pkg2.Alias2

-- pkg2/pkg2.go --
package pkg2

type Alias2 = int64

With https://pkg.go.dev/github.com/rogpeppe/go-internal/cmd/testscript, I see:

> go run .
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 int64

> go run . -godebug
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 int64

> go run . -godebug -needsyntax
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 test/pkg2.Alias2

> go run . -needsyntax
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 test/pkg2.Alias2

The first two results seem wrong; alias tracking is lost for the transitive dependency, given that we see the alias target int64 rather than the alias declared in the transitive dependency, pkg2.Alias2. This happens whether or not I set the GODEBUG flag, which should already be on by default in Go 1.23.

The issue only goes away once I set NeedSyntax, which presumably forces the current process to parse and typecheck all packages directly, rather than relying on the Go toolchain to typecheck transitive dependencies and store the results in GOCACHE, for the current process to load from a warm cache.

This bug seems to go away as of go version devel go1.24-493edb2973 2024-11-16 15:10:05 +0000 linux/amd64:

> go run .
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 test/pkg2.Alias2

> go run . -godebug
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 test/pkg2.Alias2

> go run . -godebug -needsyntax
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 test/pkg2.Alias2

> go run . -needsyntax
[stdout]
var test/pkg1.Var1 test/pkg1.Alias1
var test/pkg1.Var2 test/pkg2.Alias2
@dmitshur dmitshur changed the title go/packages: gotypesalias=1 does not seem to get used correctly for deps on Go 1.23 x/tools/go/packages: gotypesalias=1 does not seem to get used correctly for deps on Go 1.23 Nov 17, 2024
@gopherbot gopherbot added the Tools This label describes issues relating to any tools in the x/tools repository. label Nov 17, 2024
@gopherbot gopherbot added this to the Unreleased milestone Nov 17, 2024
@timothy-king timothy-king self-assigned this Nov 17, 2024
@mvdan
Copy link
Member Author

mvdan commented Nov 18, 2024

I didn't spend the time bisecting why this works on Go master (1.24). I suppose it could be because alias tracking is always on at this point, or perhaps due to other changes in how export data is generated or loaded.

@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Nov 18, 2024
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/629997 mentions this issue: [release-branch.go1.23] cmd/compile: enable alias for pkgReader

@xieyuschen
Copy link
Contributor

xieyuschen commented Nov 20, 2024

The issue locates inside the cmd/compile. packages.Load triggers go list with -compile and -export, and it relies on cmd/compile to generate the exported data.

Tool compile will be triggered twice in this scenario for pkg2 and pkg1 and the export data for pkg2 is generated first. However, when compile tries to read exportdata pkg2 for pkg1, the enableAlias is set false. As a result, compile won't respect the alias inside pkg2 and it generates pkg1's exportdata without alias.

// Currently, the compiler panics when using Alias types.
// TODO(gri) set to true once this is fixed (issue #66873)
enableAlias: false,

Then the result is read by tools/go/packages and assign type int64 to Ver2 instead of Alias2, which is what we expected.

I'm still new to the cmd/compile part and don't know a lot of things, so it's possible I've missed something important. I would appreciate any corrections or guidance. Thanks a lot!

Regarding on the CL629997, I don't know the following things but I will try to check them tomorrow.

Updated in 21Nov

  • whether it breaks the other cases we wanted to prevent before.
    It doesn't matter because the logic doesn't affect the logic of compile tool to generate exportdata. The tool could generate exportdata correctly. Current issue in go1.23.x is the reader of exportdata won't respect alias because the field of enableAlias.
  • where and how to put a test case..
    done in the new patchset of CL629997

@timothy-king
Copy link
Contributor

Great find. I suspected it was something like this, but narrowing it down is super helpful. I will follow up on this.

@mvdan
Copy link
Member Author

mvdan commented Nov 20, 2024

That would also explain why 1.24 (master) did not have this bug, as I recall some rather large import/export changes in the compiler.

@dmitshur dmitshur modified the milestones: Unreleased, Go1.24 Nov 22, 2024
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/631855 mentions this issue: [release-branch.go1.23] cmd/compile/internal/importer: enable aliases

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/632116 mentions this issue: go/packages: add a unit test for golang/go#70394

@mvdan
Copy link
Member Author

mvdan commented Nov 27, 2024

I think the milestone for this issue is not right by the way - this issue affects 1.23.x only, not 1.24, so it should probably be milestoned for the next 1.23.x release.

@dmitshur
Copy link
Contributor

dmitshur commented Nov 27, 2024

@mvdan This issue can indeed be marked as closed since it's resolved in Go 1.24, but the Go1.24 milestone is right. There is a child backport issue (#70517 in this case) that needs to refer to this one. We need this parent issue for tracking of any remaining development (e.g., like for CL 632116 which adds a test), even if the problem happened to be fixed before the issue was filed.

See https://go.dev/wiki/MinorReleases, which includes "As soon as an interested party thinks an issue should be considered for backport, they open one or two “child” issues titled like package: title [1.17 backport]. The issue should include a link to the original issue and a short rationale about why the backport might be needed." and more details.

@timothy-king
Copy link
Contributor

For a 1.22 backport, we would need to backport most of https://go.dev/cl/579935, https://go.dev/cl/585399, and possibly other subsequent CLs that build on top of these and fix bugs. These would not be "100% clean" backports either as public APIs are involved and differ between releases.

Given the relatively low volume of user complaint, the complexity/risk of the backport, and hopefully soon availability of a 1.23 fix, I am not sure a 1.22 backport makes sense at this time.

@mvdan
Copy link
Member Author

mvdan commented Nov 27, 2024

All I need is a backport to 1.23, personally.

gopherbot pushed a commit to golang/tools that referenced this issue Nov 27, 2024
Adds a unit test that reproduces golang/go#70394. That issue is
for 1.23 only. The test currently requires >=1.24 so it can
pass until there is a backport.

Updates golang/go#70394

Change-Id: I35b716d051dd3e737b4db15c3ac871d3166abfca
Reviewed-on: https://go-review.googlesource.com/c/tools/+/632116
Reviewed-by: David Chase <drchase@google.com>
Commit-Queue: Tim King <taking@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/633695 mentions this issue: all: merge master (e334696) into gopls-release-branch.0.17

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/633698 mentions this issue: go/packages: add a unit test for golang/go#70394

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/633735 mentions this issue: all: merge master (7eebab3) into gopls-release-branch.0.17

gopherbot pushed a commit to golang/tools that referenced this issue Dec 4, 2024
Also add back the x/tools replace directive for gopls.

For golang/go#70301

Merge List:

+ 2024-12-04 7eebab3 gopls/internal/golang: support extract variable at top level
+ 2024-12-04 e334696 gopls/internal/golang: ignore effects for change signature refactoring
+ 2024-12-04 3901733 internal/refactor/inline: substitute groups of dependent arguments
+ 2024-12-03 61b2408 gopls/internal/golang: add "Extract constant" counterpart
+ 2024-12-03 c01eead internal/gcimporter: require binary export data header
+ 2024-12-03 9a04136 gopls/internal/golang/stubmethods: refine crash into bug report
+ 2024-12-03 01e0b05 internal/refactor/inline: fix condition for splice assignment strategy
+ 2024-12-03 557f540 gopls/internal/golang: don't offer to move variadic parameters
+ 2024-12-03 399ee16 internal/gcimporter: update FindExportData to return a non-negative size
+ 2024-12-03 25b0003 internal/refactor/inline: more precise redundant conversion detection
+ 2024-12-03 eb46939 gopls/internal/test/marker: add reproducers for moveparam bug bash bugs
+ 2024-12-03 4296223 gopls/internal/analysis/yield: add comment about dataflow
+ 2024-12-03 7a4f3b0 internal/gcimporter: require archive files
+ 2024-12-02 2f73c61 gopls/internal/golang: avoid crash in lookupDocLinkSymbol
+ 2024-12-02 ef3d603 gopls/internal/golang/completion: fix crash with extra results
+ 2024-12-02 8ffeaba gopls/internal/settings: enable 'waitgroup' analyzer
+ 2024-12-02 4317959 go/analysis/passes/waitgroup: report WaitGroup.Add in goroutine
+ 2024-12-02 72fdfa6 gopls/internal/golang: Disable test generation for generic functions
+ 2024-12-02 b80f1ed gopls/internal/analysis/yield: peephole-optimize phi(false, x)
+ 2024-11-28 e7bd227 gopls/internal/golang: fix folding range for function calls
+ 2024-11-28 e71702b internal/versions: remove constraint.GoVersion wrapper
+ 2024-11-28 c99edec gopls/internal/golang/completion: add alias support for literals
+ 2024-11-27 bfe3046 go/packages: add a unit test for golang/go#70394
+ 2024-11-27 df87831 gopls/internal/undeclaredname: add missing colon when appropriate
+ 2024-11-26 53efd30 gopls/internal/golang: simplify package name collection in add test

Change-Id: I476e80493f61732701784befe2b130ca967b259e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests

6 participants