]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: prepend captured args to called-closure params
authorDavid Chase <drchase@google.com>
Thu, 23 Jul 2015 18:17:07 +0000 (14:17 -0400)
committerDavid Chase <drchase@google.com>
Thu, 23 Jul 2015 19:02:19 +0000 (19:02 +0000)
Old code appended, did not play well with a closure
with a ... param.

Fixes #11075.

Change-Id: Ib7c8590c5c4e576e798837e7499e00f3494efb4a
Reviewed-on: https://go-review.googlesource.com/12580
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: David Chase <drchase@google.com>

src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/walk.go
test/fixedbugs/issue11750.go [new file with mode: 0644]

index 65f77d9079924f17756ab825248f83a68bde8d38..a0dfa0bb0f446d3a7efc661acac672b41f38501b 100644 (file)
@@ -301,17 +301,18 @@ func transformclosure(xfunc *Node) {
                //      func(a int, byval int, &byref *int) {
                //              println(byval)
                //              (*&byref)++
-               //      }(42, byval, &byref)
+               //      }(byval, &byref, 42)
 
                // f is ONAME of the actual function.
                f := xfunc.Func.Nname
 
-               // Get pointer to input arguments and rewind to the end.
-               // We are going to append captured variables to input args.
+               // Get pointer to input arguments.
+               // We are going to insert captured variables before input args.
                param := &getinargx(f.Type).Type
+               original_args := *param // old input args
+               original_dcl := xfunc.Func.Dcl
+               xfunc.Func.Dcl = nil
 
-               for ; *param != nil; param = &(*param).Down {
-               }
                var v *Node
                var addr *Node
                var fld *Type
@@ -343,12 +344,14 @@ func transformclosure(xfunc *Node) {
                        fld.Type = fld.Nname.Type
                        fld.Sym = fld.Nname.Sym
 
-                       // Declare the new param and append it to input arguments.
+                       // Declare the new param and add it the first part of the input arguments.
                        xfunc.Func.Dcl = list(xfunc.Func.Dcl, fld.Nname)
 
                        *param = fld
                        param = &fld.Down
                }
+               *param = original_args
+               xfunc.Func.Dcl = concat(xfunc.Func.Dcl, original_dcl)
 
                // Recalculate param offsets.
                if f.Type.Width > 0 {
index d89d25efdd8c90f9effe6211ab95c016ff258763..91c0a47b2aef57fed22f436507e89f7375895753 100644 (file)
@@ -609,8 +609,8 @@ func walkexpr(np **Node, init **NodeList) {
                        // Transform direct call of a closure to call of a normal function.
                        // transformclosure already did all preparation work.
 
-                       // Append captured variables to argument list.
-                       n.List = concat(n.List, n.Left.Func.Enter)
+                       // Prepend captured variables to argument list.
+                       n.List = concat(n.Left.Func.Enter, n.List)
 
                        n.Left.Func.Enter = nil
 
diff --git a/test/fixedbugs/issue11750.go b/test/fixedbugs/issue11750.go
new file mode 100644 (file)
index 0000000..5e6fe60
--- /dev/null
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2015 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.
+
+// Issue 11750: mkdotargslice: typecheck failed
+
+package main
+
+func main() {
+       fn := func(names string) {
+
+       }
+       func(names ...string) {
+               for _, name := range names {
+                       fn(name)
+               }
+       }("one", "two")
+}