From 89fc415274e0f59ab4eb802ece8722a5c159d294 Mon Sep 17 00:00:00 2001 From: Chris O'Hara Date: Thu, 14 Dec 2023 12:15:15 +1000 Subject: [PATCH] Write a test that fails since receiver isn't captured --- compiler/coroutine_test.go | 18 +++---- compiler/testdata/coroutine.go | 38 ++++++++----- compiler/testdata/coroutine_durable.go | 75 ++++++++++++++++++++++---- 3 files changed, 99 insertions(+), 32 deletions(-) diff --git a/compiler/coroutine_test.go b/compiler/coroutine_test.go index abd9a60..b0df226 100644 --- a/compiler/coroutine_test.go +++ b/compiler/coroutine_test.go @@ -216,28 +216,28 @@ func TestCoroutineYield(t *testing.T) { }, { - name: "identity generic", - coro: func() { IdentityGeneric[int](11) }, - yields: []int{11}, - }, - - { - name: "identity generic (2)", + name: "generic function", coro: func() { IdentityGenericInt(11) }, yields: []int{11}, }, { - name: "identity generic (3)", + name: "generic struct", coro: func() { IdentityGenericStructInt(11) }, yields: []int{11}, }, { - name: "identity generic (4)", + name: "generic function closure", coro: func() { IdentityGenericClosureInt(11) }, yields: []int{11, 11}, }, + + { + name: "generic struct closure", + coro: func() { IdentityGenericStructClosureInt(11) }, + yields: []int{11, 100, 11, 100}, + }, } // This emulates the installation of function type information by the diff --git a/compiler/testdata/coroutine.go b/compiler/testdata/coroutine.go index ccde368..c579e0a 100644 --- a/compiler/testdata/coroutine.go +++ b/compiler/testdata/coroutine.go @@ -562,22 +562,10 @@ func IdentityGeneric[T any](n T) { coroutine.Yield[T, any](n) } -type IdentityGenericStruct[T any] struct { - n T -} - -func (i *IdentityGenericStruct[T]) Run() { - coroutine.Yield[T, any](i.n) -} - func IdentityGenericInt(n int) { IdentityGeneric[int](n) } -func IdentityGenericStructInt(n int) { - (&IdentityGenericStruct[int]{n: n}).Run() -} - func IdentityGenericClosure[T any](n T) { fn := buildClosure(n) fn() @@ -596,3 +584,29 @@ func buildClosure[T any](n T) func() { func IdentityGenericClosureInt(n int) { IdentityGenericClosure[int](n) } + +type IdentityGenericStruct[T any] struct { + n T +} + +func (i *IdentityGenericStruct[T]) Run() { + coroutine.Yield[T, any](i.n) +} + +//go:noinline +func (i *IdentityGenericStruct[T]) Closure(n T) func() { + return func() { + coroutine.Yield[T, any](i.n) + coroutine.Yield[T, any](n) + } +} + +func IdentityGenericStructInt(n int) { + (&IdentityGenericStruct[int]{n: n}).Run() +} + +func IdentityGenericStructClosureInt(n int) { + fn := (&IdentityGenericStruct[int]{n: n}).Closure(100) + fn() + fn() +} diff --git a/compiler/testdata/coroutine_durable.go b/compiler/testdata/coroutine_durable.go index e39a505..974e24c 100644 --- a/compiler/testdata/coroutine_durable.go +++ b/compiler/testdata/coroutine_durable.go @@ -3240,19 +3240,9 @@ func ReturnNamedValue() (_fn0 int) { //go:noinline func IdentityGeneric[T any](n T) { coroutine.Yield[T, any](n) } -type IdentityGenericStruct[T any] struct { - n T -} - -//go:noinline -func (i *IdentityGenericStruct[T]) Run() { coroutine.Yield[T, any](i.n) } - //go:noinline func IdentityGenericInt(n int) { IdentityGeneric[int](n) } -//go:noinline -func IdentityGenericStructInt(n int) { (&IdentityGenericStruct[int]{n: n}).Run() } - //go:noinline func IdentityGenericClosure[T any](_fn0 T) { _c := coroutine.LoadContext[T, any]() @@ -3291,7 +3281,7 @@ func IdentityGenericClosure[T any](_fn0 T) { } } -// TODO: add this go:noinline directive automatically +// TODO: add this go:noinline directive automatically (once stealthrocket/coroutine#84 is fixed) // //go:noinline func buildClosure[T any](n T) func() { @@ -3302,7 +3292,69 @@ func buildClosure[T any](n T) func() { //go:noinline func IdentityGenericClosureInt(n int) { IdentityGenericClosure[int](n) } + +type IdentityGenericStruct[T any] struct { + n T +} + +//go:noinline +func (i *IdentityGenericStruct[T]) Run() { coroutine.Yield[T, any](i.n) } + +//go:noinline +func (i *IdentityGenericStruct[T]) Closure(n T) func() { + return func() { + coroutine.Yield[T, any](i.n) + coroutine.Yield[T, any](n) + } +} + +//go:noinline +func IdentityGenericStructInt(n int) { (&IdentityGenericStruct[int]{n: n}).Run() } + +//go:noinline +func IdentityGenericStructClosureInt(_fn0 int) { + _c := coroutine.LoadContext[int, any]() + var _f0 *struct { + IP int + X0 int + X1 func() + } = coroutine.Push[struct { + IP int + X0 int + X1 func() + }](&_c.Stack) + if _f0.IP == 0 { + *_f0 = struct { + IP int + X0 int + X1 func() + }{X0: _fn0} + } + defer func() { + if !_c.Unwinding() { + coroutine.Pop(&_c.Stack) + } + }() + switch { + case _f0.IP < 2: + _f0.X1 = (&IdentityGenericStruct[int]{n: _f0.X0}).Closure(100) + _f0.IP = 2 + fallthrough + case _f0.IP < 3: + _f0.X1() + _f0.IP = 3 + fallthrough + case _f0.IP < 4: + _f0.X1() + } +} func init() { + _types.RegisterFunc[func(n int) func()]("github.com/stealthrocket/coroutine/compiler/testdata.(*IdentityGenericStruct[go.shape.int]).Closure") + _types.RegisterClosure[func(), struct { + F uintptr + D uintptr + X0 int + }]("github.com/stealthrocket/coroutine/compiler/testdata.(*IdentityGenericStruct[go.shape.int]).Closure.func1") _types.RegisterFunc[func()]("github.com/stealthrocket/coroutine/compiler/testdata.(*IdentityGenericStruct[go.shape.int]).Run") _types.RegisterFunc[func(n int)]("github.com/stealthrocket/coroutine/compiler/testdata.Double") _types.RegisterFunc[func(_fn0 int)]("github.com/stealthrocket/coroutine/compiler/testdata.EvenSquareGenerator") @@ -3312,6 +3364,7 @@ func init() { _types.RegisterFunc[func(n int)]("github.com/stealthrocket/coroutine/compiler/testdata.IdentityGenericClosureInt") _types.RegisterFunc[func(_fn0 int)]("github.com/stealthrocket/coroutine/compiler/testdata.IdentityGenericClosure[go.shape.int]") _types.RegisterFunc[func(n int)]("github.com/stealthrocket/coroutine/compiler/testdata.IdentityGenericInt") + _types.RegisterFunc[func(_fn0 int)]("github.com/stealthrocket/coroutine/compiler/testdata.IdentityGenericStructClosureInt") _types.RegisterFunc[func(n int)]("github.com/stealthrocket/coroutine/compiler/testdata.IdentityGenericStructInt") _types.RegisterFunc[func(n int)]("github.com/stealthrocket/coroutine/compiler/testdata.IdentityGeneric[go.shape.int]") _types.RegisterFunc[func(_ int)]("github.com/stealthrocket/coroutine/compiler/testdata.LoopBreakAndContinue")