Skip to content

Commit 4453ac2

Browse files
cty: Use DeepValues instead of Walk for deep marks inspections
An earlier commit added cty.DeepValues as an iter.Seq2-based alternative to Walk, and that's much easier to use for deep inspections because it doesn't require weird trickery to get the Walk to stop at the right time and smuggle result values out. However, in the process of doing this I discovered that cty.DeepValues itself was falling into that very trap of failing to terminate Walk correctly, and so this also includes a fixed version of that which will stop yielding new values once commanded to do so.
1 parent f833b10 commit 4453ac2

File tree

2 files changed

+16
-20
lines changed

2 files changed

+16
-20
lines changed

cty/marks.go

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cty
22

33
import (
44
"fmt"
5-
"io"
65
"iter"
76
"strings"
87
)
@@ -124,15 +123,12 @@ func (val Value) HasMark(mark any) bool {
124123
// HasMarkDeep is like [HasMark] but also searches any values nested inside
125124
// the given value.
126125
func (val Value) HasMarkDeep(mark any) bool {
127-
found := false
128-
Walk(val, func(p Path, v Value) (bool, error) {
126+
for _, v := range DeepValues(val) {
129127
if v.HasMark(mark) {
130-
found = true
131-
return false, io.EOF // arbitrary error just to stop the Walk early
128+
return true
132129
}
133-
return true, nil
134-
})
135-
return found
130+
}
131+
return false
136132
}
137133

138134
// ValueMarksOfType returns an iterable sequence of any marks directly
@@ -151,12 +147,11 @@ func ValueMarksOfType[T any](v Value) iter.Seq[T] {
151147
// marked with it.
152148
func ValueMarksOfTypeDeep[T any](v Value) iter.Seq[T] {
153149
return func(yield func(T) bool) {
154-
Walk(v, func(p Path, v Value) (bool, error) {
150+
for _, v := range DeepValues(v) {
155151
if !yieldValueMarksOfType(v, yield) {
156-
return false, io.EOF // arbitrary error just to stop the Walk early
152+
break
157153
}
158-
return true, nil
159-
})
154+
}
160155
}
161156
}
162157

@@ -181,15 +176,12 @@ func yieldValueMarksOfType[T any](v Value, yield func(T) bool) bool {
181176
// This operation is relatively expensive. If you only need a shallow result,
182177
// use IsMarked instead.
183178
func (val Value) ContainsMarked() bool {
184-
ret := false
185-
Walk(val, func(_ Path, v Value) (bool, error) {
179+
for _, v := range DeepValues(val) {
186180
if v.IsMarked() {
187-
ret = true
188-
return false, nil
181+
return true
189182
}
190-
return true, nil
191-
})
192-
return ret
183+
}
184+
return false
193185
}
194186

195187
func (val Value) assertUnmarked() {

cty/walk.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cty
22

33
import (
4+
"io"
45
"iter"
56
)
67

@@ -38,7 +39,10 @@ func Walk(val Value, cb func(Path, Value) (bool, error)) error {
3839
func DeepValues(val Value) iter.Seq2[Path, Value] {
3940
return func(yield func(Path, Value) bool) {
4041
Walk(val, func(p Path, v Value) (bool, error) {
41-
return yield(p, v), nil
42+
if !yield(p, v) {
43+
return false, io.EOF // arbitrary error just to get Walk to stop
44+
}
45+
return true, nil
4246
})
4347
}
4448
}

0 commit comments

Comments
 (0)