Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
internal/core/adt: fix overzealous disambiguation
Browse files Browse the repository at this point in the history
Equality is used to remove duplicate entries in a disjunction.
However, it did not consider optional fields. This could
lead to differing disjuncts being deleted.

The approach we take is to check that any of the
original StructLits with optional fields are associated
with both Vertices.
Note that it is somewhat okay for Equality to return false
negatives, as the spec does not guarantee this. At some
point we need to come up with something that is
more consistent.

This change leads to a reopening of Issue #353.

Change-Id: I7288061c7d3a51f7a754618c990a14e0275244d0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8203
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Jan 15, 2021
1 parent 355cccd commit ae1203c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
7 changes: 5 additions & 2 deletions cue/testdata/eval/closed_disjunction.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ b: field `d` not allowed:
Result:
(_|_){
// [eval]
#A: (#struct){
}
#A: (struct){ |(*(#struct){
}, (#struct){
}, (#struct){
}, (#struct){
}) }
a: (#struct){
b: (int){ 3 }
c: (int){ 3 }
Expand Down
16 changes: 10 additions & 6 deletions cue/testdata/eval/issue353.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ e: a: "hello"
}
-- out/eval --
(struct){
e: (#struct){
a: (string){ "hello" }
}
#Example: (#struct){
a: (string){ string }
}
e: (struct){ |((#struct){
a: (string){ "hello" }
}, (#struct){
a: (string){ "hello" }
}) }
#Example: (struct){ |((#struct){
a: (string){ string }
}, (#struct){
a: (string){ string }
}) }
}
-- out/compile --
--- in.cue
Expand Down
34 changes: 34 additions & 0 deletions internal/core/adt/equality.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ func equalVertex(ctx *OpContext, x *Vertex, v Value) bool {
if x.IsClosed(ctx) != y.IsClosed(ctx) {
return false
}
if !equalOptional(ctx, x, y) {
return false
}

loop1:
for _, a := range x.Arcs {
Expand Down Expand Up @@ -81,6 +84,37 @@ loop1:
return equalTerminal(ctx, v, w)
}

// equalOptional tests if x and y have the same set of close information.
// Right now this just checks if it has the same source structs that
// define optional fields.
// TODO: the following refinements are possible:
// - unify optional fields and equate the optional fields
// - do the same for pattern constraints, where the pattern constraints
// are collated by pattern equality.
// - a further refinement would collate patterns by ranges.
//
// For all these refinements it would be necessary to have well-working
// structure sharing so as to not repeatedly recompute optional arcs.
func equalOptional(ctx *OpContext, x, y *Vertex) bool {
return verifyStructs(x, y) && verifyStructs(y, x)
}

func verifyStructs(x, y *Vertex) bool {
outer:
for _, s := range x.Structs {
if !s.StructLit.HasOptional() {
continue
}
for _, t := range y.Structs {
if s.StructLit == t.StructLit {
continue outer
}
}
return false
}
return true
}

func equalTerminal(ctx *OpContext, v, w Value) bool {
if v == w {
return true
Expand Down

0 comments on commit ae1203c

Please sign in to comment.