aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCuong Manh Le <cuong.manhle.vn@gmail.com>2022-11-17 01:02:26 +0700
committerGopher Robot <gobot@golang.org>2022-12-28 16:11:17 +0000
commit5758a14e431c88996a8061435e8381a26af0a214 (patch)
treeedb8890434a13a46d30a5d133e8d1a7c0048a3ad
parent91bc4cd118ddf6e43338dd5e2d53dcc995f9831a (diff)
downloadgo-5758a14e431c88996a8061435e8381a26af0a214.tar.gz
go-5758a14e431c88996a8061435e8381a26af0a214.zip
[release-branch.go1.19] cmd/compile: fix broken IR for iface -> eface
For implementing interface to empty interface conversion, the compiler generate code like: var res *uint8 res = itab if res != nil { res = res.type } However, itab has type *uintptr, so the assignment is broken. The problem is not shown up, until CL 450215, which call typecheck on this broken assignment. To fix this, just cast itab to *uint8 when doing the conversion. Fixes #56770 Change-Id: Id42792d18e7f382578b40854d46eecd49673792c Reviewed-on: https://go-review.googlesource.com/c/go/+/451256 Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/451875 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Joedian Reid <joedian@golang.org>
-rw-r--r--src/cmd/compile/internal/walk/convert.go8
-rw-r--r--test/fixedbugs/issue56768.go37
2 files changed, 42 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go
index 72631e7dfb..07ce0b609d 100644
--- a/src/cmd/compile/internal/walk/convert.go
+++ b/src/cmd/compile/internal/walk/convert.go
@@ -79,13 +79,15 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
var typeWord ir.Node
if toType.IsEmptyInterface() {
- // Implement interface to empty interface conversion.
- // res = itab
+ // Implement interface to empty interface conversion:
+ //
+ // var res *uint8
+ // res = (*uint8)(unsafe.Pointer(itab))
// if res != nil {
// res = res.type
// }
typeWord = typecheck.Temp(types.NewPtr(types.Types[types.TUINT8]))
- init.Append(ir.NewAssignStmt(base.Pos, typeWord, itab))
+ init.Append(ir.NewAssignStmt(base.Pos, typeWord, typecheck.Conv(typecheck.Conv(itab, types.Types[types.TUNSAFEPTR]), typeWord.Type())))
nif := ir.NewIfStmt(base.Pos, typecheck.Expr(ir.NewBinaryExpr(base.Pos, ir.ONE, typeWord, typecheck.NodNil())), nil, nil)
nif.Body = []ir.Node{ir.NewAssignStmt(base.Pos, typeWord, itabType(typeWord))}
init.Append(nif)
diff --git a/test/fixedbugs/issue56768.go b/test/fixedbugs/issue56768.go
new file mode 100644
index 0000000000..1b2db4cceb
--- /dev/null
+++ b/test/fixedbugs/issue56768.go
@@ -0,0 +1,37 @@
+// compile
+
+// Copyright 2022 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
+
+type I interface {
+ M()
+}
+
+type slice []any
+
+func f() {
+ ss := struct{ i I }{}
+
+ _ = [...]struct {
+ s slice
+ }{
+ {
+ s: slice{ss.i},
+ },
+ {
+ s: slice{ss.i},
+ },
+ {
+ s: slice{ss.i},
+ },
+ {
+ s: slice{ss.i},
+ },
+ {
+ s: slice{ss.i},
+ },
+ }
+}