From fbde753a58e286c405a04388816ed044486151bb Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 25 Jun 2019 22:24:34 -0400 Subject: [PATCH] cmd/compile: make duplicate anonymous interface output deterministic Taking over CL 162240, the original CL hasn't been making progress. I just took the parts that fix the immediate issue. I left the signatslice changes out, I don't think they are necessary. Fixes #30202 Change-Id: I5b347605f0841dd925d5a73150b8bf269fa82464 Reviewed-on: https://go-review.googlesource.com/c/go/+/183852 Run-TryBot: Keith Randall Reviewed-by: David Chase TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/reflect.go | 12 +++++++++++- .../internal/gc/reproduciblebuilds_test.go | 5 ++++- .../gc/testdata/reproducible/issue30202.go | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/reproducible/issue30202.go diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 9b26ba16cb..c2d9ba2fe0 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -1659,7 +1659,17 @@ func (a typesByString) Less(i, j int) bool { // they refer to byte or uint8, such as **byte vs **uint8, // the types' ShortStrings can be identical. // To preserve deterministic sort ordering, sort these by String(). - return a[i].regular < a[j].regular + if a[i].regular != a[j].regular { + return a[i].regular < a[j].regular + } + // Identical anonymous interfaces defined in different locations + // will be equal for the above checks, but different in DWARF output. + // Sort by source position to ensure deterministic order. + // See issues 27013 and 30202. + if a[i].t.Etype == types.TINTER && a[i].t.Methods().Len() > 0 { + return a[i].t.Methods().Index(0).Pos.Before(a[j].t.Methods().Index(0).Pos) + } + return false } func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/src/cmd/compile/internal/gc/reproduciblebuilds_test.go b/src/cmd/compile/internal/gc/reproduciblebuilds_test.go index 9173f80ee3..59d1edb9e8 100644 --- a/src/cmd/compile/internal/gc/reproduciblebuilds_test.go +++ b/src/cmd/compile/internal/gc/reproduciblebuilds_test.go @@ -18,6 +18,7 @@ func TestReproducibleBuilds(t *testing.T) { tests := []string{ "issue20272.go", "issue27013.go", + "issue30202.go", } testenv.MustHaveGoBuild(t) @@ -38,7 +39,9 @@ func TestReproducibleBuilds(t *testing.T) { defer os.Remove(tmp.Name()) defer tmp.Close() for i := 0; i < iters; i++ { - out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput() + // Note: use -c 2 to expose any nondeterminism which is the result + // of the runtime scheduler. + out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-c", "2", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput() if err != nil { t.Fatalf("failed to compile: %v\n%s", err, out) } diff --git a/src/cmd/compile/internal/gc/testdata/reproducible/issue30202.go b/src/cmd/compile/internal/gc/testdata/reproducible/issue30202.go new file mode 100644 index 0000000000..7b5de2cc8b --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/reproducible/issue30202.go @@ -0,0 +1,17 @@ +// Copyright 2019 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 + +func A(x interface { + X() int +}) int { + return x.X() +} + +func B(x interface { + X() int +}) int { + return x.X() +} -- 2.50.0