Skip to content

Commit d9c62ce

Browse files
cherrymuimknyszek
authored andcommitted
[release-branch.go1.18] cmd/compile: copy blank parameter node when substituting function type
When a function type is copied (e.g. for substituting type parameters), we make copies of its parameter ir.Name nodes, so they are not shared with the old function type. But currently a blank (_) identifier is not copied but shared. The parameter node's frame offset is assigned (in ABI analysis) and then used in the concurrent backend. Shared node can cause a data race. Make a new blank parameter node to avoid sharing. (Unified IR does already not have this problem. This fixes non-unified-IR mode.) Updates #55357. Fixes #56359. Change-Id: Ie27f08e5589ac7d5d3f0d0d5de1a21e4fd2765c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/443158 Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Cherry Mui <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]> (cherry picked from commit 4725c71) Reviewed-on: https://go-review.googlesource.com/c/go/+/445177
1 parent e54e808 commit d9c62ce

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

src/cmd/compile/internal/test/race.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build !compiler_bootstrap
6+
// +build !compiler_bootstrap
7+
8+
package test
9+
10+
// The racecompile builder only builds packages, but does not build
11+
// or run tests. This is a non-test file to hold cases that (used
12+
// to) trigger compiler data races, so they will be exercised on
13+
// the racecompile builder.
14+
//
15+
// This package is not imported so functions here are not included
16+
// in the actual compiler.
17+
18+
// Issue 55357: data race when building multiple instantiations of
19+
// generic closures with _ parameters.
20+
func Issue55357() {
21+
type U struct {
22+
A int
23+
B string
24+
C string
25+
}
26+
var q T55357[U]
27+
q.Count()
28+
q.List()
29+
30+
type M struct {
31+
A int64
32+
B uint32
33+
C uint32
34+
}
35+
var q2 T55357[M]
36+
q2.Count()
37+
q2.List()
38+
}
39+
40+
type T55357[T any] struct{}
41+
42+
//go:noinline
43+
func (q *T55357[T]) do(w, v bool, fn func(bk []byte, v T) error) error {
44+
return nil
45+
}
46+
47+
func (q *T55357[T]) Count() (n int, rerr error) {
48+
err := q.do(false, false, func(kb []byte, _ T) error {
49+
n++
50+
return nil
51+
})
52+
return n, err
53+
}
54+
55+
func (q *T55357[T]) List() (list []T, rerr error) {
56+
var l []T
57+
err := q.do(false, true, func(_ []byte, v T) error {
58+
l = append(l, v)
59+
return nil
60+
})
61+
if err != nil {
62+
return nil, err
63+
}
64+
return l, nil
65+
}

src/cmd/compile/internal/typecheck/subr.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1356,14 +1356,22 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type {
13561356
newfields[i].SetNointerface(true)
13571357
}
13581358
if f.Nname != nil && ts.Vars != nil {
1359-
v := ts.Vars[f.Nname.(*ir.Name)]
1359+
n := f.Nname.(*ir.Name)
1360+
v := ts.Vars[n]
13601361
if v != nil {
13611362
// This is the case where we are
13621363
// translating the type of the function we
13631364
// are substituting, so its dcls are in
13641365
// the subst.ts.vars table, and we want to
13651366
// change to reference the new dcl.
13661367
newfields[i].Nname = v
1368+
} else if ir.IsBlank(n) {
1369+
// Blank variable is not dcl list. Make a
1370+
// new one to not share.
1371+
m := ir.NewNameAt(n.Pos(), ir.BlankNode.Sym())
1372+
m.SetType(n.Type())
1373+
m.SetTypecheck(1)
1374+
newfields[i].Nname = m
13671375
} else {
13681376
// This is the case where we are
13691377
// translating the type of a function

0 commit comments

Comments
 (0)