this repo has no description
0
fork

Configure Feed

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

cue/errors: avoid simple duplication when gathering errors

The (benchmark) test case added caused immense duplication of errors
(over 43 million). The cause is unclear, but it's suspected a bug in
comprehensions. The solution here is to detect, in errors.Append, that
the two errors are the same, and if so, avoid creating a list of both.

Fixes #3307

Signed-off-by: Matthew Sackman <matthew@cue.works>
Change-Id: I1cb3baf00888072c5a4811f9acc95fac9ed49d4b
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1199401
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+93 -208
+12 -6
cue/errors/errors.go
··· 274 274 275 275 // Append combines two errors, flattening Lists as necessary. 276 276 func Append(a, b Error) Error { 277 - switch x := a.(type) { 277 + switch a := a.(type) { 278 278 case nil: 279 279 return b 280 280 case list: 281 - return appendToList(x, b) 281 + return appendToList(a, b) 282 282 } 283 - // Preserve order of errors. 284 - list := appendToList(nil, a) 285 - list = appendToList(list, b) 286 - return list 283 + switch b := b.(type) { 284 + case nil: 285 + return a 286 + case list: 287 + return appendToList(list{a}, b) 288 + } 289 + if a == b { 290 + return a 291 + } 292 + return list{a, b} 287 293 } 288 294 289 295 // Errors reports the individual errors associated with an error, which is
+69
cue/testdata/benchmarks/issue3307.txtar
··· 1 + -- in.cue -- 2 + if _request.enabled { 3 + r1: { 4 + k1: 0 5 + k2: 0 6 + k3: 0 7 + k4: 0 8 + k5: 0 9 + k6: 0 10 + k7: 0 11 + k8: 0 12 + k9: 0 13 + k10: 0 14 + k11: 0 15 + k12: 0 16 + k13: 0 17 + k14: 0 18 + k15: 0 19 + k16: 0 20 + k17: 0 21 + } 22 + } 23 + 24 + _request: enabled: _ 25 + -- out/eval/stats -- 26 + Leaks: 0 27 + Freed: 21 28 + Reused: 16 29 + Allocs: 5 30 + Retain: 72 31 + 32 + Unifications: 21 33 + Conjuncts: 3 34 + Disjuncts: 93 35 + -- out/eval -- 36 + (_|_){ 37 + // [incomplete] incomplete bool: _ 38 + _request: (struct){ 39 + enabled: (_){ _ } 40 + } 41 + } 42 + -- out/compile -- 43 + --- in.cue 44 + { 45 + if 〈0;_request〉.enabled { 46 + r1: { 47 + k1: 0 48 + k2: 0 49 + k3: 0 50 + k4: 0 51 + k5: 0 52 + k6: 0 53 + k7: 0 54 + k8: 0 55 + k9: 0 56 + k10: 0 57 + k11: 0 58 + k12: 0 59 + k13: 0 60 + k14: 0 61 + k15: 0 62 + k16: 0 63 + k17: 0 64 + } 65 + } 66 + _request: { 67 + enabled: _ 68 + } 69 + }
+2 -2
cue/testdata/eval/dynamic_field.txtar
··· 164 164 // [incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string): 165 165 // ./in.cue:59:8 166 166 // ./in.cue:59:11 167 - // noCycleError.foo.bar.entries: key value of dynamic field must be concrete, found _|_(invalid interpolation: noCycleError.foo.baz.#ID: non-concrete value string (type string) (and 1 more errors)): 167 + // noCycleError.foo.bar.entries: key value of dynamic field must be concrete, found _|_(invalid interpolation: noCycleError.foo.baz.#ID: non-concrete value string (type string)): 168 168 // ./in.cue:61:22 169 169 } 170 170 #ID: (_|_){ ··· 201 201 // [incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string): 202 202 // ./in.cue:59:8 203 203 // ./in.cue:59:11 204 - + // noCycleError.foo.bar.entries: key value of dynamic field must be concrete, found _|_(invalid interpolation: noCycleError.foo.baz.#ID: non-concrete value string (type string) (and 1 more errors)): 204 + + // noCycleError.foo.bar.entries: key value of dynamic field must be concrete, found _|_(invalid interpolation: noCycleError.foo.baz.#ID: non-concrete value string (type string)): 205 205 + // ./in.cue:61:22 206 206 } 207 207 #ID: (_|_){
-113
internal/core/export/testdata/main/adt.txtar
··· 337 337 [errorListDef #Def] 338 338 [errorListDef 0] 339 339 [errorListDef 1] 340 - -- out/value-v3 -- 341 - == Simplified 342 - _|_ // e3: index out of range [2] with length 2 343 - == Raw 344 - _|_ // e3: index out of range [2] with length 2 345 - == Final 346 - _|_ // e3: index out of range [2] with length 2 347 - == All 348 - { 349 - @foo(bar) 350 - p1: {} 351 - d1: { 352 - foobar: int 353 - } 354 - bar: "bar" 355 - d2: { 356 - foobar: { 357 - name: "xx" 358 - foo: "xx" 359 - } 360 - } 361 - 362 - // Issue #1910 363 - a: _ 364 - comp: { 365 - for k, v in [0] 366 - let w = v { 367 - "\(a)": w 368 - "bar": w 369 - } 370 - } 371 - bytes: '\xeb \x1a\xf5\xaa\xf0\xd6\x06)' 372 - c1: true 373 - s1: """ 374 - multi 375 - bar 376 - line 377 - """ 378 - l1: [3, ...int] 379 - l2: [...int] 380 - l3: [] 381 - l4: [1, 2] 382 - l5: { 383 - #foo: int 384 - [1, 3] 385 - } 386 - #foo: int 387 - l6: { 388 - #foo: int 389 - [1, 3] 390 - } 391 - n1: 1.0 392 - n10: 10 393 - 394 - // t is true 395 - t: true 396 - e1: <1.0 397 - e2: >1.0 & <10 398 - e3: _|_ // e3: index out of range [2] with length 2 399 - e4: _|_ // e4: index 3 out of range (and 1 more errors) 400 - e5: _|_ // e3: index out of range [2] with length 2 (and 1 more errors) 401 - e6: false 402 - e7: true 403 - e8?: true 404 - m1: { 405 - // foo is an optional field 406 - foo?: 3 407 - 408 - // bar is a field 409 - bar: 4 410 - 411 - // baz is a required field. 412 - baz!: 5 413 - } 414 - y1: { 415 - src: [1, 2, 3] 416 - foo0: 1 417 - bar1: 2 418 - bar2: 3 419 - foo1: 2 420 - x: [1, 2, 3] 421 - foo2: 3 422 - } 423 - preserveKeyFieldInComprehension: 1 424 - errorStructDef: { 425 - a: 1 426 - b: _|_ // errorStructDef.b: conflicting values 2 and 1 427 - #Def: 1 428 - } 429 - errorList: [1, _|_] 430 - x: int 431 - errorListDef: { 432 - #Def: 1 433 - [1, _|_] 434 - } 435 - } 436 - == Eval 437 - _|_ // e3: index out of range [2] with length 2 438 - -- diff/-out/value-v3<==>+out/value -- 439 - diff old new 440 - --- old 441 - +++ new 442 - @@ -56,8 +56,8 @@ 443 - e1: <1.0 444 - e2: >1.0 & <10 445 - e3: _|_ // e3: index out of range [2] with length 2 446 - - e4: _|_ // e4: index 3 out of range 447 - - e5: _|_ // e3: index out of range [2] with length 2 448 - + e4: _|_ // e4: index 3 out of range (and 1 more errors) 449 - + e5: _|_ // e3: index out of range [2] with length 2 (and 1 more errors) 450 - e6: false 451 - e7: true 452 - e8?: true 453 340 -- diff/value/todo/p3 -- 454 341 Error message change. 455 342 -- out/value --
+9 -9
internal/core/export/testdata/main/let.txtar
··· 583 583 } 584 584 == Final 585 585 { 586 - comprehension: _|_ // comprehension: key value of dynamic field must be concrete, found _|_(invalid interpolation: invalid interpolation: comprehension.filepath: undefined field: name (and 1 more errors)) (and 2 more errors) 586 + comprehension: _|_ // comprehension: key value of dynamic field must be concrete, found _|_(invalid interpolation: invalid interpolation: comprehension.filepath: undefined field: name) (and 1 more errors) 587 587 complete: { 588 588 x: "a foo z" 589 589 run: { ··· 599 599 name: "two" 600 600 } 601 601 }] 602 - files: _|_ // files: key value of dynamic field must be concrete, found _|_(invalid interpolation: invalid interpolation: filepath: undefined field: name (and 1 more errors)) (and 5 more errors) 602 + files: _|_ // files: key value of dynamic field must be concrete, found _|_(invalid interpolation: invalid interpolation: filepath: undefined field: name) (and 3 more errors) 603 603 scoped: { 604 604 direct: { 605 605 a: 1 ··· 625 625 x: "foo" 626 626 incomplete: { 627 627 a: { 628 - x: _|_ // invalid interpolation: incomplete.a.x: non-concrete value string (type string) (and 1 more errors) 628 + x: _|_ // invalid interpolation: incomplete.a.x: non-concrete value string (type string) 629 629 run: { 630 630 a: string 631 631 } 632 632 } 633 633 b: { 634 - x: _|_ // invalid interpolation: incomplete.b.x: non-concrete value string (type string) (and 1 more errors) 634 + x: _|_ // invalid interpolation: incomplete.b.x: non-concrete value string (type string) 635 635 run: { 636 636 a: string 637 637 } 638 638 } 639 639 c: { 640 - x: _|_ // invalid interpolation: incomplete.c.x: non-concrete value string (type string) (and 1 more errors) 641 - x2: _|_ // invalid interpolation: incomplete.c.x2: non-concrete value string (type string) (and 1 more errors) 640 + x: _|_ // invalid interpolation: incomplete.c.x: non-concrete value string (type string) 641 + x2: _|_ // invalid interpolation: incomplete.c.x2: non-concrete value string (type string) 642 642 run: { 643 643 a: string 644 644 } ··· 647 647 } 648 648 } 649 649 d: { 650 - x: _|_ // invalid interpolation: incomplete.d.x: non-concrete value string (type string) (and 1 more errors) 651 - x2: _|_ // invalid interpolation: incomplete.d.x2: non-concrete value string (type string) (and 1 more errors) 650 + x: _|_ // invalid interpolation: incomplete.d.x: non-concrete value string (type string) 651 + x2: _|_ // invalid interpolation: incomplete.d.x2: non-concrete value string (type string) 652 652 run: { 653 653 a: string 654 654 } ··· 895 895 diff old new 896 896 --- old 897 897 +++ new 898 - @@ -216,72 +216,72 @@ 898 + @@ -216,23 +216,23 @@ 899 899 } 900 900 == Final 901 901 {
+1 -78
internal/core/export/testdata/main/simplify.txtar
··· 39 39 [additional] 40 40 [additional env] 41 41 [additional confs] 42 - -- out/value-v3 -- 43 - == Simplified 44 - { 45 - x: { 46 - y: int64 47 - } 48 - s: strings.MinRunes(4) & strings.MaxRunes(7) 49 - additional: { 50 - env: _ 51 - confs: { 52 - if env {} 53 - } 54 - } 55 - } 56 - == Raw 57 - { 58 - x: { 59 - y: >=-9223372036854775808 & <=9223372036854775807 & int 60 - } 61 - s: strings.MinRunes(4) & strings.MaxRunes(7) 62 - additional: { 63 - env: _ 64 - confs: { 65 - if env {} 66 - } 67 - } 68 - } 69 - == Final 70 - { 71 - x: { 72 - y: int64 73 - } 74 - s: strings.MinRunes(4) & strings.MaxRunes(7) 75 - additional: { 76 - env: _ 77 - confs: _|_ // additional.confs: incomplete bool: _ (and 1 more errors) 78 - } 79 - } 80 - == All 81 - { 82 - x: { 83 - y: int64 84 - } 85 - s: strings.MinRunes(4) & strings.MaxRunes(7) 86 - additional: { 87 - env: _ 88 - confs: { 89 - if env {} 90 - } 91 - } 92 - } 93 - == Eval 94 - { 95 - x: { 96 - y: >=-9223372036854775808 & <=9223372036854775807 & int 97 - } 98 - s: strings.MinRunes(4) & strings.MaxRunes(7) 99 - additional: { 100 - env: _ 101 - confs: { 102 - if env {} 103 - } 104 - } 105 - } 106 - -- diff/-out/value-v3<==>+out/value -- 107 - diff old new 108 - --- old 109 - +++ new 110 - @@ -32,7 +32,7 @@ 111 - s: strings.MinRunes(4) & strings.MaxRunes(7) 112 - additional: { 113 - env: _ 114 - - confs: _|_ // additional.confs: incomplete bool: _ (and 2 more errors) 115 - + confs: _|_ // additional.confs: incomplete bool: _ (and 1 more errors) 116 - } 117 - } 118 - == All 119 42 -- diff/value/explanation -- 120 43 Benign change in error message. 121 44 -- out/value -- ··· 153 76 s: strings.MinRunes(4) & strings.MaxRunes(7) 154 77 additional: { 155 78 env: _ 156 - confs: _|_ // additional.confs: incomplete bool: _ (and 2 more errors) 79 + confs: _|_ // additional.confs: incomplete bool: _ 157 80 } 158 81 } 159 82 == All