diff options
author | Cuong Manh Le <cuong.manhle.vn@gmail.com> | 2022-11-17 01:02:26 +0700 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2022-12-28 16:11:17 +0000 |
commit | 5758a14e431c88996a8061435e8381a26af0a214 (patch) | |
tree | edb8890434a13a46d30a5d133e8d1a7c0048a3ad | |
parent | 91bc4cd118ddf6e43338dd5e2d53dcc995f9831a (diff) | |
download | go-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.go | 8 | ||||
-rw-r--r-- | test/fixedbugs/issue56768.go | 37 |
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}, + }, + } +} |