diff --git a/cue/testdata/comprehensions/pushdown.txtar b/cue/testdata/comprehensions/pushdown.txtar index 21f6583f6..9a940bfd7 100644 --- a/cue/testdata/comprehensions/pushdown.txtar +++ b/cue/testdata/comprehensions/pushdown.txtar @@ -1060,7 +1060,6 @@ issue3729: withoutDisjunctionWithEmbed: { if true { root: {_, #sub1?: #sub2: true} } - // TODO(inline): auto-generate embedded value. @test(eq, {root: {null, #sub1?: {#sub2: true}}}) } issue3729: definitionsOnly: { diff --git a/cue/testdata/disjunctions/embed.txtar b/cue/testdata/disjunctions/embed.txtar index ab38e8c72..819b2002d 100644 --- a/cue/testdata/disjunctions/embed.txtar +++ b/cue/testdata/disjunctions/embed.txtar @@ -92,7 +92,6 @@ issue3415: full: { #A: { i: *0 | number } - // TODO(inline): include embedded scalars when generating. @test(eq, { A: {i: {11, _a: 1, _b: 10}} #A: {i: *0 | number} diff --git a/cue/testdata/eval/let.txtar b/cue/testdata/eval/let.txtar index 4c181ac1f..e0e2edff9 100644 --- a/cue/testdata/eval/let.txtar +++ b/cue/testdata/eval/let.txtar @@ -23,7 +23,8 @@ b: { a: T b: F -} +} @test(eq, {a: 4718592, b: 288}) + // Nil pointer in *core/adt.Environment.evalCached caused by a let binding // that references a list comprehension over another let-bound list. // https://cuelang.org/issue/1828 @@ -36,10 +37,14 @@ issue1828: { let L2 = L1 let L1 = [] + + @test(eq, {volumes: {}}) } ignoreErrorInLet: { let X = 1 & 2 disjunction: *X | 3 + + @test(eq, {disjunction: 3}) } -- incomprehension.cue -- // for comprehensions in list do not have to split the let as each instance @@ -52,6 +57,7 @@ list: { X } ] + @test(eq, {l: [1, 2, 3], c: [{4}, {8}, {12}]}) } referencesForDirectly: { @@ -60,6 +66,12 @@ referencesForDirectly: { let Y = v*4 // multi "\(k)": Y } + @test(eq, { + l: [1, 2, 3] + "0": 4 + "1": 8 + "2": 12 + }) } referencesForViaLet: { @@ -68,6 +80,12 @@ referencesForViaLet: { let Y = X // multi "\(k)": Y } + @test(eq, { + l: [1, 2, 3] + "0": 4 + "1": 8 + "2": 12 + }) } letClauseReferencesInert: { @@ -77,6 +95,13 @@ letClauseReferencesInert: { let Y = X // can share "\(k)": Y } + @test(eq, { + x: 2 + l: [1, 2, 3] + "0": 2 + "1": 2 + "2": 2 + }) } // for indirect references, it is okay to not "split" a let clause, as the @@ -89,7 +114,13 @@ indirectReference: { let X = y*4 // can share, as y fails if let fails. "\(k)": X } -} @test(err, code=eval, contains="conflicting values", pos=[0:20, 1:7, 1:10, 2:2, 3:6]) + @test(err, code=eval, + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[2, 1], pos=[0:20, 1:7, 1:10, 2:2, 3:6]), + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[3, 1], pos=[0:20, 1:7, 1:13, 2:2, 3:6])) + +} @test(err, code=eval, + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[2, 1], pos=[0:20, 1:7, 1:10, 2:2, 3:6]), + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[3, 1], pos=[0:20, 1:7, 1:13, 2:2, 3:6])) nestedFor: { for k, y in [ 4, 5 ] { @@ -101,6 +132,10 @@ nestedFor: { } "\(k)": X } + @test(eq, { + "0": {"1": 1, "2": 2} + "1": {"1": 1, "2": 2} + }) } -- issue2166.cue -- // Using a let clause inside a field comprehension to create a dynamic key @@ -116,6 +151,7 @@ letWithDynamicInComprehension: { let T = v (T): "1" } + @test(eq, {_i: {a: "d", b: "e"}, e: "1", d: "1"}) } -- issue2218.cue -- // Earlier let evaluation results in the wrong value: a let inside a for @@ -123,7 +159,7 @@ letWithDynamicInComprehension: { // https://cuelang.org/issue/2218 _parent_configs: { PARENT: true -} +} @test(eq) _configs: { CHILD1: { property: true @@ -139,6 +175,7 @@ disabled_parent_test: {for k, v in _configs { "parent_config": parent_config } }} + -- issue2063.cue -- import ( "encoding/yaml" @@ -156,6 +193,7 @@ keepDescending: t1: { if m == _|_ { } x: y: "" } + @test(eq, {ec: {}, bs: {x: {y: ""}}}) } keepDescending: t2: { @@ -167,6 +205,11 @@ keepDescending: t2: { if m.b == _|_ { } X: Y: strings.Join([], "") } + @test(eq, { + x: "X:\n \"Y\": \"\"\n" + ec: {} + bs: {X: {Y: ""}} + }) } -- interpolation.cue -- // evalv3 closedness regression with disjunctions and ellipses where a let @@ -177,56 +220,57 @@ issue4022: full: { _env: { KEY: *"" | _ } + @test(eq, {envScript: [""], _env: {KEY: *"" | _}}) } -- out/errors.txt -- [eval] indirectReference.y: conflicting values 2 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:10 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:10 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 indirectReference.y: conflicting values 3 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:13 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:13 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 [eval] indirectReference.y: conflicting values 2 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:10 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:10 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 indirectReference.y: conflicting values 3 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:13 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:13 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 [eval] indirectReference.y: conflicting values 2 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:10 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:10 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 indirectReference.y: conflicting values 3 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:13 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:13 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 [eval] indirectReference.y: conflicting values 2 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:10 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:10 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 indirectReference.y: conflicting values 3 and 1: - ./incomprehension.cue:41:20 - ./incomprehension.cue:42:7 - ./incomprehension.cue:42:13 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 + ./incomprehension.cue:61:20 + ./incomprehension.cue:62:7 + ./incomprehension.cue:62:13 + ./incomprehension.cue:63:2 + ./incomprehension.cue:64:6 -- out/eval/stats -- Leaks: 52 Freed: 163 diff --git a/internal/cuetxtar/inline_format.go b/internal/cuetxtar/inline_format.go index 283268eb5..da86c0910 100644 --- a/internal/cuetxtar/inline_format.go +++ b/internal/cuetxtar/inline_format.go @@ -326,6 +326,19 @@ func (w *eqWriter) writeErrAnnotation(b *strings.Builder, v cue.Value) { func (w *eqWriter) writeStruct(b *strings.Builder, vx *adt.Vertex, nestedIndent string) { b.WriteByte('{') first := true + + // If BaseValue is a concrete scalar or constraint (not a struct/list + // marker), it represents an embedded expression, e.g. {4} or {>=5}. + // *StructMarker and *ListMarker do not implement adt.Value (they lack + // Concreteness()), so this check correctly skips them. + if embVal, ok := vx.BaseValue.(adt.Value); ok { + if nestedIndent != "" { + b.WriteString("\n" + nestedIndent) + } + first = false + w.writeValue(b, value.Make(w.opCtx, embVal), nestedIndent+"\t") + } + for _, arc := range vx.Arcs { if arc.ArcType == adt.ArcNotPresent || arc.Label.IsLet() { continue diff --git a/internal/cuetxtar/testdata/inline/eq_embedded_scalar.txtar b/internal/cuetxtar/testdata/inline/eq_embedded_scalar.txtar new file mode 100644 index 000000000..a0fc4bf00 --- /dev/null +++ b/internal/cuetxtar/testdata/inline/eq_embedded_scalar.txtar @@ -0,0 +1,34 @@ +# Tests that @test(eq) correctly handles struct elements with embedded scalars. +# For-comprehension bodies like {let X = v*4; X} produce a vertex whose +# BaseValue is a scalar (not *StructMarker), so writeStruct must emit it as +# an embedded expression: {4} rather than {}. +# +# pass: already-filled @test(eq, [{4}]) must pass. +# seed: bare @test(eq) on a comprehension list is seeded with {4} elements. +-- in/test.cue -- +// Pass: comprehension body with embedded scalar — already filled. +pass: [for v in [1] { + let X = v*4 + X +}] @test(eq, [{4}]) + +// Seed: bare @test(eq); CUE_UPDATE=1 must emit {4}, not {}. +seed: [for v in [1, 2] { + let X = v*4 + X +}] @test(eq) +-- out/status.txt -- +update: output passes run +force: identical to update +-- out/update/test.cue -- +// Pass: comprehension body with embedded scalar — already filled. +pass: [for v in [1] { + let X = v*4 + X +}] @test(eq, [{4}]) + +// Seed: bare @test(eq); CUE_UPDATE=1 must emit {4}, not {}. +seed: [for v in [1, 2] { + let X = v*4 + X +}] @test(eq, [{4}, {8}])