aboutsummaryrefslogtreecommitdiff
path: root/test/closure2.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-01-29 18:33:19 +0300
committerDmitry Vyukov <dvyukov@google.com>2015-02-03 15:48:48 +0000
commiteaa872009db2018816d5e14c6349df3ab7e6df0c (patch)
treeca462c333e1353dec6e13c2d02c835a0a0538844 /test/closure2.go
parent8e2423a67dab2fe8f218dc37bb31ec26aaad7c14 (diff)
downloadgo-eaa872009db2018816d5e14c6349df3ab7e6df0c.tar.gz
go-eaa872009db2018816d5e14c6349df3ab7e6df0c.zip
cmd/gc: fix capturing by value for range statements
Kindly detected by race builders by failing TestRaceRange. ORANGE typecheck does not increment decldepth around body. Change-Id: I0df5f310cb3370a904c94d9647a9cf0f15729075 Reviewed-on: https://go-review.googlesource.com/3507 Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'test/closure2.go')
-rw-r--r--test/closure2.go135
1 files changed, 94 insertions, 41 deletions
diff --git a/test/closure2.go b/test/closure2.go
index 8947450561..4d61b45d3f 100644
--- a/test/closure2.go
+++ b/test/closure2.go
@@ -10,56 +10,109 @@
package main
func main() {
- type X struct {
- v int
- }
- var x X
- func() {
- x.v++
- }()
- if x.v != 1 {
- panic("x.v != 1")
- }
+ {
+ type X struct {
+ v int
+ }
+ var x X
+ func() {
+ x.v++
+ }()
+ if x.v != 1 {
+ panic("x.v != 1")
+ }
- type Y struct {
- X
- }
- var y Y
- func() {
- y.v = 1
- }()
- if y.v != 1 {
- panic("y.v != 1")
+ type Y struct {
+ X
+ }
+ var y Y
+ func() {
+ y.v = 1
+ }()
+ if y.v != 1 {
+ panic("y.v != 1")
+ }
}
- type Z struct {
- a [3]byte
- }
- var z Z
- func() {
- i := 0
- for z.a[1] = 1; i < 10; i++ {
+ {
+ type Z struct {
+ a [3]byte
+ }
+ var z Z
+ func() {
+ i := 0
+ for z.a[1] = 1; i < 10; i++ {
+ }
+ }()
+ if z.a[1] != 1 {
+ panic("z.a[1] != 1")
}
- }()
- if z.a[1] != 1 {
- panic("z.a[1] != 1")
}
- w := 0
- tmp := 0
- f := func() {
- if w != 1 {
- panic("w != 1")
+ {
+ w := 0
+ tmp := 0
+ f := func() {
+ if w != 1 {
+ panic("w != 1")
+ }
}
- }
- func() {
- tmp = w // force capture of w, but do not write to it yet
- _ = tmp
func() {
+ tmp = w // force capture of w, but do not write to it yet
+ _ = tmp
func() {
- w++ // write in a nested closure
+ func() {
+ w++ // write in a nested closure
+ }()
}()
}()
- }()
- f()
+ f()
+ }
+
+ {
+ var g func() int
+ for i := range [2]int{} {
+ if i == 0 {
+ g = func() int {
+ return i // test that we capture by ref here, i is mutated on every interation
+ }
+ }
+ }
+ if g() != 1 {
+ panic("g() != 1")
+ }
+ }
+
+ {
+ var g func() int
+ q := 0
+ for range [2]int{} {
+ q++
+ g = func() int {
+ return q // test that we capture by ref here
+ // q++ must on a different decldepth than q declaration
+ }
+ }
+ if g() != 2 {
+ panic("g() != 2")
+ }
+ }
+
+ {
+ var g func() int
+ var a [2]int
+ q := 0
+ for a[func() int {
+ q++
+ return 0
+ }()] = range [2]int{} {
+ g = func() int {
+ return q // test that we capture by ref here
+ // q++ must on a different decldepth than q declaration
+ }
+ }
+ if g() != 2 {
+ panic("g() != 2")
+ }
+ }
}