From 87023bb27f2cbe86c5baa9cef5ad91a6fc9a1c14 Mon Sep 17 00:00:00 2001 From: Wingrez <31106425+wingrez@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:38:59 +0000 Subject: [PATCH] go/types, types2: ensure deterministic output when reporting an init cycle Fixes #71254 Change-Id: Ie3bad281403c8ff6215e03d92760b9a378714cee GitHub-Last-Rev: 9b804a7842421dca6a97c57ce18523b593b0817d GitHub-Pull-Request: golang/go#71264 Reviewed-on: https://go-review.googlesource.com/c/go/+/642396 LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Griesemer Reviewed-by: Robert Findley Auto-Submit: Robert Griesemer --- src/cmd/compile/internal/types2/initorder.go | 10 ++++++++++ .../internal/types2/testdata/local/issue71254.go | 14 ++++++++++++++ src/go/types/initorder.go | 10 ++++++++++ 3 files changed, 34 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/local/issue71254.go diff --git a/src/cmd/compile/internal/types2/initorder.go b/src/cmd/compile/internal/types2/initorder.go index ef2ad010a6..699bfca8bb 100644 --- a/src/cmd/compile/internal/types2/initorder.go +++ b/src/cmd/compile/internal/types2/initorder.go @@ -10,6 +10,7 @@ import ( "fmt" . "internal/types/errors" "slices" + "sort" ) // initOrder computes the Info.InitOrder for package variables. @@ -139,7 +140,16 @@ func findPath(objMap map[Object]*declInfo, from, to Object, seen map[Object]bool } seen[from] = true + // sort deps for deterministic result + var deps []Object for d := range objMap[from].deps { + deps = append(deps, d) + } + sort.Slice(deps, func(i, j int) bool { + return deps[i].order() < deps[j].order() + }) + + for _, d := range deps { if d == to { return []Object{d} } diff --git a/src/cmd/compile/internal/types2/testdata/local/issue71254.go b/src/cmd/compile/internal/types2/testdata/local/issue71254.go new file mode 100644 index 0000000000..9cca9d5bc4 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/local/issue71254.go @@ -0,0 +1,14 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +const ( + B /* ERROR "initialization cycle: B refers to itself" */ = A + B + A /* ERRORx "initialization cycle for A\\s+.*A refers to B\\s+.*B refers to A" */ = A + B + + C /* ERRORx "initialization cycle for C\\s+.*C refers to D\\s+.*D refers to C" */ = E + D + D /* ERRORx "initialization cycle for D\\s+.*D refers to C\\s+.*C refers to D" */ = E + C + E = D + C +) diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index 7625c20667..adf96fe718 100644 --- a/src/go/types/initorder.go +++ b/src/go/types/initorder.go @@ -13,6 +13,7 @@ import ( "fmt" . "internal/types/errors" "slices" + "sort" ) // initOrder computes the Info.InitOrder for package variables. @@ -142,7 +143,16 @@ func findPath(objMap map[Object]*declInfo, from, to Object, seen map[Object]bool } seen[from] = true + // sort deps for deterministic result + var deps []Object for d := range objMap[from].deps { + deps = append(deps, d) + } + sort.Slice(deps, func(i, j int) bool { + return deps[i].order() < deps[j].order() + }) + + for _, d := range deps { if d == to { return []Object{d} } -- 2.48.1