Commit 31d8cbc
test: pin a caller's pointer to a slice, map or pointer as a QUIRK (#106)
Set descends into a pointer the caller allocated only when it points
at a struct. A caller's *[]T, *map[K]T or **T, as a field or a slice
element, is left alone: what it holds gets no defaults, a default that
would fail there is not reported, and a tag on the pointer stops at
it. Yet a *[]T or *map[K]T held as a map value is descended into, as
it has been since v1.6.0, whose map loop follows a pointer to a
struct, slice or map. Nothing pinned the skip, and the README said
only that a pointer to a struct is descended into:
slice := []inner{{}} // inner has Name string `default:"inner"`
err := defaults.Set(&struct{ Ptr *[]inner }{Ptr: &slice})
// err=<nil>, slice[0].Name == ""
The README's Maps paragraph and the Set doc, as the commit before this
one wrote them, erred the other way: they said a slice, map or pointer
held as a map value is filled through. A **T map value is not, since
that loop follows a pointer to nothing else.
No library code changes but the Set doc comment. set_pointer_test.go
gains TestSet_CallerPointerToContainerIsSkipped. The README's pointer
paragraph, after the sentence on a pointer to a struct, says that a
pointer the caller allocated to anything else is not descended into,
and that the same *[]T or *map[K]T held as a map value is, though a
**T held as one is not. The Maps paragraph and the Set doc now say
that no map value but a struct is stored back, and that a slice or map
held as a map value is filled through, as is a pointer to a struct,
slice or map, but not a pointer to anything else, such as a **T.
Why this way. #100 descended into all three. The maintainer keeps the
skip instead, as documented behavior. Descending walks every element
behind such a pointer on each Set, which #100 measured as
Walk/pointer/to_filled_slice/elements=1000 going from 163 ns to 182
us, and turns a default that fails there into an error where Set
returned nil. A pointer to a pointer can also lead back to itself with
no struct, slice or map between, which is all the cycle guard earlier
in this stack tracks: a throwaway probe, not committed, of a type
loop *loop pointing at itself passes here and overflows the stack once
Set follows a caller's **T.
Not a behavior change. The QUIRK comment says what is skipped, that a
*[]T or *map[K]T map value is descended into since v1.6.0
(TestSet_MapOfPointerContainers), as a caller's pointer to a struct is
anywhere, and links #100, closed in favor of this pin.
The new test has seven subtests: a caller's *[]T, *map[string]T and
**T field, a *[]T slice element and a **T map value each leave what
they hold unfilled; a tag on a caller's *[]string at a nil slice
leaves the slice nil and the pointer the caller's; and a default that
would fail behind a caller's *[]T is not reported. All pass against
the parent, whose library code this is. The whole suite, go test -race
-shuffle=on -v, gives 311 PASS lines on the parent and 319 here, the 8
new ones added. With #100's library code (a341f0d) and this test
added, six subtests fail, all but the tag one: #100 also kept the tag
from reaching through the caller's pointer. Nothing pinned the skip,
so no test is flipped.
Mutation-checked, 6 of 6 killed, and under each only the new test
fails, so before this commit nothing in the suite noticed any of them.
Descending into a caller's pointer to a slice fails four subtests: the
*[]T field, the slice element, the tag and the failing default. To a
map fails the *map[K]T field, to a pointer the **T field, and to all
three six, all but the **T map value. Following a pointer behind a map
value's pointer, which the Maps paragraph now rules out, fails the **T
map value. Carrying a tag through a caller's pointer to a slice, and
descending no further, fails only the tag subtest. Coverage stays at
100.0%, and make bench-smoke passes all 45 cases.
Replaces #100, which closes in favor of this pin.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent 6852e14 commit 31d8cbc
3 files changed
Lines changed: 109 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
80 | 83 | | |
81 | 84 | | |
82 | 85 | | |
| |||
136 | 139 | | |
137 | 140 | | |
138 | 141 | | |
139 | | - | |
140 | | - | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
141 | 145 | | |
142 | 146 | | |
143 | 147 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
80 | | - | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
81 | 82 | | |
82 | 83 | | |
83 | 84 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
141 | 240 | | |
142 | 241 | | |
143 | 242 | | |
| |||
0 commit comments