Skip to content

Commit 699ce65

Browse files
committed
cue: allow incomplete errors in Fields method
Default iterations assumes values may be incomplete. However, if a struct has an incomplete error, it errors out even if Final or Concrete are not specified. This is now changed. This is a somewhat dangerous change as it changes behavior. The old behavior was arguably a bug, though. Users can use Value.IsConcrete to guard against iterating over a struct with an incomplete error. Fixes #1517 Signed-off-by: Marcel van Lohuizen <mpvl@golang.org> Change-Id: I38fd5bd779384d52d8876bf5f7b0b5f086cbafe7 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/533457 Unity-Result: CUEcueckoo <cueckoo@cuelang.org> TryBot-Result: CUEcueckoo <cueckoo@cuelang.org> Reviewed-by: Paul Jolly <paul@myitcv.io>
1 parent b6cdc74 commit 699ce65

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

cue/types.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,14 @@ func (v Value) structValOpts(ctx *adt.OpContext, o options) (s structValue, err
13811381

13821382
obj := v.v
13831383

1384-
if !o.allowScalar {
1384+
switch b, ok := v.v.BaseValue.(*adt.Bottom); {
1385+
case ok && b.IsIncomplete() && !o.concrete && !o.final:
1386+
1387+
// TODO:
1388+
// case o.allowScalar, !o.omitHidden, !o.omitDefinitions:
1389+
// Allow scalar values if hidden or definition fields are requested?
1390+
case o.allowScalar:
1391+
default:
13851392
obj, err = v.getStruct()
13861393
if err != nil {
13871394
return structValue{}, err

cue/types_test.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ func TestFields(t *testing.T) {
702702
value string
703703
res string
704704
err string
705+
opts []Option
705706
}{{
706707
value: `{ #def: 1, _hidden: 2, opt?: 3, reg: 4 }`,
707708
res: "{reg:4,}",
@@ -725,20 +726,43 @@ func TestFields(t *testing.T) {
725726
res: "{}",
726727
}, {
727728
value: `{ for k, v in #y if v > 1 {"\(k)": v} }
728-
#y: {a:1,b:2,c:3}`,
729+
#y: {a:1,b:2,c:3}`,
729730
res: "{b:2,c:3,}",
730731
}, {
731732
value: `{ #def: 1, _hidden: 2, opt?: 3, reg: 4 }`,
732733
res: "{reg:4,}",
733734
}, {
734735
value: `{a:1,b:2,c:int}`,
735736
err: "cannot convert incomplete value",
737+
}, {
738+
value: `
739+
step1: {}
740+
step2: {prefix: 3}
741+
if step2.value > 100 {
742+
step3: {prefix: step2.value}
743+
}
744+
_hidden: 3`,
745+
res: `{step1:{},step2:{"prefix":3},}`,
746+
}, {
747+
opts: []Option{Final()},
748+
value: `
749+
step1: {}
750+
if step1.value > 100 {
751+
}`,
752+
err: "undefined field: value",
753+
}, {
754+
opts: []Option{Concrete(true)},
755+
value: `
756+
step1: {}
757+
if step1.value > 100 {
758+
}`,
759+
err: "undefined field: value",
736760
}}
737761
for _, tc := range testCases {
738762
t.Run(tc.value, func(t *testing.T) {
739763
obj := getInstance(t, tc.value).Value()
740764

741-
iter, err := obj.Fields()
765+
iter, err := obj.Fields(tc.opts...)
742766
checkFatal(t, err, tc.err, "init")
743767

744768
buf := []byte{'{'}
@@ -755,7 +779,7 @@ func TestFields(t *testing.T) {
755779
t.Errorf("got %v; want %v", got, tc.res)
756780
}
757781

758-
iter, _ = obj.Fields()
782+
iter, _ = obj.Fields(tc.opts...)
759783
for iter.Next() {
760784
want, err := iter.Value().MarshalJSON()
761785
checkFatal(t, err, tc.err, "Obj.At2")

0 commit comments

Comments
 (0)