Skip to content

Commit ddc93a5

Browse files
cuonglmgopherbot
authored andcommitted
cmd/compile: fix unified IR shapifying recursive instantiated types
Shape-based stenciling in unified IR is done by converting type argument to its underlying type. So it agressively check that type argument is not a TFORW. However, for recursive instantiated type argument, it may still be a TFORW when shapifying happens. Thus the assertion failed, causing the compiler crashing. To fix it, just allow fully instantiated type when shapifying. Fixes #54512 Fixes #54722 Change-Id: I527e3fd696388c8a37454e738f0324f0c2ec16cb Reviewed-on: https://go-review.googlesource.com/c/go/+/426335 TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Cuong Manh Le <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
1 parent c22865f commit ddc93a5

File tree

5 files changed

+67
-22
lines changed

5 files changed

+67
-22
lines changed

src/cmd/compile/internal/base/debug.go

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type DebugFlags struct {
3535
PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"`
3636
Panic int `help:"show all compiler panics"`
3737
Reshape int `help:"print information about expression reshaping"`
38+
Shapify int `help:"print information about shaping recursive types"`
3839
Slice int `help:"print information about slice compilation"`
3940
SoftFloat int `help:"force compiler to emit soft-float code"`
4041
SyncFrames int `help:"how many writer stack frames to include at sync points in unified export data"`

src/cmd/compile/internal/noder/reader.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,22 @@ func (dict *readerDict) mangle(sym *types.Sym) *types.Sym {
817817
// If basic is true, then the type argument is used to instantiate a
818818
// type parameter whose constraint is a basic interface.
819819
func shapify(targ *types.Type, basic bool) *types.Type {
820-
base.Assertf(targ.Kind() != types.TFORW, "%v is missing its underlying type", targ)
820+
if targ.Kind() == types.TFORW {
821+
if targ.IsFullyInstantiated() {
822+
// For recursive instantiated type argument, it may still be a TFORW
823+
// when shapifying happens. If we don't have targ's underlying type,
824+
// shapify won't work. The worst case is we end up not reusing code
825+
// optimally in some tricky cases.
826+
if base.Debug.Shapify != 0 {
827+
base.Warn("skipping shaping of recursive type %v", targ)
828+
}
829+
if targ.HasShape() {
830+
return targ
831+
}
832+
} else {
833+
base.Fatalf("%v is missing its underlying type", targ)
834+
}
835+
}
821836

822837
// When a pointer type is used to instantiate a type parameter
823838
// constrained by a basic interface, we know the pointer's element

test/fixedbugs/issue54722.go

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile
2+
3+
// Copyright 2022 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package p
8+
9+
type G[T any] struct {
10+
h H[G[T]]
11+
}
12+
13+
type H[T any] struct{}
14+
15+
var x G[int]

test/fixedbugs/issue54722b.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// compile
2+
3+
// Copyright 2022 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package p
8+
9+
type value[V comparable] struct {
10+
node *node[value[V]]
11+
value V
12+
}
13+
14+
type node[V comparable] struct {
15+
index *index[V]
16+
children map[string]*node[V]
17+
}
18+
19+
type index[V comparable] struct {
20+
arrays []array[V]
21+
}
22+
23+
type array[V comparable] struct {
24+
valueMap map[int]V
25+
}
26+
27+
var x value[int]
28+
var y value[*Column]
29+
30+
type Column struct{ column int }

test/typeparam/nested.go

+5-21
Original file line numberDiff line numberDiff line change
@@ -104,27 +104,11 @@ func main() {
104104
F[V]()
105105
F[W]()
106106

107-
// TODO(go.dev/issue/54512): Restore these tests. They currently
108-
// cause problems for shaping with unified IR.
109-
//
110-
// For example, instantiating X[int] requires instantiating shape
111-
// type X[shapify(int)] == X[go.shape.int]. In turn, this requires
112-
// instantiating U[shapify(X[go.shape.int])]. But we're still in the
113-
// process of constructing X[go.shape.int], so we don't yet know its
114-
// underlying type.
115-
//
116-
// Notably, this is a consequence of unified IR writing out type
117-
// declarations with a reference to the full RHS expression (i.e.,
118-
// U[X[A]]) rather than its underlying type (i.e., int), which is
119-
// necessary to support //go:notinheap. Once go.dev/issue/46731 is
120-
// implemented and unified IR is updated, I expect this will just
121-
// work.
122-
//
123-
// type X[A any] U[X[A]]
124-
//
125-
// F[X[int]]()
126-
// F[X[Int]]()
127-
// F[X[GlobalInt]]()
107+
type X[A any] U[X[A]]
108+
109+
F[X[int]]()
110+
F[X[Int]]()
111+
F[X[GlobalInt]]()
128112

129113
for j, tj := range tests {
130114
for i, ti := range tests[:j+1] {

0 commit comments

Comments
 (0)