-
Notifications
You must be signed in to change notification settings - Fork 208
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
Comments
This is expected behavior. There are two ways to work around this: 1. Avoid cycles in the types: 2. Use a non-reentrant transformer: 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 |
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. In fact, the commit mentioned (c2186a4), e.g. removed this from an // 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 // 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.
That actually seems like a very good solution and |
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
The text was updated successfully, but these errors were encountered: