this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/core/adt: fix error propagation bug in inline structs

Inline structs are not fully evaluated. This sometimes
led to error values not fully being propagated if the values
were not fully evaluated.

Fixes #3977

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: I936c662b580d5ea519a788c0103ba1cfc841e5b5
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1236065
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>

+48 -2
+28 -2
cue/testdata/eval/nonrooted.txtar
··· 11 11 out: x + 1 12 12 } 13 13 14 - err: (#fn & {x: 2}).out @test(eq, 3, incorrect) @test(err:todo, p=1, code=eval, 14 + err: (#fn & {x: 2}).out @test(err, code=eval, 15 15 contains="conflicting values", args=[1, 2]) 16 16 } 17 17 issue3977: inlineDisj1: { ··· 21 21 out: "value=\(x)" 22 22 } 23 23 24 - err: (#fn & {x: "invalid"}).out @test(eq, "value=invalid", incorrect) @test(err:todo, p=1, code=eval, contains="conflicting values") 24 + err: (#fn & {x: "invalid"}).out @test(err, code=eval, 25 + suberr=(code=eval, path=x, contains="conflicting values %s and %s", args=["2", "invalid"], pos=[-6:14, -4:8, 0:8, 0:18]), 26 + suberr=(code=eval, path=x, contains="conflicting values %s and %s", args=["3", "invalid"], pos=[-6:20, -4:8, 0:8, 0:18]), 27 + suberr=(code=eval, path=x, contains="conflicting values %s and %s", args=["4", "invalid"], pos=[-6:26, -4:8, 0:8, 0:18]), 28 + ) 25 29 } 26 30 issue3977: inlineDisj2: { 27 31 #NetworkID: 1 ··· 66 70 Conjuncts: 87 67 71 Disjuncts: 68 68 72 -- out/errors.txt -- 73 + [eval] x: conflicting values 1 and 2: 74 + ./in.cue:2:14 75 + ./in.cue:4:8 76 + ./in.cue:8:8 77 + ./in.cue:8:18 69 78 [incomplete] issue3977.inlineDisj1.#fn.out: invalid interpolation: unresolved disjunction "2" | "3" | "4" (type string): 79 + ./in.cue:15:8 80 + [eval] x: conflicting values "2" and "invalid": 81 + ./in.cue:12:14 82 + ./in.cue:14:8 83 + ./in.cue:18:8 84 + ./in.cue:18:18 85 + x: conflicting values "3" and "invalid": 86 + ./in.cue:12:20 87 + ./in.cue:14:8 88 + ./in.cue:18:8 89 + ./in.cue:18:18 90 + x: conflicting values "4" and "invalid": 91 + ./in.cue:12:26 92 + ./in.cue:14:8 93 + ./in.cue:18:8 94 + ./in.cue:18:18 95 + x: 3 errors in empty disjunction:: 70 96 ./in.cue:15:8 71 97 [eval] x: conflicting values 2 and 1: 72 98 ./in.cue:21:14
+6
internal/core/adt/context.go
··· 817 817 818 818 v := c.evaluate(arc, x, state) 819 819 820 + if arc.nonRooted && !allTasksFinished(s) { 821 + if t := c.current(); t != nil { 822 + t.node.deferred = append(t.node.deferred, s) 823 + } 824 + } 825 + 820 826 return v, c.ci 821 827 } 822 828 }
+14
internal/core/adt/sched.go
··· 286 286 // the indicate conditions. This can hold tasks from other nodes or tasks 287 287 // originating from this node itself. 288 288 blocking []*task 289 + 290 + // deferred tracks nodes that were not completed during computation and that 291 + // still need to be finalized. This is especially important for inline 292 + // structs, which may not be included in the output and thus the errors 293 + // would never be discovered. But it is also important for models where we 294 + // only do partial evaluation. 295 + deferred []*nodeContext 289 296 } 290 297 291 298 func (s *scheduler) clear() { ··· 745 752 t.err = nil 746 753 747 754 t.run.f(ctx, t, mode) 755 + 756 + for _, d := range t.node.deferred { 757 + d.node.CompleteArcsOnly(ctx) 758 + if b, ok := d.node.BaseValue.(*Bottom); ok { 759 + t.node.addBottom(b) 760 + } 761 + } 748 762 749 763 if t.state != taskWAITING { 750 764 t.blockedOn = nil