]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: recognize reassignments involving receives
authorMatthew Dempsky <mdempsky@google.com>
Sun, 20 Dec 2020 09:15:46 +0000 (01:15 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Sun, 20 Dec 2020 09:43:29 +0000 (09:43 +0000)
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 <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>

src/cmd/compile/internal/gc/inl.go
test/fixedbugs/issue43292.go [new file with mode: 0644]

index 419056985fc1446c9ee7906db345a7db32c22e8d..600d12b59b2c5f6a784bb924fcf7186b18a746ed 100644 (file)
@@ -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 (file)
index 0000000..02f1c69
--- /dev/null
@@ -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 }