diff --git a/internal/core/subsume/subsume.go b/internal/core/subsume/subsume.go index e2a6a7901c4..e6dd1ae15cf 100644 --- a/internal/core/subsume/subsume.go +++ b/internal/core/subsume/subsume.go @@ -120,11 +120,9 @@ func (s *subsumer) getError() (err errors.Error) { if s.gt != nil && s.lt != nil { // src := binSrc(token.NoPos, opUnify, s.gt, s.lt) if s.missing != 0 { - s.errf("missing field %q", s.missing.SelectorString(c)) - } else if b, ok := unifyValue(c, s.gt, s.lt).(*adt.Bottom); !ok { - s.errf("value not an instance") + s.errf("field %q not present in %v", s.missing.SelectorString(c), s.lt) } else { - s.errs = errors.Append(s.errs, b.Err) + s.errf("%v does not subsume %v", s.gt, s.lt) } } if s.errs == nil { diff --git a/internal/core/subsume/testdata/subsume.txtar b/internal/core/subsume/testdata/subsume.txtar new file mode 100644 index 00000000000..e58da38ee18 --- /dev/null +++ b/internal/core/subsume/testdata/subsume.txtar @@ -0,0 +1,1615 @@ +-- out/TestValues/0/__⊑__ -- +true +-- out/TestValues/1/__⊑_null -- +true +-- out/TestValues/2/__⊑_int -- +true +-- out/TestValues/3/__⊑_1 -- +true +-- out/TestValues/4/__⊑_float -- +true +-- out/TestValues/5/__⊑_"s" -- +true +-- out/TestValues/6/__⊑_{} -- +true +-- out/TestValues/7/__⊑_[] -- +true +-- out/TestValues/8/__⊑__|_ -- +true +-- out/TestValues/9/null_⊑__ -- +Errors: +null does not subsume _: + value:1:4 + +Result: +false +-- out/TestValues/10/int_⊑__ -- +Errors: +int does not subsume _: + value:1:4 + +Result: +false +-- out/TestValues/11/1_⊑__ -- +Errors: +1 does not subsume _: + value:1:4 + +Result: +false +-- out/TestValues/12/float_⊑__ -- +Errors: +float does not subsume _: + value:1:4 + +Result: +false +-- out/TestValues/13/"s"_⊑__ -- +Errors: +"s" does not subsume _: + value:1:4 + +Result: +false +-- out/TestValues/14/{}_⊑__ -- +Errors: +{} does not subsume _: + value:1:4 + value:1:16 + +Result: +false +-- out/TestValues/15/[]_⊑__ -- +Errors: +[] does not subsume _: + value:1:4 + value:1:16 +list does not subsume _ (type _): + value:1:16 + +Result: +false +-- out/TestValues/16/_|__⊑__ -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume _: + value:1:4 + value:1:18 + +Result: +false +-- out/TestValues/17/_|__⊑_null -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume null: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/18/_|__⊑_int -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume int: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/19/_|__⊑_1 -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume 1: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/20/_|__⊑_float -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume float: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/21/_|__⊑_"s" -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume "s": + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/22/_|__⊑_{} -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume {}: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/23/_|__⊑_[] -- +Errors: +_|_(explicit error (_|_ literal) in source) does not subsume []: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/24/_|__⊑__|_ -- +true +-- out/TestValues/25/null_⊑__|_ -- +true +-- out/TestValues/26/int_⊑__|_ -- +true +-- out/TestValues/27/1_⊑__|_ -- +true +-- out/TestValues/28/float_⊑__|_ -- +true +-- out/TestValues/29/"s"_⊑__|_ -- +true +-- out/TestValues/30/{}_⊑__|_ -- +true +-- out/TestValues/31/[]_⊑__|_ -- +true +-- out/TestValues/32/true_⊑__|_ -- +true +-- out/TestValues/33/_|__⊑__|_ -- +true +-- out/TestValues/34/null_⊑_null -- +true +-- out/TestValues/35/null_⊑_1 -- +Errors: +null does not subsume 1: + value:1:4 + value:1:13 + +Result: +false +-- out/TestValues/36/1_⊑_null -- +Errors: +1 does not subsume null: + value:1:4 + value:1:13 + +Result: +false +-- out/TestValues/37/true_⊑_true -- +true +-- out/TestValues/38/true_⊑_false -- +Errors: +true does not subsume false: + value:1:4 + value:1:13 + +Result: +false +-- out/TestValues/39/"a"_⊑_"a" -- +true +-- out/TestValues/40/"a"_⊑_"b" -- +Errors: +"a" does not subsume "b": + value:1:4 + value:1:15 + +Result: +false +-- out/TestValues/41/string_⊑_"a" -- +true +-- out/TestValues/42/"a"_⊑_string -- +Errors: +"a" does not subsume string: + value:1:4 + value:1:15 + +Result: +false +-- out/TestValues/43/1_⊑_1 -- +true +-- out/TestValues/44/1.0_⊑_1.0 -- +true +-- out/TestValues/45/3.0_⊑_3.0 -- +true +-- out/TestValues/46/1.0_⊑_1 -- +Errors: +1.0 does not subsume 1: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/47/1_⊑_1.0 -- +Errors: +1 does not subsume 1.0: + value:1:4 + value:1:10 + +Result: +false +-- out/TestValues/48/3_⊑_3.0 -- +Errors: +3 does not subsume 3.0: + value:1:4 + value:1:10 + +Result: +false +-- out/TestValues/49/int_⊑_1 -- +true +-- out/TestValues/50/int_⊑_int_&_1 -- +true +-- out/TestValues/51/float_⊑_1.0 -- +true +-- out/TestValues/52/float_⊑_1 -- +Errors: +float does not subsume 1: + value:1:4 + value:1:14 + +Result: +false +-- out/TestValues/53/int_⊑_1.0 -- +Errors: +int does not subsume 1.0: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/54/int_⊑_int -- +true +-- out/TestValues/55/number_⊑_int -- +true +-- out/TestValues/64/{}_⊑_{} -- +true +-- out/TestValues/65/{}_⊑_{a:_1} -- +true +-- out/TestValues/66/{a:1}_⊑_{a:1,_b:1} -- +true +-- out/TestValues/67/{s:_{_a:1}_}_⊑_{_s:_{_a:1,_b:2_}} -- +true +-- out/TestValues/68/{}_⊑_{} -- +true +-- out/TestValues/69/{}_⊑_{}_&_c,_c:_{} -- +true +-- out/TestValues/70/{a:1}_⊑_{}-v3 -- +Errors: +field "a" not present in {}: + value:1:14 +regular field is constraint in subsumed value: a + +Result: +false +-- diff/-out/TestValues/70/{a:1}_⊑_{}-v3<==>+out/TestValues/70/{a:1}_⊑_{} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {}: + value:1:14 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + + Result: + false +-- out/TestValues/70/{a:1}_⊑_{}-v3-noshare -- +Errors: +field "a" not present in {}: + value:1:14 +regular field is constraint in subsumed value: a + +Result: +false +-- diff/-out/TestValues/70/{a:1}_⊑_{}-v3-noshare<==>+out/TestValues/70/{a:1}_⊑_{} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {}: + value:1:14 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + + Result: + false +-- out/TestValues/70/{a:1}_⊑_{} -- +Errors: +field "a" not present in {}: + value:1:14 +required field is optional in subsumed value: a + +Result: +false +-- out/TestValues/71/{a:1,_b:1}_⊑_{a:1}-v3 -- +Errors: +field "b" not present in {a:1}: + value:1:19 +regular field is constraint in subsumed value: b + +Result: +false +-- diff/-out/TestValues/71/{a:1,_b:1}_⊑_{a:1}-v3<==>+out/TestValues/71/{a:1,_b:1}_⊑_{a:1} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "b" not present in {a:1}: + value:1:19 +-required field is optional in subsumed value: b ++regular field is constraint in subsumed value: b + + Result: + false +-- out/TestValues/71/{a:1,_b:1}_⊑_{a:1}-v3-noshare -- +Errors: +field "b" not present in {a:1}: + value:1:19 +regular field is constraint in subsumed value: b + +Result: +false +-- diff/-out/TestValues/71/{a:1,_b:1}_⊑_{a:1}-v3-noshare<==>+out/TestValues/71/{a:1,_b:1}_⊑_{a:1} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "b" not present in {a:1}: + value:1:19 +-required field is optional in subsumed value: b ++regular field is constraint in subsumed value: b + + Result: + false +-- out/TestValues/71/{a:1,_b:1}_⊑_{a:1} -- +Errors: +field "b" not present in {a:1}: + value:1:19 +required field is optional in subsumed value: b + +Result: +false +-- out/TestValues/72/{s:_{_a:1}_}_⊑_{_s:_{}}-v3 -- +Errors: +field "a" not present in {}: + value:1:26 +regular field is constraint in subsumed value: a +{a:1} does not subsume {}: + value:1:8 + value:1:26 + +Result: +false +-- diff/-out/TestValues/72/{s:_{_a:1}_}_⊑_{_s:_{}}-v3<==>+out/TestValues/72/{s:_{_a:1}_}_⊑_{_s:_{}} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {}: + value:1:26 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + {a:1} does not subsume {}: + value:1:8 + value:1:26 +-- out/TestValues/72/{s:_{_a:1}_}_⊑_{_s:_{}}-v3-noshare -- +Errors: +field "a" not present in {}: + value:1:26 +regular field is constraint in subsumed value: a +{a:1} does not subsume {}: + value:1:8 + value:1:26 + +Result: +false +-- diff/-out/TestValues/72/{s:_{_a:1}_}_⊑_{_s:_{}}-v3-noshare<==>+out/TestValues/72/{s:_{_a:1}_}_⊑_{_s:_{}} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {}: + value:1:26 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + {a:1} does not subsume {}: + value:1:8 + value:1:26 +-- out/TestValues/72/{s:_{_a:1}_}_⊑_{_s:_{}} -- +Errors: +field "a" not present in {}: + value:1:26 +required field is optional in subsumed value: a +{a:1} does not subsume {}: + value:1:8 + value:1:26 + +Result: +false +-- out/TestValues/84/1_|_2_⊑_2_|_1 -- +true +-- out/TestValues/85/1_|_2_⊑_1_|_2 -- +true +-- out/TestValues/86/number_⊑_2_|_1 -- +true +-- out/TestValues/87/number_⊑_2_|_1 -- +true +-- out/TestValues/88/int_⊑_1_|_2_|_3.1 -- +Errors: +int does not subsume 3.1: + value:1:4 + value:1:20 + +Result: +false +-- out/TestValues/89/float_|_number_⊑_1_|_2_|_3.1 -- +true +-- out/TestValues/90/int_⊑_1_|_2_|_3.1 -- +Errors: +int does not subsume 3.1: + value:1:4 + value:1:20 + +Result: +false +-- out/TestValues/91/1_|_2_⊑_1 -- +true +-- out/TestValues/92/1_|_2_⊑_2 -- +true +-- out/TestValues/93/1_|_2_⊑_3 -- +Errors: +1 does not subsume 3: + value:1:4 + value:1:14 + +Result: +false +-- out/TestValues/150/number_|_*1_⊑_number_|_*2 -- +Errors: +1 does not subsume 2: + value:1:14 + value:1:30 + +Result: +false +-- out/TestValues/151/number_|_*2_⊑_number_|_*2 -- +true +-- out/TestValues/152/int_|_*float_⊑_int_|_*2.0 -- +true +-- out/TestValues/153/int_|_*2_⊑_int_|_*2.0 -- +Errors: +2 does not subsume 2.0: + value:1:11 + value:1:24 + +Result: +false +-- out/TestValues/154/number_|_*2_|_*3_⊑_number_|_*2 -- +true +-- out/TestValues/155/number_⊑_number_|_*2 -- +true +-- out/TestValues/170/>=2_⊑_>=2 -- +true +-- out/TestValues/171/>=1_⊑_>=2 -- +true +-- out/TestValues/172/>0_⊑_>=2 -- +true +-- out/TestValues/173/>1_⊑_>1 -- +true +-- out/TestValues/174/>=1_⊑_>1 -- +true +-- out/TestValues/175/>1_⊑_>=1 -- +Errors: +>1 does not subsume >=1: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/176/>=1_⊑_>=1 -- +true +-- out/TestValues/177/<1_⊑_<1 -- +true +-- out/TestValues/178/<=1_⊑_<1 -- +true +-- out/TestValues/179/<1_⊑_<=1 -- +Errors: +<1 does not subsume <=1: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/180/<=1_⊑_<=1 -- +true +-- out/TestValues/181/!=1_⊑_!=1 -- +true +-- out/TestValues/182/!=1_⊑_!=2 -- +Errors: +!=1 does not subsume !=2: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/183/!=1_⊑_<=1 -- +Errors: +!=1 does not subsume <=1: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/184/!=1_⊑_<1 -- +true +-- out/TestValues/185/!=1_⊑_>=1 -- +Errors: +!=1 does not subsume >=1: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/186/!=1_⊑_<1 -- +true +-- out/TestValues/187/!=1_⊑_<=0 -- +true +-- out/TestValues/188/!=1_⊑_>=2 -- +true +-- out/TestValues/189/!=1_⊑_>1 -- +true +-- out/TestValues/195/>=2_⊑_!=2 -- +Errors: +>=2 does not subsume !=2: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/196/>2_⊑_!=2 -- +Errors: +>2 does not subsume !=2: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/197/<2_⊑_!=2 -- +Errors: +<2 does not subsume !=2: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/198/<=2_⊑_!=2 -- +Errors: +<=2 does not subsume !=2: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/200/=~"foo"_⊑_=~"foo" -- +true +-- out/TestValues/201/=~"foo"_⊑_=~"bar" -- +Errors: +=~"foo" does not subsume =~"bar": + value:1:4 + value:1:16 + +Result: +false +-- out/TestValues/202/=~"foo1"_⊑_=~"foo" -- +Errors: +=~"foo1" does not subsume =~"foo": + value:1:4 + value:1:17 + +Result: +false +-- out/TestValues/203/!~"foo"_⊑_!~"foo" -- +true +-- out/TestValues/204/!~"foo"_⊑_!~"bar" -- +Errors: +!~"foo" does not subsume !~"bar": + value:1:4 + value:1:16 + +Result: +false +-- out/TestValues/205/!~"foo"_⊑_!~"foo1" -- +Errors: +!~"foo" does not subsume !~"foo1": + value:1:4 + value:1:16 + +Result: +false +-- out/TestValues/210/=~"foo"_⊑_=~"foo1" -- +Errors: +=~"foo" does not subsume =~"foo1": + value:1:4 + value:1:16 + +Result: +false +-- out/TestValues/211/!~"foo1"_⊑_!~"foo" -- +Errors: +!~"foo1" does not subsume !~"foo": + value:1:4 + value:1:17 + +Result: +false +-- out/TestValues/220/<5_⊑_4 -- +true +-- out/TestValues/221/<5_⊑_5 -- +Errors: +<5 does not subsume 5: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/222/<=5_⊑_5 -- +true +-- out/TestValues/223/<=5.0_⊑_5.00000001 -- +Errors: +<=5.0 does not subsume 5.00000001: + value:1:4 + value:1:14 + +Result: +false +-- out/TestValues/224/>5_⊑_6 -- +true +-- out/TestValues/225/>5_⊑_5 -- +Errors: +>5 does not subsume 5: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/226/>=5_⊑_5 -- +true +-- out/TestValues/227/>=5_⊑_4 -- +Errors: +>=5 does not subsume 4: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/228/!=5_⊑_6 -- +true +-- out/TestValues/229/!=5_⊑_5 -- +Errors: +!=5 does not subsume 5: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/230/!=5.0_⊑_5.0 -- +Errors: +!=5.0 does not subsume 5.0: + value:1:4 + value:1:14 + +Result: +false +-- out/TestValues/231/!=5.0_⊑_5 -- +Errors: +!=5.0 does not subsume 5: + value:1:4 + value:1:14 + +Result: +false +-- out/TestValues/250/=~_#"^\d{3}$"#_⊑_"123" -- +true +-- out/TestValues/251/=~_#"^\d{3}$"#_⊑_"1234" -- +Errors: +=~"^\\d{3}$" does not subsume "1234": + value:1:4 + value:1:23 + +Result: +false +-- out/TestValues/252/!~_#"^\d{3}$"#_⊑_"1234" -- +true +-- out/TestValues/253/!~_#"^\d{3}$"#_⊑_"123" -- +Errors: +!~"^\\d{3}$" does not subsume "123": + value:1:4 + value:1:23 + +Result: +false +-- out/TestValues/300/>0_⊑_>=2_&_<=100 -- +true +-- out/TestValues/301/>0_⊑_>=0_&_<=100 -- +Errors: +>0 does not subsume >=0: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/310/>=0_&_<=100_⊑_10 -- +true +-- out/TestValues/311/>=0_&_<=100_⊑_>=0_&_<=100 -- +true +-- out/TestValues/312/!=2_&_!=4_⊑_>3 -- +Errors: +!=4 does not subsume >3: + value:1:10 + value:1:18 + +Result: +false +-- out/TestValues/313/!=2_&_!=4_⊑_>5 -- +true +-- out/TestValues/314/>=0_&_<=100_⊑_>=0_&_<=150 -- +Errors: +<=100 does not subsume >=0: + value:1:10 + value:1:20 + +Result: +false +-- out/TestValues/315/>=0_&_<=150_⊑_>=0_&_<=100 -- +true +-- out/TestValues/330/>5_⊑_>10_|_8 -- +true +-- out/TestValues/331/>8_⊑_>10_|_8 -- +Errors: +>8 does not subsume 8: + value:1:4 + value:1:17 + +Result: +false +-- out/TestValues/400/{foo:_1}_⊑_{}-v3 -- +Errors: +field "foo" not present in {}: + value:1:17 +regular field is constraint in subsumed value: foo + +Result: +false +-- diff/-out/TestValues/400/{foo:_1}_⊑_{}-v3<==>+out/TestValues/400/{foo:_1}_⊑_{} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "foo" not present in {}: + value:1:17 +-required field is optional in subsumed value: foo ++regular field is constraint in subsumed value: foo + + Result: + false +-- out/TestValues/400/{foo:_1}_⊑_{}-v3-noshare -- +Errors: +field "foo" not present in {}: + value:1:17 +regular field is constraint in subsumed value: foo + +Result: +false +-- diff/-out/TestValues/400/{foo:_1}_⊑_{}-v3-noshare<==>+out/TestValues/400/{foo:_1}_⊑_{} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "foo" not present in {}: + value:1:17 +-required field is optional in subsumed value: foo ++regular field is constraint in subsumed value: foo + + Result: + false +-- out/TestValues/400/{foo:_1}_⊑_{} -- +Errors: +field "foo" not present in {}: + value:1:17 +required field is optional in subsumed value: foo + +Result: +false +-- out/TestValues/401/{foo?:_1}_⊑_{} -- +Errors: +1 does not subsume _: + value:1:11 +1? does not subsume _: + value:1:11 + +Result: +false +-- out/TestValues/402/{}_⊑_{foo:_1} -- +true +-- out/TestValues/403/{}_⊑_{foo?:_1} -- +true +-- out/TestValues/404/{foo:_1}_⊑_{foo:_1} -- +true +-- out/TestValues/405/{foo?:_1}_⊑_{foo:_1} -- +true +-- out/TestValues/406/{foo?:_1}_⊑_{foo?:_1} -- +true +-- out/TestValues/407/{foo:_1}_⊑_{foo?:_1} -- +Errors: +1 does not subsume 1: + value:1:10 + value:1:24 +1 does not subsume 1?: + value:1:10 + value:1:24 + +Result: +false +-- out/TestValues/408/{foo:_1}_⊑_{foo:_2} -- +Errors: +1 does not subsume 2: + value:1:10 + value:1:23 + +Result: +false +-- out/TestValues/409/{foo?:_1}_⊑_{foo:_2} -- +Errors: +1 does not subsume 2: + value:1:11 + value:1:24 +1? does not subsume 2: + value:1:11 + value:1:24 + +Result: +false +-- out/TestValues/410/{foo?:_1}_⊑_{foo?:_2} -- +Errors: +1 does not subsume 2: + value:1:11 + value:1:25 +1? does not subsume 2?: + value:1:11 + value:1:25 + +Result: +false +-- out/TestValues/411/{foo:_1}_⊑_{foo?:_2} -- +Errors: +1 does not subsume 2: + value:1:10 + value:1:24 +1 does not subsume 2?: + value:1:10 + value:1:24 + +Result: +false +-- out/TestValues/412/{foo:_number}_⊑_{foo:_2} -- +true +-- out/TestValues/413/{foo?:_number}_⊑_{foo:_2} -- +true +-- out/TestValues/414/{foo?:_number}_⊑_{foo?:_2} -- +true +-- out/TestValues/415/{foo:_number}_⊑_{foo?:_2} -- +Errors: +number does not subsume 2: + value:1:10 + value:1:29 +number does not subsume 2?: + value:1:10 + value:1:29 + +Result: +false +-- out/TestValues/416/{foo:_1}_⊑_{foo:_number} -- +Errors: +1 does not subsume number: + value:1:10 + value:1:23 + +Result: +false +-- out/TestValues/417/{foo?:_1}_⊑_{foo:_number} -- +Errors: +1 does not subsume number: + value:1:11 + value:1:24 +1? does not subsume number: + value:1:11 + value:1:24 + +Result: +false +-- out/TestValues/418/{foo?:_1}_⊑_{foo?:_number} -- +Errors: +1 does not subsume number: + value:1:11 + value:1:25 +1? does not subsume number?: + value:1:11 + value:1:25 + +Result: +false +-- out/TestValues/419/{foo:_1}_⊑_{foo?:_number} -- +Errors: +1 does not subsume number: + value:1:10 + value:1:24 +1 does not subsume number?: + value:1:10 + value:1:24 + +Result: +false +-- out/TestValues/420/{foo?:__}_⊑_{} -- +true +-- out/TestValues/430/{[_]:_4}_⊑_{[_]:_int}-v3 -- +Errors: +4 does not subsume int: + value:1:10 + value:1:23 + +Result: +false +-- diff/-out/TestValues/430/{[_]:_4}_⊑_{[_]:_int}-v3<==>+out/TestValues/430/{[_]:_4}_⊑_{[_]:_int} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: +-{} does not subsume {}: inexact subsumption: +- value:1:4 +- value:1:17 ++4 does not subsume int: ++ value:1:10 ++ value:1:23 + + Result: + false +-- out/TestValues/430/{[_]:_4}_⊑_{[_]:_int}-v3-noshare -- +Errors: +4 does not subsume int: + value:1:10 + value:1:23 + +Result: +false +-- diff/-out/TestValues/430/{[_]:_4}_⊑_{[_]:_int}-v3-noshare<==>+out/TestValues/430/{[_]:_4}_⊑_{[_]:_int} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: +-{} does not subsume {}: inexact subsumption: +- value:1:4 +- value:1:17 ++4 does not subsume int: ++ value:1:10 ++ value:1:23 + + Result: + false +-- out/TestValues/430/{[_]:_4}_⊑_{[_]:_int} -- +Errors: +{} does not subsume {}: inexact subsumption: + value:1:4 + value:1:17 + +Result: +false +-- out/TestValues/431/{[_]:_int}_⊑_{[_]:_2}-v3 -- +true +-- out/TestValues/431/{[_]:_int}_⊑_{[_]:_2}-v3-noshare -- +true +-- out/TestValues/432/{[string]:_int,_[<"m"]:_3}_⊑_{[string]:_2,_[<"m"]:_3}-v3 -- +true +-- out/TestValues/432/{[string]:_int,_[<"m"]:_3}_⊑_{[string]:_2,_[<"m"]:_3}-v3-noshare -- +true +-- out/TestValues/433/{[<"m"]:_3,_[string]:_int}_⊑_{[string]:_2,_[<"m"]:_3}-v3 -- +true +-- out/TestValues/433/{[<"m"]:_3,_[string]:_int}_⊑_{[string]:_2,_[<"m"]:_3}-v3-noshare -- +true +-- out/TestValues/434/{[<"n"]:_3,_[string]:_int}_⊑_{[string]:_2,_[<"m"]:_3} -- +Errors: +{} does not subsume {}: inexact subsumption: + value:1:4 + value:1:35 + +Result: +false +-- out/TestValues/435/{[string]:_<5,_[string]:_int}_⊑_{[string]:_<=3,_[string]:_3}-v3 -- +true +-- out/TestValues/435/{[string]:_<5,_[string]:_int}_⊑_{[string]:_<=3,_[string]:_3}-v3-noshare -- +true +-- out/TestValues/436/{[string]:_>5}_⊑_{[string]:_1,_[string]:_2}-v3 -- +true +-- out/TestValues/436/{[string]:_>5}_⊑_{[string]:_1,_[string]:_2}-v3-noshare -- +true +-- out/TestValues/437/{[_]:_>5,_[>"b"]:_int}_⊑_{[_]:_6} -- +Errors: +{} does not subsume {}: inexact subsumption: + value:1:4 + value:1:31 + +Result: +false +-- out/TestValues/438/{}_⊑_{[_]:_6} -- +true +-- out/TestValues/460/{1,_#foo:_number}_⊑_{1,_#foo:_1} -- +true +-- out/TestValues/461/{1,_#foo?:_number}_⊑_{1,_#foo:_1} -- +true +-- out/TestValues/462/{1,_#foo?:_number}_⊑_{1,_#foo?:_1} -- +true +-- out/TestValues/463/{1,_#foo:_number}_⊑_{1,_#foo?:_1} -- +Errors: +number does not subsume 1: + value:1:14 + value:1:37 +number does not subsume 1?: + value:1:14 + value:1:37 + +Result: +false +-- out/TestValues/464/{int,_#foo:_number}_⊑_{1,_#foo:_1} -- +true +-- out/TestValues/465/{int,_#foo:_1}_⊑_{1,_#foo:_number} -- +Errors: +1 does not subsume number: + value:1:16 + value:1:33 + +Result: +false +-- out/TestValues/466/{1,_#foo:_number}_⊑_{int,_#foo:_1} -- +Errors: +1 does not subsume int: + value:1:5 + value:1:27 + +Result: +false +-- out/TestValues/467/{1,_#foo:_1}_⊑_{int,_#foo:_number} -- +Errors: +1 does not subsume int: + value:1:5 + value:1:22 + +Result: +false +-- out/TestValues/506/[]_⊑_[] -- +true +-- out/TestValues/507/[1]_⊑_[1] -- +true +-- out/TestValues/508/[1]_⊑_[2] -- +Errors: +1 does not subsume 2: + value:1:5 + value:1:13 + +Result: +false +-- out/TestValues/509/[1]_⊑_[2,_3] -- +Errors: +[1] does not subsume [2,3]: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/510/[{b:_string}],_b:_[{_⊑_"foo"}] -- +true +-- out/TestValues/511/[...{b:_string}],_b:_[{_⊑_"foo"}] -- +true +-- out/TestValues/512/[{b:_"foo"}],_b:_[{_⊑_string}] -- +Errors: +"foo" does not subsume string: + value:1:9 + value:1:26 + +Result: +false +-- out/TestValues/513/[{b:_string}],_b:_[{b:_"foo"},_...{_⊑_"foo"}] -- +Errors: +[{b:string}] does not subsume [{b:"foo"}]: + value:1:4 + value:1:22 + +Result: +false +-- out/TestValues/520/[_,_int,_...]_⊑_[int,_string,_...string] -- +Errors: +int does not subsume string: + value:1:8 + value:1:28 + +Result: +false +-- out/TestValues/600/close({})_⊑_{a:_1} -- +Errors: +{} does not subsume {a:1}: + value:1:4 + value:1:18 + +Result: +false +-- out/TestValues/601/close({a:_1})_⊑_{a:_1} -- +Errors: +{a:1} does not subsume {a:1}: + value:1:4 + value:1:22 + +Result: +false +-- out/TestValues/602/close({a:_1,_b:_1})_⊑_{a:_1} -- +Errors: +{a:1,b:1} does not subsume {a:1}: + value:1:4 + value:1:28 + +Result: +false +-- out/TestValues/603/{a:_1}_⊑_close({})-v3 -- +Errors: +field "a" not present in {}: + value:1:15 +regular field is constraint in subsumed value: a + +Result: +false +-- diff/-out/TestValues/603/{a:_1}_⊑_close({})-v3<==>+out/TestValues/603/{a:_1}_⊑_close({}) -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {}: + value:1:15 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + + Result: + false +-- out/TestValues/603/{a:_1}_⊑_close({})-v3-noshare -- +Errors: +field "a" not present in {}: + value:1:15 +regular field is constraint in subsumed value: a + +Result: +false +-- diff/-out/TestValues/603/{a:_1}_⊑_close({})-v3-noshare<==>+out/TestValues/603/{a:_1}_⊑_close({}) -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {}: + value:1:15 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + + Result: + false +-- out/TestValues/603/{a:_1}_⊑_close({}) -- +Errors: +field "a" not present in {}: + value:1:15 +required field is optional in subsumed value: a + +Result: +false +-- out/TestValues/604/{a:_1}_⊑_close({a:_1}) -- +true +-- out/TestValues/605/{a:_1},_b:_close({a:_1_⊑_1}) -- +true +-- out/TestValues/606/close({b?:_1}),_b:_close({_⊑_1}) -- +true +-- out/TestValues/607/close({b:_1})_⊑_close({b?:_1}) -- +Errors: +1 does not subsume 1: + value:1:14 + value:1:33 +1 does not subsume 1?: + value:1:14 + value:1:33 + +Result: +false +-- out/TestValues/608/{}_⊑_close({}) -- +true +-- out/TestValues/609/{}_⊑_close({foo?:_1}) -- +true +-- out/TestValues/610/{foo?:1}_⊑_close({}) -- +true +-- out/TestValues/611/close({foo?:1})_⊑_close({bar?:_1}) -- +Errors: +field not allowed in closed struct: bar +{foo?:1} does not subsume {bar?:1}: + value:1:4 + value:1:24 + +Result: +false +-- out/TestValues/612/{foo?:1}_⊑_close({bar?:_1}) -- +true +-- out/TestValues/613/{foo?:1}_⊑_close({bar:_1}) -- +true +-- out/TestValues/630/{#a:_1}_⊑_{a:_1}-v3 -- +Errors: +field "#a" not present in {a:1}: + value:1:16 +regular field is constraint in subsumed value: #a + +Result: +false +-- diff/-out/TestValues/630/{#a:_1}_⊑_{a:_1}-v3<==>+out/TestValues/630/{#a:_1}_⊑_{a:_1} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "#a" not present in {a:1}: + value:1:16 +-required field is optional in subsumed value: #a ++regular field is constraint in subsumed value: #a + + Result: + false +-- out/TestValues/630/{#a:_1}_⊑_{a:_1}-v3-noshare -- +Errors: +field "#a" not present in {a:1}: + value:1:16 +regular field is constraint in subsumed value: #a + +Result: +false +-- diff/-out/TestValues/630/{#a:_1}_⊑_{a:_1}-v3-noshare<==>+out/TestValues/630/{#a:_1}_⊑_{a:_1} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "#a" not present in {a:1}: + value:1:16 +-required field is optional in subsumed value: #a ++regular field is constraint in subsumed value: #a + + Result: + false +-- out/TestValues/630/{#a:_1}_⊑_{a:_1} -- +Errors: +field "#a" not present in {a:1}: + value:1:16 +required field is optional in subsumed value: #a + +Result: +false +-- out/TestValues/631/{a:_1}_⊑_{#a:_1}-v3 -- +Errors: +field "a" not present in {#a:1}: + value:1:15 +regular field is constraint in subsumed value: a + +Result: +false +-- diff/-out/TestValues/631/{a:_1}_⊑_{#a:_1}-v3<==>+out/TestValues/631/{a:_1}_⊑_{#a:_1} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {#a:1}: + value:1:15 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + + Result: + false +-- out/TestValues/631/{a:_1}_⊑_{#a:_1}-v3-noshare -- +Errors: +field "a" not present in {#a:1}: + value:1:15 +regular field is constraint in subsumed value: a + +Result: +false +-- diff/-out/TestValues/631/{a:_1}_⊑_{#a:_1}-v3-noshare<==>+out/TestValues/631/{a:_1}_⊑_{#a:_1} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "a" not present in {#a:1}: + value:1:15 +-required field is optional in subsumed value: a ++regular field is constraint in subsumed value: a + + Result: + false +-- out/TestValues/631/{a:_1}_⊑_{#a:_1} -- +Errors: +field "a" not present in {#a:1}: + value:1:15 +required field is optional in subsumed value: a + +Result: +false +-- out/TestValues/700/[string]:_1_⊑_{foo:_1} -- +true +-- out/TestValues/701/[string]:_int_⊑_{foo:_1} -- +true +-- out/TestValues/702/{["foo"]:_int}_⊑_{foo:_1} -- +true +-- out/TestValues/703/close({["foo"]:_1})_⊑_{bar:_1} -- +Errors: +field not allowed in closed struct: bar +{} does not subsume {bar:1}: + value:1:4 + value:1:28 + +Result: +false +-- out/TestValues/704/{foo:_1}_⊑_{foo?:_1} -- +Errors: +1 does not subsume 1: + value:1:10 + value:1:24 +1 does not subsume 1?: + value:1:10 + value:1:24 + +Result: +false +-- out/TestValues/705/close({})_⊑_{foo?:_1} -- +true +-- out/TestValues/706/close({})_⊑_close({foo?:_1}) -- +true +-- out/TestValues/707/{}_⊑_close({}) -- +true +-- out/TestValues/708/{[string]:_1}_⊑_{foo:_2} -- +Errors: +1 does not subsume 2: + value:1:15 + value:1:28 + +Result: +false +-- out/TestValues/709/{}_⊑_close({foo?:_1}) -- +true +-- out/TestValues/710/{foo:_[...string]}_⊑_{}-v3 -- +Errors: +field "foo" not present in {}: + value:1:27 +regular field is constraint in subsumed value: foo + +Result: +false +-- diff/-out/TestValues/710/{foo:_[...string]}_⊑_{}-v3<==>+out/TestValues/710/{foo:_[...string]}_⊑_{} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "foo" not present in {}: + value:1:27 +-required field is optional in subsumed value: foo ++regular field is constraint in subsumed value: foo + + Result: + false +-- out/TestValues/710/{foo:_[...string]}_⊑_{}-v3-noshare -- +Errors: +field "foo" not present in {}: + value:1:27 +regular field is constraint in subsumed value: foo + +Result: +false +-- diff/-out/TestValues/710/{foo:_[...string]}_⊑_{}-v3-noshare<==>+out/TestValues/710/{foo:_[...string]}_⊑_{} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: + field "foo" not present in {}: + value:1:27 +-required field is optional in subsumed value: foo ++regular field is constraint in subsumed value: foo + + Result: + false +-- out/TestValues/710/{foo:_[...string]}_⊑_{} -- +Errors: +field "foo" not present in {}: + value:1:27 +required field is optional in subsumed value: foo + +Result: +false +-- out/TestValues/800/close({})_⊑_{foo:_1} -- +true +-- out/TestValues/804/{foo:_1}_⊑_{foo?:_1} -- +Errors: +1 does not subsume 1: + value:1:10 + value:1:24 +1 does not subsume 1?: + value:1:10 + value:1:24 + +Result: +false +-- out/TestValues/805/close({})_⊑_{foo?:_1} -- +true +-- out/TestValues/806/close({})_⊑_close({foo?:_1}) -- +true +-- out/TestValues/807/{}_⊑_close({}) -- +true +-- out/TestValues/808/{[string]:_1}_⊑_{foo:_2}-v3 -- +Errors: +1 does not subsume 2: + value:1:15 + value:1:28 + +Result: +false +-- diff/-out/TestValues/808/{[string]:_1}_⊑_{foo:_2}-v3<==>+out/TestValues/808/{[string]:_1}_⊑_{foo:_2} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: +-{} does not subsume {foo:2}: inexact subsumption: +- value:1:4 +- value:1:22 ++1 does not subsume 2: ++ value:1:15 ++ value:1:28 + + Result: + false +-- out/TestValues/808/{[string]:_1}_⊑_{foo:_2}-v3-noshare -- +Errors: +1 does not subsume 2: + value:1:15 + value:1:28 + +Result: +false +-- diff/-out/TestValues/808/{[string]:_1}_⊑_{foo:_2}-v3-noshare<==>+out/TestValues/808/{[string]:_1}_⊑_{foo:_2} -- +diff old new +--- old ++++ new +@@ -1,7 +1,7 @@ + Errors: +-{} does not subsume {foo:2}: inexact subsumption: +- value:1:4 +- value:1:22 ++1 does not subsume 2: ++ value:1:15 ++ value:1:28 + + Result: + false +-- out/TestValues/808/{[string]:_1}_⊑_{foo:_2} -- +Errors: +{} does not subsume {foo:2}: inexact subsumption: + value:1:4 + value:1:22 + +Result: +false +-- out/TestValues/809/{}_⊑_close({foo?:_1}) -- +true +-- out/TestValues/950/[]_⊑_[] -- +true +-- out/TestValues/951/[...]_⊑_[] -- +true +-- out/TestValues/952/[...]_⊑_[...] -- +true +-- out/TestValues/953/[]_⊑_[...] -- +Errors: +[] does not subsume []: + value:1:4 + value:1:11 + +Result: +false +-- out/TestValues/954/[2]_⊑_[2] -- +true +-- out/TestValues/955/[int]_⊑_[2] -- +true +-- out/TestValues/956/[2]_⊑_[int] -- +Errors: +2 does not subsume int: + value:1:5 + value:1:13 + +Result: +false +-- out/TestValues/957/[int]_⊑_[int] -- +true +-- out/TestValues/958/[...2]_⊑_[2] -- +true +-- out/TestValues/959/[...int]_⊑_[2] -- +true +-- out/TestValues/960/[...2]_⊑_[int] -- +Errors: +2 does not subsume int: + value:1:8 + value:1:16 + +Result: +false +-- out/TestValues/961/[...int]_⊑_[int] -- +true +-- out/TestValues/962/[2]_⊑_[...2] -- +Errors: +[2] does not subsume []: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/963/[int]_⊑_[...2] -- +Errors: +[int] does not subsume []: + value:1:4 + value:1:14 + +Result: +false +-- out/TestValues/964/[2]_⊑_[...int] -- +Errors: +[2] does not subsume []: + value:1:4 + value:1:12 + +Result: +false +-- out/TestValues/965/[int]_⊑_[...int] -- +Errors: +[int] does not subsume []: + value:1:4 + value:1:14 + +Result: +false +-- out/TestValues/966/[...int]_⊑_["foo"] -- +Errors: +int does not subsume "foo": + value:1:8 + value:1:18 + +Result: +false +-- out/TestValues/967/["foo"]_⊑_[...int] -- +Errors: +["foo"] does not subsume []: + value:1:4 + value:1:16 + +Result: +false +-- out/TestValues/970/[]_⊑_[...int] -- +true +-- out/TestValues/971/[2]_⊑_[2,_...int] -- +true +-- out/TestValues/980/[]_⊑_[...int] -- +true +-- out/TestValues/981/[2]_⊑_[2,_...int] -- +true diff --git a/internal/core/subsume/value_test.go b/internal/core/subsume/value_test.go index 2f09730ae18..67e9fa88a06 100644 --- a/internal/core/subsume/value_test.go +++ b/internal/core/subsume/value_test.go @@ -15,6 +15,7 @@ package subsume_test import ( + "fmt" "regexp" "strconv" "strings" @@ -26,6 +27,7 @@ import ( "cuelang.org/go/internal/core/eval" "cuelang.org/go/internal/core/subsume" "cuelang.org/go/internal/cuetdtest" + "cuelang.org/go/internal/cuetxtar" ) const ( @@ -47,6 +49,11 @@ func TestValues(t *testing.T) { skip_v2 bool // Bug only exists in v2. Won't fix. } + test := cuetxtar.TxTarTest{ + Root: "testdata", + Name: "values", + Matrix: cuetdtest.FullMatrix, + } testCases := []subsumeTest{ // Top subsumes everything 0: {subsumes: true, in: `a: _, b: _ `}, @@ -460,55 +467,67 @@ func TestValues(t *testing.T) { const cutset = "\n ," key := strings.Trim(m[1], cutset) + " ⊑ " + strings.Trim(m[2], cutset) - cuetdtest.FullMatrix.Run(t, strconv.Itoa(i)+"/"+key, func(t *testing.T, m *cuetdtest.M) { - if tc.skip_v2 && m.IsDefault() { - t.Skipf("skipping v2 test") - } - r := m.Runtime() - - file, err := parser.ParseFile("subsume", tc.in) - if err != nil { - t.Fatal(err) - } - - root, errs := compile.Files(nil, r, "", file) - if errs != nil { - t.Fatal(errs) - } - - ctx := eval.NewContext(r, root) - root.Finalize(ctx) - - // Use low-level lookup to avoid evaluation. - var a, b adt.Value - for _, arc := range root.Arcs { - switch arc.Label { - case ctx.StringLabel("a"): - a = arc - case ctx.StringLabel("b"): - b = arc + t.Run(strconv.Itoa(i)+"/"+key, func(t *testing.T) { + test.Name = t.Name() + test.Run(t, func(t *cuetxtar.Test) { + if tc.skip_v2 && t.IsDefault() { + t.Skipf("skipping v2 test") + } + r := t.Runtime() + + file, err := parser.ParseFile("value", tc.in) + if err != nil { + t.Fatal(err) + } + + root, errs := compile.Files(nil, r, "", file) + if errs != nil { + t.Fatal(errs) + } + + ctx := eval.NewContext(r, root) + root.Finalize(ctx) + + // Use low-level lookup to avoid evaluation. + var a, b adt.Value + for _, arc := range root.Arcs { + switch arc.Label { + case ctx.StringLabel("a"): + a = arc + case ctx.StringLabel("b"): + b = arc + } } - } - - switch tc.mode { - case subNone: - err = subsume.Value(ctx, a, b) - case subSchema: - err = subsume.API.Value(ctx, a, b) - // TODO: see comments above. - // case subNoOptional: - // err = IgnoreOptional.Value(ctx, a, b) - case subDefaults: - p := subsume.Profile{Defaults: true} - err = p.Value(ctx, a, b) - case subFinal: - err = subsume.Final.Value(ctx, a, b) - } - got := err == nil - - if got != tc.subsumes { - t.Errorf("got %v; want %v (%v vs %v)", got, tc.subsumes, a.Kind(), b.Kind()) - } + + switch tc.mode { + case subNone: + errs = subsume.Value(ctx, a, b) + case subSchema: + errs = subsume.API.Value(ctx, a, b) + // TODO: see comments above. + // case subNoOptional: + // err = IgnoreOptional.Value(ctx, a, b) + case subDefaults: + p := subsume.Profile{Defaults: true} + errs = p.Value(ctx, a, b) + case subFinal: + errs = subsume.Final.Value(ctx, a, b) + } + got := errs == nil + + if got != tc.subsumes { + t.Errorf("got %v; want %v (%v vs %v)", got, tc.subsumes, a.Kind(), b.Kind()) + } + + if errs != nil { + fmt.Fprintln(t, "Errors:") + t.WriteErrors(errs) + fmt.Fprintln(t, "") + fmt.Fprintln(t, "Result:") + } + + fmt.Fprint(t, strconv.FormatBool(got)) + }) }) } } diff --git a/internal/core/subsume/vertex.go b/internal/core/subsume/vertex.go index 855ce6fbce9..bd9693ec248 100644 --- a/internal/core/subsume/vertex.go +++ b/internal/core/subsume/vertex.go @@ -149,6 +149,9 @@ func (s *subsumer) vertices(x, y *adt.Vertex) bool { if b == nil { // y.f is optional if !aOpt { + s.missing = f + s.gt = a + s.lt = y s.errf("required field is optional in subsumed value: %v", f) return false } @@ -170,11 +173,11 @@ func (s *subsumer) vertices(x, y *adt.Vertex) bool { continue } - s.missing = f s.gt = a - s.lt = y + s.lt = b + + s.errf("%v%s does not subsume %v%s", a, a.ArcType.Suffix(), b, b.ArcType.Suffix()) - s.errf("field %v not present in %v", f, y) return false } @@ -350,6 +353,9 @@ func (s *subsumer) verticesDev(x, y *adt.Vertex) bool { b := y.Lookup(f) if b == nil { if !isConstraint { + s.missing = f + s.gt = a + s.lt = y s.errf("regular field is constraint in subsumed value: %v", f) return false } @@ -373,11 +379,10 @@ func (s *subsumer) verticesDev(x, y *adt.Vertex) bool { continue } - s.missing = f s.gt = a - s.lt = y + s.lt = b - s.errf("field %v not present in %v", f, y) + s.errf("%v%s does not subsume %v%s", a, a.ArcType.Suffix(), b, b.ArcType.Suffix()) return false }