this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/core/export: fix hidden field visibility for anonymous pkgID

When exporting a vertex with an empty pkgID (e.g. from a sub-value
looked up via LookupPath when the root has no associated instance),
hidden fields were silently suppressed even with ShowHidden=true.

The root cause: anonymous-package hidden labels store "_" as their pkgID
(the anonymous package marker), but the exporter's e.pkgID was "" when
no build.Instance is available. The comparison label.PkgID(ctx) ==
e.pkgID evaluated "_" == "" = false, so no hidden fields were emitted.

Fix: in structComposite, treat e.pkgID=="" as "_" before the comparison,
so anonymous exporters can see anonymous labels.

Also fix internal/cuetxtar inline.go to pass cue.Definitions(true) and
cue.Hidden(true) to formatValue, so that @test(eq, ...) directives on
fields with hidden or definition sub-fields produce correct expected
values. This is what triggered the discovery of the value.go bug.

Convert cue/testdata/scalars/yield.txtar to inline @test format.

Add regression tests in cue/syntax_test.go exercising the sub-value +
Final export path that triggered the bug.

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: I93ca352da3866c24643d7a07a466cbe4255fd75d
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1235231
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+67 -102
+27
cue/syntax_test.go
··· 230 230 path: "#person.children", 231 231 options: o(cue.Raw()), 232 232 out: `[...#person]`, 233 + }, { 234 + // Hidden fields in sub-values must appear when ShowHidden is true and 235 + // cue.Final() is used. GetInstanceFromNode only tracks root vertices; a 236 + // sub-value from LookupPath has instance()=nil → ID()="". The Vertex 237 + // export path (taken when o.final=true) calls structComposite, which 238 + // checks label.PkgID(e.ctx)==e.pkgID. With e.pkgID=="" but 239 + // label.PkgID="_" (anonymous package marker), the comparison failed and 240 + // hidden fields were dropped. Fix: map e.pkgID=="" to "_". 241 + name: "hidden field in sub-value", 242 + in: `outer: {a: 1, _hidden: "secret"}`, 243 + path: "outer", 244 + options: o(cue.Final(), cue.Hidden(true)), 245 + out: `{ 246 + a: 1 247 + _hidden: "secret" 248 + }`, 249 + }, { 250 + // Hidden-definition fields (_#name) have pkgID "_" in anonymous contexts 251 + // and were affected by the same bug when accessed as a sub-value with Final. 252 + name: "hidden-def field in sub-value", 253 + in: `outer: {_#cond: true, a: 1}`, 254 + path: "outer", 255 + options: o(cue.Final(), cue.Hidden(true)), 256 + out: `{ 257 + _#cond: true 258 + a: 1 259 + }`, 233 260 }} 234 261 for _, tc := range testCases { 235 262 t.Run(tc.name, func(t *testing.T) {
+9 -9
cue/testdata/eval/nonrooted.txtar
··· 69 69 [incomplete] issue3977.inlineDisj1.#fn.out: invalid interpolation: unresolved disjunction "2" | "3" | "4" (type string): 70 70 ./in.cue:14:8 71 71 [eval] x: conflicting values 2 and 1: 72 - ./in.cue:22:14 73 - ./in.cue:24:8 74 - ./in.cue:30:8 75 - ./in.cue:30:19 72 + ./in.cue:20:14 73 + ./in.cue:22:8 74 + ./in.cue:26:8 75 + ./in.cue:26:19 76 76 x: conflicting values 4 and 1: 77 - ./in.cue:22:14 78 - ./in.cue:24:8 79 - ./in.cue:30:8 80 - ./in.cue:30:23 77 + ./in.cue:20:14 78 + ./in.cue:22:8 79 + ./in.cue:26:8 80 + ./in.cue:26:23 81 81 x: 2 errors in empty disjunction:: 82 - ./in.cue:25:8 82 + ./in.cue:23:8 83 83 -- out/compile -- 84 84 --- in.cue 85 85 {
+3 -3
cue/testdata/fulleval/055_issue318.txtar
··· 19 19 ./in.cue:3:8 20 20 ./in.cue:3:24 21 21 [eval] #T.out2: invalid interpolation: undefined field: y: 22 - ./in.cue:4:8 23 - ./in.cue:4:15 22 + ./in.cue:6:8 23 + ./in.cue:6:15 24 24 [eval] #T.vy: undefined field: y: 25 - ./in.cue:6:12 25 + ./in.cue:8:12 26 26 -- out/compile -- 27 27 --- in.cue 28 28 {
+22 -84
cue/testdata/scalars/yield.txtar
··· 1 1 // Issue #729 2 - #todo:inline: medium — comprehension; may need @test(final) for incomplete fields 3 2 -- in.cue -- 4 3 ifScalar: { 5 4 _#cond: true 6 5 7 6 if _#cond {5} 7 + @test(eq, { 8 + 5 9 + _#cond: true 10 + }) 8 11 } 9 12 10 13 ifScalarConflict: { ··· 13 16 if _#cond {5} 14 17 15 18 "soo" 19 + @test(err, code=eval, contains="conflicting values", args=["soo", 5, string, int], pos=[0:19, 3:2, 3:13, 5:2]) 16 20 } 17 21 18 22 ifScalarNested: { ··· 20 24 21 25 if _#cond {{{5}}} 22 26 27 + @test(eq, {5, _#cond: true}) 23 28 } 24 - -- out/eval/stats -- 25 - Leaks: 0 26 - Freed: 7 27 - Reused: 2 28 - Allocs: 5 29 - Retain: 0 30 - 31 - Unifications: 7 32 - Conjuncts: 16 33 - Disjuncts: 0 34 - 35 - NumCloseIDs: 12 36 - -- out/evalalpha -- 37 - Errors: 38 - ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): 29 + -- out/errors.txt -- 30 + [eval] ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): 39 31 ./in.cue:7:19 40 32 ./in.cue:10:2 41 33 ./in.cue:10:13 42 34 ./in.cue:12:2 43 - 44 - Result: 45 - (_|_){ 46 - // [eval] 47 - ifScalar: (int){ 48 - 5 49 - _#cond: (bool){ true } 50 - } 51 - ifScalarConflict: (_|_){ 52 - // [eval] ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): 53 - // ./in.cue:7:19 54 - // ./in.cue:10:2 55 - // ./in.cue:10:13 56 - // ./in.cue:12:2 57 - _#cond: (bool){ true } 58 - } 59 - ifScalarNested: (int){ 60 - 5 61 - _#cond: (bool){ true } 62 - } 63 - } 64 - -- diff/-out/evalalpha<==>+out/eval -- 65 - diff old new 66 - --- old 67 - +++ new 68 - @@ -1,5 +1,6 @@ 69 - Errors: 70 - ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): 71 - + ./in.cue:7:19 72 - ./in.cue:10:2 73 - ./in.cue:10:13 74 - ./in.cue:12:2 75 - @@ -13,6 +14,7 @@ 76 - } 77 - ifScalarConflict: (_|_){ 78 - // [eval] ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): 79 - + // ./in.cue:7:19 80 - // ./in.cue:10:2 81 - // ./in.cue:10:13 82 - // ./in.cue:12:2 83 - -- diff/todo/p2 -- 84 - Missing error positions 85 - -- out/eval -- 86 - Errors: 87 - ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): 88 - ./in.cue:10:2 89 - ./in.cue:10:13 90 - ./in.cue:12:2 91 - 92 - Result: 93 - (_|_){ 94 - // [eval] 95 - ifScalar: (int){ 96 - 5 97 - _#cond: (bool){ true } 98 - } 99 - ifScalarConflict: (_|_){ 100 - // [eval] ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): 101 - // ./in.cue:10:2 102 - // ./in.cue:10:13 103 - // ./in.cue:12:2 104 - _#cond: (bool){ true } 105 - } 106 - ifScalarNested: (int){ 107 - 5 108 - _#cond: (bool){ true } 109 - } 110 - } 111 35 -- out/compile -- 112 36 --- in.cue 113 37 { ··· 135 59 } 136 60 } 137 61 } 62 + -- out/eval/stats -- 63 + Leaks: 0 64 + Freed: 7 65 + Reused: 2 66 + Allocs: 5 67 + Retain: 0 68 + 69 + Unifications: 7 70 + Conjuncts: 16 71 + Disjuncts: 0 72 + 73 + NumCloseIDs: 12 74 + -- out/diff-v2-v3.txt -- 75 + v2 does not report in.cue:7:19 in the error; v3 does.
+4 -1
internal/core/export/value.go
··· 15 15 package export 16 16 17 17 import ( 18 + "cmp" 18 19 "fmt" 19 20 "slices" 20 21 "strings" ··· 426 427 case adt.DefinitionLabel: 427 428 show = p.ShowDefinitions 428 429 case adt.HiddenLabel, adt.HiddenDefinitionLabel: 429 - show = p.ShowHidden && label.PkgID(e.ctx) == e.pkgID 430 + lpkg := label.PkgID(e.ctx) 431 + pkgID := cmp.Or(e.pkgID, "_") 432 + show = p.ShowHidden && lpkg == pkgID 430 433 } 431 434 if !show { 432 435 continue
+2 -5
internal/cuetxtar/inline.go
··· 1251 1251 // cue.Final() routes to Vertex() export (no _#def wrapping) and sets 1252 1252 // omitOptional=true. cue.Optional(true) applied afterwards re-enables 1253 1253 // optional fields, giving us the complete value without internals. 1254 - syn := v.Syntax(cue.Docs(true), cue.Final(), cue.Optional(true)) 1255 - if syn == nil { 1256 - return fmt.Sprintf("%v", v) 1257 - } 1254 + syn := v.Syntax(cue.Docs(true), cue.Final(), cue.Optional(true), cue.Definitions(true), cue.Hidden(true)) 1258 1255 b, err := format.Node(syn) 1259 1256 if err != nil { 1260 - return fmt.Sprintf("%v", v) 1257 + return fmt.Sprintf("%#v", v) 1261 1258 } 1262 1259 return string(b) 1263 1260 }