cue/errors: don't equate error messages without line info

Previously, if two messages had no line and path information,
the two were equated and one was erased.

Not it falls back to the error message.

Change-Id: I9dff793777c2384939dac0873729dc77981d165a
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6482
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/testdata/script/eval_errs.txt b/cmd/cue/cmd/testdata/script/eval_errs.txt
index c2ce221..933c97d 100644
--- a/cmd/cue/cmd/testdata/script/eval_errs.txt
+++ b/cmd/cue/cmd/testdata/script/eval_errs.txt
@@ -7,6 +7,9 @@
 bar: empty disjunction: conflicting values int and "str" (mismatched types int and string):
     ./errs.cue:5:10
     ./errs.cue:6:16
+bar: empty disjunction: conflicting values string and 2 (mismatched types string and int):
+    ./errs.cue:5:21
+    ./errs.cue:6:26
 x.q: conflicting values "hello" and "goodbye":
     ./errs.cue:1:4
     ./errs.cue:2:4
diff --git a/cue/errors/errors.go b/cue/errors/errors.go
index 63706e5..7a28c25 100644
--- a/cue/errors/errors.go
+++ b/cue/errors/errors.go
@@ -362,11 +362,7 @@
 	var last Error
 	i := 0
 	for _, e := range *p {
-		pos := e.Position()
-		if last == nil ||
-			pos.Filename() != last.Position().Filename() ||
-			pos.Line() != last.Position().Line() ||
-			!equalPath(e.Path(), last.Path()) {
+		if last == nil || !approximateEqual(last, e) {
 			last = e
 			(*p)[i] = e
 			i++
@@ -375,6 +371,17 @@
 	(*p) = (*p)[0:i]
 }
 
+func approximateEqual(a, b Error) bool {
+	aPos := a.Position()
+	bPos := b.Position()
+	if aPos == token.NoPos || bPos == token.NoPos {
+		return a.Error() == b.Error()
+	}
+	return aPos.Filename() == bPos.Filename() &&
+		aPos.Line() == bPos.Line() &&
+		equalPath(a.Path(), b.Path())
+}
+
 // An List implements the error interface.
 func (p list) Error() string {
 	format, args := p.Msg()
diff --git a/cuego/examples_test.go b/cuego/examples_test.go
index 257771e..afac635 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>)
-	// empty disjunction: conflicting values 5 and 2
+	// empty disjunction: conflicting values 5 and 2 (and 1 more errors)
 }
 
 func ExampleConstrain() {