From c6ade67b538f585a309c52d271b17119cf18f98b Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Fri, 21 Aug 2020 17:39:06 +0200 Subject: [PATCH] internal/core/export: fix bug 473 Ensure that exporter always exports a struct literal, and not an arbitrary expression. TODO: this can be enforced at compile time by changing the type of the Value field to *ast.StructLit. This is a breaking change in the API though. At some point this will be useful, as it will help prevent users of the API to make similar errors. Fixes #473 Change-Id: I26d1590c9b793ad5c82b02f69af47795a4bbd1a4 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6950 Reviewed-by: Paul Jolly Reviewed-by: CUE cueckoo --- cmd/cue/cmd/testdata/script/issue473.txt | 36 ++++++++++++++++++++++++ internal/core/compile/compile.go | 1 + internal/core/export/adt.go | 6 +++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 cmd/cue/cmd/testdata/script/issue473.txt diff --git a/cmd/cue/cmd/testdata/script/issue473.txt b/cmd/cue/cmd/testdata/script/issue473.txt new file mode 100644 index 00000000000..29516559d67 --- /dev/null +++ b/cmd/cue/cmd/testdata/script/issue473.txt @@ -0,0 +1,36 @@ +cue eval --out json x.cue + +-- cue.mod/module.cue -- +module: "mod.com" +-- x.cue -- +package x + +#Guide: { + Terminals: [string]: #Terminal + + Steps: [string]: #Step + + #TerminalName: or([ for k, _ in Terminals {k}]) + + #Step: { + Terminal: #TerminalName + Cmd: string + } + + #Terminal: { + Image: string + } +} + +g: #Guide & { + Terminals: client: { + Image: "golang" + } + + Steps: { + list: { + Terminal: "client" + Cmd: "ls" + } + } +} \ No newline at end of file diff --git a/internal/core/compile/compile.go b/internal/core/compile/compile.go index 6a174f7beb5..853a6a66fa2 100644 --- a/internal/core/compile/compile.go +++ b/internal/core/compile/compile.go @@ -663,6 +663,7 @@ func (c *compiler) comprehension(x *ast.Comprehension) adt.Elem { prev = next } + // TODO: make x.Value an *ast.StructLit and this is redundant. if y, ok := x.Value.(*ast.StructLit); !ok { return c.errf(x.Value, "comprehension value must be struct, found %T", y) diff --git a/internal/core/export/adt.go b/internal/core/export/adt.go index 27a94d566b1..d73b0ebb140 100644 --- a/internal/core/export/adt.go +++ b/internal/core/export/adt.go @@ -398,7 +398,11 @@ func (e *exporter) comprehension(y adt.Yielder) ast.Expr { y = x.Dst case *adt.ValueClause: - c.Value = e.expr(x.StructLit) + v := e.expr(x.StructLit) + if _, ok := v.(*ast.StructLit); !ok { + v = ast.NewStruct(ast.Embed(v)) + } + c.Value = v return c default: