diff --git a/_fixtures/issue3548.go b/_fixtures/issue3548.go new file mode 100644 index 0000000000..e3f10537c7 --- /dev/null +++ b/_fixtures/issue3548.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" +) + +type Thing struct { + str string +} + +func (d *Thing) Test() bool { + return d != nil +} + +func callit(f func()) { + f() +} + +func main() { + cases := []struct { + name string + thing Thing + }{ + { + name: "Success", + thing: Thing{str: "hello"}, + }, + } + + for _, c := range cases { + callit(func() { + fmt.Println("hello", c.thing.Test()) + }) + } +} diff --git a/pkg/proc/variables_test.go b/pkg/proc/variables_test.go index 0d9dc98fdb..b90abaf168 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -1722,3 +1722,23 @@ func TestBadUnsafePtr(t *testing.T) { } }) } + +func TestCapturedVariable(t *testing.T) { + // Checks that variables captured by a closure (that are not pointers) are + // readable. See issue #3548. + // This was broken in Go 1.21 due to a compiler bug. + if goversion.VersionAfterOrEqual(runtime.Version(), 1, 21) && !goversion.VersionAfterOrEqual(runtime.Version(), 1, 22) { + t.Skip("broken") + } + withTestProcess("issue3548", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { + setFileBreakpoint(p, t, fixture.Source, 32) + assertNoError(grp.Continue(), t, "Continue()") + v := evalVariable(p, t, "c") + assertVariable(t, v, varTest{ + name: "c", + preserveName: true, + value: "struct { main.name string; main.thing main.Thing } {name: \"Success\", thing: main.Thing {str: \"hello\"}}", + varType: "struct { main.name string; main.thing main.Thing }", + }) + }) +}