From 89b44b4e2bb2f88474d6b8476f5c28ea2aea9b28 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 20 Dec 2020 01:15:46 -0800 Subject: [PATCH] cmd/compile: recognize reassignments involving receives Previously, reassigned was failing to detect reassignments due to channel receives in select statements (OSELRECV, OSELRECV2), or due to standalone 2-value receive assignments (OAS2RECV). This was reported as a devirtualization panic, but could have caused mis-inlining as well. Fixes #43292. Change-Id: Ic8079c20c0587aeacff9596697fdeba80a697b12 Reviewed-on: https://go-review.googlesource.com/c/go/+/279352 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/inl.go | 8 +++- test/fixedbugs/issue43292.go | 59 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue43292.go diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 419056985f..600d12b59b 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -832,16 +832,20 @@ func (v *reassignVisitor) visit(n *Node) *Node { return nil } switch n.Op { - case OAS: + case OAS, OSELRECV: if n.Left == v.name && n != v.name.Name.Defn { return n } - case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE: + case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV: for _, p := range n.List.Slice() { if p == v.name && n != v.name.Name.Defn { return n } } + case OSELRECV2: + if (n.Left == v.name || n.List.First() == v.name) && n != v.name.Name.Defn { + return n + } } if a := v.visit(n.Left); a != nil { return a diff --git a/test/fixedbugs/issue43292.go b/test/fixedbugs/issue43292.go new file mode 100644 index 0000000000..02f1c69bd1 --- /dev/null +++ b/test/fixedbugs/issue43292.go @@ -0,0 +1,59 @@ +// run + +// Copyright 2020 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 main + +func main() { + { + i := I(A{}) + + b := make(chan I, 1) + b <- B{} + + var ok bool + i, ok = <-b + _ = ok + + i.M() + } + + { + i := I(A{}) + + b := make(chan I, 1) + b <- B{} + + select { + case i = <-b: + } + + i.M() + } + + { + i := I(A{}) + + b := make(chan I, 1) + b <- B{} + + var ok bool + select { + case i, ok = <-b: + } + _ = ok + + i.M() + } +} + +type I interface{ M() int } + +type T int + +func (T) M() int { return 0 } + +type A struct{ T } +type B struct{ T } -- 2.48.1