internal/core/eval: add more positions to conflict errors
This should bring conflict errors mostly up to par with v0.2.2.
It also adds some context errors for definitions. More refined
tracing of references (in acceptor.Canopy) will be able to
address Issue #129.
Change-Id: Ic359a324c2d3034b4895b06cb7f91c3c546a8a0a
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7302
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt b/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt
index 59f8451..71d9d02 100644
--- a/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt
@@ -3,7 +3,9 @@
cmp stderr cmd_baddisplay.out
-- cmd_baddisplay.out --
-command.baddisplay.display.text: conflicting values 42 and string (mismatched types int and string)
+command.baddisplay.display.text: conflicting values 42 and string (mismatched types int and string):
+ ./task_tool.cue:6:9
+ tool/cli:4:9
-- task.cue --
package home
message: "Hello world!"
diff --git a/cmd/cue/cmd/testdata/script/def_jsonschema.txt b/cmd/cue/cmd/testdata/script/def_jsonschema.txt
index 0d00218..c1515e8 100644
--- a/cmd/cue/cmd/testdata/script/def_jsonschema.txt
+++ b/cmd/cue/cmd/testdata/script/def_jsonschema.txt
@@ -68,7 +68,11 @@
age: twenty
-- expect-stderr2 --
-age: conflicting values "twenty" and int (mismatched types string and int)
+age: conflicting values "twenty" and int (mismatched types string and int):
+ ./data.yaml:1:7
+ ./schema.json:18:7
-- expect-stderr3 --
-age: conflicting values "twenty" and int (mismatched types string and int)
+age: conflicting values "twenty" and int (mismatched types string and int):
+ ./data.yaml:1:7
+ ./schema.json:18:7
-- cue.mod --
diff --git a/cmd/cue/cmd/testdata/script/eval_errs.txt b/cmd/cue/cmd/testdata/script/eval_errs.txt
index 3b0c20b..bb3be9e 100644
--- a/cmd/cue/cmd/testdata/script/eval_errs.txt
+++ b/cmd/cue/cmd/testdata/script/eval_errs.txt
@@ -4,8 +4,12 @@
-- expect-stdout --
-- expect-stderr --
-bar.b: conflicting values 2 and string (mismatched types int and string)
-x.q: incompatible values "goodbye" and "hello"
+bar.b: conflicting values 2 and string (mismatched types int and string):
+ ./errs.cue:5:21
+ ./errs.cue:6:26
+x.q: conflicting values "goodbye" and "hello":
+ ./errs.cue:1:4
+ ./errs.cue:2:4
-- errs.cue --
a: "hello"
b: "goodbye"
diff --git a/cmd/cue/cmd/testdata/script/vet_file.txt b/cmd/cue/cmd/testdata/script/vet_file.txt
index 6f2f2a2..3797681 100644
--- a/cmd/cue/cmd/testdata/script/vet_file.txt
+++ b/cmd/cue/cmd/testdata/script/vet_file.txt
@@ -6,10 +6,14 @@
-- expect-stderr --
translations.hello.lang: incomplete value string
-translations.hello.lang: conflicting values false and string (mismatched types bool and string)
+translations.hello.lang: conflicting values false and string (mismatched types bool and string):
+ ./data.yaml:13:11
+ ./vet.cue:3:31
-- expect-stderr2 --
translations.hello.lang: incomplete value string
-translations.hello.lang: conflicting values false and string (mismatched types bool and string)
+translations.hello.lang: conflicting values false and string (mismatched types bool and string):
+ ./data.yaml:13:11
+ ./vet.cue:3:31
-- vet.cue --
package foo
diff --git a/cue/testdata/basicrewrite/001_regexp.txtar b/cue/testdata/basicrewrite/001_regexp.txtar
index 3da41ea..fe56fa7 100644
--- a/cue/testdata/basicrewrite/001_regexp.txtar
+++ b/cue/testdata/basicrewrite/001_regexp.txtar
@@ -66,7 +66,9 @@
}
-- out/eval --
Errors:
-e3: conflicting values !="a" and <5 (mismatched types string and number)
+e3: conflicting values !="a" and <5 (mismatched types string and number):
+ ./in.cue:22:5
+ ./in.cue:22:13
b3: invalid value "foo" (out of bound =~"[a-z]{4}"):
./in.cue:10:5
e1: cannot use 1 (type int) as type (string|bytes):
@@ -101,6 +103,8 @@
// ./in.cue:21:5
}
e3: (_|_){
- // [eval] e3: conflicting values !="a" and <5 (mismatched types string and number)
+ // [eval] e3: conflicting values !="a" and <5 (mismatched types string and number):
+ // ./in.cue:22:5
+ // ./in.cue:22:13
}
}
diff --git a/cue/testdata/basicrewrite/004_booleans.txtar b/cue/testdata/basicrewrite/004_booleans.txtar
index c27259b..c2bab8c 100644
--- a/cue/testdata/basicrewrite/004_booleans.txtar
+++ b/cue/testdata/basicrewrite/004_booleans.txtar
@@ -27,7 +27,9 @@
}
-- out/eval --
Errors:
-e: incompatible values false and true
+e: conflicting values false and true:
+ ./in.cue:5:4
+ ./in.cue:6:4
Result:
(_|_){
@@ -35,6 +37,8 @@
t: (bool){ true }
f: (bool){ false }
e: (_|_){
- // [eval] e: incompatible values false and true
+ // [eval] e: conflicting values false and true:
+ // ./in.cue:5:4
+ // ./in.cue:6:4
}
}
diff --git a/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar b/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar
index c96c492..652f86a 100644
--- a/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar
+++ b/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar
@@ -30,7 +30,9 @@
}
-- out/eval --
Errors:
-f: incompatible values false and true
+f: conflicting values false and true:
+ ./in.cue:6:4
+ ./in.cue:6:11
Result:
(_|_){
@@ -41,6 +43,8 @@
d: (bool){ true }
e: (bool){ true }
f: (_|_){
- // [eval] f: incompatible values false and true
+ // [eval] f: conflicting values false and true:
+ // ./in.cue:6:4
+ // ./in.cue:6:11
}
}
diff --git a/cue/testdata/basicrewrite/006_basic_type.txtar b/cue/testdata/basicrewrite/006_basic_type.txtar
index ac0aa54..7d185c0 100644
--- a/cue/testdata/basicrewrite/006_basic_type.txtar
+++ b/cue/testdata/basicrewrite/006_basic_type.txtar
@@ -34,7 +34,9 @@
}
-- out/eval --
Errors:
-d: conflicting values int and float (mismatched types int and float)
+d: conflicting values int and float (mismatched types int and float):
+ ./in.cue:5:4
+ ./in.cue:5:10
Result:
(_|_){
@@ -43,7 +45,9 @@
b: (int){ 1 }
c: (float){ 1.0 }
d: (_|_){
- // [eval] d: conflicting values int and float (mismatched types int and float)
+ // [eval] d: conflicting values int and float (mismatched types int and float):
+ // ./in.cue:5:4
+ // ./in.cue:5:10
}
e: (string){ "4" }
f: (bool){ true }
diff --git a/cue/testdata/basicrewrite/010_lists.txtar b/cue/testdata/basicrewrite/010_lists.txtar
index c46ccba..438ef25 100644
--- a/cue/testdata/basicrewrite/010_lists.txtar
+++ b/cue/testdata/basicrewrite/010_lists.txtar
@@ -76,15 +76,19 @@
}
-- out/eval --
Errors:
-e: conflicting values 4 and [] (mismatched types int and list)
+e: conflicting values 4 and [] (mismatched types int and list):
+ ./in.cue:4:8
+ ./in.cue:4:13
e2: invalid list index d (type string):
./in.cue:5:12
e3: invalid negative index -1:
./in.cue:6:8
e4.3: invalid value 8 (out of bound <=5):
./in.cue:7:24
+ ./in.cue:7:41
e5.3: invalid value 8 (out of bound <=5):
./in.cue:8:39
+ ./in.cue:8:18
Result:
(_|_){
@@ -101,7 +105,9 @@
2: (int){ 3 }
}
e: (_|_){
- // [eval] e: conflicting values 4 and [] (mismatched types int and list)
+ // [eval] e: conflicting values 4 and [] (mismatched types int and list):
+ // ./in.cue:4:8
+ // ./in.cue:4:13
}
e2: (_|_){
// [eval] e2: invalid list index d (type string):
@@ -119,6 +125,7 @@
3: (_|_){
// [eval] e4.3: invalid value 8 (out of bound <=5):
// ./in.cue:7:24
+ // ./in.cue:7:41
}
}
e5: (_|_){
@@ -129,6 +136,7 @@
3: (_|_){
// [eval] e5.3: invalid value 8 (out of bound <=5):
// ./in.cue:8:39
+ // ./in.cue:8:18
}
}
}
diff --git a/cue/testdata/basicrewrite/013_obj_unify.txtar b/cue/testdata/basicrewrite/013_obj_unify.txtar
index 0dcbbe8..b8a0ae5 100644
--- a/cue/testdata/basicrewrite/013_obj_unify.txtar
+++ b/cue/testdata/basicrewrite/013_obj_unify.txtar
@@ -75,7 +75,9 @@
}
-- out/eval --
Errors:
-e: conflicting values 1 and {a:3} (mismatched types int and struct)
+e: conflicting values 1 and {a:3} (mismatched types int and struct):
+ ./in.cue:7:5
+ ./in.cue:8:4
Result:
(_|_){
@@ -97,7 +99,9 @@
b: (int){ 2 }
}
e: (_|_){
- // [eval] e: conflicting values 1 and {a:3} (mismatched types int and struct)
+ // [eval] e: conflicting values 1 and {a:3} (mismatched types int and struct):
+ // ./in.cue:7:5
+ // ./in.cue:8:4
a: (int){ 3 }
}
}
diff --git a/cue/testdata/basicrewrite/015_types.txtar b/cue/testdata/basicrewrite/015_types.txtar
index bea293c..04d05fd 100644
--- a/cue/testdata/basicrewrite/015_types.txtar
+++ b/cue/testdata/basicrewrite/015_types.txtar
@@ -39,8 +39,12 @@
}
-- out/eval --
Errors:
-e: conflicting values int and string (mismatched types int and string)
-e2: conflicting values 1 and string (mismatched types int and string)
+e: conflicting values int and string (mismatched types int and string):
+ ./in.cue:5:5
+ ./in.cue:5:11
+e2: conflicting values 1 and string (mismatched types int and string):
+ ./in.cue:6:5
+ ./in.cue:6:9
b: value can never become concrete:
./in.cue:7:5
p: invalid operation +true (+ bool):
@@ -56,10 +60,14 @@
s: (string){ string }
t: (string){ "s" }
e: (_|_){
- // [eval] e: conflicting values int and string (mismatched types int and string)
+ // [eval] e: conflicting values int and string (mismatched types int and string):
+ // ./in.cue:5:5
+ // ./in.cue:5:11
}
e2: (_|_){
- // [eval] e2: conflicting values 1 and string (mismatched types int and string)
+ // [eval] e2: conflicting values 1 and string (mismatched types int and string):
+ // ./in.cue:6:5
+ // ./in.cue:6:9
}
b: (_|_){
// [eval] b: value can never become concrete:
diff --git a/cue/testdata/benchmarks/dedupelem.txtar b/cue/testdata/benchmarks/dedupelem.txtar
index de9ad65..71c4729 100644
--- a/cue/testdata/benchmarks/dedupelem.txtar
+++ b/cue/testdata/benchmarks/dedupelem.txtar
@@ -15,7 +15,9 @@
foo: [{type: "float"}] & [...#Value]
-- out/eval --
Errors:
-foo.0.type: incompatible values "string" and "float"
+foo.0.type: conflicting values "string" and "float":
+ ./in.cue:5:14
+ ./in.cue:10:14
Result:
(_|_){
@@ -32,7 +34,9 @@
0: (_|_){
// [eval]
type: (_|_){
- // [eval] foo.0.type: incompatible values "string" and "float"
+ // [eval] foo.0.type: conflicting values "string" and "float":
+ // ./in.cue:5:14
+ // ./in.cue:10:14
}
}
}
diff --git a/cue/testdata/comprehensions/lists.txtar b/cue/testdata/comprehensions/lists.txtar
index 05db0d8..bdb012e 100644
--- a/cue/testdata/comprehensions/lists.txtar
+++ b/cue/testdata/comprehensions/lists.txtar
@@ -5,7 +5,9 @@
b: [ for x in a { x } ]
-- out/eval --
Errors:
-a.1.b: incompatible values 3 and 2
+a.1.b: conflicting values 3 and 2:
+ ./in.cue:2:17
+ ./in.cue:2:21
Result:
(_|_){
@@ -18,12 +20,16 @@
1: (_|_){
// [eval]
b: (_|_){
- // [eval] a.1.b: incompatible values 3 and 2
+ // [eval] a.1.b: conflicting values 3 and 2:
+ // ./in.cue:2:17
+ // ./in.cue:2:21
}
}
}
b: (_|_){
- // [eval] a.1.b: incompatible values 3 and 2
+ // [eval] a.1.b: conflicting values 3 and 2:
+ // ./in.cue:2:17
+ // ./in.cue:2:21
}
}
-- out/compile --
diff --git a/cue/testdata/cycle/021_delayed_constraint_failure.txtar b/cue/testdata/cycle/021_delayed_constraint_failure.txtar
index ca71e0f..8e769c7 100644
--- a/cue/testdata/cycle/021_delayed_constraint_failure.txtar
+++ b/cue/testdata/cycle/021_delayed_constraint_failure.txtar
@@ -26,17 +26,25 @@
}
-- out/eval --
Errors:
-b: incompatible values 200 and 210
-x: incompatible values 101 and 100
+b: conflicting values 200 and 210:
+ ./in.cue:2:4
+ ./in.cue:3:4
+x: conflicting values 101 and 100:
+ ./in.cue:5:4
+ ./in.cue:6:4
Result:
(_|_){
// [eval]
a: (int){ 100 }
b: (_|_){
- // [eval] b: incompatible values 200 and 210
+ // [eval] b: conflicting values 200 and 210:
+ // ./in.cue:2:4
+ // ./in.cue:3:4
}
x: (_|_){
- // [eval] x: incompatible values 101 and 100
+ // [eval] x: conflicting values 101 and 100:
+ // ./in.cue:5:4
+ // ./in.cue:6:4
}
}
diff --git a/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar b/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar
index 42cb241..875d6e0 100644
--- a/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar
+++ b/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar
@@ -28,7 +28,9 @@
}
-- out/eval --
Errors:
-a.x: incompatible values "hey!?" and "hey"
+a.x: conflicting values "hey!?" and "hey":
+ ./in.cue:2:5
+ ./in.cue:5:7
Result:
(_|_){
@@ -36,10 +38,14 @@
a: (_|_){
// [eval]
x: (_|_){
- // [eval] a.x: incompatible values "hey!?" and "hey"
+ // [eval] a.x: conflicting values "hey!?" and "hey":
+ // ./in.cue:2:5
+ // ./in.cue:5:7
}
y: (_|_){
- // [eval] a.x: incompatible values "hey!?" and "hey"
+ // [eval] a.x: conflicting values "hey!?" and "hey":
+ // ./in.cue:2:5
+ // ./in.cue:5:7
}
}
}
diff --git a/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar b/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar
index ee95f65..069cc13 100644
--- a/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar
+++ b/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar
@@ -159,8 +159,9 @@
}
-- out/eval --
Errors:
-xe3: incompatible values 7 and 6:
- ./in.cue:44:6
+xe3: conflicting values 7 and 6:
+ ./in.cue:45:6
+ ./in.cue:45:10
Result:
(_|_){
@@ -191,20 +192,24 @@
// [incomplete] xe1: empty disjunction
}
xe2: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:44:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:45:6
+ // ./in.cue:45:10
}
xe3: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:44:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:45:6
+ // ./in.cue:45:10
}
xe4: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:44:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:45:6
+ // ./in.cue:45:10
}
xe5: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:44:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:45:6
+ // ./in.cue:45:10
}
xf1: (int){ |((int){ 8 }, (int){ 9 }) }
xf2: (_|_){
diff --git a/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar b/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar
index de11972..eafd7f1 100644
--- a/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar
+++ b/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar
@@ -129,8 +129,9 @@
}
-- out/eval --
Errors:
-xe3: incompatible values 7 and 6:
- ./in.cue:37:6
+xe3: conflicting values 7 and 6:
+ ./in.cue:38:6
+ ./in.cue:38:10
Result:
(_|_){
@@ -161,20 +162,24 @@
// [incomplete] xe1: empty disjunction
}
xe2: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:37:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:38:6
+ // ./in.cue:38:10
}
xe3: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:37:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:38:6
+ // ./in.cue:38:10
}
xe4: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:37:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:38:6
+ // ./in.cue:38:10
}
xe5: (_|_){
- // [eval] xe3: incompatible values 7 and 6:
- // ./in.cue:37:6
+ // [eval] xe3: conflicting values 7 and 6:
+ // ./in.cue:38:6
+ // ./in.cue:38:10
}
z1: (int){ |(*(int){ 11 }, (int){ 13 }) }
z2: (int){ 10 }
diff --git a/cue/testdata/cycle/issue429.txtar b/cue/testdata/cycle/issue429.txtar
index e7b5983..d6615d0 100644
--- a/cue/testdata/cycle/issue429.txtar
+++ b/cue/testdata/cycle/issue429.txtar
@@ -54,8 +54,10 @@
Errors:
es3.max: invalid value 5 (out of bound >10):
./in.cue:5:10
+ ./in.cue:22:10
er3.min: invalid value 5 (out of bound <5):
./in.cue:29:10
+ ./in.cue:44:10
Result:
(_|_){
@@ -92,6 +94,7 @@
max: (_|_){
// [eval] es3.max: invalid value 5 (out of bound >10):
// ./in.cue:5:10
+ // ./in.cue:22:10
}
}
#nonEmptyRange: (#struct){
@@ -119,10 +122,12 @@
min: (_|_){
// [eval] er3.min: invalid value 5 (out of bound <5):
// ./in.cue:29:10
+ // ./in.cue:44:10
}
max: (_|_){
// [eval] er3.min: invalid value 5 (out of bound <5):
// ./in.cue:29:10
+ // ./in.cue:44:10
}
}
}
diff --git a/cue/testdata/cycle/structural.txtar b/cue/testdata/cycle/structural.txtar
index 0f76200..fabbba1 100644
--- a/cue/testdata/cycle/structural.txtar
+++ b/cue/testdata/cycle/structural.txtar
@@ -221,7 +221,9 @@
a1.f.0: structural cycle
a3.f.g: structural cycle
b4.x.y.0: structural cycle
-b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list)
+b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list):
+ ./in.cue:51:16
+ ./in.cue:51:17
b6.b.a.0.0: structural cycle
b6.x.a.0: structural cycle
b7.a.0: structural cycle
@@ -233,18 +235,34 @@
e1.b.c: structural cycle
e2.a.c: structural cycle
e2.b.c: structural cycle
-e3.a: conflicting values [a] and {c:a} (mismatched types list and struct)
-e3.a.0: conflicting values [a] and {c:a} (mismatched types list and struct)
+e3.a: conflicting values [a] and {c:a} (mismatched types list and struct):
+ ./in.cue:114:8
+ ./in.cue:115:8
+e3.a.0: conflicting values [a] and {c:a} (mismatched types list and struct):
+ ./in.cue:114:8
+ ./in.cue:115:8
e3.a.0: structural cycle
-e3.a.c: conflicting values [a] and {c:a} (mismatched types list and struct)
+e3.a.c: conflicting values [a] and {c:a} (mismatched types list and struct):
+ ./in.cue:114:8
+ ./in.cue:115:8
e3.a.c: structural cycle
-e3.b: conflicting values [b] and {c:b} (mismatched types list and struct)
-e3.b.0: conflicting values [b] and {c:b} (mismatched types list and struct)
+e3.b: conflicting values [b] and {c:b} (mismatched types list and struct):
+ ./in.cue:117:8
+ ./in.cue:118:8
+e3.b.0: conflicting values [b] and {c:b} (mismatched types list and struct):
+ ./in.cue:117:8
+ ./in.cue:118:8
e3.b.0: structural cycle
-e3.b.c: conflicting values [b] and {c:b} (mismatched types list and struct)
+e3.b.c: conflicting values [b] and {c:b} (mismatched types list and struct):
+ ./in.cue:117:8
+ ./in.cue:118:8
e3.b.c: structural cycle
-e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct)
-e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct)
+e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct):
+ ./in.cue:122:13
+ ./in.cue:123:9
+e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct):
+ ./in.cue:125:9
+ ./in.cue:126:13
z1.z.f.h.h: structural cycle
z1.z.g.h: structural cycle
b4.x.y.0: structural cycle:
@@ -365,7 +383,9 @@
a: (_|_){
// [eval]
0: (_|_){
- // [eval] b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list)
+ // [eval] b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list):
+ // ./in.cue:51:16
+ // ./in.cue:51:17
0: (_|_){
// [structural cycle] b6.b.a.0.0: structural cycle
}
@@ -580,9 +600,13 @@
e3: (_|_){
// [eval]
a: (_|_){
- // [eval] e3.a: conflicting values [a] and {c:a} (mismatched types list and struct)
+ // [eval] e3.a: conflicting values [a] and {c:a} (mismatched types list and struct):
+ // ./in.cue:114:8
+ // ./in.cue:115:8
c: (_|_){
- // [eval] e3.a.c: conflicting values [a] and {c:a} (mismatched types list and struct)
+ // [eval] e3.a.c: conflicting values [a] and {c:a} (mismatched types list and struct):
+ // ./in.cue:114:8
+ // ./in.cue:115:8
// e3.a.c: structural cycle
c: (_|_){// 〈1;a〉
}
@@ -590,7 +614,9 @@
}
}
0: (_|_){
- // [eval] e3.a.0: conflicting values [a] and {c:a} (mismatched types list and struct)
+ // [eval] e3.a.0: conflicting values [a] and {c:a} (mismatched types list and struct):
+ // ./in.cue:114:8
+ // ./in.cue:115:8
// e3.a.0: structural cycle
c: (_|_){// 〈1;a〉
}
@@ -599,9 +625,13 @@
}
}
b: (_|_){
- // [eval] e3.b: conflicting values [b] and {c:b} (mismatched types list and struct)
+ // [eval] e3.b: conflicting values [b] and {c:b} (mismatched types list and struct):
+ // ./in.cue:117:8
+ // ./in.cue:118:8
c: (_|_){
- // [eval] e3.b.c: conflicting values [b] and {c:b} (mismatched types list and struct)
+ // [eval] e3.b.c: conflicting values [b] and {c:b} (mismatched types list and struct):
+ // ./in.cue:117:8
+ // ./in.cue:118:8
// e3.b.c: structural cycle
c: (_|_){// 〈1;b〉
}
@@ -609,7 +639,9 @@
}
}
0: (_|_){
- // [eval] e3.b.0: conflicting values [b] and {c:b} (mismatched types list and struct)
+ // [eval] e3.b.0: conflicting values [b] and {c:b} (mismatched types list and struct):
+ // ./in.cue:117:8
+ // ./in.cue:118:8
// e3.b.0: structural cycle
c: (_|_){// 〈1;b〉
}
@@ -623,7 +655,9 @@
a: (_|_){
// [eval]
0: (_|_){
- // [eval] e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct)
+ // [eval] e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct):
+ // ./in.cue:122:13
+ // ./in.cue:123:9
0: (struct){
c: (int){ 1 }
}
@@ -632,7 +666,9 @@
b: (_|_){
// [eval]
0: (_|_){
- // [eval] e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct)
+ // [eval] e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct):
+ // ./in.cue:125:9
+ // ./in.cue:126:13
0: (struct){
c: (int){ 1 }
}
diff --git a/cue/testdata/eval/conflicts.txtar b/cue/testdata/eval/conflicts.txtar
new file mode 100644
index 0000000..7d94f0d
--- /dev/null
+++ b/cue/testdata/eval/conflicts.txtar
@@ -0,0 +1,93 @@
+-- in.cue --
+i: int
+s: string
+
+t0: {
+ v: i & s
+}
+
+t1: {
+ #d1: {
+ a: b: 3
+ }
+
+ #d2: {
+ a: b: 4
+ }
+
+ x: #d1 & #d2
+}
+
+-- out/eval --
+Errors:
+t0.v: conflicting values int and string (mismatched types int and string):
+ ./in.cue:1:4
+ ./in.cue:2:4
+t1.x.a.b: conflicting values 4 and 3:
+ ./in.cue:10:15
+ ./in.cue:14:15
+ ./in.cue:17:8
+ ./in.cue:17:14
+
+Result:
+(_|_){
+ // [eval]
+ i: (int){ int }
+ s: (string){ string }
+ t0: (_|_){
+ // [eval]
+ v: (_|_){
+ // [eval] t0.v: conflicting values int and string (mismatched types int and string):
+ // ./in.cue:1:4
+ // ./in.cue:2:4
+ }
+ }
+ t1: (_|_){
+ // [eval]
+ #d1: (#struct){
+ a: (#struct){
+ b: (int){ 3 }
+ }
+ }
+ #d2: (#struct){
+ a: (#struct){
+ b: (int){ 4 }
+ }
+ }
+ x: (_|_){
+ // [eval]
+ a: (_|_){
+ // [eval]
+ b: (_|_){
+ // [eval] t1.x.a.b: conflicting values 4 and 3:
+ // ./in.cue:10:15
+ // ./in.cue:14:15
+ // ./in.cue:17:8
+ // ./in.cue:17:14
+ }
+ }
+ }
+ }
+}
+-- out/compile --
+--- in.cue
+{
+ i: int
+ s: string
+ t0: {
+ v: (〈1;i〉 & 〈1;s〉)
+ }
+ t1: {
+ #d1: {
+ a: {
+ b: 3
+ }
+ }
+ #d2: {
+ a: {
+ b: 4
+ }
+ }
+ x: (〈0;#d1〉 & 〈0;#d2〉)
+ }
+}
diff --git a/cue/testdata/eval/disjunctions.txtar b/cue/testdata/eval/disjunctions.txtar
index 6e30441..3da17e7 100644
--- a/cue/testdata/eval/disjunctions.txtar
+++ b/cue/testdata/eval/disjunctions.txtar
@@ -61,7 +61,9 @@
-- out/eval --
Errors:
-f.val: conflicting values 3 and string (mismatched types int and string)
+f.val: conflicting values 3 and string (mismatched types int and string):
+ ./in.cue:9:7
+ ./in.cue:15:28
Result:
(_|_){
@@ -91,7 +93,9 @@
// [eval]
name: (string){ "str" }
val: (_|_){
- // [eval] f.val: conflicting values 3 and string (mismatched types int and string)
+ // [eval] f.val: conflicting values 3 and string (mismatched types int and string):
+ // ./in.cue:9:7
+ // ./in.cue:15:28
}
}
e1: (struct){
diff --git a/cue/testdata/export/008.txtar b/cue/testdata/export/008.txtar
index 07c94c0..9d3454b 100644
--- a/cue/testdata/export/008.txtar
+++ b/cue/testdata/export/008.txtar
@@ -16,7 +16,10 @@
}
-- out/eval --
Errors:
-a.0: incompatible values 4 and 3
+a.0: conflicting values 4 and 3:
+ ./in.cue:1:1
+ ./in.cue:1:7
+ ./in.cue:1:11
Result:
(_|_){
@@ -24,7 +27,10 @@
a: (_|_){
// [eval]
0: (_|_){
- // [eval] a.0: incompatible values 4 and 3
+ // [eval] a.0: conflicting values 4 and 3:
+ // ./in.cue:1:1
+ // ./in.cue:1:7
+ // ./in.cue:1:11
}
}
}
diff --git "a/cue/testdata/fulleval/024_Issue_\04323.txtar" "b/cue/testdata/fulleval/024_Issue_\04323.txtar"
index 0f41876..ff50d17 100644
--- "a/cue/testdata/fulleval/024_Issue_\04323.txtar"
+++ "b/cue/testdata/fulleval/024_Issue_\04323.txtar"
@@ -28,7 +28,9 @@
}
-- out/eval --
Errors:
-y.a: incompatible values 2 and 3
+y.a: conflicting values 2 and 3:
+ ./in.cue:1:21
+ ./in.cue:2:12
Result:
(_|_){
@@ -41,7 +43,9 @@
y: (_|_){
// [eval]
a: (_|_){
- // [eval] y.a: incompatible values 2 and 3
+ // [eval] y.a: conflicting values 2 and 3:
+ // ./in.cue:1:21
+ // ./in.cue:2:12
}
}
}
diff --git a/cue/testdata/fulleval/031_comparison_against_bottom.txtar b/cue/testdata/fulleval/031_comparison_against_bottom.txtar
index 01f11eb..7c946bb 100644
--- a/cue/testdata/fulleval/031_comparison_against_bottom.txtar
+++ b/cue/testdata/fulleval/031_comparison_against_bottom.txtar
@@ -61,29 +61,33 @@
}
-- out/eval --
Errors:
-err: incompatible values 2 and 1:
- ./in.cue:2:4
+err: conflicting values 2 and 1:
+ ./in.cue:12:6
+ ./in.cue:12:10
Result:
(_|_){
// [eval]
a: (bool){ true }
b: (_|_){
- // [eval] err: incompatible values 2 and 1:
- // ./in.cue:2:4
+ // [eval] err: conflicting values 2 and 1:
+ // ./in.cue:12:6
+ // ./in.cue:12:10
}
c: (bool){ true }
d: (bool){ false }
e: (_|_){
- // [eval] err: incompatible values 2 and 1:
- // ./in.cue:2:4
+ // [eval] err: conflicting values 2 and 1:
+ // ./in.cue:12:6
+ // ./in.cue:12:10
}
f: (bool){ true }
g: (bool){ false }
h: (bool){ true }
i: (bool){ false }
err: (_|_){
- // [eval] err: incompatible values 2 and 1:
- // ./in.cue:2:4
+ // [eval] err: conflicting values 2 and 1:
+ // ./in.cue:12:6
+ // ./in.cue:12:10
}
}
diff --git a/cue/testdata/resolve/006_arithmetic.txtar b/cue/testdata/resolve/006_arithmetic.txtar
index 789a19a..17f73a4 100644
--- a/cue/testdata/resolve/006_arithmetic.txtar
+++ b/cue/testdata/resolve/006_arithmetic.txtar
@@ -30,7 +30,9 @@
}
-- out/eval --
Errors:
-e2: conflicting values int and 2 (mismatched types int and float)
+e2: conflicting values int and 2 (mismatched types int and float):
+ ./in.cue:6:5
+ ./in.cue:6:11
Result:
(_|_){
@@ -41,6 +43,8 @@
v5: (float){ 2.0 }
v6: (float){ 1 }
e2: (_|_){
- // [eval] e2: conflicting values int and 2 (mismatched types int and float)
+ // [eval] e2: conflicting values int and 2 (mismatched types int and float):
+ // ./in.cue:6:5
+ // ./in.cue:6:11
}
}
diff --git a/cue/testdata/resolve/011_bounds.txtar b/cue/testdata/resolve/011_bounds.txtar
index 6dfa594..6fca110 100644
--- a/cue/testdata/resolve/011_bounds.txtar
+++ b/cue/testdata/resolve/011_bounds.txtar
@@ -138,17 +138,33 @@
}
-- out/eval --
Errors:
-e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|list|struct|number))
-e2: conflicting values !=null and null (mismatched types (bool|string|bytes|list|struct|number) and null)
-e5: incompatible bounds >1 and <0
-e6: incompatible bounds >11 and <11
-e7: incompatible bounds >=11 and <11
-e8: incompatible bounds >11 and <=11
-e9: conflicting values >"a" and <1 (mismatched types string and number)
+e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|list|struct|number)):
+ ./in.cue:40:5
+ ./in.cue:40:12
+e2: conflicting values !=null and null (mismatched types (bool|string|bytes|list|struct|number) and null):
+ ./in.cue:41:5
+ ./in.cue:41:14
+e5: incompatible bounds >1 and <0:
+ ./in.cue:44:5
+ ./in.cue:44:10
+e6: incompatible bounds >11 and <11:
+ ./in.cue:45:5
+ ./in.cue:45:11
+e7: incompatible bounds >=11 and <11:
+ ./in.cue:46:5
+ ./in.cue:46:12
+e8: incompatible bounds >11 and <=11:
+ ./in.cue:47:5
+ ./in.cue:47:11
+e9: conflicting values >"a" and <1 (mismatched types string and number):
+ ./in.cue:48:5
+ ./in.cue:48:12
e3: invalid value 1 (out of bound >1):
./in.cue:42:5
+ ./in.cue:42:10
e4: invalid value 0 (out of bound <0):
./in.cue:43:5
+ ./in.cue:43:10
Result:
(_|_){
@@ -184,32 +200,48 @@
s23e: (number){ &(>0.0, <2.0) }
s30: (int){ &(>0, int) }
e1: (_|_){
- // [eval] e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|list|struct|number))
+ // [eval] e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|list|struct|number)):
+ // ./in.cue:40:5
+ // ./in.cue:40:12
}
e2: (_|_){
- // [eval] e2: conflicting values !=null and null (mismatched types (bool|string|bytes|list|struct|number) and null)
+ // [eval] e2: conflicting values !=null and null (mismatched types (bool|string|bytes|list|struct|number) and null):
+ // ./in.cue:41:5
+ // ./in.cue:41:14
}
e3: (_|_){
// [eval] e3: invalid value 1 (out of bound >1):
// ./in.cue:42:5
+ // ./in.cue:42:10
}
e4: (_|_){
// [eval] e4: invalid value 0 (out of bound <0):
// ./in.cue:43:5
+ // ./in.cue:43:10
}
e5: (_|_){
- // [eval] e5: incompatible bounds >1 and <0
+ // [eval] e5: incompatible bounds >1 and <0:
+ // ./in.cue:44:5
+ // ./in.cue:44:10
}
e6: (_|_){
- // [eval] e6: incompatible bounds >11 and <11
+ // [eval] e6: incompatible bounds >11 and <11:
+ // ./in.cue:45:5
+ // ./in.cue:45:11
}
e7: (_|_){
- // [eval] e7: incompatible bounds >=11 and <11
+ // [eval] e7: incompatible bounds >=11 and <11:
+ // ./in.cue:46:5
+ // ./in.cue:46:12
}
e8: (_|_){
- // [eval] e8: incompatible bounds >11 and <=11
+ // [eval] e8: incompatible bounds >11 and <=11:
+ // ./in.cue:47:5
+ // ./in.cue:47:11
}
e9: (_|_){
- // [eval] e9: conflicting values >"a" and <1 (mismatched types string and number)
+ // [eval] e9: conflicting values >"a" and <1 (mismatched types string and number):
+ // ./in.cue:48:5
+ // ./in.cue:48:12
}
}
diff --git a/cue/testdata/resolve/012_bound_conversions.txtar b/cue/testdata/resolve/012_bound_conversions.txtar
index 15343ae..12b79ee 100644
--- a/cue/testdata/resolve/012_bound_conversions.txtar
+++ b/cue/testdata/resolve/012_bound_conversions.txtar
@@ -48,11 +48,15 @@
}
-- out/eval --
Errors:
-c4: conflicting values <2 and int (mismatched types float and int)
+c4: conflicting values <2 and int (mismatched types float and int):
+ ./in.cue:14:18
+ ./in.cue:14:23
c1: invalid value 1.2 (out of bound >1.3):
./in.cue:10:12
+ ./in.cue:10:6
c2: invalid value 1.2 (out of bound >1.3):
./in.cue:11:12
+ ./in.cue:11:5
Result:
(_|_){
@@ -67,13 +71,17 @@
c1: (_|_){
// [eval] c1: invalid value 1.2 (out of bound >1.3):
// ./in.cue:10:12
+ // ./in.cue:10:6
}
c2: (_|_){
// [eval] c2: invalid value 1.2 (out of bound >1.3):
// ./in.cue:11:12
+ // ./in.cue:11:5
}
c3: (float){ 1.2 }
c4: (_|_){
- // [eval] c4: conflicting values <2 and int (mismatched types float and int)
+ // [eval] c4: conflicting values <2 and int (mismatched types float and int):
+ // ./in.cue:14:18
+ // ./in.cue:14:23
}
}
diff --git a/cue/testdata/resolve/023_correct_error_messages.txtar b/cue/testdata/resolve/023_correct_error_messages.txtar
index 15e2296..d013d42 100644
--- a/cue/testdata/resolve/023_correct_error_messages.txtar
+++ b/cue/testdata/resolve/023_correct_error_messages.txtar
@@ -15,12 +15,16 @@
}
-- out/eval --
Errors:
-a: conflicting values "a" and 1 (mismatched types string and int)
+a: conflicting values "a" and 1 (mismatched types string and int):
+ ./in.cue:1:4
+ ./in.cue:1:10
Result:
(_|_){
// [eval]
a: (_|_){
- // [eval] a: conflicting values "a" and 1 (mismatched types string and int)
+ // [eval] a: conflicting values "a" and 1 (mismatched types string and int):
+ // ./in.cue:1:4
+ // ./in.cue:1:10
}
}
diff --git a/cue/testdata/resolve/045_range_unification.txtar b/cue/testdata/resolve/045_range_unification.txtar
index ad88f66..e55f77f 100644
--- a/cue/testdata/resolve/045_range_unification.txtar
+++ b/cue/testdata/resolve/045_range_unification.txtar
@@ -134,19 +134,33 @@
}
-- out/eval --
Errors:
-b14: incompatible bounds >=6 and <=5
-b7: incompatible bounds >=6 and <=5
-c3: conflicting values string and >=1 (mismatched types string and number)
-c4: conflicting values <=5 and string (mismatched types number and string)
-n2: incompatible bounds >=1.1 and <=1.3
+b14: incompatible bounds >=6 and <=5:
+ ./in.cue:29:6
+ ./in.cue:29:24
+b7: incompatible bounds >=6 and <=5:
+ ./in.cue:21:11
+ ./in.cue:21:17
+c3: conflicting values string and >=1 (mismatched types string and number):
+ ./in.cue:34:5
+ ./in.cue:34:14
+c4: conflicting values <=5 and string (mismatched types number and string):
+ ./in.cue:35:11
+ ./in.cue:35:17
+n2: incompatible bounds >=1.1 and <=1.3:
+ ./in.cue:42:11
+ ./in.cue:42:19
a4: invalid value 6 (out of bound <=5):
./in.cue:5:11
+ ./in.cue:5:17
a5: invalid value 0 (out of bound >=1):
./in.cue:6:5
+ ./in.cue:6:17
a9: invalid value 6 (out of bound <=5):
./in.cue:11:16
+ ./in.cue:11:6
a10: invalid value 0 (out of bound >=1):
./in.cue:12:10
+ ./in.cue:12:6
Result:
(_|_){
@@ -157,10 +171,12 @@
a4: (_|_){
// [eval] a4: invalid value 6 (out of bound <=5):
// ./in.cue:5:11
+ // ./in.cue:5:17
}
a5: (_|_){
// [eval] a5: invalid value 0 (out of bound >=1):
// ./in.cue:6:5
+ // ./in.cue:6:17
}
a6: (int){ 3 }
a7: (int){ 1 }
@@ -168,10 +184,12 @@
a9: (_|_){
// [eval] a9: invalid value 6 (out of bound <=5):
// ./in.cue:11:16
+ // ./in.cue:11:6
}
a10: (_|_){
// [eval] a10: invalid value 0 (out of bound >=1):
// ./in.cue:12:10
+ // ./in.cue:12:6
}
b1: (number){ &(>=1, <=5) }
b2: (number){ 1 }
@@ -180,7 +198,9 @@
b5: (number){ &(>=3, <=5) }
b6: (number){ 5 }
b7: (_|_){
- // [eval] b7: incompatible bounds >=6 and <=5
+ // [eval] b7: incompatible bounds >=6 and <=5:
+ // ./in.cue:21:11
+ // ./in.cue:21:17
}
b8: (number){ &(>=1, <=5) }
b9: (number){ 1 }
@@ -189,21 +209,29 @@
b12: (number){ &(>=3, <=5) }
b13: (number){ 5 }
b14: (_|_){
- // [eval] b14: incompatible bounds >=6 and <=5
+ // [eval] b14: incompatible bounds >=6 and <=5:
+ // ./in.cue:29:6
+ // ./in.cue:29:24
}
c1: (int){ &(>=1, <=5, int) }
c2: (int){ &(>=1, <=5, int) }
c3: (_|_){
- // [eval] c3: conflicting values string and >=1 (mismatched types string and number)
+ // [eval] c3: conflicting values string and >=1 (mismatched types string and number):
+ // ./in.cue:34:5
+ // ./in.cue:34:14
}
c4: (_|_){
- // [eval] c4: conflicting values <=5 and string (mismatched types number and string)
+ // [eval] c4: conflicting values <=5 and string (mismatched types number and string):
+ // ./in.cue:35:11
+ // ./in.cue:35:17
}
s1: (string){ "e" }
s2: (string){ "ee" }
n1: (number){ &(>=1, <=2) }
n2: (_|_){
- // [eval] n2: incompatible bounds >=1.1 and <=1.3
+ // [eval] n2: incompatible bounds >=1.1 and <=1.3:
+ // ./in.cue:42:11
+ // ./in.cue:42:19
}
n3: (int){ 2 }
n4: (float){ 0.09999 }
diff --git a/cue/testdata/resolve/046_predefined_ranges.txtar b/cue/testdata/resolve/046_predefined_ranges.txtar
index 33d556c..1308e36 100644
--- a/cue/testdata/resolve/046_predefined_ranges.txtar
+++ b/cue/testdata/resolve/046_predefined_ranges.txtar
@@ -29,7 +29,8 @@
}
-- out/eval --
Errors:
-e1: invalid value 100000 (out of bound <=32767)
+e1: invalid value 100000 (out of bound <=32767):
+ ./in.cue:8:5
Result:
(_|_){
@@ -37,6 +38,7 @@
k1: (int){ 44 }
k2: (int){ -8000000000 }
e1: (_|_){
- // [eval] e1: invalid value 100000 (out of bound <=32767)
+ // [eval] e1: invalid value 100000 (out of bound <=32767):
+ // ./in.cue:8:5
}
}
diff --git a/cuego/examples_test.go b/cuego/examples_test.go
index ad880d7..e46f1dd 100644
--- a/cuego/examples_test.go
+++ b/cuego/examples_test.go
@@ -42,7 +42,7 @@
//Output:
// completed: cuego_test.Sum{A:1, B:5, C:6} (err: <nil>)
// completed: cuego_test.Sum{A:2, B:6, C:8} (err: <nil>)
- // A: incompatible values 5 and 2 (and 3 more errors)
+ // A: conflicting values 5 and 2 (and 3 more errors)
}
func ExampleConstrain() {
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index bdf1af9..7511b51 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -332,6 +332,9 @@
}
// Validate calls validates value for the given validator.
+//
+// TODO(errors): return boolean instead: only the caller has enough information
+// to generate a proper error message.
func (c *OpContext) Validate(check Validator, value Value) *Bottom {
// TODO: use a position stack to push both values.
saved := c.src
diff --git a/internal/core/adt/errors.go b/internal/core/adt/errors.go
index 1f54c86..5085e28 100644
--- a/internal/core/adt/errors.go
+++ b/internal/core/adt/errors.go
@@ -201,8 +201,8 @@
}
}
-// A valueError is returned as a result of evaluating a value.
-type valueError struct {
+// A ValueError is returned as a result of evaluating a value.
+type ValueError struct {
r Runtime
v *Vertex
pos token.Pos
@@ -210,6 +210,20 @@
errors.Message
}
+func (v *ValueError) AddPosition(n Node) {
+ if n == nil {
+ return
+ }
+ if p := pos(n); p != token.NoPos {
+ for _, q := range v.auxpos {
+ if p == q {
+ return
+ }
+ }
+ v.auxpos = append(v.auxpos, p)
+ }
+}
+
func (c *OpContext) errNode() *Vertex {
return c.vertex
}
@@ -225,14 +239,16 @@
}
func (c *OpContext) AddPosition(n Node) {
- c.positions = append(c.positions, n)
+ if n != nil {
+ c.positions = append(c.positions, n)
+ }
}
-func (c *OpContext) Newf(format string, args ...interface{}) *valueError {
+func (c *OpContext) Newf(format string, args ...interface{}) *ValueError {
return c.NewPosf(c.pos(), format, args...)
}
-func (c *OpContext) NewPosf(p token.Pos, format string, args ...interface{}) *valueError {
+func (c *OpContext) NewPosf(p token.Pos, format string, args ...interface{}) *ValueError {
var a []token.Pos
if len(c.positions) > 0 {
a = make([]token.Pos, 0, len(c.positions))
@@ -248,7 +264,7 @@
}
}
}
- return &valueError{
+ return &ValueError{
r: c.Runtime,
v: c.errNode(),
pos: p,
@@ -257,19 +273,19 @@
}
}
-func (e *valueError) Error() string {
+func (e *ValueError) Error() string {
return errors.String(e)
}
-func (e *valueError) Position() token.Pos {
+func (e *ValueError) Position() token.Pos {
return e.pos
}
-func (e *valueError) InputPositions() (a []token.Pos) {
+func (e *ValueError) InputPositions() (a []token.Pos) {
return e.auxpos
}
-func (e *valueError) Path() (a []string) {
+func (e *ValueError) Path() (a []string) {
for _, f := range appendPath(nil, e.v) {
a = append(a, f.SelectorString(e.r))
}
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index ea55ec3..ff1b2de 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -394,6 +394,8 @@
if v.B {
return nil
}
+ // TODO(errors): use "invalid value %v (not an %s)" if x is a
+ // predeclared identifier such as `int`.
return c.NewErrf("invalid value %v (out of bound %s)",
c.Str(y), c.Str(x))
diff --git a/internal/core/eval/eval.go b/internal/core/eval/eval.go
index 556d1a3..654fdc0 100644
--- a/internal/core/eval/eval.go
+++ b/internal/core/eval/eval.go
@@ -454,15 +454,15 @@
for n.maybeSetCache(); n.expandOne(); n.maybeSetCache() {
}
- if aList := n.addLists(ctx); aList != nil {
- n.updateNodeType(adt.ListKind, aList)
+ if aList, id := n.addLists(ctx); aList != nil {
+ n.updateNodeType(adt.ListKind, aList, id)
} else {
break
}
}
if n.aStruct != nil {
- n.updateNodeType(adt.StructKind, n.aStruct)
+ n.updateNodeType(adt.StructKind, n.aStruct, n.aStructID)
}
switch err := n.getErr(); {
@@ -524,15 +524,32 @@
if v != nil && adt.IsConcrete(v) {
if n.lowerBound != nil {
if b := ctx.Validate(n.lowerBound, v); b != nil {
+ // TODO(errors): make Validate return boolean and generate
+ // optimized conflict message. Also track and inject IDs
+ // to determine origin location.s
+ if e, _ := b.Err.(*adt.ValueError); e != nil {
+ e.AddPosition(n.lowerBound)
+ e.AddPosition(v)
+ }
n.addBottom(b)
}
}
if n.upperBound != nil {
if b := ctx.Validate(n.upperBound, v); b != nil {
+ // TODO(errors): make Validate return boolean and generate
+ // optimized conflict message. Also track and inject IDs
+ // to determine origin location.s
+ if e, _ := b.Err.(*adt.ValueError); e != nil {
+ e.AddPosition(n.upperBound)
+ e.AddPosition(v)
+ }
n.addBottom(b)
}
}
for _, v := range n.checks {
+ // TODO(errors): make Validate return boolean and generate
+ // optimized conflict message. Also track and inject IDs
+ // to determine origin location.s
if b := ctx.Validate(v, n.node); b != nil {
n.addBottom(b)
}
@@ -727,11 +744,13 @@
arcMap map[arcKey]bool
// Current value (may be under construction)
- scalar adt.Value // TODO: use Value in node.
+ scalar adt.Value // TODO: use Value in node.
+ scalarID adt.ID
// Concrete conjuncts
kind adt.Kind
kindExpr adt.Expr // expr that adjust last value (for error reporting)
+ kindID adt.ID // for error tracing
lowerBound *adt.BoundValue // > or >=
upperBound *adt.BoundValue // < or <=
checks []adt.Validator // BuiltinValidator, other bound values.
@@ -745,6 +764,7 @@
// TODO: remove this and annotate directly in acceptor.
needClose bool
aStruct adt.Expr
+ aStructID adt.ID
hasTop bool
// Expression conjuncts
@@ -770,7 +790,50 @@
return a
}
-func (n *nodeContext) updateNodeType(k adt.Kind, v adt.Expr) bool {
+// TODO(errors): return a dedicated ConflictError that can track original
+// positions on demand.
+//
+// Fully detailed origin tracking could be created on the back of CloseIDs
+// tracked in acceptor.Canopy. To make this fully functional, the following
+// still needs to be implemented:
+//
+// - We need to know the ID for every value involved in the conflict.
+// (There may be multiple if the result comes from a simplification).
+// - CloseIDs should be forked not only for definitions, but all references.
+// - Upon forking a CloseID, it should keep track of its enclosing CloseID
+// as well (probably as a pointer to the origin so that the reference
+// persists after compaction).
+//
+// The modifications to the CloseID algorithm may also benefit the computation
+// of `{ #A } == #A`, which currently is not done.
+//
+func (n *nodeContext) addConflict(
+ v1, v2 adt.Node,
+ k1, k2 adt.Kind,
+ id1, id2 adt.ID) {
+
+ ctx := n.ctx
+
+ var err *adt.ValueError
+ if k1 == k2 {
+ err = ctx.NewPosf(token.NoPos,
+ "conflicting values %s and %s", ctx.Str(v1), ctx.Str(v2))
+ } else {
+ err = ctx.NewPosf(token.NoPos,
+ "conflicting values %s and %s (mismatched types %s and %s)",
+ ctx.Str(v1), ctx.Str(v2), k1, k2)
+ }
+
+ ci := closedInfo(n.node)
+ err.AddPosition(v1)
+ err.AddPosition(v2)
+ err.AddPosition(ci.node(id1).Src)
+ err.AddPosition(ci.node(id2).Src)
+
+ n.addErr(err)
+}
+
+func (n *nodeContext) updateNodeType(k adt.Kind, v adt.Expr, id adt.ID) bool {
ctx := n.ctx
kind := n.kind & k
@@ -781,9 +844,7 @@
case kind == adt.BottomKind:
if n.kindExpr != nil {
- n.addErr(ctx.Newf(
- "conflicting values %s and %s (mismatched types %s and %s)",
- ctx.Str(n.kindExpr), ctx.Str(v), n.kind, k))
+ n.addConflict(n.kindExpr, v, n.kind, k, n.kindID, id)
} else {
n.addErr(ctx.Newf(
"conflicting value %s (mismatched types %s and %s)",
@@ -1190,6 +1251,7 @@
if x, ok := v.(*adt.Vertex); ok {
if m, ok := x.Value.(*adt.StructMarker); ok {
n.aStruct = x
+ n.aStructID = id
if m.NeedClose {
ci := closedInfo(n.node)
ci.isClosed = true // TODO: remove
@@ -1248,7 +1310,7 @@
return
}
- if !n.updateNodeType(v.Kind(), v) {
+ if !n.updateNodeType(v.Kind(), v, id) {
return
}
@@ -1280,7 +1342,13 @@
case adt.LessThanOp, adt.LessEqualOp:
if y := n.upperBound; y != nil {
n.upperBound = nil
- n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y), id)
+ v := adt.SimplifyBounds(ctx, n.kind, x, y)
+ if err := valueError(v); err != nil {
+ err.AddPosition(v)
+ err.AddPosition(n.upperBound)
+ err.AddPosition(closedInfo(n.node).node(id).Src)
+ }
+ n.addValueConjunct(env, v, id)
return
}
n.upperBound = x
@@ -1288,7 +1356,13 @@
case adt.GreaterThanOp, adt.GreaterEqualOp:
if y := n.lowerBound; y != nil {
n.lowerBound = nil
- n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y), id)
+ v := adt.SimplifyBounds(ctx, n.kind, x, y)
+ if err := valueError(v); err != nil {
+ err.AddPosition(v)
+ err.AddPosition(n.lowerBound)
+ err.AddPosition(closedInfo(n.node).node(id).Src)
+ }
+ n.addValueConjunct(env, v, id)
return
}
n.lowerBound = x
@@ -1332,7 +1406,7 @@
case adt.Value: // *NullLit, *BoolLit, *NumLit, *StringLit, *BytesLit
if y := n.scalar; y != nil {
if b, ok := adt.BinOp(ctx, adt.EqualOp, x, y).(*adt.Bool); !ok || !b.B {
- n.addErr(ctx.Newf("incompatible values %s and %s", ctx.Str(x), ctx.Str(y)))
+ n.addConflict(x, y, x.Kind(), y.Kind(), n.scalarID, id)
}
// TODO: do we need to explicitly add again?
// n.scalar = nil
@@ -1340,6 +1414,7 @@
break
}
n.scalar = x
+ n.scalarID = id
default:
panic(fmt.Sprintf("unknown value type %T", x))
@@ -1347,6 +1422,11 @@
if n.lowerBound != nil && n.upperBound != nil {
if u := adt.SimplifyBounds(ctx, n.kind, n.lowerBound, n.upperBound); u != nil {
+ if err := valueError(u); err != nil {
+ err.AddPosition(n.lowerBound)
+ err.AddPosition(n.upperBound)
+ err.AddPosition(closedInfo(n.node).node(id).Src)
+ }
n.lowerBound = nil
n.upperBound = nil
n.addValueConjunct(env, u, id)
@@ -1354,6 +1434,21 @@
}
}
+func valueError(v adt.Value) *adt.ValueError {
+ if v == nil {
+ return nil
+ }
+ b, _ := v.(*adt.Bottom)
+ if b == nil {
+ return nil
+ }
+ err, _ := b.Err.(*adt.ValueError)
+ if err == nil {
+ return nil
+ }
+ return err
+}
+
// addStruct collates the declarations of a struct.
//
// addStruct fulfills two additional pivotal functions:
@@ -1406,11 +1501,13 @@
case *adt.OptionalField:
if x.Label.IsString() {
n.aStruct = s
+ n.aStructID = closeID
}
opt.AddOptional(ctx, x)
case *adt.DynamicField:
n.aStruct = s
+ n.aStructID = closeID
hasOther = x
n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x, closeID})
opt.AddDynamic(ctx, childEnv, x)
@@ -1438,11 +1535,13 @@
case *adt.BulkOptionalField:
n.aStruct = s
+ n.aStructID = closeID
hasBulk = x
opt.AddBulk(ctx, x)
case *adt.Ellipsis:
n.aStruct = s
+ n.aStructID = closeID
hasBulk = x
opt.AddEllipsis(ctx, x)
@@ -1457,6 +1556,7 @@
if !hasEmbed {
n.aStruct = s
+ n.aStructID = closeID
}
// Apply existing fields
@@ -1472,6 +1572,7 @@
case *adt.Field:
if x.Label.IsString() {
n.aStruct = s
+ n.aStructID = closeID
}
n.insertField(x.Label, adt.MakeConjunct(childEnv, x, closeID))
}
@@ -1626,9 +1727,9 @@
//
// TODO(embeddedScalars): for embedded scalars, there should be another pass
// of evaluation expressions after expanding lists.
-func (n *nodeContext) addLists(c *adt.OpContext) (oneOfTheLists adt.Expr) {
+func (n *nodeContext) addLists(c *adt.OpContext) (oneOfTheLists adt.Expr, anID adt.ID) {
if len(n.lists) == 0 && len(n.vLists) == 0 {
- return nil
+ return nil, 0
}
isOpen := true
@@ -1681,6 +1782,7 @@
outer:
for i, l := range n.lists {
oneOfTheLists = l.list
+ anID = l.id
n.updateCyclicStatus(l.env)
@@ -1806,7 +1908,7 @@
n.lists = n.lists[:0]
n.vLists = n.vLists[:0]
- return oneOfTheLists
+ return oneOfTheLists, anID
}
func (n *nodeContext) invalidListLength(na, nb int, a, b adt.Expr) {
diff --git a/internal/core/validate/validate_test.go b/internal/core/validate/validate_test.go
index a47afbd..496ad3b 100644
--- a/internal/core/validate/validate_test.go
+++ b/internal/core/validate/validate_test.go
@@ -65,20 +65,20 @@
in: `
1 & 2
`,
- out: "eval\nincompatible values 2 and 1",
+ out: "eval\nconflicting values 2 and 1:\n test:2:3\n test:2:7",
}, {
desc: "evaluation error in field",
in: `
x: 1 & 2
`,
- out: "eval\nx: incompatible values 2 and 1",
+ out: "eval\nx: conflicting values 2 and 1:\n test:2:6\n test:2:10",
}, {
desc: "first error",
in: `
x: 1 & 2
y: 2 & 4
`,
- out: "eval\nx: incompatible values 2 and 1",
+ out: "eval\nx: conflicting values 2 and 1:\n test:2:6\n test:2:10",
}, {
desc: "all errors",
cfg: &Config{AllErrors: true},
@@ -87,8 +87,12 @@
y: 2 & 4
`,
out: `eval
-x: incompatible values 2 and 1
-y: incompatible values 4 and 2`,
+x: conflicting values 2 and 1:
+ test:2:6
+ test:2:10
+y: conflicting values 4 and 2:
+ test:3:6
+ test:3:10`,
}, {
desc: "incomplete",
cfg: &Config{Concrete: true},
@@ -142,7 +146,7 @@
y: string
x: 1 & 2
`,
- out: "eval\nx: incompatible values 2 and 1",
+ out: "eval\nx: conflicting values 2 and 1:\n test:3:6\n test:3:10",
}, {
desc: "consider defaults for concreteness",
cfg: &Config{Concrete: true},
diff --git a/pkg/math/testdata/issue418.txtar b/pkg/math/testdata/issue418.txtar
index fba9bb9..547f2e9 100644
--- a/pkg/math/testdata/issue418.txtar
+++ b/pkg/math/testdata/issue418.txtar
@@ -14,7 +14,9 @@
}
-- out/math --
Errors:
-b.y: conflicting values int and 3.47970044315009900124277 (mismatched types int and float)
+b.y: conflicting values int and 3.47970044315009900124277 (mismatched types int and float):
+ ./in.cue:11:8
+ ./in.cue:12:8
Result:
(_|_){
@@ -27,7 +29,9 @@
// [eval]
x: (float){ 32.45 }
y: (_|_){
- // [eval] b.y: conflicting values int and 3.47970044315009900124277 (mismatched types int and float)
+ // [eval] b.y: conflicting values int and 3.47970044315009900124277 (mismatched types int and float):
+ // ./in.cue:11:8
+ // ./in.cue:12:8
}
}
}
diff --git a/pkg/struct/testdata/gen.txtar b/pkg/struct/testdata/gen.txtar
index 2b5e7b5..4d46fa3 100644
--- a/pkg/struct/testdata/gen.txtar
+++ b/pkg/struct/testdata/gen.txtar
@@ -10,7 +10,9 @@
t5: struct.MaxFields(2) & {a: 1}
-- out/structs --
Errors:
-t1: conflicting values struct.MinFields(0) and "" (mismatched types struct and string)
+t1: conflicting values struct.MinFields(0) and "" (mismatched types struct and string):
+ ./in.cue:3:5
+ ./in.cue:3:27
t3: invalid value {a:1} (does not satisfy struct.MinFields(2)):
./in.cue:5:5
t4: invalid value {a:1} (does not satisfy struct.MaxFields(0)):
@@ -20,7 +22,9 @@
(_|_){
// [eval]
t1: (_|_){
- // [eval] t1: conflicting values struct.MinFields(0) and "" (mismatched types struct and string)
+ // [eval] t1: conflicting values struct.MinFields(0) and "" (mismatched types struct and string):
+ // ./in.cue:3:5
+ // ./in.cue:3:27
}
t2: (struct){
a: (int){ 1 }