]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: don't assume ImportStack always set on PackageError
authorMichael Matloob <matloob@golang.org>
Thu, 8 Jun 2023 20:20:17 +0000 (16:20 -0400)
committerMichael Matloob <matloob@golang.org>
Fri, 9 Jun 2023 22:48:58 +0000 (22:48 +0000)
When determining DepsErrors for packages, we were trying to sort
errors by the top package on their ImportStack (which would likely be
the package the error was generated for) to get a deterministic
error order.

The problem is that some PackageErrors don't have ImportStacks set on
them. Fall back to sorting the errors by the error text (instead of
making things more complicated by tracking the packages that produced
the errors more closely).

Fixes #59905

Change-Id: Id305e1e70801f8909fd6463383b8eda193559787
Reviewed-on: https://go-review.googlesource.com/c/go/+/501978
Run-TryBot: Michael Matloob <matloob@golang.org>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
src/cmd/go/internal/list/list.go
src/cmd/go/testdata/script/list_issue_59905.txt [new file with mode: 0644]

index 2427b022a1cb2da414da9eaeb6fdb7b42c9bca2a..1addadfea0103814236141af79d77b6fff8f395e 100644 (file)
@@ -949,6 +949,15 @@ func collectDepsErrors(p *load.Package) {
        // one error set on it.
        sort.Slice(p.DepsErrors, func(i, j int) bool {
                stki, stkj := p.DepsErrors[i].ImportStack, p.DepsErrors[j].ImportStack
+               // Some packages are missing import stacks. To ensure deterministic
+               // sort order compare two errors that are missing import stacks by
+               // their errors' error texts.
+               if len(stki) == 0 {
+                       if len(stkj) != 0 {
+                               return true
+                       }
+                       return p.DepsErrors[i].Err.Error() < p.DepsErrors[j].Err.Error()
+               }
                pathi, pathj := stki[len(stki)-1], stkj[len(stkj)-1]
                return pathi < pathj
        })
diff --git a/src/cmd/go/testdata/script/list_issue_59905.txt b/src/cmd/go/testdata/script/list_issue_59905.txt
new file mode 100644 (file)
index 0000000..7480462
--- /dev/null
@@ -0,0 +1,66 @@
+# Expect no panic
+go list -f '{{if .DepsErrors}}{{.DepsErrors}}{{end}}' -export -e -deps
+cmpenv stdout wanterr
+
+-- wanterr --
+[# test/main/level1a
+level1a${/}pkg.go:5:2: level2x redeclared in this block
+       level1a${/}pkg.go:4:2: other declaration of level2x
+level1a${/}pkg.go:5:2: "test/main/level1a/level2y" imported as level2x and not used
+level1a${/}pkg.go:8:39: undefined: level2y
+ # test/main/level1b
+level1b${/}pkg.go:5:2: level2x redeclared in this block
+       level1b${/}pkg.go:4:2: other declaration of level2x
+level1b${/}pkg.go:5:2: "test/main/level1b/level2y" imported as level2x and not used
+level1b${/}pkg.go:8:39: undefined: level2y
+]
+-- go.mod --
+module test/main
+
+go 1.20
+-- main.go --
+package main
+
+import (
+       "test/main/level1a"
+       "test/main/level1b"
+)
+
+func main() {
+       level1a.Print()
+       level1b.Print()
+}
+-- level1a/pkg.go --
+package level1a
+
+import (
+       "test/main/level1a/level2x"
+       "test/main/level1a/level2y"
+)
+
+func Print() { println(level2x.Value, level2y.Value) }
+-- level1a/level2x/pkg.go --
+package level2x
+
+var Value = "1a/2x"
+-- level1a/level2y/pkg.go --
+package level2x
+
+var Value = "1a/2y"
+-- level1b/pkg.go --
+package level1b
+
+import (
+       "test/main/level1b/level2x"
+       "test/main/level1b/level2y"
+)
+
+func Print() { println(level2x.Value, level2y.Value) }
+-- level1b/level2x/pkg.go --
+package level2x
+
+var Value = "1b/2x"
+-- level1b/level2y/pkg.go --
+package level2x
+
+var Value = "1b/2y"
\ No newline at end of file