this repo has no description
0
fork

Configure Feed

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

internal/core/adt: refine cycle handling in LetReference.resolve

This fix addresses a regression where reordering fields in data files
caused spurious cycle errors. The original check was too restrictive,
only allowing early return of an arc if it was not being evaluated.

Allow returning a let arc early if it contains a cycle placeholder,
regardless of whether it is currently being evaluated.
This allows the caller to handle the cycle appropriately,
such as by allowing it in an interpolation if it eventually resolves.

We maintain the arcState nil check for arcs with no value yet (b == nil)
to prevent infinite recursion and hangs on cycles through 'let'.

Fixes #4244.

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

+80 -103
+8 -8
cue/testdata/benchmarks/issue2176.txtar
··· 58 58 "2": (datastream & {marker: length: 14}).marker.position 59 59 } 60 60 -- out/evalalpha/stats -- 61 - Leaks: 327 62 - Freed: 477 63 - Reused: 427 64 - Allocs: 377 61 + Leaks: 389 62 + Freed: 415 63 + Reused: 369 64 + Allocs: 435 65 65 Retain: 0 66 66 67 67 Unifications: 476 ··· 91 91 -MisalignedConjunct: 1216 92 92 - 93 93 -NumCloseIDs: 12 94 - +Leaks: 327 95 - +Freed: 477 96 - +Reused: 427 97 - +Allocs: 377 94 + +Leaks: 389 95 + +Freed: 415 96 + +Reused: 369 97 + +Allocs: 435 98 98 +Retain: 0 99 99 + 100 100 +Unifications: 476
+19 -42
cue/testdata/cycle/issue4244.txtar
··· 22 22 id: "foo" 23 23 } 24 24 -- out/evalalpha -- 25 - Errors: 26 - case2.subid: invalid value "foo:sub" (out of bound =~"^:sub$"): 27 - ./in.cue:8:10 28 - ./in.cue:11:9 29 - ./in.cue:20:9 30 - 31 - Result: 32 - (_|_){ 33 - // [eval] 25 + (struct){ 34 26 #schema: (#struct){ 35 27 let splits#1 = (_|_){ 36 - // [cycle] #schema.#ID: invalid interpolation: cycle with field: prefix: 28 + // [incomplete] #schema.prefix: invalid interpolation: index out of range [0] with length 1: 37 29 // ./in.cue:7:12 38 - // ./in.cue:7:16 30 + // ./in.cue:5:22 39 31 } 40 32 let prefix#2 = (_|_){ 41 33 // [incomplete] #schema.prefix: index out of range [0] with length 1: 42 34 // ./in.cue:5:22 43 35 } 44 36 #ID: (_|_){ 45 - // [cycle] #schema.#ID: invalid interpolation: cycle with field: prefix: 37 + // [incomplete] #schema.prefix: invalid interpolation: index out of range [0] with length 1: 46 38 // ./in.cue:7:12 47 - // ./in.cue:7:16 39 + // ./in.cue:5:22 48 40 } 49 41 #SubID: (_|_){ 50 - // [cycle] #schema.#ID: invalid interpolation: cycle with field: prefix: 42 + // [incomplete] #schema.prefix: invalid interpolation: index out of range [0] with length 1: 51 43 // ./in.cue:8:12 52 - // ./in.cue:7:16 44 + // ./in.cue:5:22 53 45 } 54 46 id: (_|_){ 55 - // [cycle] #schema.#ID: invalid interpolation: cycle with field: prefix: 47 + // [incomplete] #schema.prefix: invalid interpolation: index out of range [0] with length 1: 56 48 // ./in.cue:7:12 57 - // ./in.cue:7:16 49 + // ./in.cue:5:22 58 50 } 59 51 subid: (_|_){ 60 - // [cycle] #schema.#ID: invalid interpolation: cycle with field: prefix: 52 + // [incomplete] #schema.prefix: invalid interpolation: index out of range [0] with length 1: 61 53 // ./in.cue:8:12 62 - // ./in.cue:7:16 54 + // ./in.cue:5:22 63 55 } 64 56 } 65 57 case1: (#struct){ ··· 72 64 #ID: (string){ =~"^foo$" } 73 65 #SubID: (string){ =~"^foo:sub$" } 74 66 } 75 - case2: (_|_){ 76 - // [eval] 77 - subid: (_|_){ 78 - // [eval] case2.subid: invalid value "foo:sub" (out of bound =~"^:sub$"): 79 - // ./in.cue:8:10 80 - // ./in.cue:11:9 81 - // ./in.cue:20:9 82 - } 83 - id: (_|_){ 84 - // [cycle] case2.id: invalid interpolation: cycle with field: prefix: 85 - // ./in.cue:7:12 86 - // ./in.cue:7:16 87 - } 88 - let splits#1 = (_|_){ 89 - // [cycle] case2.id: invalid interpolation: cycle with field: prefix: 90 - // ./in.cue:7:12 91 - // ./in.cue:7:16 67 + case2: (#struct){ 68 + subid: (string){ "foo:sub" } 69 + id: (string){ "foo" } 70 + let splits#1 = (#list){ 71 + 0: (string){ "foo" } 92 72 } 93 - let prefix#2 = (_|_){ 94 - // [cycle] case2.id: cycle with field: prefix: 95 - // ./in.cue:7:16 96 - } 97 - #ID: (string){ =~"^$" } 98 - #SubID: (string){ =~"^:sub$" } 73 + let prefix#2 = (string){ "foo" } 74 + #ID: (string){ =~"^foo$" } 75 + #SubID: (string){ =~"^foo:sub$" } 99 76 } 100 77 } 101 78 -- out/compile --
+12 -12
cue/testdata/definitions/typocheck.txtar
··· 628 628 out: #C & #B 629 629 } 630 630 -- out/evalalpha/stats -- 631 - Leaks: 73 631 + Leaks: 77 632 632 Freed: 863 633 633 Reused: 815 634 - Allocs: 121 634 + Allocs: 125 635 635 Retain: 0 636 636 637 - Unifications: 765 638 - Conjuncts: 1529 637 + Unifications: 767 638 + Conjuncts: 1532 639 639 Disjuncts: 84 640 640 Notifications: 7 641 641 642 - NumCloseIDs: 440 642 + NumCloseIDs: 441 643 643 644 - ConjunctInfos: 1115 644 + ConjunctInfos: 1118 645 645 MaxConjunctInfos: 5 646 646 MaxReqSets: 9 647 647 MaxRedirect: 2 ··· 661 661 -Disjuncts: 1209 662 662 - 663 663 -NumCloseIDs: 3 664 - +Leaks: 73 664 + +Leaks: 77 665 665 +Freed: 863 666 666 +Reused: 815 667 - +Allocs: 121 667 + +Allocs: 125 668 668 +Retain: 0 669 669 + 670 - +Unifications: 765 671 - +Conjuncts: 1529 670 + +Unifications: 767 671 + +Conjuncts: 1532 672 672 +Disjuncts: 84 673 673 +Notifications: 7 674 674 + 675 - +NumCloseIDs: 440 675 + +NumCloseIDs: 441 676 676 + 677 - +ConjunctInfos: 1115 677 + +ConjunctInfos: 1118 678 678 +MaxConjunctInfos: 5 679 679 +MaxReqSets: 9 680 680 +MaxRedirect: 2
+6 -6
cue/testdata/disjunctions/errors.txtar
··· 151 151 } 152 152 } 153 153 -- out/evalalpha/stats -- 154 - Leaks: 33 154 + Leaks: 31 155 155 Freed: 207 156 - Reused: 188 157 - Allocs: 52 156 + Reused: 187 157 + Allocs: 51 158 158 Retain: 0 159 159 160 160 Unifications: 116 ··· 181 181 -MisalignedConjunct: 1 182 182 - 183 183 -NumCloseIDs: 11 184 - +Leaks: 33 184 + +Leaks: 31 185 185 +Freed: 207 186 - +Reused: 188 187 - +Allocs: 52 186 + +Reused: 187 187 + +Allocs: 51 188 188 +Retain: 0 189 189 + 190 190 +Unifications: 116
+8 -8
cue/testdata/eval/counters.txtar
··· 250 250 } 251 251 } 252 252 -- out/evalalpha/stats -- 253 - Leaks: 73 253 + Leaks: 67 254 254 Freed: 150 255 255 Reused: 133 256 - Allocs: 90 256 + Allocs: 84 257 257 Retain: 0 258 258 259 - Unifications: 165 260 - Conjuncts: 268 259 + Unifications: 160 260 + Conjuncts: 261 261 261 Disjuncts: 36 262 262 263 263 NumCloseIDs: 60 ··· 279 279 -MisalignedConjunct: 10 280 280 - 281 281 -NumCloseIDs: 16 282 - +Leaks: 73 282 + +Leaks: 67 283 283 +Freed: 150 284 284 +Reused: 133 285 - +Allocs: 90 285 + +Allocs: 84 286 286 +Retain: 0 287 287 + 288 - +Unifications: 165 289 - +Conjuncts: 268 288 + +Unifications: 160 289 + +Conjuncts: 261 290 290 +Disjuncts: 36 291 291 + 292 292 +NumCloseIDs: 60
+16 -16
cue/testdata/eval/issue3672.txtar
··· 300 300 } 301 301 } 302 302 -- out/evalalpha/stats -- 303 - Leaks: 344 304 - Freed: 1758 305 - Reused: 1700 306 - Allocs: 402 303 + Leaks: 345 304 + Freed: 1760 305 + Reused: 1702 306 + Allocs: 403 307 307 Retain: 0 308 308 309 309 Unifications: 386 310 - Conjuncts: 2349 311 - Disjuncts: 574 310 + Conjuncts: 2354 311 + Disjuncts: 576 312 312 313 - NumCloseIDs: 819 313 + NumCloseIDs: 821 314 314 315 - ConjunctInfos: 885 315 + ConjunctInfos: 886 316 316 MaxConjunctInfos: 7 317 317 MaxReqSets: 15 318 318 MaxRedirect: 6 ··· 330 330 -Unifications: 140273 331 331 -Conjuncts: 468967 332 332 -Disjuncts: 330375 333 - +Leaks: 344 334 - +Freed: 1758 335 - +Reused: 1700 336 - +Allocs: 402 333 + +Leaks: 345 334 + +Freed: 1760 335 + +Reused: 1702 336 + +Allocs: 403 337 337 +Retain: 0 338 338 + 339 339 +Unifications: 386 340 - +Conjuncts: 2349 341 - +Disjuncts: 574 340 + +Conjuncts: 2354 341 + +Disjuncts: 576 342 342 + 343 - +NumCloseIDs: 819 343 + +NumCloseIDs: 821 344 344 + 345 - +ConjunctInfos: 885 345 + +ConjunctInfos: 886 346 346 +MaxConjunctInfos: 7 347 347 +MaxReqSets: 15 348 348 +MaxRedirect: 6
+10 -10
cue/testdata/eval/issue3801.txtar
··· 97 97 } 98 98 } 99 99 -- out/evalalpha/stats -- 100 - Leaks: 36 100 + Leaks: 40 101 101 Freed: 200 102 102 Reused: 171 103 - Allocs: 65 103 + Allocs: 69 104 104 Retain: 0 105 105 106 - Unifications: 167 107 - Conjuncts: 324 106 + Unifications: 169 107 + Conjuncts: 327 108 108 Disjuncts: 14 109 109 110 - NumCloseIDs: 76 110 + NumCloseIDs: 77 111 111 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- 112 112 diff old new 113 113 --- old ··· 122 122 -Unifications: 332 123 123 -Conjuncts: 783 124 124 -Disjuncts: 373 125 - +Leaks: 36 125 + +Leaks: 40 126 126 +Freed: 200 127 127 +Reused: 171 128 - +Allocs: 65 128 + +Allocs: 69 129 129 +Retain: 0 130 130 + 131 - +Unifications: 167 132 - +Conjuncts: 324 131 + +Unifications: 169 132 + +Conjuncts: 327 133 133 +Disjuncts: 14 134 134 + 135 - +NumCloseIDs: 76 135 + +NumCloseIDs: 77 136 136 -- out/eval/stats -- 137 137 Leaks: 98 138 138 Freed: 260
+1 -1
internal/core/adt/expr.go
··· 782 782 // If the arc has a running state, we must use the cache mechanism 783 783 // to properly detect and handle cycles. 784 784 arcState := arc.getState(ctx) 785 - if !arc.MultiLet && (b == nil || isCyclePlaceholder(b)) && arcState == nil { 785 + if !arc.MultiLet && ((b == nil && arcState == nil) || isCyclePlaceholder(b)) { 786 786 return arc 787 787 } 788 788