Skip to content

Commit 05c089f

Browse files
committed
cmd/compile/internal/staticinit: fix panic in interface conversion
This patch fixes a panic from incorrect interface conversion from *ir.BasicLit to *ir.ConstExpr. This only occurs when nounified GOEXPERIMENT is set, so ideally it should be backported to Go 1.20 and removed from master. Fixes #58339
1 parent f9da938 commit 05c089f

File tree

5 files changed

+140
-9
lines changed

5 files changed

+140
-9
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
From 834bbf50df46f2e5a9339b3d2b1ef334793551dc Mon Sep 17 00:00:00 2001
2+
From: Sung Yoon Whang <[email protected]>
3+
Date: Tue, 7 Feb 2023 12:08:30 -0800
4+
Subject: [PATCH] cmd/compile/internal/staticinit: fix panic in interface
5+
conversion
6+
7+
This patch fixes a panic from incorrect interface conversion
8+
from *ir.BasicLit to *ir.ConstExpr. This only occurs when nounified
9+
GOEXPERIMENT is set, so ideally it should be backported to Go 1.20
10+
and removed from master.
11+
12+
Fixes #58339
13+
---
14+
src/cmd/compile/internal/staticinit/sched.go | 10 ++--------
15+
test/fixedbugs/issue58339.dir/a.go | 17 +++++++++++++++++
16+
test/fixedbugs/issue58339.dir/b.go | 9 +++++++++
17+
test/fixedbugs/issue58339.go | 7 +++++++
18+
4 files changed, 35 insertions(+), 8 deletions(-)
19+
create mode 100644 test/fixedbugs/issue58339.dir/a.go
20+
create mode 100644 test/fixedbugs/issue58339.dir/b.go
21+
create mode 100644 test/fixedbugs/issue58339.go
22+
23+
diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go
24+
index f954c246f7..b9ca265a48 100644
25+
--- a/src/cmd/compile/internal/staticinit/sched.go
26+
+++ b/src/cmd/compile/internal/staticinit/sched.go
27+
@@ -864,13 +864,7 @@ func subst(n ir.Node, m map[*ir.Name]ir.Node) (ir.Node, bool) {
28+
x = ir.Copy(x)
29+
ir.EditChildrenWithHidden(x, edit)
30+
if x, ok := x.(*ir.ConvExpr); ok && x.X.Op() == ir.OLITERAL {
31+
- // A conversion of variable or expression involving variables
32+
- // may become a conversion of constant after inlining the parameters
33+
- // and doing constant evaluation. Truncations that were valid
34+
- // on variables are not valid on constants, so we might have
35+
- // generated invalid code that will trip up the rest of the compiler.
36+
- // Fix those by truncating the constants.
37+
- if x, ok := truncate(x.X.(*ir.ConstExpr), x.Type()); ok {
38+
+ if x, ok := truncate(x.X, x.Type()); ok {
39+
return x
40+
}
41+
valid = false
42+
@@ -885,7 +879,7 @@ func subst(n ir.Node, m map[*ir.Name]ir.Node) (ir.Node, bool) {
43+
// truncate returns the result of force converting c to type t,
44+
// truncating its value as needed, like a conversion of a variable.
45+
// If the conversion is too difficult, truncate returns nil, false.
46+
-func truncate(c *ir.ConstExpr, t *types.Type) (*ir.ConstExpr, bool) {
47+
+func truncate(c ir.Node, t *types.Type) (ir.Node, bool) {
48+
ct := c.Type()
49+
cv := c.Val()
50+
if ct.Kind() != t.Kind() {
51+
diff --git a/test/fixedbugs/issue58339.dir/a.go b/test/fixedbugs/issue58339.dir/a.go
52+
new file mode 100644
53+
index 0000000000..22cbe0c6f9
54+
--- /dev/null
55+
+++ b/test/fixedbugs/issue58339.dir/a.go
56+
@@ -0,0 +1,17 @@
57+
+// Copyright 2023 The Go Authors. All rights reserved.
58+
+// Use of this source code is governed by a BSD-style
59+
+// license that can be found in the LICENSE file.
60+
+
61+
+package a
62+
+
63+
+func Assert(msgAndArgs ...any) {
64+
+}
65+
+
66+
+func Run() int {
67+
+ Assert("%v")
68+
+ return 0
69+
+}
70+
+
71+
+func Run2() int {
72+
+ return Run()
73+
+}
74+
diff --git a/test/fixedbugs/issue58339.dir/b.go b/test/fixedbugs/issue58339.dir/b.go
75+
new file mode 100644
76+
index 0000000000..1736ec7adb
77+
--- /dev/null
78+
+++ b/test/fixedbugs/issue58339.dir/b.go
79+
@@ -0,0 +1,9 @@
80+
+// Copyright 2023 The Go Authors. All rights reserved.
81+
+// Use of this source code is governed by a BSD-style
82+
+// license that can be found in the LICENSE file.
83+
+
84+
+package b
85+
+
86+
+import "./a"
87+
+
88+
+var A = a.Run2()
89+
diff --git a/test/fixedbugs/issue58339.go b/test/fixedbugs/issue58339.go
90+
new file mode 100644
91+
index 0000000000..5c4c5c0a8f
92+
--- /dev/null
93+
+++ b/test/fixedbugs/issue58339.go
94+
@@ -0,0 +1,7 @@
95+
+// compiledir
96+
+
97+
+// Copyright 2023 The Go Authors. All rights reserved.
98+
+// Use of this source code is governed by a BSD-style
99+
+// license that can be found in the LICENSE file.
100+
+
101+
+package ignored
102+
--
103+
2.37.1 (Apple Git-137.1)
104+

src/cmd/compile/internal/staticinit/sched.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -864,13 +864,7 @@ func subst(n ir.Node, m map[*ir.Name]ir.Node) (ir.Node, bool) {
864864
x = ir.Copy(x)
865865
ir.EditChildrenWithHidden(x, edit)
866866
if x, ok := x.(*ir.ConvExpr); ok && x.X.Op() == ir.OLITERAL {
867-
// A conversion of variable or expression involving variables
868-
// may become a conversion of constant after inlining the parameters
869-
// and doing constant evaluation. Truncations that were valid
870-
// on variables are not valid on constants, so we might have
871-
// generated invalid code that will trip up the rest of the compiler.
872-
// Fix those by truncating the constants.
873-
if x, ok := truncate(x.X.(*ir.ConstExpr), x.Type()); ok {
867+
if x, ok := truncate(x.X, x.Type()); ok {
874868
return x
875869
}
876870
valid = false
@@ -885,7 +879,7 @@ func subst(n ir.Node, m map[*ir.Name]ir.Node) (ir.Node, bool) {
885879
// truncate returns the result of force converting c to type t,
886880
// truncating its value as needed, like a conversion of a variable.
887881
// If the conversion is too difficult, truncate returns nil, false.
888-
func truncate(c *ir.ConstExpr, t *types.Type) (*ir.ConstExpr, bool) {
882+
func truncate(c ir.Node, t *types.Type) (ir.Node, bool) {
889883
ct := c.Type()
890884
cv := c.Val()
891885
if ct.Kind() != t.Kind() {
@@ -907,7 +901,7 @@ func truncate(c *ir.ConstExpr, t *types.Type) (*ir.ConstExpr, bool) {
907901
}
908902
}
909903
}
910-
c = ir.NewConstExpr(cv, c).(*ir.ConstExpr)
904+
c = ir.NewConstExpr(cv, c)
911905
c.SetType(t)
912906
return c, true
913907
}

test/fixedbugs/issue58339.dir/a.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2023 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+
package a
6+
7+
func Assert(msgAndArgs ...any) {
8+
}
9+
10+
func Run() int {
11+
Assert("%v")
12+
return 0
13+
}
14+
15+
func Run2() int {
16+
return Run()
17+
}

test/fixedbugs/issue58339.dir/b.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2023 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+
package b
6+
7+
import "./a"
8+
9+
var A = a.Run2()

test/fixedbugs/issue58339.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compiledir
2+
3+
// Copyright 2023 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 ignored

0 commit comments

Comments
 (0)