diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2015-01-29 18:33:19 +0300 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2015-02-03 15:48:48 +0000 |
commit | eaa872009db2018816d5e14c6349df3ab7e6df0c (patch) | |
tree | ca462c333e1353dec6e13c2d02c835a0a0538844 /test/closure2.go | |
parent | 8e2423a67dab2fe8f218dc37bb31ec26aaad7c14 (diff) | |
download | go-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.go | 135 |
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") + } + } } |