Skip to content

Commit

Permalink
[release-branch.go1.19] cmd/compile: fix broken IR for iface -> eface
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
cuonglm authored and gopherbot committed Dec 28, 2022
1 parent 91bc4cd commit 5758a14
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/cmd/compile/internal/walk/convert.go
Expand Up @@ -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)
Expand Down
37 changes: 37 additions & 0 deletions 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},
},
}
}

0 comments on commit 5758a14

Please sign in to comment.