diff --git a/cue/testdata/eval/disjunctioncross.txtar b/cue/testdata/eval/disjunctioncross.txtar index 92ab5f556..cf5261a4b 100644 --- a/cue/testdata/eval/disjunctioncross.txtar +++ b/cue/testdata/eval/disjunctioncross.txtar @@ -176,7 +176,7 @@ issue3967: { }) } -- out/errors.txt -- -[incomplete] issue3967.error.nested.out: undefined field: kind: +[cycle] issue3967.error.nested.out: undefined field: kind: ./in.cue:131:17 [cycle] issue3967.error.local.out.oneOrTwo.two: circular dependency in evaluation of conditionals: X.two.optional changed after evaluation: ./in.cue:150:10 diff --git a/internal/core/adt/errors.go b/internal/core/adt/errors.go index 2edbe0a70..d1bb69a6c 100644 --- a/internal/core/adt/errors.go +++ b/internal/core/adt/errors.go @@ -279,6 +279,13 @@ func (v *Vertex) reportFieldError(c *OpContext, pos token.Pos, f Feature, intMsg // If v is an error, we need to adopt the worst error. if b := v.Bottom(); b != nil && !isCyclePlaceholder(b) { code = b.Code + } else if s := v.state; s != nil && s.errs != nil && s.errs.Code == CycleError { + // Also check cycle errors in the state (e.g. from failed + // comprehension tasks) that have not yet been promoted to BaseValue. + // This ensures that when a comp fails due to a mutual cycle, lookups + // of fields on the same vertex report CycleError instead of + // IncompleteError, allowing validate to propagate the cycle. + code = s.errs.Code } else if !v.Accept(c, f) { code = EvalError }