Skip to content

Commit b0f7009

Browse files
moustafabclaude
andcommitted
fix(simplecue): handle CUE v0.16 single-branch Expr() in getReference for Type | *Default structs
In CUE v0.11, Expr() on a value like `VariableOption | *{...}` returned (NoOp, [typeVertex, defaultVertex]) — two expressions. getReference relied on len(exprs) == 2 to detect this pattern and extract exprs[0] as the named reference. In CUE v0.16, when the default struct is subsumed by the named type, Expr() filters the default branch and returns (NoOp, [typeVertex]) — a single expression. The len(exprs) != 2 guard caused an early return of false, so declareNode fell through to StructKind handling and iterated the concrete default's fields instead of the abstract type's fields, generating a wrong anonymous struct type rather than a reference to the named type. Fix: allow len(exprs) == 1 as a valid case when op == NoOp and the single branch has a reference path. We additionally confirm v.Default() succeeds to rule out unrelated single-expr NoOp values. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2a988bb commit b0f7009

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

internal/simplecue/generator.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,20 +426,33 @@ func getReference(v cue.Value) (bool, cue.Value, cue.Value) {
426426

427427
op, exprs := v.Expr()
428428

429-
if len(exprs) != 2 {
429+
if len(exprs) == 0 || len(exprs) > 2 {
430430
return false, v, v
431431
}
432432

433433
_, path = exprs[0].ReferencePath()
434434
if v.Kind() == cue.BottomKind && v.IncompleteKind() == cue.StructKind && path.String() != "" {
435435
// When a struct with defaults is completely filled, it usually has a NoOp op.
436+
// In CUE v0.16+, `A | *B` where B is subsumed by A may reduce Expr() to (NoOp, [A]),
437+
// filtering out the default branch entirely. We handle both the two-expr (v0.11) and
438+
// one-expr (v0.16) cases identically: return the type branch (exprs[0]) as the reference.
436439
if op == cue.NoOp {
437-
return true, exprs[0], v
440+
if len(exprs) == 1 {
441+
// v0.16: only the type branch remains in Expr(); confirm v still has a default.
442+
if _, ok := v.Default(); ok {
443+
return true, exprs[0], v
444+
}
445+
} else {
446+
// len(exprs) == 2: v0.11 behavior — both type branch and default struct present.
447+
return true, exprs[0], v
448+
}
438449
}
439450

440451
// Accepts [AStruct | *{ ... }] and skips [AStruct | BStruct]
441-
if _, ok := v.Default(); ok {
442-
return true, exprs[0], v
452+
if len(exprs) == 2 {
453+
if _, ok := v.Default(); ok {
454+
return true, exprs[0], v
455+
}
443456
}
444457
}
445458

0 commit comments

Comments
 (0)