Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AcyclicTransformer that does not recursively apply to itself in an infinite cycle #77

Closed
AlD opened this issue Mar 16, 2018 · 2 comments

Comments

@AlD
Copy link

AlD commented Mar 16, 2018

Despite the efforts from #29 and related, the below code will still cause an infinite recursion, if no Filter is provided.
Is this expected?
If yes, I think the removed comments referring to this issue (e.g. c2186a4#diff-80edd9c1cccda07a46cde07a99b4e236L261) should be re-added.

package main

import (
	"fmt"
	"github.com/google/go-cmp/cmp"
	"strings"
)

func main() {
	a := "foo bar"
	b := "baz qux"
	fmt.Printf("%v", cmp.Equal(a, b, cmp.Transformer("", func(in string) []string { return strings.Split(in, " ") })))
}
$ go run cmptest.go
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x4fc7d2, 0xe)
	/usr/lib/google-golang/src/runtime/panic.go:622 +0x8a
runtime.newstack()
	/usr/lib/google-golang/src/runtime/stack.go:1054 +0x71f
runtime.morestack()
	/usr/lib/google-golang/src/runtime/asm_amd64.s:480 +0x89

goroutine 1 [running]:
sync.(*Map).Load(0x5973c0, 0x4e30a0, 0xc440100428, 0x0, 0x0, 0x0)
	/usr/lib/google-golang/src/sync/map.go:102 +0x2f9 fp=0xc440100308 sp=0xc440100300 pc=0x460a99
reflect.funcLayout(0x4d9bc0, 0x0, 0x4d3400, 0x4d3401, 0x4d3400, 0x0, 0x0)
	/usr/lib/google-golang/src/reflect/type.go:3076 +0xa2 fp=0xc440100530 sp=0xc440100308 pc=0x4926f2
reflect.Value.call(0x4d9bc0, 0x502e28, 0x13, 0x4fb22a, 0x4, 0xc440100920, 0x1, 0x1, 0x0, 0x0, ...)
	/usr/lib/google-golang/src/reflect/value.go:405 +0x642 fp=0xc4401007f0 sp=0xc440100530 pc=0x4949a2
reflect.Value.Call(0x4d9bc0, 0x502e28, 0x13, 0xc440100920, 0x1, 0x1, 0x18, 0x4ee6a0, 0x0)
	/usr/lib/google-golang/src/reflect/value.go:308 +0xa4 fp=0xc440100858 sp=0xc4401007f0 pc=0x494244
github.com/google/go-cmp/cmp.(*state).callTRFunc(0xc42009a000, 0x4d9bc0, 0x502e28, 0x13, 0x4d3400, 0xc426dc72d0, 0x198, 0x0, 0x8ea5389315cdc701, 0x8e00000000000000)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:326 +0x3c5 fp=0xc440100948 sp=0xc440100858 pc=0x4b72f5
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc72d0, 0x198, 0x4d3400, 0xc426dc72e0, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:264 +0x1c2 fp=0xc4401009e0 sp=0xc440100948 pc=0x4ba902
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc72d0, 0x198, 0x4d3400, 0xc426dc72e0, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440100a80 sp=0xc4401009e0 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc72d0, 0x198, 0x4d3400, 0xc426dc72e0, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440100bd0 sp=0xc440100a80 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc72d0, 0x198, 0x4d3400, 0xc426dc72e0, 0x198, 0x48c903, 0xc440100cb0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440100c40 sp=0xc440100bd0 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440100cc0 sp=0xc440100c40 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440100ef0, 0x97, 0xc440100e40, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440100df0 sp=0xc440100cc0 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440100ef0, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc440100e50 sp=0xc440100df0 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf9f0, 0x97, 0x4d1400, 0xc426dcfa20, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440100f48 sp=0xc440100e50 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf9f0, 0x97, 0x4d1400, 0xc426dcfa20, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440101098 sp=0xc440100f48 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc72b0, 0x198, 0x4d3400, 0xc426dc72c0, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440101130 sp=0xc440101098 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc72b0, 0x198, 0x4d3400, 0xc426dc72c0, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc4401011d0 sp=0xc440101130 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc72b0, 0x198, 0x4d3400, 0xc426dc72c0, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440101320 sp=0xc4401011d0 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc72b0, 0x198, 0x4d3400, 0xc426dc72c0, 0x198, 0x48c903, 0xc440101400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440101390 sp=0xc440101320 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440101410 sp=0xc440101390 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440101640, 0x97, 0xc440101590, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440101540 sp=0xc440101410 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440101640, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc4401015a0 sp=0xc440101540 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf990, 0x97, 0x4d1400, 0xc426dcf9c0, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440101698 sp=0xc4401015a0 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf990, 0x97, 0x4d1400, 0xc426dcf9c0, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc4401017e8 sp=0xc440101698 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc7290, 0x198, 0x4d3400, 0xc426dc72a0, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440101880 sp=0xc4401017e8 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc7290, 0x198, 0x4d3400, 0xc426dc72a0, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440101920 sp=0xc440101880 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc7290, 0x198, 0x4d3400, 0xc426dc72a0, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440101a70 sp=0xc440101920 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc7290, 0x198, 0x4d3400, 0xc426dc72a0, 0x198, 0x48c903, 0xc440101b50)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440101ae0 sp=0xc440101a70 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440101b60 sp=0xc440101ae0 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440101d90, 0x97, 0xc440101ce0, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440101c90 sp=0xc440101b60 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440101d90, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc440101cf0 sp=0xc440101c90 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf930, 0x97, 0x4d1400, 0xc426dcf960, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440101de8 sp=0xc440101cf0 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf930, 0x97, 0x4d1400, 0xc426dcf960, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440101f38 sp=0xc440101de8 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc7270, 0x198, 0x4d3400, 0xc426dc7280, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440101fd0 sp=0xc440101f38 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc7270, 0x198, 0x4d3400, 0xc426dc7280, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440102070 sp=0xc440101fd0 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc7270, 0x198, 0x4d3400, 0xc426dc7280, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc4401021c0 sp=0xc440102070 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc7270, 0x198, 0x4d3400, 0xc426dc7280, 0x198, 0x48c903, 0xc4401022a0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440102230 sp=0xc4401021c0 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc4401022b0 sp=0xc440102230 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc4401024e0, 0x97, 0xc440102430, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc4401023e0 sp=0xc4401022b0 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc4401024e0, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc440102440 sp=0xc4401023e0 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf8d0, 0x97, 0x4d1400, 0xc426dcf900, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440102538 sp=0xc440102440 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf8d0, 0x97, 0x4d1400, 0xc426dcf900, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440102688 sp=0xc440102538 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc7250, 0x198, 0x4d3400, 0xc426dc7260, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440102720 sp=0xc440102688 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc7250, 0x198, 0x4d3400, 0xc426dc7260, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc4401027c0 sp=0xc440102720 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc7250, 0x198, 0x4d3400, 0xc426dc7260, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440102910 sp=0xc4401027c0 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc7250, 0x198, 0x4d3400, 0xc426dc7260, 0x198, 0x48c903, 0xc4401029f0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440102980 sp=0xc440102910 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440102a00 sp=0xc440102980 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440102c30, 0x97, 0xc440102b80, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440102b30 sp=0xc440102a00 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440102c30, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc440102b90 sp=0xc440102b30 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf870, 0x97, 0x4d1400, 0xc426dcf8a0, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440102c88 sp=0xc440102b90 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf870, 0x97, 0x4d1400, 0xc426dcf8a0, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440102dd8 sp=0xc440102c88 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc7230, 0x198, 0x4d3400, 0xc426dc7240, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440102e70 sp=0xc440102dd8 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc7230, 0x198, 0x4d3400, 0xc426dc7240, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440102f10 sp=0xc440102e70 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc7230, 0x198, 0x4d3400, 0xc426dc7240, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440103060 sp=0xc440102f10 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc7230, 0x198, 0x4d3400, 0xc426dc7240, 0x198, 0x48c903, 0xc440103140)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc4401030d0 sp=0xc440103060 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440103150 sp=0xc4401030d0 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440103380, 0x97, 0xc4401032d0, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440103280 sp=0xc440103150 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440103380, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc4401032e0 sp=0xc440103280 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf810, 0x97, 0x4d1400, 0xc426dcf840, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc4401033d8 sp=0xc4401032e0 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf810, 0x97, 0x4d1400, 0xc426dcf840, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440103528 sp=0xc4401033d8 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc7210, 0x198, 0x4d3400, 0xc426dc7220, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc4401035c0 sp=0xc440103528 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc7210, 0x198, 0x4d3400, 0xc426dc7220, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440103660 sp=0xc4401035c0 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc7210, 0x198, 0x4d3400, 0xc426dc7220, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc4401037b0 sp=0xc440103660 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc7210, 0x198, 0x4d3400, 0xc426dc7220, 0x198, 0x48c903, 0xc440103890)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440103820 sp=0xc4401037b0 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc4401038a0 sp=0xc440103820 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440103ad0, 0x97, 0xc440103a20, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc4401039d0 sp=0xc4401038a0 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440103ad0, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc440103a30 sp=0xc4401039d0 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf7b0, 0x97, 0x4d1400, 0xc426dcf7e0, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440103b28 sp=0xc440103a30 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf7b0, 0x97, 0x4d1400, 0xc426dcf7e0, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440103c78 sp=0xc440103b28 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc71f0, 0x198, 0x4d3400, 0xc426dc7200, 0x198, 0xc426dc7200)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440103d10 sp=0xc440103c78 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc71f0, 0x198, 0x4d3400, 0xc426dc7200, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440103db0 sp=0xc440103d10 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc71f0, 0x198, 0x4d3400, 0xc426dc7200, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440103f00 sp=0xc440103db0 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc71f0, 0x198, 0x4d3400, 0xc426dc7200, 0x198, 0x48c903, 0xc440103fe0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440103f70 sp=0xc440103f00 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440103ff0 sp=0xc440103f70 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440104220, 0x97, 0xc440104170, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440104120 sp=0xc440103ff0 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440104220, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc440104180 sp=0xc440104120 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf750, 0x97, 0x4d1400, 0xc426dcf780, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440104278 sp=0xc440104180 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf750, 0x97, 0x4d1400, 0xc426dcf780, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc4401043c8 sp=0xc440104278 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc71d0, 0x198, 0x4d3400, 0xc426dc71e0, 0x198, 0xc426dc7100)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440104460 sp=0xc4401043c8 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc71d0, 0x198, 0x4d3400, 0xc426dc71e0, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440104500 sp=0xc440104460 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc71d0, 0x198, 0x4d3400, 0xc426dc71e0, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440104650 sp=0xc440104500 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc71d0, 0x198, 0x4d3400, 0xc426dc71e0, 0x198, 0x48c903, 0xc440104730)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc4401046c0 sp=0xc440104650 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440104740 sp=0xc4401046c0 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc440104970, 0x97, 0xc4401048c0, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440104870 sp=0xc440104740 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc440104970, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc4401048d0 sp=0xc440104870 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf6f0, 0x97, 0x4d1400, 0xc426dcf720, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc4401049c8 sp=0xc4401048d0 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf6f0, 0x97, 0x4d1400, 0xc426dcf720, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440104b18 sp=0xc4401049c8 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc71b0, 0x198, 0x4d3400, 0xc426dc71c0, 0x198, 0xc426dc7100)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440104bb0 sp=0xc440104b18 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc71b0, 0x198, 0x4d3400, 0xc426dc71c0, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc440104c50 sp=0xc440104bb0 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc71b0, 0x198, 0x4d3400, 0xc426dc71c0, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc440104da0 sp=0xc440104c50 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc71b0, 0x198, 0x4d3400, 0xc426dc71c0, 0x198, 0x48c903, 0xc440104e80)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440104e10 sp=0xc440104da0 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc440104e90 sp=0xc440104e10 pc=0x4bd108
github.com/google/go-cmp/cmp/internal/diff.searchGraph(0x1, 0x1, 0xc4401050c0, 0x97, 0xc440105010, 0x40f9f8)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:222 +0x251 fp=0xc440104fc0 sp=0xc440104e90 pc=0x4ae7b1
github.com/google/go-cmp/cmp/internal/diff.Difference(0x1, 0x1, 0xc4401050c0, 0x1, 0x0, 0x0, 0x0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/internal/diff/diff.go:121 +0x43 fp=0xc440105020 sp=0xc440104fc0 pc=0x4ae493
github.com/google/go-cmp/cmp.(*state).compareArray(0xc42009a000, 0x4d1400, 0xc426dcf690, 0x97, 0x4d1400, 0xc426dcf6c0, 0x97, 0x511ea0, 0x4d1400)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:380 +0x249 fp=0xc440105118 sp=0xc440105020 pc=0x4b7d59
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d1400, 0xc426dcf690, 0x97, 0x4d1400, 0xc426dcf6c0, 0x97)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:266 +0x9ce fp=0xc440105268 sp=0xc440105118 pc=0x4b558e
github.com/google/go-cmp/cmp.(*transformer).apply(0xc42006e040, 0xc42009a000, 0x4d3400, 0xc426dc7190, 0x198, 0x4d3400, 0xc426dc71a0, 0x198, 0xc426dc7100)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/options.go:266 +0x288 fp=0xc440105300 sp=0xc440105268 pc=0x4ba9c8
github.com/google/go-cmp/cmp.(*state).tryOptions(0xc42009a000, 0x4d3400, 0xc426dc7190, 0x198, 0x4d3400, 0xc426dc71a0, 0x198, 0x511ea0, 0x4d3400, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:307 +0x14d fp=0xc4401053a0 sp=0xc440105300 pc=0x4b6bed
github.com/google/go-cmp/cmp.(*state).compareAny(0xc42009a000, 0x4d3400, 0xc426dc7190, 0x198, 0x4d3400, 0xc426dc71a0, 0x198)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:202 +0x347 fp=0xc4401054f0 sp=0xc4401053a0 pc=0x4b4f07
github.com/google/go-cmp/cmp.(*state).statelessCompare(0xc42009a000, 0x4d3400, 0xc426dc7190, 0x198, 0x4d3400, 0xc426dc71a0, 0x198, 0x48c903, 0xc4401055d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:176 +0xcc fp=0xc440105560 sp=0xc4401054f0 pc=0x4b4b3c
github.com/google/go-cmp/cmp.(*state).compareArray.func1(0x0, 0x0, 0x0, 0x5b37d0)
	/usr/share/gocode/src/github.com/google/go-cmp/cmp/compare.go:382 +0x108 fp=0xc4401055e0 sp=0xc440105560 pc=0x4bd108
...additional frames elided...
exit status 2
@dsnet
Copy link
Collaborator

dsnet commented Mar 16, 2018

This is expected behavior. There are two ways to work around this:

1. Avoid cycles in the types:
You have a transformer that converts string => []string. It is not hard to see from the types that this is an infinite cycle. You could work around this by defining a new type: type MyString string and make the transformation go from string => []MyString. However, this doesn't work nicely with Go's type system since strings.Split returns a []string and can't be casted into a []MyString.

2. Use a non-reentrant transformer:
We deliberately chose to make transformers reentrant by default because the reentrant version is strictly more powerful than a non-reentrant one (but has the infinite loop issue). You can use a PathFilter to convert a transformer into a non-reentrant one (i.e., the transformer isn't applied on the transformed output itself).

func main() {
	a := "foo bar"
	b := "baz qux"
	
	opt := NonReentrantTransfomer("", func(in string) []string { return strings.Split(in, " ") })
	fmt.Println(cmp.Diff(a, b, opt))
}

func NonReentrantTransfomer(name string, f interface{}) cmp.Option {
	xform := cmp.Transformer(name, f)
	return cmp.FilterPath(func(p cmp.Path) bool {
		for _, ps := range p {
			if t, ok := ps.(cmp.Transform); ok && t.Option() == xform {
				return false
			}
		}
		return true
	}, xform)
}

I want to add NonReentrantTransformer to the cmpopts package, but I don't have a good name for it. We can also adjust the documentation for cmp.Transformer to suggest using cmpopts.NonReentrantTransformer.

@AlD AlD changed the title Transformer from []string to string causes infinite recursion Transformer from string to []string causes infinite recursion Mar 19, 2018
@AlD
Copy link
Author

AlD commented Mar 19, 2018

Thanks for the detailed response.

I understand how to work around this (now), and I actually use a ValueFilter that checks the string for the delimiter character.
I do think the documentation and comments should make this more obvious, though.

In fact, the commit mentioned (c2186a4), e.g. removed this from an []int to []int Transformer in cmp/example_test.go:

// Since the transformer transforms []int into []int, there is problem where
// this is recursively applied forever. To prevent this, use a FilterValues	
// to first check for the condition upon which the transformer ought to apply.	
trans := cmp.FilterValues(func(x, y []int) bool {	
	return !sort.IntsAreSorted(x) || !sort.IntsAreSorted(y)	
}, cmp.Transformer("Sort", func(in []int) []int {
…

And for Transformer() replaced this:

// If T and R are the same type, an additional filter must be applied to
// act as the base case to prevent an infinite recursion applying the same
// transform to itself (see the SortedSlice example).

With:

// To help prevent some cases of infinite recursive cycles applying the
// same transform to the output of itself (e.g., in the case where the
// input and output types are the same), an implicit filter is added such that
// a transformer is applicable only if that exact transformer is not already
// in the tail of the Path since the last non-Transform step.

Which makes it sound like the problem is taken care of automagically.
Having the previous hints in place would have probably guided me into the right direction quicker.

I want to add NonReentrantTransformer to the cmpopts package, but I don't have a good name for it. We can also adjust the documentation for cmp.Transformer to suggest using cmpopts.NonReentrantTransformer.

That actually seems like a very good solution and NonReentrantTransformer sounds good to me, too.

@dsnet dsnet changed the title Transformer from string to []string causes infinite recursion Add AcyclicTransformer Mar 21, 2018
@dsnet dsnet changed the title Add AcyclicTransformer Add AcyclicTransformer that does not recursively apply to itself in an infinite cycle Mar 21, 2018
dsnet added a commit that referenced this issue Mar 21, 2018
Add AcyclicTransformer helper, which wraps Transformer with a FilterPath
that ensures that the transformer cannot be recursively applied upon
the output of itself. Adjust documentation of Transformer to suggest usage
of AcyclicTransformer if necessary.

Fixes #77
dsnet added a commit that referenced this issue Mar 21, 2018
Add AcyclicTransformer helper, which wraps Transformer with a FilterPath
that ensures that the transformer cannot be recursively applied upon
the output of itself. Adjust documentation of Transformer to suggest usage
of AcyclicTransformer if necessary.

Fixes #77
dsnet added a commit that referenced this issue Mar 26, 2018
Add AcyclicTransformer helper, which wraps Transformer with a FilterPath
that ensures that the transformer cannot be recursively applied upon
the output of itself. Adjust documentation of Transformer to suggest usage
of AcyclicTransformer if necessary.

Fixes #77
dsnet added a commit that referenced this issue Mar 26, 2018
Add AcyclicTransformer helper, which wraps Transformer with a FilterPath
that ensures that the transformer cannot be recursively applied upon
the output of itself. Adjust documentation of Transformer to suggest usage
of AcyclicTransformer if necessary.

Fixes #77
@dsnet dsnet closed this as completed in #82 Mar 26, 2018
dsnet added a commit that referenced this issue Mar 26, 2018
Add AcyclicTransformer helper, which wraps Transformer with a FilterPath
that ensures that the transformer cannot be recursively applied upon
the output of itself. Adjust documentation of Transformer to suggest usage
of AcyclicTransformer if necessary.

Fixes #77
dsnet added a commit that referenced this issue Mar 26, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(SplitLines, main.main.func1): string => []string
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
dsnet added a commit that referenced this issue Mar 26, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(SplitLines, main.main.func1): string => []string
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
dsnet added a commit that referenced this issue Mar 26, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(SplitLines, main.main.func1): string => []string
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
dsnet added a commit that referenced this issue Mar 27, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(T1, main.main.func1): complex64 => complex128
	Transformer(T2, main.main.func2): complex128 => [2]float64
	Transformer(T3, main.main.func3): float64 => complex64
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
dsnet added a commit that referenced this issue Mar 27, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(T1, main.main.func1): complex64 => complex128
	Transformer(T2, main.main.func2): complex128 => [2]float64
	Transformer(T3, main.main.func3): float64 => complex64
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
dsnet added a commit that referenced this issue Mar 27, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(T1, main.main.func1): complex64 => complex128
	Transformer(T2, main.main.func2): complex128 => [2]float64
	Transformer(T3, main.main.func3): float64 => complex64
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
dsnet added a commit that referenced this issue Mar 27, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(T1, main.main.func1): complex64 => complex128
	Transformer(T2, main.main.func2): complex128 => [2]float64
	Transformer(T3, main.main.func3): float64 => complex64
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
dsnet added a commit that referenced this issue Mar 27, 2018
After some hard-coded limit, check the path for recursive transformers.
Note that detecting an infinite cycle of recursive transformers
would be equivalent to solving the halting problem,
so we could misdiagnose a valid recursion as infinite.

For this reason, the check only triggers after some minimum stack size
so that correctness is not compromised for nearly all situations.
However, the threshold is low enough to trigger before the Go runtime
panics with a stack overflow (which is not recoverable).

Example panic message:
<<<
panic: recursive set of Transformers detected:
	Transformer(T1, main.main.func1): complex64 => complex128
	Transformer(T2, main.main.func2): complex128 => [2]float64
	Transformer(T3, main.main.func3): float64 => complex64
consider using cmpopts.AcyclicTransformer
>>>

Updates #77
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants