Skip to content

Commit

Permalink
pkg/internal: fix decimal and string list errors
Browse files Browse the repository at this point in the history
Fixes regression introduced in 0ffde15.
Problem was bug that converted an incomplete error to a
permanent error.

The solution is to not use the public API, but rather
the internal one, and pass errors up more directly.

This also fixes a bug with slice, which masked
unevaluated arcs with a finalized one. This issue
did not surface before as the API would proactively
evaluate arcs.  For this reason (and because slices
are officially not supported), the lower level
implementations now defensively still proactively
evaluate, even if this should not be necessary.

Fixes #776

Change-Id: I76f9e36cf28d5bde0f0a629958c7d07b909d48f5
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8742
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Feb 16, 2021
1 parent 17ea1d5 commit 38f0f63
Show file tree
Hide file tree
Showing 3 changed files with 283 additions and 62 deletions.
221 changes: 207 additions & 14 deletions cue/testdata/builtins/incomplete.txtar
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
-- in.cue --
import "list"
import (
"list"
"strings"
)


list1: {
Expand Down Expand Up @@ -40,73 +43,217 @@ value2: {
len('sf' | 'dd')
}

incompleteArgDecimalList: {
a: #a & {param: 123}
#a: {
param: int
transformed: +param
max: list.Max([transformed])
}
}

incompleteArgStringList: {
a: #a & {param: "123"}
#a: {
param: string
transformed: param+""
joined: strings.Join([transformed], "-")
}
}

incompleteList: {
x: _
decimal: list.Max(x)
str: strings.Join(x, "")
}

incompleteListError: {
x: y + []
y: _
decimal: list.Max(x)
str: strings.Join(x, "")
}

badListType: {
x: 2
decimal: list.Max(x)
str: strings.Join(x, "")
}

badListError: {
x: 2 + y
y: "foo"
decimal: list.Max(x)
str: strings.Join(x, "")
}

-- out/eval --
(struct){
Errors:
badListType.decimal: cannot use 2 (type int) as list in argument 1 to list.Max:
./in.cue:77:8
badListType.str: cannot use 2 (type int) as list in argument 1 to strings.Join:
./in.cue:77:8
badListError.x: invalid operands 2 and "foo" to '+' (type int and string):
./in.cue:83:8

Result:
(_|_){
// [eval]
list1: (struct){
Out1: (#list){
0: (_|_){
// [cycle] cycle error:
// ./in.cue:13:23
// ./in.cue:16:23
}
}
Out2: (#list){
0: (_|_){
// [cycle] cycle error:
// ./in.cue:13:23
// ./in.cue:16:23
}
}
Out3: (#list){
0: (_|_){
// [cycle] cycle error:
// ./in.cue:13:23
// ./in.cue:16:23
}
}
Top: (#list){
0: (_|_){
// [cycle] cycle error:
// ./in.cue:13:23
// ./in.cue:16:23
}
}
_Sub: (_|_){
// [incomplete] list1._Sub: undefined field b:
// ./in.cue:16:13
// ./in.cue:19:13
}
a: (struct){
}
}
list2: (struct){
Out1: (_|_){
// [cycle] cycle error:
// ./in.cue:27:21
// ./in.cue:30:21
}
Out2: (_|_){
// [cycle] cycle error:
// ./in.cue:27:21
// ./in.cue:30:21
}
Out3: (_|_){
// [cycle] cycle error:
// ./in.cue:27:21
// ./in.cue:30:21
}
_Top: (_|_){
// [cycle] cycle error:
// ./in.cue:27:21
// ./in.cue:30:21
}
#Sub: (_|_){
// [incomplete] list2.#Sub: undefined field b:
// ./in.cue:30:13
// ./in.cue:33:13
}
a: (struct){
}
}
value1: (struct){
a: (_|_){
// [incomplete] value1.a: unresolved disjunction 'sf' | 'dd' (type bytes):
// ./in.cue:35:8
// ./in.cue:38:8
}
}
value2: (_|_){
// [incomplete] value2: unresolved disjunction 'sf' | 'dd' (type bytes):
// ./in.cue:39:5
// ./in.cue:42:5
}
incompleteArgDecimalList: (struct){
a: (#struct){
param: (int){ 123 }
transformed: (int){ 123 }
max: (int){ 123 }
}
#a: (#struct){
param: (int){ int }
transformed: (_|_){
// [incomplete] incompleteArgDecimalList.#a.transformed: operand param of '+' not concrete (was int):
// ./in.cue:49:23
}
max: (_|_){
// [incomplete] 0: operand param of '+' not concrete (was int):
// ./in.cue:49:23
}
}
}
incompleteArgStringList: (struct){
a: (#struct){
param: (string){ "123" }
transformed: (string){ "123" }
joined: (string){ "123" }
}
#a: (#struct){
param: (string){ string }
transformed: (_|_){
// [incomplete] incompleteArgStringList.#a.transformed: non-concrete value string in operand to +:
// ./in.cue:58:22
}
joined: (_|_){
// [incomplete] 0: non-concrete value string in operand to +:
// ./in.cue:58:22
}
}
}
incompleteList: (struct){
x: (_){ _ }
decimal: (_|_){
// [incomplete] incompleteList.decimal: non-concrete list for argument 0:
// ./in.cue:65:14
}
str: (_|_){
// [incomplete] incompleteList.str: non-concrete list for argument 0:
// ./in.cue:66:14
}
}
incompleteListError: (struct){
x: (_|_){
// [incomplete] incompleteListError.x: non-concrete value _ in operand to +:
// ./in.cue:70:8
}
y: (_){ _ }
decimal: (_|_){
// [incomplete] incompleteListError.x: non-concrete value _ in operand to +:
// ./in.cue:70:8
}
str: (_|_){
// [incomplete] incompleteListError.x: non-concrete value _ in operand to +:
// ./in.cue:70:8
}
}
badListType: (_|_){
// [eval]
x: (int){ 2 }
decimal: (_|_){
// [eval] badListType.decimal: cannot use 2 (type int) as list in argument 1 to list.Max:
// ./in.cue:77:8
}
str: (_|_){
// [eval] badListType.str: cannot use 2 (type int) as list in argument 1 to strings.Join:
// ./in.cue:77:8
}
}
badListError: (_|_){
// [eval]
x: (_|_){
// [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string):
// ./in.cue:83:8
}
y: (string){ "foo" }
decimal: (_|_){
// [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string):
// ./in.cue:83:8
}
str: (_|_){
// [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string):
// ./in.cue:83:8
}
}
}
-- out/compile --
Expand Down Expand Up @@ -152,4 +299,50 @@ value2: {
value2: {
len(('sf'|'dd'))
}
incompleteArgDecimalList: {
a: (〈0;#a〉 & {
param: 123
})
#a: {
param: int
transformed: +〈0;param〉
max: 〈import;list〉.Max([
〈0;transformed〉,
])
}
}
incompleteArgStringList: {
a: (〈0;#a〉 & {
param: "123"
})
#a: {
param: string
transformed: (〈0;param〉 + "")
joined: 〈import;strings〉.Join([
〈0;transformed〉,
], "-")
}
}
incompleteList: {
x: _
decimal: 〈import;list〉.Max(〈0;x〉)
str: 〈import;strings〉.Join(〈0;x〉, "")
}
incompleteListError: {
x: (〈0;y〉 + [])
y: _
decimal: 〈import;list〉.Max(〈0;x〉)
str: 〈import;strings〉.Join(〈0;x〉, "")
}
badListType: {
x: 2
decimal: 〈import;list〉.Max(〈0;x〉)
str: 〈import;strings〉.Join(〈0;x〉, "")
}
badListError: {
x: (2 + 〈0;y〉)
y: "foo"
decimal: 〈import;list〉.Max(〈0;x〉)
str: 〈import;strings〉.Join(〈0;x〉, "")
}
}
8 changes: 4 additions & 4 deletions internal/core/adt/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -951,10 +951,10 @@ func (x *SliceExpr) evaluate(c *OpContext) Value {
c.AddBottom(&Bottom{Src: a.Source(), Err: err})
return nil
}
n.Arcs = append(n.Arcs, &Vertex{
Label: label,
Conjuncts: a.Conjuncts,
})
arc := *a
arc.Parent = n
arc.Label = label
n.Arcs = append(n.Arcs, &arc)
}
n.status = Finalized
return n
Expand Down

0 comments on commit 38f0f63

Please sign in to comment.