From dfc376ffcbbf6ccfe24436342060fed7c8d5d313 Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Wed, 27 May 2026 08:48:22 +0200 Subject: [PATCH] internal/core/compile: isolate txtar goldens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move compile golden outputs out of cue/testdata and into the compile package's own testdata tree, with CUE_UPDATE=1 syncing inputs from cue/testdata into testdata/sync before regenerating compile outputs. Fixes #4344 Signed-off-by: Marcel van Lohuizen Change-Id: Iceed6daa3e18e568dd402662658b51457814cfec Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1237923 Reviewed-by: Daniel Martí TryBot-Result: CUEcueckoo Unity-Result: CUE porcuepine --- cue/testdata/basicrewrite/000_errors.txtar | 11 - cue/testdata/basicrewrite/001_regexp.txtar | 23 - .../basicrewrite/002_arithmetic.txtar | 27 - .../003_integer-specific_arithmetic.txtar | 28 - cue/testdata/basicrewrite/004_booleans.txtar | 10 - .../basicrewrite/005_boolean_arithmetic.txtar | 10 - .../basicrewrite/006_basic_type.txtar | 12 - .../basicrewrite/007_strings_and_bytes.txtar | 12 - cue/testdata/basicrewrite/008_escaping.txtar | 6 - cue/testdata/basicrewrite/009_reference.txtar | 18 - cue/testdata/basicrewrite/010_lists.txtar | 50 - cue/testdata/basicrewrite/012_selecting.txtar | 31 - cue/testdata/basicrewrite/013_obj_unify.txtar | 42 - .../basicrewrite/014_disjunctions.txtar | 23 - cue/testdata/basicrewrite/015_types.txtar | 13 - .../basicrewrite/016_comparison.txtar | 596 ---- cue/testdata/basicrewrite/017_null.txtar | 11 - .../018_self-reference_cycles.txtar | 71 - .../019_resolved_self-reference_cycles.txtar | 78 - ...lved_self-reference_cycles__Issue_19.txtar | 11 - .../basicrewrite/aliases/aliases.txtar | 14 - cue/testdata/benchmarks/chain.txtar | 1004 ------ cue/testdata/benchmarks/cycle.txtar | 23 - cue/testdata/benchmarks/cycleshare.txtar | 77 - cue/testdata/benchmarks/decimal.txtar | 15 - cue/testdata/benchmarks/deduparc.txtar | 27 - cue/testdata/benchmarks/dedupelem.txtar | 81 - cue/testdata/benchmarks/disjunctelim.txtar | 126 - cue/testdata/benchmarks/disjunction.txtar | 110 - .../benchmarks/inlinedisjunction.txtar | 40 - cue/testdata/benchmarks/issue1684.txtar | 112 - cue/testdata/benchmarks/issue2176.txtar | 48 - cue/testdata/benchmarks/issue3307.txtar | 28 - cue/testdata/benchmarks/issue3334.txtar | 68 - cue/testdata/benchmarks/issue3514.txtar | 50 - cue/testdata/benchmarks/issue3517.txtar | 63 - cue/testdata/benchmarks/issue3633.txtar | 144 - cue/testdata/benchmarks/issue572.txtar | 14 - cue/testdata/benchmarks/listdedup.txtar | 37 - cue/testdata/benchmarks/listdisj.txtar | 26 - .../benchmarks/mergeddisjunction.txtar | 56 - cue/testdata/benchmarks/share.txtar | 41 - cue/testdata/benchmarks/sharefg.txtar | 264 -- cue/testdata/benchmarks/sort.txtar | 62 - cue/testdata/benchmarks/typocheck.txtar | 31 - cue/testdata/builtins/056_issue314.txtar | 26 - cue/testdata/builtins/all.txtar | 38 - cue/testdata/builtins/and.txtar | 34 - cue/testdata/builtins/args.txtar | 21 - cue/testdata/builtins/closeall.txtar | 45 - cue/testdata/builtins/closed.txtar | 243 -- cue/testdata/builtins/default.txtar | 22 - cue/testdata/builtins/error.txtar | 66 - cue/testdata/builtins/export.txtar | 33 - cue/testdata/builtins/incomplete.txtar | 99 - cue/testdata/builtins/intdiv.txtar | 32 - cue/testdata/builtins/issue299.txtar | 13 - cue/testdata/builtins/issue4208.txtar | 16 - cue/testdata/builtins/issue490.txtar | 11 - cue/testdata/builtins/issue_3567.txtar | 10 - cue/testdata/builtins/list/issue332.txtar | 19 - cue/testdata/builtins/list/sort.txtar | 14 - cue/testdata/builtins/matchif.txtar | 45 - cue/testdata/builtins/matchn.txtar | 647 ---- cue/testdata/builtins/or.txtar | 36 - cue/testdata/builtins/reclose.txtar | 193 -- cue/testdata/builtins/validators.txtar | 314 -- cue/testdata/builtins/versionchk.txtar | 7 - .../choosedefault/000_pick_first.txtar | 12 - .../001_simple_disambiguation_conflict.txtar | 7 - .../002_associativity_of_defaults.txtar | 71 - cue/testdata/compile/alias.txtar | 9 - cue/testdata/compile/err_top.txtar | 41 - cue/testdata/compile/erralias.txtar | 18 - cue/testdata/compile/experiment.txtar | 9 - cue/testdata/compile/fields.txtar | 8 - cue/testdata/compile/files.txtar | 18 - cue/testdata/compile/json.txtar | 16 - cue/testdata/compile/labels.txtar | 60 - cue/testdata/compile/let.txtar | 127 - cue/testdata/compile/postfixexpr.txtar | 18 - cue/testdata/compile/scope.txtar | 45 - .../015_list_comprehension.txtar | 27 - .../045_comprehension_and_skipped_field.txtar | 18 - .../comprehensions/checkdefined.txtar | 192 -- cue/testdata/comprehensions/closed.txtar | 130 - .../comprehensions/deferfieldsetknown.txtar | 28 - cue/testdata/comprehensions/else.txtar | 288 -- .../comprehensions/else_compile_errors.txtar | 30 - .../comprehensions/else_on_error.txtar | 25 - cue/testdata/comprehensions/errors.txtar | 39 - cue/testdata/comprehensions/fields.txtar | 51 - cue/testdata/comprehensions/for.txtar | 41 - cue/testdata/comprehensions/iferror.txtar | 98 - cue/testdata/comprehensions/incomplete.txtar | 16 - cue/testdata/comprehensions/issue1732.txtar | 139 - cue/testdata/comprehensions/issue2171.txtar | 12 - cue/testdata/comprehensions/issue2481.txtar | 52 - cue/testdata/comprehensions/issue287.txtar | 20 - cue/testdata/comprehensions/issue293.txtar | 38 - cue/testdata/comprehensions/issue3762.txtar | 115 - cue/testdata/comprehensions/issue3763.txtar | 90 - cue/testdata/comprehensions/issue3929.txtar | 104 - cue/testdata/comprehensions/issue436.txtar | 21 - cue/testdata/comprehensions/issue507.txtar | 30 - cue/testdata/comprehensions/issue837.txtar | 80 - cue/testdata/comprehensions/issue843.txtar | 49 - cue/testdata/comprehensions/lists.txtar | 17 - cue/testdata/comprehensions/multi.txtar | 46 - cue/testdata/comprehensions/nested.txtar | 105 - cue/testdata/comprehensions/nested2.txtar | 367 --- cue/testdata/comprehensions/nestembed.txtar | 29 - .../comprehensions/open_iter_writeback.txtar | 35 - .../comprehensions/optional_ref_yield.txtar | 36 - cue/testdata/comprehensions/pushdown.txtar | 1444 --------- cue/testdata/comprehensions/try.txtar | 549 ---- .../comprehensions/try_compile_errors.txtar | 45 - ...015_reference_across_tuples_and_back.txtar | 14 - .../021_delayed_constraint_failure.txtar | 9 - cue/testdata/cycle/023_reentrance.txtar | 38 - ...e_references_that_would_be_ambiguous.txtar | 21 - ...erence_cycles_conflicts_with_strings.txtar | 11 - ...f-reference_cycles_with_disjunctions.txtar | 19 - ...lf-reference_cycles_with_disjunction.txtar | 37 - ...ycles_with_disjunction_with_defaults.txtar | 32 - cue/testdata/cycle/builtins.txtar | 410 --- cue/testdata/cycle/chain.txtar | 295 -- cue/testdata/cycle/compbottom.txtar | 46 - cue/testdata/cycle/compbottom2.txtar | 441 --- cue/testdata/cycle/compbottomnofinal.txtar | 84 - cue/testdata/cycle/comprehension.txtar | 729 ----- cue/testdata/cycle/constraints.txtar | 383 --- cue/testdata/cycle/cycle_with_bounds.txtar | 11 - cue/testdata/cycle/disjunction.txtar | 68 - cue/testdata/cycle/evaluate.txtar | 145 - cue/testdata/cycle/expression.txtar | 103 - cue/testdata/cycle/freeze.txtar | 144 - cue/testdata/cycle/inline.txtar | 246 -- cue/testdata/cycle/inline_non_recursive.txtar | 184 -- cue/testdata/cycle/issue1960.txtar | 98 - cue/testdata/cycle/issue241.txtar | 35 - cue/testdata/cycle/issue242.txtar | 198 -- cue/testdata/cycle/issue2526.txtar | 9 - cue/testdata/cycle/issue306.txtar | 10 - cue/testdata/cycle/issue3118.txtar | 32 - cue/testdata/cycle/issue3527.txtar | 32 - cue/testdata/cycle/issue3570.txtar | 9 - cue/testdata/cycle/issue3571.txtar | 48 - cue/testdata/cycle/issue3827.txtar | 38 - cue/testdata/cycle/issue4203.txtar | 40 - cue/testdata/cycle/issue4210.txtar | 43 - cue/testdata/cycle/issue4228.txtar | 101 - cue/testdata/cycle/issue4230.txtar | 25 - cue/testdata/cycle/issue4244.txtar | 20 - cue/testdata/cycle/issue4253.txtar | 25 - cue/testdata/cycle/issue429.txtar | 45 - cue/testdata/cycle/issue494.txtar | 79 - cue/testdata/cycle/issue502.txtar | 83 - cue/testdata/cycle/issue990.txtar | 95 - cue/testdata/cycle/patterns.txtar | 34 - cue/testdata/cycle/self.txtar | 488 --- cue/testdata/cycle/structural.txtar | 835 ----- cue/testdata/cycle/with_defaults.txtar | 17 - .../026_combined_definitions.txtar | 48 - ...e_closing_starting_at_non-definition.txtar | 25 - .../032_definitions_with_embedding.txtar | 26 - cue/testdata/definitions/033_Issue_#153.txtar | 24 - .../036_closing_with_failed_optional.txtar | 36 - .../036_optionals_in_open_structs.txtar | 16 - .../037_closing_with_comprehensions.txtar | 45 - .../037_conjunction_of_optional_sets.txtar | 22 - ...inue_recursive_closing_for_optionals.txtar | 14 - .../039_augment_closed_optionals.txtar | 26 - cue/testdata/definitions/comprehensions.txtar | 15 - cue/testdata/definitions/defembed.txtar | 19 - cue/testdata/definitions/dynamic.txtar | 37 - cue/testdata/definitions/embed.txtar | 84 - cue/testdata/definitions/exclude.txtar | 100 - cue/testdata/definitions/explicitopen.txtar | 559 ---- cue/testdata/definitions/fields.txtar | 444 --- cue/testdata/definitions/files.txtar | 25 - cue/testdata/definitions/hidden.txtar | 31 - cue/testdata/definitions/issue271.txtar | 17 +- cue/testdata/definitions/issue317.txtar | 57 - cue/testdata/definitions/issue320.txtar | 15 - cue/testdata/definitions/issue342.txtar | 24 - cue/testdata/definitions/issue359.txtar | 54 - cue/testdata/definitions/issue367.txtar | 26 - cue/testdata/definitions/issue370.txtar | 18 - cue/testdata/definitions/issue3834.txtar | 121 - cue/testdata/definitions/issue3851.txtar | 25 - cue/testdata/definitions/issue4000.txtar | 58 - cue/testdata/definitions/issue419.txtar | 19 - cue/testdata/definitions/issue471.txtar | 21 - cue/testdata/definitions/issue483.txtar | 24 - cue/testdata/definitions/issue491.txtar | 39 - cue/testdata/definitions/issue493.txtar | 16 - cue/testdata/definitions/issue496.txtar | 11 - cue/testdata/definitions/issue497.txtar | 13 - cue/testdata/definitions/issue533.txtar | 18 - cue/testdata/definitions/issue539.txtar | 14 - cue/testdata/definitions/list.txtar | 18 - cue/testdata/definitions/root1.txtar | 9 - cue/testdata/definitions/root2.txtar | 7 - cue/testdata/definitions/root3.txtar | 11 - cue/testdata/definitions/root4.txtar | 13 - cue/testdata/definitions/root5.txtar | 28 - cue/testdata/definitions/root6.txtar | 26 - cue/testdata/definitions/root7.txtar | 14 - cue/testdata/definitions/root8.txtar | 26 - cue/testdata/definitions/typocheck.txtar | 1104 ------- cue/testdata/definitions/visibility.txtar | 12 - cue/testdata/disjunctions/019_ips.txtar | 34 - cue/testdata/disjunctions/confluence.txtar | 27 - cue/testdata/disjunctions/crossembed.txtar | 10 - cue/testdata/disjunctions/defaults.txtar | 28 - cue/testdata/disjunctions/defembed.txtar | 39 - cue/testdata/disjunctions/discriminator.txtar | 107 - cue/testdata/disjunctions/edge.txtar | 146 - cue/testdata/disjunctions/elimination.txtar | 1322 -------- cue/testdata/disjunctions/embed.txtar | 116 - cue/testdata/disjunctions/errors.txtar | 230 -- cue/testdata/disjunctions/incomplete.txtar | 72 - cue/testdata/disjunctions/issue2209.txtar | 124 - cue/testdata/disjunctions/issue3850.txtar | 95 - cue/testdata/disjunctions/issue3857.txtar | 86 - cue/testdata/disjunctions/issue4339.txtar | 13 - cue/testdata/disjunctions/nested.txtar | 77 - cue/testdata/disjunctions/operands.txtar | 41 - cue/testdata/disjunctions/propagate_err.txtar | 38 - cue/testdata/disjunctions/resolve.txtar | 34 - cue/testdata/disjunctions/specdeviation.txtar | 47 - cue/testdata/eval/basictypes.txtar | 54 - cue/testdata/eval/bounds.txtar | 321 -- cue/testdata/eval/bulk.txtar | 265 -- cue/testdata/eval/closed_disjunction.txtar | 22 - cue/testdata/eval/closedness.txtar | 1317 -------- cue/testdata/eval/comprehensions.txtar | 171 - cue/testdata/eval/conflicts.txtar | 22 - cue/testdata/eval/conjuncts.txtar | 92 - cue/testdata/eval/counters.txtar | 149 - cue/testdata/eval/cycles_ref.txtar | 15 - cue/testdata/eval/deref.txtar | 50 - cue/testdata/eval/discontinuous.txtar | 30 - cue/testdata/eval/disjselfcycle.txtar | 97 - cue/testdata/eval/disjunctioncross.txtar | 129 - cue/testdata/eval/disjunctions.txtar | 569 ---- cue/testdata/eval/dynamic_field.txtar | 110 - cue/testdata/eval/embed.txtar | 189 -- cue/testdata/eval/errunifiy.txtar | 8 - cue/testdata/eval/expressions.txtar | 35 - cue/testdata/eval/fields.txtar | 17 - cue/testdata/eval/incomplete.txtar | 41 - cue/testdata/eval/incompleteperm.txtar | 32 - cue/testdata/eval/insertion.txtar | 130 - cue/testdata/eval/issue1640.txtar | 25 - cue/testdata/eval/issue1886.txtar | 25 - cue/testdata/eval/issue2146.txtar | 51 - cue/testdata/eval/issue2235.txtar | 132 - cue/testdata/eval/issue2337.txtar | 38 - cue/testdata/eval/issue2550.txtar | 10 - cue/testdata/eval/issue2649.txtar | 5 - cue/testdata/eval/issue285.txtar | 20 - cue/testdata/eval/issue295.txtar | 10 - cue/testdata/eval/issue3301.txtar | 25 - cue/testdata/eval/issue3330.txtar | 39 - cue/testdata/eval/issue349.txtar | 14 - cue/testdata/eval/issue353.txtar | 16 - cue/testdata/eval/issue3672.txtar | 176 - cue/testdata/eval/issue3688.txtar | 48 - cue/testdata/eval/issue3709.txtar | 7 - cue/testdata/eval/issue3801.txtar | 142 - cue/testdata/eval/issue3805.txtar | 97 - cue/testdata/eval/issue3813.txtar | 17 - cue/testdata/eval/issue3905.txtar | 56 - cue/testdata/eval/issue3919.txtar | 117 - cue/testdata/eval/issue494.txtar | 53 - cue/testdata/eval/issue500.txtar | 42 - cue/testdata/eval/issue545.txtar | 27 - cue/testdata/eval/issue599.txtar | 78 - cue/testdata/eval/issue962.txtar | 10 - cue/testdata/eval/let.txtar | 200 -- cue/testdata/eval/letjoin.txtar | 152 - cue/testdata/eval/lists.txtar | 31 - cue/testdata/eval/merge.txtar | 38 - cue/testdata/eval/nonrooted.txtar | 64 - cue/testdata/eval/notify.txtar | 39 - cue/testdata/eval/openinline.txtar | 93 - cue/testdata/eval/required.txtar | 109 - cue/testdata/eval/resolve_basic.txtar | 13 - cue/testdata/eval/resolve_env.txtar | 27 - cue/testdata/eval/selectors.txtar | 27 - cue/testdata/eval/sharing.txtar | 337 -- cue/testdata/eval/shortcircuit.txtar | 16 - cue/testdata/eval/shortcircuit_noexp.txtar | 6 - cue/testdata/eval/structs.txtar | 7 - cue/testdata/eval/unify.txtar | 25 - cue/testdata/eval/v0.7.txtar | 507 --- cue/testdata/eval/v0.7errorprop.txtar | 9 - cue/testdata/export/000.txtar | 5 - cue/testdata/export/001.txtar | 5 - cue/testdata/export/002.txtar | 5 - cue/testdata/export/003.txtar | 5 - cue/testdata/export/004.txtar | 10 - cue/testdata/export/005.txtar | 12 - cue/testdata/export/006.txtar | 14 - cue/testdata/export/007.txtar | 14 - cue/testdata/export/008.txtar | 9 - cue/testdata/export/009.txtar | 27 - cue/testdata/export/010.txtar | 27 - cue/testdata/export/011.txtar | 11 - cue/testdata/export/012.txtar | 8 - cue/testdata/export/013.txtar | 7 - cue/testdata/export/014.txtar | 7 - cue/testdata/export/015.txtar | 10 - cue/testdata/export/016.txtar | 19 - cue/testdata/export/017.txtar | 15 - cue/testdata/export/018.txtar | 15 - cue/testdata/export/019.txtar | 8 - cue/testdata/export/020.txtar | 8 - cue/testdata/export/021.txtar | 18 - cue/testdata/export/022.txtar | 24 - cue/testdata/export/023.txtar | 29 - cue/testdata/export/024.txtar | 23 - cue/testdata/export/025.txtar | 18 - cue/testdata/export/026.txtar | 13 - cue/testdata/export/027.txtar | 9 - cue/testdata/export/028.txtar | 16 - cue/testdata/export/029.txtar | 20 - cue/testdata/export/030.txtar | 19 - cue/testdata/export/031.txtar | 14 - cue/testdata/export/032.txtar | 8 - cue/testdata/export/issue2119.txtar | 36 - cue/testdata/export/issue2244.txtar | 24 - cue/testdata/export/issue854.txtar | 7 +- .../000_detect_conflicting_value.txtar | 6 - ...nflicts_in_optional_fields_are_okay_.txtar | 13 - .../002_resolve_all_disjunctions.txtar | 23 - .../fulleval/003_field_templates.txtar | 35 - .../fulleval/004_field_comprehension.txtar | 20 - .../fulleval/005_conditional_field.txtar | 22 - ...rencing_field_in_field_comprehension.txtar | 17 - .../007_different_labels_for_templates.txtar | 17 - .../008_nested_templates_in_one_field.txtar | 37 - ...mplate_unification_within_one_struct.txtar | 27 - ...ld_comprehensions_with_multiple_keys.txtar | 44 - ..._field_comprehensions_with_templates.txtar | 22 - .../fulleval/012_disjunctions_of_lists.txtar | 17 - cue/testdata/fulleval/013_normalization.txtar | 7 - ...fault_disambiguation_and_elimination.txtar | 11 - ...6_struct_comprehension_with_template.txtar | 29 - ...lutions_in_struct_comprehension_keys.txtar | 11 - ...018_recursive_evaluation_within_list.txtar | 24 - ...20_complex_interaction_of_groundness.txtar | 31 - .../fulleval/021_complex_groundness_2.txtar | 36 - ...references_from_template_to_concrete.txtar | 21 - cue/testdata/fulleval/024_Issue_#23.txtar | 12 - ..._incomplete_errors_to_non-incomplete.txtar | 21 - .../027_len_of_incomplete_types.txtar | 33 - .../fulleval/028_slice_rewrite_bug.txtar | 19 - cue/testdata/fulleval/029_Issue_#94.txtar | 30 - ...eferences_with_interleaved_embedding.txtar | 25 - .../031_comparison_against_bottom.txtar | 30 - ..._not_fail_on_non-concrete_empty_list.txtar | 19 - .../034_label_and_field_aliases.txtar | 19 - .../035_optionals_with_label_filters.txtar | 48 - cue/testdata/fulleval/040.txtar | 18 - cue/testdata/fulleval/041.txtar | 13 - .../042_cross-dependent_comprehension.txtar | 16 - .../043_optional_expanded_before_lookup.txtar | 16 - cue/testdata/fulleval/044_Issue_#178.txtar | 8 - .../046_non-structural_direct_cycles.txtar | 12 - .../047_dont_bind_to_string_labels.txtar | 9 - ...t_pass_incomplete_values_to_builtins.txtar | 6 - .../049_alias_reuse_in_nested_scope.txtar | 35 - ...0_json_Marshaling_detects_incomplete.txtar | 12 - .../fulleval/051_detectIncompleteYAML.txtar | 21 - .../fulleval/052_detectIncompleteJSON.txtar | 21 - cue/testdata/fulleval/053_issue312.txtar | 11 - cue/testdata/fulleval/054_issue312.txtar | 14 - cue/testdata/fulleval/055_issue318.txtar | 13 - cue/testdata/inlinetest/closedness.txtar | 39 - cue/testdata/inlinetest/debug.txtar | 16 - cue/testdata/inlinetest/decl_eq.txtar | 10 - cue/testdata/inlinetest/decl_eq_mixed.txtar | 6 - cue/testdata/inlinetest/decl_eq_pattern.txtar | 10 - cue/testdata/inlinetest/hidden_fields.txtar | 22 - cue/testdata/inlinetest/permute.txtar | 30 - cue/testdata/inlinetest/struct_eq.txtar | 8 - cue/testdata/inlinetest/structural.txtar | 28 - cue/testdata/inlinetest/validators.txtar | 10 - .../interpolation/041_interpolation.txtar | 11 - .../042_multiline_interpolation.txtar | 28 - cue/testdata/interpolation/incomplete.txtar | 16 - cue/testdata/interpolation/issue487.txtar | 22 - cue/testdata/interpolation/scalars.txtar | 15 - cue/testdata/lists/019_list_types.txtar | 68 - cue/testdata/lists/020_list_compilefail.txtar | 47 - cue/testdata/lists/021_list_equality.txtar | 279 -- cue/testdata/packages/builtin.txtar | 7 - cue/testdata/packages/embed.txtar | 6 - cue/testdata/packages/issue398.txtar | 6 - cue/testdata/packages/sub.txtar | 6 - cue/testdata/references/alias.txtar | 151 - cue/testdata/references/alias_err.txtar | 33 - cue/testdata/references/embed_self.txtar | 6 - cue/testdata/references/errors.txtar | 25 - cue/testdata/references/incomplete.txtar | 33 - cue/testdata/references/index.txtar | 57 - cue/testdata/references/labels.txtar | 152 - cue/testdata/references/labelstop.txtar | 10 - cue/testdata/references/let.txtar | 185 -- cue/testdata/references/letcycle.txtar | 111 - cue/testdata/references/optional.txtar | 16 - cue/testdata/references/package.txtar | 6 - cue/testdata/references/self.txtar | 101 - cue/testdata/references/value.txtar | 29 - .../resolve/000_convert___to_top.txtar | 7 - cue/testdata/resolve/001.txtar | 16 - cue/testdata/resolve/004.txtar | 11 - cue/testdata/resolve/005_JSON.txtar | 10 - cue/testdata/resolve/006_arithmetic.txtar | 10 - cue/testdata/resolve/007_inequality.txtar | 10 - cue/testdata/resolve/008_attributes.txtar | 14 - .../009_optional_field_unification.txtar | 19 - ...ptional_field_resolves_to_incomplete.txtar | 9 - cue/testdata/resolve/011_bounds.txtar | 55 - .../resolve/012_bound_conversions.txtar | 15 - .../resolve/013_custom_validators.txtar | 10 - .../resolve/014_null_coalescing.txtar | 7 - cue/testdata/resolve/016_index.txtar | 49 - .../resolve/017_disjunctions_of_lists.txtar | 19 - cue/testdata/resolve/018_slice.txtar | 27 - .../resolve/022_list_unification.txtar | 17 - .../resolve/023_correct_error_messages.txtar | 5 - cue/testdata/resolve/024_structs.txtar | 17 - cue/testdata/resolve/025_definitions.txtar | 45 - .../resolve/027_new-style_definitions.txtar | 18 - ...over_closedness_to_enclosed_template.txtar | 44 - .../030_definitions_with_disjunctions.txtar | 24 - ...nitions_with_disjunctions_recurisive.txtar | 17 - ...finition_with_struct_and_disjunction.txtar | 16 - .../resolve/034_closing_structs.txtar | 31 - .../035_excluded_embedding_from_closing.txtar | 26 - .../038_incomplete_comprehensions.txtar | 19 - .../resolve/039_reference_to_root.txtar | 28 - ...references_from_template_to_concrete.txtar | 23 - .../043_diamond-shaped_constraints.txtar | 20 - .../resolve/044_field_templates.txtar | 35 - .../resolve/045_range_unification.txtar | 39 - .../resolve/046_predefined_ranges.txtar | 12 - .../resolve/046_predefined_ranges_error.txtar | 6 - .../resolve/047_struct_comprehensions.txtar | 27 - cue/testdata/resolve/048_builtins.txtar | 100 - cue/testdata/scalars/embed.txtar | 162 - cue/testdata/scalars/embed_bound.txtar | 12 - cue/testdata/scalars/emptystruct.txtar | 66 - cue/testdata/scalars/yield.txtar | 27 - internal/core/compile/compile_test.go | 54 +- internal/core/compile/testdata/README.md | 13 + .../sync/basicrewrite/000_errors.txtar | 19 + .../sync/basicrewrite/001_regexp.txtar | 49 + .../sync/basicrewrite/002_arithmetic.txtar | 56 + .../003_integer-specific_arithmetic.txtar | 56 + .../sync/basicrewrite/004_booleans.txtar | 17 + .../basicrewrite/005_boolean_arithmetic.txtar | 17 + .../sync/basicrewrite/006_basic_type.txtar | 21 + .../basicrewrite/007_strings_and_bytes.txtar | 24 + .../sync/basicrewrite/008_escaping.txtar | 11 + .../sync/basicrewrite/009_reference.txtar | 37 + .../sync/basicrewrite/010_lists.txtar | 61 + .../sync/basicrewrite/012_selecting.txtar | 39 + .../sync/basicrewrite/013_obj_unify.txtar | 52 + .../sync/basicrewrite/014_disjunctions.txtar | 54 + .../sync/basicrewrite/015_types.txtar | 23 + .../sync/basicrewrite/016_comparison.txtar | 792 +++++ .../testdata/sync/basicrewrite/017_null.txtar | 21 + .../018_self-reference_cycles.txtar | 184 ++ .../019_resolved_self-reference_cycles.txtar | 121 + ...lved_self-reference_cycles__Issue_19.txtar | 23 + .../sync/basicrewrite/aliases/aliases.txtar | 34 + .../testdata/sync/benchmarks/chain.txtar | 2006 ++++++++++++ .../testdata/sync/benchmarks/cycle.txtar | 42 + .../testdata/sync/benchmarks/cycleshare.txtar | 107 + .../testdata/sync/benchmarks/decimal.txtar | 41 + .../testdata/sync/benchmarks/deduparc.txtar | 53 + .../testdata/sync/benchmarks/dedupelem.txtar | 97 + .../sync/benchmarks/disjunctelim.txtar | 178 + .../sync/benchmarks/disjunction.txtar | 139 + .../sync/benchmarks/inlinedisjunction.txtar | 60 + .../testdata/sync/benchmarks/issue1684.txtar | 165 + .../testdata/sync/benchmarks/issue2176.txtar | 108 + .../testdata/sync/benchmarks/issue3307.txtar | 57 + .../testdata/sync/benchmarks/issue3334.txtar | 319 ++ .../testdata/sync/benchmarks/issue3514.txtar | 93 + .../testdata/sync/benchmarks/issue3517.txtar | 132 + .../testdata/sync/benchmarks/issue3633.txtar | 257 ++ .../testdata/sync/benchmarks/issue572.txtar | 36 + .../testdata/sync/benchmarks/listdedup.txtar | 161 + .../testdata/sync/benchmarks/listdisj.txtar | 47 + .../sync/benchmarks/mergeddisjunction.txtar | 87 + .../testdata/sync/benchmarks/share.txtar | 48 + .../testdata/sync/benchmarks/sharefg.txtar | 434 +++ .../testdata/sync/benchmarks/sort.txtar | 76 + .../testdata/sync/benchmarks/typocheck.txtar | 57 + .../testdata/sync/builtins/056_issue314.txtar | 62 + .../compile/testdata/sync/builtins/all.txtar | 77 + .../compile/testdata/sync/builtins/and.txtar | 60 + .../compile/testdata/sync/builtins/args.txtar | 46 + .../testdata/sync/builtins/closeall.txtar | 97 + .../testdata/sync/builtins/closed.txtar | 415 +++ .../testdata/sync/builtins/default.txtar | 31 + .../testdata/sync/builtins/error.txtar | 163 + .../testdata/sync/builtins/export.txtar | 60 + .../testdata/sync/builtins/incomplete.txtar | 208 ++ .../testdata/sync/builtins/intdiv.txtar | 72 + .../testdata/sync/builtins/issue299.txtar | 22 + .../testdata/sync/builtins/issue4208.txtar | 53 + .../testdata/sync/builtins/issue490.txtar | 42 + .../testdata/sync/builtins/issue_3567.txtar | 14 + .../sync/builtins/list/issue332.txtar | 37 + .../testdata/sync/builtins/list/sort.txtar | 18 + .../testdata/sync/builtins/matchif.txtar | 60 + .../testdata/sync/builtins/matchn.txtar | 1170 +++++++ .../compile/testdata/sync/builtins/or.txtar | 47 + .../testdata/sync/builtins/reclose.txtar | 329 ++ .../testdata/sync/builtins/validators.txtar | 600 ++++ .../testdata/sync/builtins/versionchk.txtar | 15 + .../sync/choosedefault/000_pick_first.txtar | 19 + .../001_simple_disambiguation_conflict.txtar | 11 + .../002_associativity_of_defaults.txtar | 143 + .../compile/testdata/sync/compile/alias.txtar | 18 + .../testdata/sync/compile/err_top.txtar | 69 + .../testdata/sync/compile/erralias.txtar | 30 + .../testdata/sync/compile/experiment.txtar | 20 + .../testdata/sync/compile/fields.txtar | 13 + .../compile/testdata/sync/compile/files.txtar | 30 + .../compile/testdata/sync/compile/json.txtar | 44 + .../testdata/sync/compile/labels.txtar | 92 + .../compile/testdata/sync/compile/let.txtar | 200 ++ .../testdata/sync/compile/postfixexpr.txtar | 50 + .../compile/testdata/sync/compile/scope.txtar | 91 + .../015_list_comprehension.txtar | 41 + .../045_comprehension_and_skipped_field.txtar | 33 + .../sync/comprehensions/checkdefined.txtar | 316 ++ .../testdata/sync/comprehensions/closed.txtar | 275 ++ .../comprehensions/deferfieldsetknown.txtar | 43 + .../testdata/sync/comprehensions/else.txtar | 474 +++ .../comprehensions/else_compile_errors.txtar | 53 + .../sync/comprehensions/else_on_error.txtar | 48 + .../testdata/sync/comprehensions/errors.txtar | 94 + .../testdata/sync/comprehensions/fields.txtar | 137 + .../testdata/sync/comprehensions/for.txtar | 56 + .../sync/comprehensions/iferror.txtar | 217 ++ .../sync/comprehensions/incomplete.txtar | 23 + .../sync/comprehensions/issue1732.txtar | 351 ++ .../sync/comprehensions/issue2171.txtar | 23 + .../sync/comprehensions/issue2481.txtar | 134 + .../sync/comprehensions/issue287.txtar | 31 + .../sync/comprehensions/issue293.txtar | 82 + .../sync/comprehensions/issue3762.txtar | 238 ++ .../sync/comprehensions/issue3763.txtar | 189 ++ .../sync/comprehensions/issue3929.txtar | 299 ++ .../sync/comprehensions/issue436.txtar | 47 + .../sync/comprehensions/issue507.txtar | 59 + .../sync/comprehensions/issue837.txtar | 157 + .../sync/comprehensions/issue843.txtar | 121 + .../testdata/sync/comprehensions/lists.txtar | 21 + .../testdata/sync/comprehensions/multi.txtar | 78 + .../testdata/sync/comprehensions/nested.txtar | 208 ++ .../sync/comprehensions/nested2.txtar | 845 +++++ .../sync/comprehensions/nestembed.txtar | 51 + .../comprehensions/open_iter_writeback.txtar | 77 + .../comprehensions/optional_ref_yield.txtar | 91 + .../sync/comprehensions/pushdown.txtar | 2868 +++++++++++++++++ .../testdata/sync/comprehensions/try.txtar | 1099 +++++++ .../comprehensions/try_compile_errors.txtar | 79 + ...015_reference_across_tuples_and_back.txtar | 23 + .../021_delayed_constraint_failure.txtar | 20 + .../testdata/sync/cycle/023_reentrance.txtar | 65 + ...e_references_that_would_be_ambiguous.txtar | 35 + ...erence_cycles_conflicts_with_strings.txtar | 19 + ...f-reference_cycles_with_disjunctions.txtar | 31 + ...lf-reference_cycles_with_disjunction.txtar | 124 + ...ycles_with_disjunction_with_defaults.txtar | 90 + .../testdata/sync/cycle/builtins.txtar | 776 +++++ .../compile/testdata/sync/cycle/chain.txtar | 792 +++++ .../testdata/sync/cycle/compbottom.txtar | 148 + .../testdata/sync/cycle/compbottom2.txtar | 813 +++++ .../sync/cycle/compbottomnofinal.txtar | 219 ++ .../testdata/sync/cycle/comprehension.txtar | 1511 +++++++++ .../testdata/sync/cycle/constraints.txtar | 673 ++++ .../sync/cycle/cycle_with_bounds.txtar | 21 + .../testdata/sync/cycle/disjunction.txtar | 156 + .../testdata/sync/cycle/evaluate.txtar | 301 ++ .../testdata/sync/cycle/expression.txtar | 214 ++ .../compile/testdata/sync/cycle/freeze.txtar | 252 ++ .../compile/testdata/sync/cycle/inline.txtar | 462 +++ .../sync/cycle/inline_non_recursive.txtar | 341 ++ .../testdata/sync/cycle/issue1960.txtar | 174 + .../testdata/sync/cycle/issue241.txtar | 64 + .../testdata/sync/cycle/issue242.txtar | 296 ++ .../testdata/sync/cycle/issue2526.txtar | 19 + .../testdata/sync/cycle/issue306.txtar | 18 + .../testdata/sync/cycle/issue3118.txtar | 73 + .../testdata/sync/cycle/issue3527.txtar | 73 + .../testdata/sync/cycle/issue3570.txtar | 16 + .../testdata/sync/cycle/issue3571.txtar | 106 + .../testdata/sync/cycle/issue3827.txtar | 77 + .../testdata/sync/cycle/issue4203.txtar | 91 + .../testdata/sync/cycle/issue4210.txtar | 67 + .../testdata/sync/cycle/issue4228.txtar | 197 ++ .../testdata/sync/cycle/issue4230.txtar | 48 + .../testdata/sync/cycle/issue4244.txtar | 57 + .../testdata/sync/cycle/issue4253.txtar | 51 + .../testdata/sync/cycle/issue429.txtar | 123 + .../testdata/sync/cycle/issue494.txtar | 110 + .../testdata/sync/cycle/issue502.txtar | 175 + .../testdata/sync/cycle/issue990.txtar | 285 ++ .../testdata/sync/cycle/patterns.txtar | 61 + .../compile/testdata/sync/cycle/self.txtar | 846 +++++ .../testdata/sync/cycle/structural.txtar | 1679 ++++++++++ .../testdata/sync/cycle/with_defaults.txtar | 36 + .../026_combined_definitions.txtar | 76 + ...e_closing_starting_at_non-definition.txtar | 36 + .../032_definitions_with_embedding.txtar | 46 + .../sync/definitions/033_Issue_#153.txtar | 57 + .../036_closing_with_failed_optional.txtar | 68 + .../036_optionals_in_open_structs.txtar | 29 + .../037_closing_with_comprehensions.txtar | 80 + .../037_conjunction_of_optional_sets.txtar | 44 + ...inue_recursive_closing_for_optionals.txtar | 21 + .../039_augment_closed_optionals.txtar | 44 + .../sync/definitions/comprehensions.txtar | 31 + .../testdata/sync/definitions/defembed.txtar | 41 + .../testdata/sync/definitions/dynamic.txtar | 81 + .../testdata/sync/definitions/embed.txtar | 164 + .../testdata/sync/definitions/exclude.txtar | 197 ++ .../sync/definitions/explicitopen.txtar | 785 +++++ .../testdata/sync/definitions/fields.txtar | 825 +++++ .../testdata/sync/definitions/files.txtar | 59 + .../testdata/sync/definitions/hidden.txtar | 73 + .../testdata/sync/definitions/issue271.txtar | 27 + .../testdata/sync/definitions/issue317.txtar | 117 + .../testdata/sync/definitions/issue320.txtar | 34 + .../testdata/sync/definitions/issue342.txtar | 64 + .../testdata/sync/definitions/issue359.txtar | 137 + .../testdata/sync/definitions/issue367.txtar | 35 + .../testdata/sync/definitions/issue370.txtar | 41 + .../testdata/sync/definitions/issue3834.txtar | 270 ++ .../testdata/sync/definitions/issue3851.txtar | 44 + .../testdata/sync/definitions/issue4000.txtar | 127 + .../testdata/sync/definitions/issue419.txtar | 45 + .../testdata/sync/definitions/issue471.txtar | 56 + .../testdata/sync/definitions/issue483.txtar | 40 + .../testdata/sync/definitions/issue491.txtar | 78 + .../testdata/sync/definitions/issue493.txtar | 31 + .../testdata/sync/definitions/issue496.txtar | 24 + .../testdata/sync/definitions/issue497.txtar | 26 + .../testdata/sync/definitions/issue533.txtar | 41 + .../testdata/sync/definitions/issue539.txtar | 34 + .../testdata/sync/definitions/list.txtar | 25 + .../testdata/sync/definitions/root1.txtar | 20 + .../testdata/sync/definitions/root2.txtar | 16 + .../testdata/sync/definitions/root3.txtar | 21 + .../testdata/sync/definitions/root4.txtar | 33 + .../testdata/sync/definitions/root5.txtar | 89 + .../testdata/sync/definitions/root6.txtar | 49 + .../testdata/sync/definitions/root7.txtar | 19 + .../testdata/sync/definitions/root8.txtar | 44 + .../testdata/sync/definitions/typocheck.txtar | 2096 ++++++++++++ .../sync/definitions/visibility.txtar | 28 + .../testdata/sync/disjunctions/019_ips.txtar | 67 + .../sync/disjunctions/confluence.txtar | 53 + .../sync/disjunctions/crossembed.txtar | 38 + .../testdata/sync/disjunctions/defaults.txtar | 60 + .../testdata/sync/disjunctions/defembed.txtar | 98 + .../sync/disjunctions/discriminator.txtar | 234 ++ .../testdata/sync/disjunctions/edge.txtar | 319 ++ .../sync/disjunctions/elimination.txtar | 2480 ++++++++++++++ .../testdata/sync/disjunctions/embed.txtar | 223 ++ .../testdata/sync/disjunctions/errors.txtar | 479 +++ .../sync/disjunctions/incomplete.txtar | 176 + .../sync/disjunctions/issue2209.txtar | 297 ++ .../sync/disjunctions/issue3850.txtar | 192 ++ .../sync/disjunctions/issue3857.txtar | 175 + .../sync/disjunctions/issue4339.txtar | 30 + .../testdata/sync/disjunctions/nested.txtar | 156 + .../testdata/sync/disjunctions/operands.txtar | 83 + .../sync/disjunctions/propagate_err.txtar | 77 + .../testdata/sync/disjunctions/resolve.txtar | 48 + .../sync/disjunctions/specdeviation.txtar | 127 + .../testdata/sync/eval/basictypes.txtar | 78 + .../compile/testdata/sync/eval/bounds.txtar | 614 ++++ .../compile/testdata/sync/eval/bulk.txtar | 493 +++ .../sync/eval/closed_disjunction.txtar | 40 + .../testdata/sync/eval/closedness.txtar | 2290 +++++++++++++ .../testdata/sync/eval/comprehensions.txtar | 311 ++ .../testdata/sync/eval/conflicts.txtar | 54 + .../testdata/sync/eval/conjuncts.txtar | 189 ++ .../compile/testdata/sync/eval/counters.txtar | 316 ++ .../testdata/sync/eval/cycles_ref.txtar | 24 + .../compile/testdata/sync/eval/deref.txtar | 89 + .../testdata/sync/eval/discontinuous.txtar | 51 + .../testdata/sync/eval/disjselfcycle.txtar | 174 + .../testdata/sync/eval/disjunctioncross.txtar | 306 ++ .../testdata/sync/eval/disjunctions.txtar | 1097 +++++++ .../testdata/sync/eval/dynamic_field.txtar | 222 ++ .../compile/testdata/sync/eval/embed.txtar | 354 ++ .../testdata/sync/eval/errunifiy.txtar | 15 + .../testdata/sync/eval/expressions.txtar | 56 + .../compile/testdata/sync/eval/fields.txtar | 28 + .../testdata/sync/eval/incomplete.txtar | 115 + .../testdata/sync/eval/incompleteperm.txtar | 60 + .../testdata/sync/eval/insertion.txtar | 254 ++ .../testdata/sync/eval/issue1640.txtar | 54 + .../testdata/sync/eval/issue1886.txtar | 90 + .../testdata/sync/eval/issue2146.txtar | 114 + .../testdata/sync/eval/issue2235.txtar | 268 ++ .../testdata/sync/eval/issue2337.txtar | 92 + .../testdata/sync/eval/issue2550.txtar | 24 + .../testdata/sync/eval/issue2649.txtar | 14 + .../compile/testdata/sync/eval/issue285.txtar | 41 + .../compile/testdata/sync/eval/issue295.txtar | 21 + .../testdata/sync/eval/issue3301.txtar | 57 + .../testdata/sync/eval/issue3330.txtar | 77 + .../compile/testdata/sync/eval/issue349.txtar | 40 + .../compile/testdata/sync/eval/issue353.txtar | 36 + .../testdata/sync/eval/issue3672.txtar | 315 ++ .../testdata/sync/eval/issue3688.txtar | 98 + .../testdata/sync/eval/issue3709.txtar | 27 + .../testdata/sync/eval/issue3801.txtar | 309 ++ .../testdata/sync/eval/issue3805.txtar | 330 ++ .../testdata/sync/eval/issue3813.txtar | 37 + .../testdata/sync/eval/issue3905.txtar | 149 + .../testdata/sync/eval/issue3919.txtar | 234 ++ .../compile/testdata/sync/eval/issue494.txtar | 69 + .../compile/testdata/sync/eval/issue500.txtar | 64 + .../compile/testdata/sync/eval/issue545.txtar | 101 + .../compile/testdata/sync/eval/issue599.txtar | 182 ++ .../compile/testdata/sync/eval/issue962.txtar | 24 + .../core/compile/testdata/sync/eval/let.txtar | 430 +++ .../compile/testdata/sync/eval/letjoin.txtar | 339 ++ .../compile/testdata/sync/eval/lists.txtar | 40 + .../compile/testdata/sync/eval/merge.txtar | 60 + .../testdata/sync/eval/nonrooted.txtar | 125 + .../compile/testdata/sync/eval/notify.txtar | 106 + .../testdata/sync/eval/openinline.txtar | 191 ++ .../compile/testdata/sync/eval/required.txtar | 231 ++ .../testdata/sync/eval/resolve_basic.txtar | 23 + .../testdata/sync/eval/resolve_env.txtar | 45 + .../testdata/sync/eval/selectors.txtar | 45 + .../compile/testdata/sync/eval/sharing.txtar | 704 ++++ .../testdata/sync/eval/shortcircuit.txtar | 48 + .../sync/eval/shortcircuit_noexp.txtar | 16 + .../compile/testdata/sync/eval/structs.txtar | 11 + .../compile/testdata/sync/eval/unify.txtar | 39 + .../compile/testdata/sync/eval/v0.7.txtar | 843 +++++ .../testdata/sync/eval/v0.7errorprop.txtar | 17 + .../compile/testdata/sync/export/000.txtar | 8 + .../compile/testdata/sync/export/001.txtar | 8 + .../compile/testdata/sync/export/002.txtar | 8 + .../compile/testdata/sync/export/003.txtar | 8 + .../compile/testdata/sync/export/004.txtar | 18 + .../compile/testdata/sync/export/005.txtar | 15 + .../compile/testdata/sync/export/006.txtar | 17 + .../compile/testdata/sync/export/007.txtar | 23 + .../compile/testdata/sync/export/008.txtar | 12 + .../compile/testdata/sync/export/009.txtar | 38 + .../compile/testdata/sync/export/010.txtar | 39 + .../compile/testdata/sync/export/011.txtar | 15 + .../compile/testdata/sync/export/012.txtar | 12 + .../compile/testdata/sync/export/013.txtar | 12 + .../compile/testdata/sync/export/014.txtar | 13 + .../compile/testdata/sync/export/015.txtar | 18 + .../compile/testdata/sync/export/016.txtar | 38 + .../compile/testdata/sync/export/017.txtar | 19 + .../compile/testdata/sync/export/018.txtar | 19 + .../compile/testdata/sync/export/019.txtar | 12 + .../compile/testdata/sync/export/020.txtar | 12 + .../compile/testdata/sync/export/021.txtar | 30 + .../compile/testdata/sync/export/022.txtar | 43 + .../compile/testdata/sync/export/023.txtar | 54 + .../compile/testdata/sync/export/024.txtar | 41 + .../compile/testdata/sync/export/025.txtar | 32 + .../compile/testdata/sync/export/026.txtar | 21 + .../compile/testdata/sync/export/027.txtar | 22 + .../compile/testdata/sync/export/028.txtar | 26 + .../compile/testdata/sync/export/029.txtar | 33 + .../compile/testdata/sync/export/030.txtar | 38 + .../compile/testdata/sync/export/031.txtar | 22 + .../compile/testdata/sync/export/032.txtar | 14 + .../testdata/sync/export/issue2119.txtar | 92 + .../testdata/sync/export/issue2244.txtar | 71 + .../testdata/sync/export/issue854.txtar | 26 + .../000_detect_conflicting_value.txtar | 13 + ...nflicts_in_optional_fields_are_okay_.txtar | 25 + .../002_resolve_all_disjunctions.txtar | 40 + .../sync/fulleval/003_field_templates.txtar | 52 + .../fulleval/004_field_comprehension.txtar | 43 + .../sync/fulleval/005_conditional_field.txtar | 47 + ...rencing_field_in_field_comprehension.txtar | 26 + .../007_different_labels_for_templates.txtar | 21 + .../008_nested_templates_in_one_field.txtar | 49 + ...mplate_unification_within_one_struct.txtar | 41 + ...ld_comprehensions_with_multiple_keys.txtar | 72 + ..._field_comprehensions_with_templates.txtar | 39 + .../fulleval/012_disjunctions_of_lists.txtar | 24 + .../sync/fulleval/013_normalization.txtar | 15 + ...fault_disambiguation_and_elimination.txtar | 23 + ...6_struct_comprehension_with_template.txtar | 64 + ...lutions_in_struct_comprehension_keys.txtar | 13 + ...018_recursive_evaluation_within_list.txtar | 39 + ...20_complex_interaction_of_groundness.txtar | 44 + .../fulleval/021_complex_groundness_2.txtar | 60 + ...references_from_template_to_concrete.txtar | 32 + .../sync/fulleval/024_Issue_#23.txtar | 19 + ..._incomplete_errors_to_non-incomplete.txtar | 46 + .../027_len_of_incomplete_types.txtar | 47 + .../sync/fulleval/028_slice_rewrite_bug.txtar | 37 + .../sync/fulleval/029_Issue_#94.txtar | 57 + ...eferences_with_interleaved_embedding.txtar | 44 + .../031_comparison_against_bottom.txtar | 43 + ..._not_fail_on_non-concrete_empty_list.txtar | 39 + .../034_label_and_field_aliases.txtar | 48 + .../035_optionals_with_label_filters.txtar | 81 + .../compile/testdata/sync/fulleval/040.txtar | 43 + .../compile/testdata/sync/fulleval/041.txtar | 25 + .../042_cross-dependent_comprehension.txtar | 29 + .../043_optional_expanded_before_lookup.txtar | 33 + .../sync/fulleval/044_Issue_#178.txtar | 25 + .../046_non-structural_direct_cycles.txtar | 21 + .../047_dont_bind_to_string_labels.txtar | 16 + ...t_pass_incomplete_values_to_builtins.txtar | 13 + .../049_alias_reuse_in_nested_scope.txtar | 58 + ...0_json_Marshaling_detects_incomplete.txtar | 24 + .../fulleval/051_detectIncompleteYAML.txtar | 48 + .../fulleval/052_detectIncompleteJSON.txtar | 48 + .../testdata/sync/fulleval/053_issue312.txtar | 24 + .../testdata/sync/fulleval/054_issue312.txtar | 22 + .../testdata/sync/fulleval/055_issue318.txtar | 29 + .../testdata/sync/inlinetest/closedness.txtar | 73 + .../testdata/sync/inlinetest/debug.txtar | 66 + .../testdata/sync/inlinetest/decl_eq.txtar | 29 + .../sync/inlinetest/decl_eq_mixed.txtar | 14 + .../sync/inlinetest/decl_eq_pattern.txtar | 17 + .../sync/inlinetest/hidden_fields.txtar | 55 + .../testdata/sync/inlinetest/permute.txtar | 101 + .../testdata/sync/inlinetest/struct_eq.txtar | 14 + .../testdata/sync/inlinetest/structural.txtar | 73 + .../testdata/sync/inlinetest/validators.txtar | 23 + .../interpolation/041_interpolation.txtar | 19 + .../042_multiline_interpolation.txtar | 74 + .../sync/interpolation/incomplete.txtar | 32 + .../sync/interpolation/issue487.txtar | 44 + .../testdata/sync/interpolation/scalars.txtar | 35 + .../testdata/sync/lists/019_list_types.txtar | 95 + .../sync/lists/020_list_compilefail.txtar | 61 + .../sync/lists/021_list_equality.txtar | 343 ++ .../testdata/sync/packages/builtin.txtar | 15 + .../testdata/sync/packages/embed.txtar | 33 + .../testdata/sync/packages/issue398.txtar | 32 + .../compile/testdata/sync/packages/sub.txtar | 24 + .../testdata/sync/references/alias.txtar | 364 +++ .../testdata/sync/references/alias_err.txtar | 60 + .../testdata/sync/references/embed_self.txtar | 10 + .../testdata/sync/references/errors.txtar | 57 + .../testdata/sync/references/incomplete.txtar | 64 + .../testdata/sync/references/index.txtar | 88 + .../testdata/sync/references/labels.txtar | 273 ++ .../testdata/sync/references/labelstop.txtar | 16 + .../testdata/sync/references/let.txtar | 304 ++ .../testdata/sync/references/letcycle.txtar | 161 + .../testdata/sync/references/optional.txtar | 27 + .../testdata/sync/references/package.txtar | 32 + .../testdata/sync/references/self.txtar | 208 ++ .../testdata/sync/references/value.txtar | 50 + .../sync/resolve/000_convert___to_top.txtar | 11 + .../compile/testdata/sync/resolve/001.txtar | 21 + .../compile/testdata/sync/resolve/004.txtar | 16 + .../testdata/sync/resolve/005_JSON.txtar | 16 + .../sync/resolve/006_arithmetic.txtar | 19 + .../sync/resolve/007_inequality.txtar | 17 + .../sync/resolve/008_attributes.txtar | 20 + .../009_optional_field_unification.txtar | 31 + ...ptional_field_resolves_to_incomplete.txtar | 15 + .../testdata/sync/resolve/011_bounds.txtar | 120 + .../sync/resolve/012_bound_conversions.txtar | 30 + .../sync/resolve/013_custom_validators.txtar | 21 + .../sync/resolve/014_null_coalescing.txtar | 11 + .../testdata/sync/resolve/016_index.txtar | 71 + .../resolve/017_disjunctions_of_lists.txtar | 24 + .../testdata/sync/resolve/018_slice.txtar | 37 + .../sync/resolve/022_list_unification.txtar | 20 + .../resolve/023_correct_error_messages.txtar | 8 + .../testdata/sync/resolve/024_structs.txtar | 28 + .../sync/resolve/025_definitions.txtar | 86 + .../resolve/027_new-style_definitions.txtar | 30 + ...over_closedness_to_enclosed_template.txtar | 68 + .../030_definitions_with_disjunctions.txtar | 40 + ...nitions_with_disjunctions_recurisive.txtar | 29 + ...finition_with_struct_and_disjunction.txtar | 30 + .../sync/resolve/034_closing_structs.txtar | 50 + .../035_excluded_embedding_from_closing.txtar | 45 + .../038_incomplete_comprehensions.txtar | 38 + .../sync/resolve/039_reference_to_root.txtar | 48 + ...references_from_template_to_concrete.txtar | 40 + .../043_diamond-shaped_constraints.txtar | 38 + .../sync/resolve/044_field_templates.txtar | 57 + .../sync/resolve/045_range_unification.txtar | 85 + .../sync/resolve/046_predefined_ranges.txtar | 24 + .../resolve/046_predefined_ranges_error.txtar | 9 + .../resolve/047_struct_comprehensions.txtar | 49 + .../testdata/sync/resolve/048_builtins.txtar | 202 ++ .../compile/testdata/sync/scalars/embed.txtar | 349 ++ .../testdata/sync/scalars/embed_bound.txtar | 28 + .../testdata/sync/scalars/emptystruct.txtar | 195 ++ .../compile/testdata/sync/scalars/yield.txtar | 55 + 918 files changed, 64930 insertions(+), 33585 deletions(-) create mode 100644 internal/core/compile/testdata/README.md create mode 100644 internal/core/compile/testdata/sync/basicrewrite/000_errors.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/001_regexp.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/002_arithmetic.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/003_integer-specific_arithmetic.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/004_booleans.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/005_boolean_arithmetic.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/006_basic_type.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/007_strings_and_bytes.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/008_escaping.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/009_reference.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/010_lists.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/012_selecting.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/013_obj_unify.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/014_disjunctions.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/015_types.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/016_comparison.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/017_null.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/018_self-reference_cycles.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/019_resolved_self-reference_cycles.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/020_resolved_self-reference_cycles__Issue_19.txtar create mode 100644 internal/core/compile/testdata/sync/basicrewrite/aliases/aliases.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/chain.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/cycle.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/cycleshare.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/decimal.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/deduparc.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/dedupelem.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/disjunctelim.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/disjunction.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/inlinedisjunction.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue1684.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue2176.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue3307.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue3334.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue3514.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue3517.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue3633.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/issue572.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/listdedup.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/listdisj.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/mergeddisjunction.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/share.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/sharefg.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/sort.txtar create mode 100644 internal/core/compile/testdata/sync/benchmarks/typocheck.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/056_issue314.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/all.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/and.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/args.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/closeall.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/closed.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/default.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/error.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/export.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/intdiv.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/issue299.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/issue4208.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/issue490.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/issue_3567.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/list/issue332.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/list/sort.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/matchif.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/matchn.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/or.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/reclose.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/validators.txtar create mode 100644 internal/core/compile/testdata/sync/builtins/versionchk.txtar create mode 100644 internal/core/compile/testdata/sync/choosedefault/000_pick_first.txtar create mode 100644 internal/core/compile/testdata/sync/choosedefault/001_simple_disambiguation_conflict.txtar create mode 100644 internal/core/compile/testdata/sync/choosedefault/002_associativity_of_defaults.txtar create mode 100644 internal/core/compile/testdata/sync/compile/alias.txtar create mode 100644 internal/core/compile/testdata/sync/compile/err_top.txtar create mode 100644 internal/core/compile/testdata/sync/compile/erralias.txtar create mode 100644 internal/core/compile/testdata/sync/compile/experiment.txtar create mode 100644 internal/core/compile/testdata/sync/compile/fields.txtar create mode 100644 internal/core/compile/testdata/sync/compile/files.txtar create mode 100644 internal/core/compile/testdata/sync/compile/json.txtar create mode 100644 internal/core/compile/testdata/sync/compile/labels.txtar create mode 100644 internal/core/compile/testdata/sync/compile/let.txtar create mode 100644 internal/core/compile/testdata/sync/compile/postfixexpr.txtar create mode 100644 internal/core/compile/testdata/sync/compile/scope.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/015_list_comprehension.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/045_comprehension_and_skipped_field.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/checkdefined.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/closed.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/deferfieldsetknown.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/else.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/else_compile_errors.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/else_on_error.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/errors.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/fields.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/for.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/iferror.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue1732.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue2171.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue2481.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue287.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue293.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue3762.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue3763.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue3929.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue436.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue507.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue837.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/issue843.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/lists.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/multi.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/nested.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/nested2.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/nestembed.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/open_iter_writeback.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/optional_ref_yield.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/pushdown.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/try.txtar create mode 100644 internal/core/compile/testdata/sync/comprehensions/try_compile_errors.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/015_reference_across_tuples_and_back.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/021_delayed_constraint_failure.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/023_reentrance.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/049_self-reference_cycles_conflicts_with_strings.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/builtins.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/chain.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/compbottom.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/compbottom2.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/compbottomnofinal.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/comprehension.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/constraints.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/cycle_with_bounds.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/disjunction.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/evaluate.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/expression.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/freeze.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/inline.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/inline_non_recursive.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue1960.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue241.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue242.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue2526.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue306.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue3118.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue3527.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue3570.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue3571.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue3827.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue4203.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue4210.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue4228.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue4230.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue4244.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue4253.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue429.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue494.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue502.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/issue990.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/patterns.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/self.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/structural.txtar create mode 100644 internal/core/compile/testdata/sync/cycle/with_defaults.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/026_combined_definitions.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/028_recursive_closing_starting_at_non-definition.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/032_definitions_with_embedding.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/033_Issue_#153.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/036_closing_with_failed_optional.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/036_optionals_in_open_structs.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/037_closing_with_comprehensions.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/037_conjunction_of_optional_sets.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/038_continue_recursive_closing_for_optionals.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/039_augment_closed_optionals.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/comprehensions.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/defembed.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/dynamic.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/embed.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/exclude.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/explicitopen.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/fields.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/files.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/hidden.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue271.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue317.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue320.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue342.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue359.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue367.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue370.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue3834.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue3851.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue4000.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue419.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue471.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue483.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue491.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue493.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue496.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue497.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue533.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/issue539.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/list.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root1.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root2.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root3.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root4.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root5.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root6.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root7.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/root8.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/typocheck.txtar create mode 100644 internal/core/compile/testdata/sync/definitions/visibility.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/019_ips.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/confluence.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/crossembed.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/defaults.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/defembed.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/discriminator.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/edge.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/elimination.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/embed.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/errors.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/issue2209.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/issue3850.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/issue3857.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/issue4339.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/nested.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/operands.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/propagate_err.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/resolve.txtar create mode 100644 internal/core/compile/testdata/sync/disjunctions/specdeviation.txtar create mode 100644 internal/core/compile/testdata/sync/eval/basictypes.txtar create mode 100644 internal/core/compile/testdata/sync/eval/bounds.txtar create mode 100644 internal/core/compile/testdata/sync/eval/bulk.txtar create mode 100644 internal/core/compile/testdata/sync/eval/closed_disjunction.txtar create mode 100644 internal/core/compile/testdata/sync/eval/closedness.txtar create mode 100644 internal/core/compile/testdata/sync/eval/comprehensions.txtar create mode 100644 internal/core/compile/testdata/sync/eval/conflicts.txtar create mode 100644 internal/core/compile/testdata/sync/eval/conjuncts.txtar create mode 100644 internal/core/compile/testdata/sync/eval/counters.txtar create mode 100644 internal/core/compile/testdata/sync/eval/cycles_ref.txtar create mode 100644 internal/core/compile/testdata/sync/eval/deref.txtar create mode 100644 internal/core/compile/testdata/sync/eval/discontinuous.txtar create mode 100644 internal/core/compile/testdata/sync/eval/disjselfcycle.txtar create mode 100644 internal/core/compile/testdata/sync/eval/disjunctioncross.txtar create mode 100644 internal/core/compile/testdata/sync/eval/disjunctions.txtar create mode 100644 internal/core/compile/testdata/sync/eval/dynamic_field.txtar create mode 100644 internal/core/compile/testdata/sync/eval/embed.txtar create mode 100644 internal/core/compile/testdata/sync/eval/errunifiy.txtar create mode 100644 internal/core/compile/testdata/sync/eval/expressions.txtar create mode 100644 internal/core/compile/testdata/sync/eval/fields.txtar create mode 100644 internal/core/compile/testdata/sync/eval/incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/eval/incompleteperm.txtar create mode 100644 internal/core/compile/testdata/sync/eval/insertion.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue1640.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue1886.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue2146.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue2235.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue2337.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue2550.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue2649.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue285.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue295.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3301.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3330.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue349.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue353.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3672.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3688.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3709.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3801.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3805.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3813.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3905.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue3919.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue494.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue500.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue545.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue599.txtar create mode 100644 internal/core/compile/testdata/sync/eval/issue962.txtar create mode 100644 internal/core/compile/testdata/sync/eval/let.txtar create mode 100644 internal/core/compile/testdata/sync/eval/letjoin.txtar create mode 100644 internal/core/compile/testdata/sync/eval/lists.txtar create mode 100644 internal/core/compile/testdata/sync/eval/merge.txtar create mode 100644 internal/core/compile/testdata/sync/eval/nonrooted.txtar create mode 100644 internal/core/compile/testdata/sync/eval/notify.txtar create mode 100644 internal/core/compile/testdata/sync/eval/openinline.txtar create mode 100644 internal/core/compile/testdata/sync/eval/required.txtar create mode 100644 internal/core/compile/testdata/sync/eval/resolve_basic.txtar create mode 100644 internal/core/compile/testdata/sync/eval/resolve_env.txtar create mode 100644 internal/core/compile/testdata/sync/eval/selectors.txtar create mode 100644 internal/core/compile/testdata/sync/eval/sharing.txtar create mode 100644 internal/core/compile/testdata/sync/eval/shortcircuit.txtar create mode 100644 internal/core/compile/testdata/sync/eval/shortcircuit_noexp.txtar create mode 100644 internal/core/compile/testdata/sync/eval/structs.txtar create mode 100644 internal/core/compile/testdata/sync/eval/unify.txtar create mode 100644 internal/core/compile/testdata/sync/eval/v0.7.txtar create mode 100644 internal/core/compile/testdata/sync/eval/v0.7errorprop.txtar create mode 100644 internal/core/compile/testdata/sync/export/000.txtar create mode 100644 internal/core/compile/testdata/sync/export/001.txtar create mode 100644 internal/core/compile/testdata/sync/export/002.txtar create mode 100644 internal/core/compile/testdata/sync/export/003.txtar create mode 100644 internal/core/compile/testdata/sync/export/004.txtar create mode 100644 internal/core/compile/testdata/sync/export/005.txtar create mode 100644 internal/core/compile/testdata/sync/export/006.txtar create mode 100644 internal/core/compile/testdata/sync/export/007.txtar create mode 100644 internal/core/compile/testdata/sync/export/008.txtar create mode 100644 internal/core/compile/testdata/sync/export/009.txtar create mode 100644 internal/core/compile/testdata/sync/export/010.txtar create mode 100644 internal/core/compile/testdata/sync/export/011.txtar create mode 100644 internal/core/compile/testdata/sync/export/012.txtar create mode 100644 internal/core/compile/testdata/sync/export/013.txtar create mode 100644 internal/core/compile/testdata/sync/export/014.txtar create mode 100644 internal/core/compile/testdata/sync/export/015.txtar create mode 100644 internal/core/compile/testdata/sync/export/016.txtar create mode 100644 internal/core/compile/testdata/sync/export/017.txtar create mode 100644 internal/core/compile/testdata/sync/export/018.txtar create mode 100644 internal/core/compile/testdata/sync/export/019.txtar create mode 100644 internal/core/compile/testdata/sync/export/020.txtar create mode 100644 internal/core/compile/testdata/sync/export/021.txtar create mode 100644 internal/core/compile/testdata/sync/export/022.txtar create mode 100644 internal/core/compile/testdata/sync/export/023.txtar create mode 100644 internal/core/compile/testdata/sync/export/024.txtar create mode 100644 internal/core/compile/testdata/sync/export/025.txtar create mode 100644 internal/core/compile/testdata/sync/export/026.txtar create mode 100644 internal/core/compile/testdata/sync/export/027.txtar create mode 100644 internal/core/compile/testdata/sync/export/028.txtar create mode 100644 internal/core/compile/testdata/sync/export/029.txtar create mode 100644 internal/core/compile/testdata/sync/export/030.txtar create mode 100644 internal/core/compile/testdata/sync/export/031.txtar create mode 100644 internal/core/compile/testdata/sync/export/032.txtar create mode 100644 internal/core/compile/testdata/sync/export/issue2119.txtar create mode 100644 internal/core/compile/testdata/sync/export/issue2244.txtar create mode 100644 internal/core/compile/testdata/sync/export/issue854.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/000_detect_conflicting_value.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/002_resolve_all_disjunctions.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/003_field_templates.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/004_field_comprehension.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/005_conditional_field.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/006_referencing_field_in_field_comprehension.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/007_different_labels_for_templates.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/008_nested_templates_in_one_field.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/009_template_unification_within_one_struct.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/010_field_comprehensions_with_multiple_keys.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/011_field_comprehensions_with_templates.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/012_disjunctions_of_lists.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/013_normalization.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/014_default_disambiguation_and_elimination.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/016_struct_comprehension_with_template.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/017_resolutions_in_struct_comprehension_keys.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/018_recursive_evaluation_within_list.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/020_complex_interaction_of_groundness.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/021_complex_groundness_2.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/022_references_from_template_to_concrete.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/024_Issue_#23.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/027_len_of_incomplete_types.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/028_slice_rewrite_bug.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/029_Issue_#94.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/030_retain_references_with_interleaved_embedding.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/031_comparison_against_bottom.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/034_label_and_field_aliases.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/035_optionals_with_label_filters.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/040.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/041.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/042_cross-dependent_comprehension.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/043_optional_expanded_before_lookup.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/044_Issue_#178.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/046_non-structural_direct_cycles.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/047_dont_bind_to_string_labels.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/049_alias_reuse_in_nested_scope.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/050_json_Marshaling_detects_incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/051_detectIncompleteYAML.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/052_detectIncompleteJSON.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/053_issue312.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/054_issue312.txtar create mode 100644 internal/core/compile/testdata/sync/fulleval/055_issue318.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/closedness.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/debug.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/decl_eq.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/decl_eq_mixed.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/decl_eq_pattern.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/hidden_fields.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/permute.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/struct_eq.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/structural.txtar create mode 100644 internal/core/compile/testdata/sync/inlinetest/validators.txtar create mode 100644 internal/core/compile/testdata/sync/interpolation/041_interpolation.txtar create mode 100644 internal/core/compile/testdata/sync/interpolation/042_multiline_interpolation.txtar create mode 100644 internal/core/compile/testdata/sync/interpolation/incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/interpolation/issue487.txtar create mode 100644 internal/core/compile/testdata/sync/interpolation/scalars.txtar create mode 100644 internal/core/compile/testdata/sync/lists/019_list_types.txtar create mode 100644 internal/core/compile/testdata/sync/lists/020_list_compilefail.txtar create mode 100644 internal/core/compile/testdata/sync/lists/021_list_equality.txtar create mode 100644 internal/core/compile/testdata/sync/packages/builtin.txtar create mode 100644 internal/core/compile/testdata/sync/packages/embed.txtar create mode 100644 internal/core/compile/testdata/sync/packages/issue398.txtar create mode 100644 internal/core/compile/testdata/sync/packages/sub.txtar create mode 100644 internal/core/compile/testdata/sync/references/alias.txtar create mode 100644 internal/core/compile/testdata/sync/references/alias_err.txtar create mode 100644 internal/core/compile/testdata/sync/references/embed_self.txtar create mode 100644 internal/core/compile/testdata/sync/references/errors.txtar create mode 100644 internal/core/compile/testdata/sync/references/incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/references/index.txtar create mode 100644 internal/core/compile/testdata/sync/references/labels.txtar create mode 100644 internal/core/compile/testdata/sync/references/labelstop.txtar create mode 100644 internal/core/compile/testdata/sync/references/let.txtar create mode 100644 internal/core/compile/testdata/sync/references/letcycle.txtar create mode 100644 internal/core/compile/testdata/sync/references/optional.txtar create mode 100644 internal/core/compile/testdata/sync/references/package.txtar create mode 100644 internal/core/compile/testdata/sync/references/self.txtar create mode 100644 internal/core/compile/testdata/sync/references/value.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/000_convert___to_top.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/001.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/004.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/005_JSON.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/006_arithmetic.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/007_inequality.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/008_attributes.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/009_optional_field_unification.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/010_optional_field_resolves_to_incomplete.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/011_bounds.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/012_bound_conversions.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/013_custom_validators.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/014_null_coalescing.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/016_index.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/017_disjunctions_of_lists.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/018_slice.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/022_list_unification.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/023_correct_error_messages.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/024_structs.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/025_definitions.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/027_new-style_definitions.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/030_definitions_with_disjunctions.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/031_definitions_with_disjunctions_recurisive.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/033_top-level_definition_with_struct_and_disjunction.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/034_closing_structs.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/035_excluded_embedding_from_closing.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/038_incomplete_comprehensions.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/039_reference_to_root.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/040_references_from_template_to_concrete.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/043_diamond-shaped_constraints.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/044_field_templates.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/045_range_unification.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/046_predefined_ranges.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/046_predefined_ranges_error.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/047_struct_comprehensions.txtar create mode 100644 internal/core/compile/testdata/sync/resolve/048_builtins.txtar create mode 100644 internal/core/compile/testdata/sync/scalars/embed.txtar create mode 100644 internal/core/compile/testdata/sync/scalars/embed_bound.txtar create mode 100644 internal/core/compile/testdata/sync/scalars/emptystruct.txtar create mode 100644 internal/core/compile/testdata/sync/scalars/yield.txtar diff --git a/cue/testdata/basicrewrite/000_errors.txtar b/cue/testdata/basicrewrite/000_errors.txtar index 92596fb96..92bc077cd 100644 --- a/cue/testdata/basicrewrite/000_errors.txtar +++ b/cue/testdata/basicrewrite/000_errors.txtar @@ -13,17 +13,6 @@ explicit error (_|_ literal) in source: ./in.cue:1:10 [user] explicit error (_|_ literal) in source: ./in.cue:2:11 --- out/compile -- ---- in.cue -{ - a: (_|_(explicit error (_|_ literal) in source) & _|_(explicit error (_|_ literal) in source)) - b: (null & _|_(explicit error (_|_ literal) in source)) - c: (〈0;b〉.a == _|_(explicit error (_|_ literal) in source)) - d: (_|_(explicit error (_|_ literal) in source) != 〈0;b〉.a) - e: (_|_(explicit error (_|_ literal) in source) == _|_(explicit error (_|_ literal) in source)) - f: (({} & false) == _|_(explicit error (_|_ literal) in source)) - g: (_|_(explicit error (_|_ literal) in source) != ({} & false)) -} -- out/eval/stats -- Leaks: 0 Freed: 10 diff --git a/cue/testdata/basicrewrite/001_regexp.txtar b/cue/testdata/basicrewrite/001_regexp.txtar index af62871c9..9936a6d53 100644 --- a/cue/testdata/basicrewrite/001_regexp.txtar +++ b/cue/testdata/basicrewrite/001_regexp.txtar @@ -37,29 +37,6 @@ e3: !="a" & <5 @test(err, code=eval, [eval] e3: conflicting values !="a" and <5 (mismatched types string and number): ./in.cue:24:5 ./in.cue:24:13 --- out/compile -- ---- in.cue -{ - c1: ("a" =~ "a") - c2: ("foo" =~ "[a-z]{3}") - c3: ("foo" =~ "[a-z]{4}") - c4: ("foo" !~ "[a-z]{4}") - b1: =~"a" - b1: "a" - b2: =~"[a-z]{3}" - b2: "foo" - b3: =~"[a-z]{4}" - b3: "foo" - b4: !~"[a-z]{4}" - b4: "foo" - s1: (!="b" & =~"c") - s2: (=~"c" & !="b") - s3: (!="b" & =~"[a-z]") - s4: (=~"[a-z]" & !="b") - e1: ("foo" =~ 1) - e2: ("foo" !~ true) - e3: (!="a" & <5) -} -- out/eval/stats -- Leaks: 0 Freed: 16 diff --git a/cue/testdata/basicrewrite/002_arithmetic.txtar b/cue/testdata/basicrewrite/002_arithmetic.txtar index 58afe7f0e..04b89e8d6 100644 --- a/cue/testdata/basicrewrite/002_arithmetic.txtar +++ b/cue/testdata/basicrewrite/002_arithmetic.txtar @@ -61,30 +61,3 @@ Retain: 0 Unifications: 24 Conjuncts: 26 Disjuncts: 24 --- out/compile -- ---- in.cue -{ - i1: (1 & int) - i2: (2 & int) - sum: (-1 + +2) - div1: ((2.0 / 3) * 6) - div2: ((2 / 3) * 6) - div3: (1.00 / 1.00) - divZero: (1.0 / 0) - div00: (0 / 0) - b: (1 != 4) - add: (〈0;div1〉 + 1.0) - idiv00: div(0, 0) - imod00: mod(0, 0) - iquo00: quo(0, 0) - irem00: rem(0, 0) - v1: (1000000000000 / 2.0) - v2: (2.0 == 2) - v3: (2.0 / 3.0) - v5: div(〈0;i1〉, 〈0;i2〉) - e0: (2 + "a") - e5: div(1.0, 2) - e6: rem(2, 2.0) - e7: quo(2, 2.0) - e8: mod(1.0, 1) -} diff --git a/cue/testdata/basicrewrite/003_integer-specific_arithmetic.txtar b/cue/testdata/basicrewrite/003_integer-specific_arithmetic.txtar index 2398797bb..3f72f362d 100644 --- a/cue/testdata/basicrewrite/003_integer-specific_arithmetic.txtar +++ b/cue/testdata/basicrewrite/003_integer-specific_arithmetic.txtar @@ -43,34 +43,6 @@ me2: mod(2, 1.0) @test(err, code=eval, pos=[0:13], contains="cannot use") ./in.cue:26:10 [eval] me2: cannot use 1.0 (type float) as int in argument 2 to mod: ./in.cue:27:13 --- out/compile -- ---- in.cue -{ - q1: quo(5, 2) - q2: quo(5, -2) - q3: quo(-5, 2) - q4: quo(-5, -2) - qe1: quo(2.0, 1) - qe2: quo(2, 1.0) - r1: rem(5, 2) - r2: rem(5, -2) - r3: rem(-5, 2) - r4: rem(-5, -2) - re1: rem(2.0, 1) - re2: rem(2, 1.0) - d1: div(5, 2) - d2: div(5, -2) - d3: div(-5, 2) - d4: div(-5, -2) - de1: div(2.0, 1) - de2: div(2, 1.0) - m1: mod(5, 2) - m2: mod(5, -2) - m3: mod(-5, 2) - m4: mod(-5, -2) - me1: mod(2.0, 1) - me2: mod(2, 1.0) -} -- out/eval/stats -- Leaks: 0 Freed: 25 diff --git a/cue/testdata/basicrewrite/004_booleans.txtar b/cue/testdata/basicrewrite/004_booleans.txtar index 81cc016b0..02039cfa9 100644 --- a/cue/testdata/basicrewrite/004_booleans.txtar +++ b/cue/testdata/basicrewrite/004_booleans.txtar @@ -9,16 +9,6 @@ e: !true [eval] e: conflicting values false and true: ./in.cue:5:4 ./in.cue:6:4 --- out/compile -- ---- in.cue -{ - t: true - t: !false - f: false - f: !〈0;t〉 - e: true - e: !true -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar b/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar index b7b921d2c..1e656f18c 100644 --- a/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar +++ b/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar @@ -9,16 +9,6 @@ f: true & false @test(err, code=eval, pos=[0:4, 0:11]) [eval] f: conflicting values false and true: ./in.cue:6:4 ./in.cue:6:11 --- out/compile -- ---- in.cue -{ - a: (true && true) - b: (true || false) - c: (false == true) - d: (false != true) - e: (true & true) - f: (true & false) -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/basicrewrite/006_basic_type.txtar b/cue/testdata/basicrewrite/006_basic_type.txtar index ddbbf2ca3..a2cbf1b9c 100644 --- a/cue/testdata/basicrewrite/006_basic_type.txtar +++ b/cue/testdata/basicrewrite/006_basic_type.txtar @@ -11,18 +11,6 @@ f: bool [eval] d: conflicting values int and float (mismatched types int and float): ./in.cue:5:4 ./in.cue:5:10 --- out/compile -- ---- in.cue -{ - a: (1 & int) - b: (number & 1) - c: 1.0 - c: float - d: (int & float) - e: ("4" & string) - f: true - f: bool -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/basicrewrite/007_strings_and_bytes.txtar b/cue/testdata/basicrewrite/007_strings_and_bytes.txtar index 2e15df50d..4f494ab51 100644 --- a/cue/testdata/basicrewrite/007_strings_and_bytes.txtar +++ b/cue/testdata/basicrewrite/007_strings_and_bytes.txtar @@ -17,18 +17,6 @@ e1: 'b' + "c" @test(err, code=eval) [eval] e1: invalid operands 'b' and "c" to '+' (type bytes and string): ./in.cue:11:5 ./in.cue:11:11 --- out/compile -- ---- in.cue -{ - s0: ("foo" + "bar") - s1: (3 * "abc") - s2: ("abc" * 2) - b0: ('foo' + 'bar') - b1: (3 * 'abc') - b2: ('abc' * 2) - e0: ("a" + '') - e1: ('b' + "c") -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/basicrewrite/008_escaping.txtar b/cue/testdata/basicrewrite/008_escaping.txtar index f03ad5870..88a1b9377 100644 --- a/cue/testdata/basicrewrite/008_escaping.txtar +++ b/cue/testdata/basicrewrite/008_escaping.txtar @@ -3,12 +3,6 @@ a: "foo\nbar" @test(eq, "foo\nbar") b: a @test(eq, "foo\nbar") // TODO: mimic http://exploringjs.com/es6/ch_template-literals.html#sec_introduction-template-literals --- out/compile -- ---- in.cue -{ - a: "foo\nbar" - b: 〈0;a〉 -} -- out/eval/stats -- Leaks: 0 Freed: 3 diff --git a/cue/testdata/basicrewrite/009_reference.txtar b/cue/testdata/basicrewrite/009_reference.txtar index d31f355bc..b6484fc7b 100644 --- a/cue/testdata/basicrewrite/009_reference.txtar +++ b/cue/testdata/basicrewrite/009_reference.txtar @@ -17,24 +17,6 @@ e: { v: e.v } } --- out/compile -- ---- in.cue -{ - a: 〈0;b〉 - b: 2 - d: { - d: 3 - e: 〈0;d〉 - } - e: { - e: { - v: 1 - } - f: { - v: 〈1;e〉.v - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/basicrewrite/010_lists.txtar b/cue/testdata/basicrewrite/010_lists.txtar index 6f1a4f012..879bf88d2 100644 --- a/cue/testdata/basicrewrite/010_lists.txtar +++ b/cue/testdata/basicrewrite/010_lists.txtar @@ -24,56 +24,6 @@ e5: [1, 2, 4, 8] & [1, 2, ...>=4 & <=5] @test(err, code=eval, pos=[0:39, 0:18 [eval] e5.3: invalid value 8 (out of bound <=5): ./in.cue:10:39 ./in.cue:10:18 --- out/compile -- ---- in.cue -{ - list: [ - 1, - 2, - 3, - ] - index: [ - 1, - 2, - 3, - ][1] - unify: ([ - 1, - 2, - 3, - ] & [ - _, - 2, - 3, - ]) - e: ([] & 4) - e2: [ - 3, - ]["d"] - e3: [ - 3, - ][-1] - e4: ([ - 1, - 2, - ...(>=4 & <=5), - ] & [ - 1, - 2, - 4, - 8, - ]) - e5: ([ - 1, - 2, - 4, - 8, - ] & [ - 1, - 2, - ...(>=4 & <=5), - ]) -} -- out/eval/stats -- Leaks: 4 Freed: 23 diff --git a/cue/testdata/basicrewrite/012_selecting.txtar b/cue/testdata/basicrewrite/012_selecting.txtar index ca444a448..31405bbfa 100644 --- a/cue/testdata/basicrewrite/012_selecting.txtar +++ b/cue/testdata/basicrewrite/012_selecting.txtar @@ -18,37 +18,6 @@ h: [3].b @test(err, code=eval, pos=[0:13]) -- todo.txt -- Some error messages could use improvement. Address after query extension is implemented. --- out/compile -- ---- in.cue -{ - obj: { - a: 1 - b: 2 - } - index: { - a: 1 - b: 2 - }["b"] - mulidx: { - a: 1 - b: { - a: 1 - b: 3 - } - }["b"]["b"] - e: { - a: 1 - }[4] - f: { - a: 1 - }.b - g: { - a: 1 - }["b"] - h: [ - 3, - ].b -} -- out/eval/stats -- Leaks: 9 Freed: 10 diff --git a/cue/testdata/basicrewrite/013_obj_unify.txtar b/cue/testdata/basicrewrite/013_obj_unify.txtar index 6a4d00acc..ceecd7a7d 100644 --- a/cue/testdata/basicrewrite/013_obj_unify.txtar +++ b/cue/testdata/basicrewrite/013_obj_unify.txtar @@ -12,48 +12,6 @@ e: {a: 3} [eval] e: conflicting values 1 and {a:3} (mismatched types int and struct): ./in.cue:8:4 ./in.cue:9:4 --- out/compile -- ---- in.cue -{ - o1: ({ - a: 1 - } & { - b: 2 - }) - o2: ({ - a: 1 - b: 2 - } & { - b: 2 - }) - o3: ({ - a: 1 - } & { - a: 1 - b: 2 - }) - o4: ({ - a: 1 - } & { - b: 2 - }) - o4: ({ - a: 1 - b: 2 - } & { - b: 2 - }) - o4: ({ - a: 1 - } & { - a: 1 - b: 2 - }) - e: 1 - e: { - a: 3 - } -} -- out/eval/stats -- Leaks: 0 Freed: 15 diff --git a/cue/testdata/basicrewrite/014_disjunctions.txtar b/cue/testdata/basicrewrite/014_disjunctions.txtar index 89b0b5931..c64de189f 100644 --- a/cue/testdata/basicrewrite/014_disjunctions.txtar +++ b/cue/testdata/basicrewrite/014_disjunctions.txtar @@ -39,26 +39,3 @@ Retain: 1 Unifications: 18 Conjuncts: 150 Disjuncts: 135 --- out/compile -- ---- in.cue -{ - o1: (1|2|3) - o2: ((1|2|3) & 1) - o3: (2 & (1|*2|3)) - o4: ((1|*2|3) & (1|2|*3)) - o5: ((1|*2|3) & (3|*2|1)) - o6: ((1|2|3) & (3|1|2)) - o7: ((1|2|3) & (2|3)) - o8: ((1|2|3) & (3|2)) - o9: ((2|3) & (1|2|3)) - o10: ((3|2) & (1|*2|3)) - m1: ((1|(*2|3)) & (>=2 & <=3)) - m2: ((1|(*2|3)) & (2|3)) - m3: ((*1|*(*2|3)) & (2|3)) - m4: ((2|3) & (*2|3)) - m5: ((*2|3) & (2|3)) - i1: ([ - 1, - 2, - ][3]|"c") -} diff --git a/cue/testdata/basicrewrite/015_types.txtar b/cue/testdata/basicrewrite/015_types.txtar index b25eb4e32..556c8b706 100644 --- a/cue/testdata/basicrewrite/015_types.txtar +++ b/cue/testdata/basicrewrite/015_types.txtar @@ -21,19 +21,6 @@ m: -false @test(err, code=eval, pos=[0:5], contains="invalid operation") ./in.cue:8:5 [eval] m: invalid operation -false (- bool): ./in.cue:9:5 --- out/compile -- ---- in.cue -{ - i: int - j: (int & 3) - s: string - t: ("s" & string) - e: (int & string) - e2: (1 & string) - b: !int - p: +true - m: -false -} -- out/eval/stats -- Leaks: 0 Freed: 10 diff --git a/cue/testdata/basicrewrite/016_comparison.txtar b/cue/testdata/basicrewrite/016_comparison.txtar index b3869a2e1..a72c9597b 100644 --- a/cue/testdata/basicrewrite/016_comparison.txtar +++ b/cue/testdata/basicrewrite/016_comparison.txtar @@ -230,602 +230,6 @@ lists.eErrPassthrough: invalid right-hand value to '==' (type list): 1: conflict -- out/diff-v2-v3.txt -- lists.eIncompat: v3 reports "incomplete" (list element type is abstract) while v2 reports "eval" (permanent type mismatch [int] vs [string]). Verdict: worsening -- v3 does not yet promote the type mismatch to a permanent eval error. --- out/compile -- ---- in.cue -{ - numbers: { - tLss: (1 < 2) - tLeq: (1 <= 1.0) - tLeq: (2.0 <= 3) - tEql: (1 == 1.0) - tNeq: (1.0 == 1) - tGeq: (2.0 >= 2) - tGtr: !(2 > 3) - tExpr: (("a" + "b") == "ab") - } -} ---- lists.cue -{ - lists: { - t1: ([] == []) - t2: ([ - 1, - 2, - 3, - ] == [ - 1, - 2, - 3, - ]) - t3: ([ - 1, - "foo", - true, - ] == [ - 1, - "foo", - true, - ]) - t4: ([ - [ - 1, - 2, - ], - [ - 3, - 4, - ], - ] == [ - [ - 1, - 2, - ], - [ - 3, - 4, - ], - ]) - t5: (([ - 1, - ...int, - ] & [ - 1, - 2, - 3, - ]) == [ - 1, - 2, - 3, - ]) - t6: ([ - 1, - ] == ([ - ...1, - ] & [ - _, - ])) - t7: ([ - { - a: 1 - }, - ] == ([ - ...{ - a: 1 - }, - ] & [ - _, - ])) - t8: ([ - { - a: 1 - }, - ] != [ - ...{ - a: 1 - }, - ]) - t9: ([ - ...int, - ] == [ - ...string, - ]) - f1: ([ - 1, - 2, - 3, - ] == [ - 1, - 2, - 4, - ]) - f2: ([ - 1, - 2, - 3, - ] == [ - 1, - 2, - ]) - f3: ([ - 1, - 2, - 3, - ] == [ - 1, - 3, - 2, - ]) - f4: ([] == [ - 1, - ]) - f5: ([ - 1, - 2, - ] == [ - 1, - "2", - ]) - f6: ([ - (*1|2|3), - ] == [ - (*2|3|4), - ]) - eIncompat: ([ - int, - ] == [ - string, - ]) - eErrPassthrough: ([ - (1 / 0), - ] == [ - 1, - ]) - _e3l: {} - eErrPassthrough: ([ - 〈1;_e3l〉.b, - ] == [ - 1, - ]) - eErrPassthrough: ([ - 1, - 2, - ] == [ - 1, - (int & string), - ]) - tNeq1: ([ - 1, - 2, - ] != [ - 1, - 3, - ]) - fNeq2: ([ - 1, - 2, - ] != [ - 1, - 2, - ]) - } -} ---- structs.cue -{ - structs: { - eq: { - t1: ({} == {}) - t2: ({ - a: 1 - b: "foo" - } == { - a: 1 - b: "foo" - }) - t3: ({ - a: 1 - b: 2 - } == { - b: 2 - a: 1 - }) - t4: ({ - a: { - x: 1 - y: 2 - } - } == { - a: { - x: 1 - y: 2 - } - }) - t5: (({ - a: 1 - b: 2 - c: 3 - } & { - d: 4 - }) == { - a: 1 - b: 2 - c: 3 - d: 4 - }) - t6: ({ - { - { - { - a: 1 - } - } - } - } == { - { - a: 1 - } - }) - t7: ({ - [string]: int - } == { - [string]: string - }) - _t8l: (*1|2|3) - t8: ({ - a: 〈1;_t8l〉 - } == { - a: (3|*1) - }) - f1: ({ - a: 1 - b: "foo" - } == { - a: 2 - b: "foo" - }) - f2: ({ - a: 1 - b: "foo" - } == { - a: 1 - c: "foo" - }) - f3: ({ - a: { - x: 1 - } - } == { - a: { - x: 2 - } - }) - f4: ({ - a: 1 - b: 2 - } == { - a: 1 - }) - f5: ({} == { - a: 1 - }) - f6: ({ - a: 1 - } == 1) - f7: ({ - a: 1 - b?: 2 - } == { - a: 1 - b: 2 - }) - f8: ({ - { - { - { - a: 1 - } - } - } - } == { - { - a: 1 - b: 2 - } - }) - _f9r: (*2|3|4) - f9: ({ - a: (*1|2|3) - } == { - a: 〈1;_f9r〉 - }) - tNe1: ({ - a: 1 - } != { - a: 2 - }) - fNe1: ({ - a: 2 - } != { - a: 2 - }) - } - } - ignore: { - t0: ({ - _hidden: 1 - } == { - _hidden: 2 - }) - t1: ({ - _hidden: 1 - } == {}) - t1: ({} == { - _hidden: 1 - }) - t2: ({ - #def: 1 - } == { - #def: 2 - }) - t3: ({ - #def: 1 - } == {}) - t4: ({} == { - #def: 1 - }) - t5: ({ - _#hiddenDef: 1 - } == { - _#hiddenDef: 2 - }) - t6: ({ - _#hiddenDef: 1 - } == {}) - t7: ({} == { - _#hiddenDef: 1 - }) - f0: ({ - _hidden: 1 - } != { - _hidden: 2 - }) - f1: ({ - _hidden: 1 - } != {}) - f1: ({} != { - _hidden: 1 - }) - f2: ({ - #def: 1 - } != { - #def: 2 - }) - f3: ({ - #def: 1 - } != {}) - f4: ({} != { - #def: 1 - }) - f5: ({ - _#hiddenDef: 1 - } != { - _#hiddenDef: 2 - }) - f6: ({ - _#hiddenDef: 1 - } != {}) - f7: ({} != { - _#hiddenDef: 1 - }) - } - embeddedScalars: { - _one: 1 - _two: 2 - t1: (1 == { - 1 - }) - t2: ([ - 1, - ] == [ - { - 1 - }, - ]) - t3: ({ - a: 1 - } == { - a: { - 1 - } - }) - t4: ([ - 〈1;_one〉, - ] == [ - { - 〈2;_one〉 - }, - ]) - f1: (〈0;_one〉 == [ - { - 〈2;_two〉 - }, - ]) - f2: ({ - a: 〈1;_two〉 - } == { - a: { - 〈2;_one〉 - } - }) - f3: (〈0;_one〉 == { - 〈1;_two〉 - }) - f4: ([ - 〈1;_two〉, - ] == [ - { - 〈2;_one〉 - }, - ]) - } - incomplete: { - _int: int - _string: string - iErr1: ({ - a!: 〈1;_int〉 - } == { - a!: 〈1;_int〉 - }) - iErr2: ({ - a!: 〈1;_int〉 - } == { - a!: 1 - }) - eErr3: ({ - a: 〈1;_int〉 - } == { - a: 〈1;_string〉 - }) - eErr4: ({ - a: (1 / 0) - } == { - a: 1 - }) - eErr5: ({ - a: 1 - } == { - a: (〈1;_int〉 & 〈1;_string〉) - }) - iErr6: ({ - a!: 1 - } == { - a: 1 - }) - eErr7: ({ - a: 1 - } == { - a!: 2 - }) - tNe1: ({ - a: 1 - } != { - a: 2 - }) - fNe1: ({ - a: 2 - } != { - a: 2 - }) - } -} ---- typediff.cue -{ - diffTypes: { - fScalar1: (2 == "s") - fScalar2: ("s" == 2) - fScalar3: (true == 2) - fStruct1: ({ - a: 1 - } == "s") - fList1: (5 == [ - 5, - ]) - fList2: ("ab" == [ - "a", - "b", - ]) - fList3: (true == [ - true, - ]) - fList4: ({ - a: 1 - } == [ - { - a: 1 - }, - ]) - fList5: ([ - 1, - 2, - ] == 3) - fList6: ([ - 1, - 2, - ] == "ab") - fList7: ([ - true, - ] == false) - fList8: ([ - 1, - 2, - ] == { - a: 1 - }) - fList9: ([ - 1, - 2, - ] == null) - tNeList1: ([ - 1, - 2, - ] != 3) - tNeList2: ([ - 1, - 2, - ] != "ab") - _int: int - _string: string - iRecursive1: ([ - 〈1;_int〉, - ] == [ - 〈1;_int〉, - ]) - eRecursive2: ([ - 〈1;_int〉, - ] == [ - 〈1;_string〉, - ]) - fRecursive3: ([ - 1, - 2, - ] == [ - 1, - "2", - ]) - tRecursive4: ([ - ...int, - ] == [ - ...string, - ]) - fRecursive5: ([ - 1, - "a", - ] == [ - 1, - 2, - ]) - eNe1: ([ - 1, - 2, - ] != [ - 〈1;_int〉, - ]) - iNe2: ([ - 〈1;_int〉, - ] != [ - 1, - ]) - iNe3: ({ - a: 1 - } != { - a: 〈1;_int〉 - }) - iNe4: ({ - a: 〈1;_int〉 - } != { - a: 1 - }) - } -} -- out/eval/stats -- Leaks: 0 Freed: 547 diff --git a/cue/testdata/basicrewrite/017_null.txtar b/cue/testdata/basicrewrite/017_null.txtar index dd5fd9e5f..5e3655994 100644 --- a/cue/testdata/basicrewrite/017_null.txtar +++ b/cue/testdata/basicrewrite/017_null.txtar @@ -11,17 +11,6 @@ call: null() @test(err, code=eval, pos=[0:7], contains="cannot call non-fun -- out/errors.txt -- [eval] call: cannot call non-function null (type null): ./in.cue:9:7 --- out/compile -- ---- in.cue -{ - eql: (null == null) - neq: (null != null) - unf: (null & null) - eq1: (null == 1) - eq2: (1 == null) - ne1: ("s" != null) - call: null() -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/basicrewrite/018_self-reference_cycles.txtar b/cue/testdata/basicrewrite/018_self-reference_cycles.txtar index cf9ef1543..f0fbc6e6c 100644 --- a/cue/testdata/basicrewrite/018_self-reference_cycles.txtar +++ b/cue/testdata/basicrewrite/018_self-reference_cycles.txtar @@ -196,74 +196,3 @@ Conjuncts: 91 Disjuncts: 10 NumCloseIDs: 10 --- out/compile -- ---- disjunction.cue -{ - oneway: { - t1: { - a: (*1|int) - a: (〈0;b〉 + 1) - b: <〈0;a〉 - } - t2: (〈0;t1〉 & { - a: 3 - }) - } - issue3669: { - #Schema: { - two: (1 + 〈0;one〉) - one: (〈0;two〉 - 1) - } - out: (〈0;#Schema〉 & { - two: (0|*2) - }) - } -} ---- in.cue -{ - a: (〈0;b〉 - 100) - b: (〈0;a〉 + 100) - c: [ - 〈1;c〉[1], - 〈1;c〉[0], - ] - d: (〈0;e〉 - 1) - e: (1 + 〈0;d〉) - e: (*2|0) -} ---- issue3737.cue -{ - issue3737: { - reduced1: { - #A: { - a: (〈0;b〉 * 12) - b: (〈0;a〉 / 12) - } - x: 〈0;#A〉 - x: { - b: 1000.0 - } - y: (〈0;#A〉|*〈0;x〉) - y: { - b: (〈1;x〉.b * 0.7) - } - } - } - issue3737: { - reduced2: { - x: (〈0;#TimeSpan〉 & { - start: 〈1;y〉.start - end: 1000.0 - }) - y: (〈0;#TimeSpan〉 & { - duration: 100.0 - end: 〈1;x〉.end - }) - #TimeSpan: { - start: (〈0;end〉 - 〈0;duration〉) - duration: (〈0;end〉 - 〈0;start〉) - end: (〈0;start〉 + 〈0;duration〉) - } - } - } -} diff --git a/cue/testdata/basicrewrite/019_resolved_self-reference_cycles.txtar b/cue/testdata/basicrewrite/019_resolved_self-reference_cycles.txtar index 069db87d0..8b389aa1b 100644 --- a/cue/testdata/basicrewrite/019_resolved_self-reference_cycles.txtar +++ b/cue/testdata/basicrewrite/019_resolved_self-reference_cycles.txtar @@ -51,81 +51,3 @@ Retain: 10 Unifications: 62 Conjuncts: 105 Disjuncts: 70 --- out/compile -- ---- in.cue -{ - math: { - a: (〈0;b〉 - 100) - b: (〈0;a〉 + 100) - b: 200 - } - a: 100 - list: { - t0: { - c: [ - 〈1;c〉[0], - ] - } - } - list: { - t1: { - p1: { - c: [ - 〈1;c〉[1], - 〈4;a〉, - ] - } - } - } - list: { - t1: { - p2: { - c: [ - 〈4;a〉, - 〈1;c〉[0], - ] - } - } - } - nodes: { - t1: { - p1: { - s1: (〈0;s1〉 & { - a: 1 - }) - } - } - } - nodes: { - t1: { - p2: { - s1: ({ - a: 1 - } & 〈0;s1〉) - } - } - } - nodes: { - t2: { - s1: (〈0;s2〉 & { - a: 1 - }) - s2: (〈0;s1〉 & { - b: 2 - }) - } - } - nodes: { - t3: { - s1: (〈0;s2〉 & { - a: 1 - }) - s2: (〈0;s3〉 & { - b: 2 - }) - s3: (〈0;s1〉 & { - c: 3 - }) - } - } -} diff --git a/cue/testdata/basicrewrite/020_resolved_self-reference_cycles__Issue_19.txtar b/cue/testdata/basicrewrite/020_resolved_self-reference_cycles__Issue_19.txtar index 572187855..744c42be8 100644 --- a/cue/testdata/basicrewrite/020_resolved_self-reference_cycles__Issue_19.txtar +++ b/cue/testdata/basicrewrite/020_resolved_self-reference_cycles__Issue_19.txtar @@ -10,17 +10,6 @@ z3: z1 - 3 @test(eq, 8) z3: 8 // TODO: extensive tests with disjunctions. --- out/compile -- ---- in.cue -{ - x: (〈0;y〉 + 100) - y: (〈0;x〉 - 100) - x: 200 - z1: (〈0;z2〉 + 1) - z2: (〈0;z3〉 + 2) - z3: (〈0;z1〉 - 3) - z3: 8 -} -- out/eval/stats -- Leaks: 0 Freed: 6 diff --git a/cue/testdata/basicrewrite/aliases/aliases.txtar b/cue/testdata/basicrewrite/aliases/aliases.txtar index 1e647a9c4..d5ef30af6 100644 --- a/cue/testdata/basicrewrite/aliases/aliases.txtar +++ b/cue/testdata/basicrewrite/aliases/aliases.txtar @@ -18,20 +18,6 @@ t1: { let b = 3 d: 3 }) --- out/compile -- ---- in.cue -{ - t0: { - _a: _ - let _b#1 = 〈0;_a〉 - _out: 〈0;let _b#1〉 - } - t1: { - _a: 〈0;let b#2〉 - let b#2 = 〈0;d〉 - d: 3 - } -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/benchmarks/chain.txtar b/cue/testdata/benchmarks/chain.txtar index 3d7e7a84a..92feb8128 100644 --- a/cue/testdata/benchmarks/chain.txtar +++ b/cue/testdata/benchmarks/chain.txtar @@ -1000,1010 +1000,6 @@ f997: f996 f998: f997 f999: f998 f1000: f999 @test(eq, string) --- out/compile -- ---- in.cue -{ - f1: string - f2: 〈0;f1〉 - f3: 〈0;f2〉 - f4: 〈0;f3〉 - f5: 〈0;f4〉 - f6: 〈0;f5〉 - f7: 〈0;f6〉 - f8: 〈0;f7〉 - f9: 〈0;f8〉 - f10: 〈0;f9〉 - f11: 〈0;f10〉 - f12: 〈0;f11〉 - f13: 〈0;f12〉 - f14: 〈0;f13〉 - f15: 〈0;f14〉 - f16: 〈0;f15〉 - f17: 〈0;f16〉 - f18: 〈0;f17〉 - f19: 〈0;f18〉 - f20: 〈0;f19〉 - f21: 〈0;f20〉 - f22: 〈0;f21〉 - f23: 〈0;f22〉 - f24: 〈0;f23〉 - f25: 〈0;f24〉 - f26: 〈0;f25〉 - f27: 〈0;f26〉 - f28: 〈0;f27〉 - f29: 〈0;f28〉 - f30: 〈0;f29〉 - f31: 〈0;f30〉 - f32: 〈0;f31〉 - f33: 〈0;f32〉 - f34: 〈0;f33〉 - f35: 〈0;f34〉 - f36: 〈0;f35〉 - f37: 〈0;f36〉 - f38: 〈0;f37〉 - f39: 〈0;f38〉 - f40: 〈0;f39〉 - f41: 〈0;f40〉 - f42: 〈0;f41〉 - f43: 〈0;f42〉 - f44: 〈0;f43〉 - f45: 〈0;f44〉 - f46: 〈0;f45〉 - f47: 〈0;f46〉 - f48: 〈0;f47〉 - f49: 〈0;f48〉 - f50: 〈0;f49〉 - f51: 〈0;f50〉 - f52: 〈0;f51〉 - f53: 〈0;f52〉 - f54: 〈0;f53〉 - f55: 〈0;f54〉 - f56: 〈0;f55〉 - f57: 〈0;f56〉 - f58: 〈0;f57〉 - f59: 〈0;f58〉 - f60: 〈0;f59〉 - f61: 〈0;f60〉 - f62: 〈0;f61〉 - f63: 〈0;f62〉 - f64: 〈0;f63〉 - f65: 〈0;f64〉 - f66: 〈0;f65〉 - f67: 〈0;f66〉 - f68: 〈0;f67〉 - f69: 〈0;f68〉 - f70: 〈0;f69〉 - f71: 〈0;f70〉 - f72: 〈0;f71〉 - f73: 〈0;f72〉 - f74: 〈0;f73〉 - f75: 〈0;f74〉 - f76: 〈0;f75〉 - f77: 〈0;f76〉 - f78: 〈0;f77〉 - f79: 〈0;f78〉 - f80: 〈0;f79〉 - f81: 〈0;f80〉 - f82: 〈0;f81〉 - f83: 〈0;f82〉 - f84: 〈0;f83〉 - f85: 〈0;f84〉 - f86: 〈0;f85〉 - f87: 〈0;f86〉 - f88: 〈0;f87〉 - f89: 〈0;f88〉 - f90: 〈0;f89〉 - f91: 〈0;f90〉 - f92: 〈0;f91〉 - f93: 〈0;f92〉 - f94: 〈0;f93〉 - f95: 〈0;f94〉 - f96: 〈0;f95〉 - f97: 〈0;f96〉 - f98: 〈0;f97〉 - f99: 〈0;f98〉 - f100: 〈0;f99〉 - f101: 〈0;f100〉 - f102: 〈0;f101〉 - f103: 〈0;f102〉 - f104: 〈0;f103〉 - f105: 〈0;f104〉 - f106: 〈0;f105〉 - f107: 〈0;f106〉 - f108: 〈0;f107〉 - f109: 〈0;f108〉 - f110: 〈0;f109〉 - f111: 〈0;f110〉 - f112: 〈0;f111〉 - f113: 〈0;f112〉 - f114: 〈0;f113〉 - f115: 〈0;f114〉 - f116: 〈0;f115〉 - f117: 〈0;f116〉 - f118: 〈0;f117〉 - f119: 〈0;f118〉 - f120: 〈0;f119〉 - f121: 〈0;f120〉 - f122: 〈0;f121〉 - f123: 〈0;f122〉 - f124: 〈0;f123〉 - f125: 〈0;f124〉 - f126: 〈0;f125〉 - f127: 〈0;f126〉 - f128: 〈0;f127〉 - f129: 〈0;f128〉 - f130: 〈0;f129〉 - f131: 〈0;f130〉 - f132: 〈0;f131〉 - f133: 〈0;f132〉 - f134: 〈0;f133〉 - f135: 〈0;f134〉 - f136: 〈0;f135〉 - f137: 〈0;f136〉 - f138: 〈0;f137〉 - f139: 〈0;f138〉 - f140: 〈0;f139〉 - f141: 〈0;f140〉 - f142: 〈0;f141〉 - f143: 〈0;f142〉 - f144: 〈0;f143〉 - f145: 〈0;f144〉 - f146: 〈0;f145〉 - f147: 〈0;f146〉 - f148: 〈0;f147〉 - f149: 〈0;f148〉 - f150: 〈0;f149〉 - f151: 〈0;f150〉 - f152: 〈0;f151〉 - f153: 〈0;f152〉 - f154: 〈0;f153〉 - f155: 〈0;f154〉 - f156: 〈0;f155〉 - f157: 〈0;f156〉 - f158: 〈0;f157〉 - f159: 〈0;f158〉 - f160: 〈0;f159〉 - f161: 〈0;f160〉 - f162: 〈0;f161〉 - f163: 〈0;f162〉 - f164: 〈0;f163〉 - f165: 〈0;f164〉 - f166: 〈0;f165〉 - f167: 〈0;f166〉 - f168: 〈0;f167〉 - f169: 〈0;f168〉 - f170: 〈0;f169〉 - f171: 〈0;f170〉 - f172: 〈0;f171〉 - f173: 〈0;f172〉 - f174: 〈0;f173〉 - f175: 〈0;f174〉 - f176: 〈0;f175〉 - f177: 〈0;f176〉 - f178: 〈0;f177〉 - f179: 〈0;f178〉 - f180: 〈0;f179〉 - f181: 〈0;f180〉 - f182: 〈0;f181〉 - f183: 〈0;f182〉 - f184: 〈0;f183〉 - f185: 〈0;f184〉 - f186: 〈0;f185〉 - f187: 〈0;f186〉 - f188: 〈0;f187〉 - f189: 〈0;f188〉 - f190: 〈0;f189〉 - f191: 〈0;f190〉 - f192: 〈0;f191〉 - f193: 〈0;f192〉 - f194: 〈0;f193〉 - f195: 〈0;f194〉 - f196: 〈0;f195〉 - f197: 〈0;f196〉 - f198: 〈0;f197〉 - f199: 〈0;f198〉 - f200: 〈0;f199〉 - f201: 〈0;f200〉 - f202: 〈0;f201〉 - f203: 〈0;f202〉 - f204: 〈0;f203〉 - f205: 〈0;f204〉 - f206: 〈0;f205〉 - f207: 〈0;f206〉 - f208: 〈0;f207〉 - f209: 〈0;f208〉 - f210: 〈0;f209〉 - f211: 〈0;f210〉 - f212: 〈0;f211〉 - f213: 〈0;f212〉 - f214: 〈0;f213〉 - f215: 〈0;f214〉 - f216: 〈0;f215〉 - f217: 〈0;f216〉 - f218: 〈0;f217〉 - f219: 〈0;f218〉 - f220: 〈0;f219〉 - f221: 〈0;f220〉 - f222: 〈0;f221〉 - f223: 〈0;f222〉 - f224: 〈0;f223〉 - f225: 〈0;f224〉 - f226: 〈0;f225〉 - f227: 〈0;f226〉 - f228: 〈0;f227〉 - f229: 〈0;f228〉 - f230: 〈0;f229〉 - f231: 〈0;f230〉 - f232: 〈0;f231〉 - f233: 〈0;f232〉 - f234: 〈0;f233〉 - f235: 〈0;f234〉 - f236: 〈0;f235〉 - f237: 〈0;f236〉 - f238: 〈0;f237〉 - f239: 〈0;f238〉 - f240: 〈0;f239〉 - f241: 〈0;f240〉 - f242: 〈0;f241〉 - f243: 〈0;f242〉 - f244: 〈0;f243〉 - f245: 〈0;f244〉 - f246: 〈0;f245〉 - f247: 〈0;f246〉 - f248: 〈0;f247〉 - f249: 〈0;f248〉 - f250: 〈0;f249〉 - f251: 〈0;f250〉 - f252: 〈0;f251〉 - f253: 〈0;f252〉 - f254: 〈0;f253〉 - f255: 〈0;f254〉 - f256: 〈0;f255〉 - f257: 〈0;f256〉 - f258: 〈0;f257〉 - f259: 〈0;f258〉 - f260: 〈0;f259〉 - f261: 〈0;f260〉 - f262: 〈0;f261〉 - f263: 〈0;f262〉 - f264: 〈0;f263〉 - f265: 〈0;f264〉 - f266: 〈0;f265〉 - f267: 〈0;f266〉 - f268: 〈0;f267〉 - f269: 〈0;f268〉 - f270: 〈0;f269〉 - f271: 〈0;f270〉 - f272: 〈0;f271〉 - f273: 〈0;f272〉 - f274: 〈0;f273〉 - f275: 〈0;f274〉 - f276: 〈0;f275〉 - f277: 〈0;f276〉 - f278: 〈0;f277〉 - f279: 〈0;f278〉 - f280: 〈0;f279〉 - f281: 〈0;f280〉 - f282: 〈0;f281〉 - f283: 〈0;f282〉 - f284: 〈0;f283〉 - f285: 〈0;f284〉 - f286: 〈0;f285〉 - f287: 〈0;f286〉 - f288: 〈0;f287〉 - f289: 〈0;f288〉 - f290: 〈0;f289〉 - f291: 〈0;f290〉 - f292: 〈0;f291〉 - f293: 〈0;f292〉 - f294: 〈0;f293〉 - f295: 〈0;f294〉 - f296: 〈0;f295〉 - f297: 〈0;f296〉 - f298: 〈0;f297〉 - f299: 〈0;f298〉 - f300: 〈0;f299〉 - f301: 〈0;f300〉 - f302: 〈0;f301〉 - f303: 〈0;f302〉 - f304: 〈0;f303〉 - f305: 〈0;f304〉 - f306: 〈0;f305〉 - f307: 〈0;f306〉 - f308: 〈0;f307〉 - f309: 〈0;f308〉 - f310: 〈0;f309〉 - f311: 〈0;f310〉 - f312: 〈0;f311〉 - f313: 〈0;f312〉 - f314: 〈0;f313〉 - f315: 〈0;f314〉 - f316: 〈0;f315〉 - f317: 〈0;f316〉 - f318: 〈0;f317〉 - f319: 〈0;f318〉 - f320: 〈0;f319〉 - f321: 〈0;f320〉 - f322: 〈0;f321〉 - f323: 〈0;f322〉 - f324: 〈0;f323〉 - f325: 〈0;f324〉 - f326: 〈0;f325〉 - f327: 〈0;f326〉 - f328: 〈0;f327〉 - f329: 〈0;f328〉 - f330: 〈0;f329〉 - f331: 〈0;f330〉 - f332: 〈0;f331〉 - f333: 〈0;f332〉 - f334: 〈0;f333〉 - f335: 〈0;f334〉 - f336: 〈0;f335〉 - f337: 〈0;f336〉 - f338: 〈0;f337〉 - f339: 〈0;f338〉 - f340: 〈0;f339〉 - f341: 〈0;f340〉 - f342: 〈0;f341〉 - f343: 〈0;f342〉 - f344: 〈0;f343〉 - f345: 〈0;f344〉 - f346: 〈0;f345〉 - f347: 〈0;f346〉 - f348: 〈0;f347〉 - f349: 〈0;f348〉 - f350: 〈0;f349〉 - f351: 〈0;f350〉 - f352: 〈0;f351〉 - f353: 〈0;f352〉 - f354: 〈0;f353〉 - f355: 〈0;f354〉 - f356: 〈0;f355〉 - f357: 〈0;f356〉 - f358: 〈0;f357〉 - f359: 〈0;f358〉 - f360: 〈0;f359〉 - f361: 〈0;f360〉 - f362: 〈0;f361〉 - f363: 〈0;f362〉 - f364: 〈0;f363〉 - f365: 〈0;f364〉 - f366: 〈0;f365〉 - f367: 〈0;f366〉 - f368: 〈0;f367〉 - f369: 〈0;f368〉 - f370: 〈0;f369〉 - f371: 〈0;f370〉 - f372: 〈0;f371〉 - f373: 〈0;f372〉 - f374: 〈0;f373〉 - f375: 〈0;f374〉 - f376: 〈0;f375〉 - f377: 〈0;f376〉 - f378: 〈0;f377〉 - f379: 〈0;f378〉 - f380: 〈0;f379〉 - f381: 〈0;f380〉 - f382: 〈0;f381〉 - f383: 〈0;f382〉 - f384: 〈0;f383〉 - f385: 〈0;f384〉 - f386: 〈0;f385〉 - f387: 〈0;f386〉 - f388: 〈0;f387〉 - f389: 〈0;f388〉 - f390: 〈0;f389〉 - f391: 〈0;f390〉 - f392: 〈0;f391〉 - f393: 〈0;f392〉 - f394: 〈0;f393〉 - f395: 〈0;f394〉 - f396: 〈0;f395〉 - f397: 〈0;f396〉 - f398: 〈0;f397〉 - f399: 〈0;f398〉 - f400: 〈0;f399〉 - f401: 〈0;f400〉 - f402: 〈0;f401〉 - f403: 〈0;f402〉 - f404: 〈0;f403〉 - f405: 〈0;f404〉 - f406: 〈0;f405〉 - f407: 〈0;f406〉 - f408: 〈0;f407〉 - f409: 〈0;f408〉 - f410: 〈0;f409〉 - f411: 〈0;f410〉 - f412: 〈0;f411〉 - f413: 〈0;f412〉 - f414: 〈0;f413〉 - f415: 〈0;f414〉 - f416: 〈0;f415〉 - f417: 〈0;f416〉 - f418: 〈0;f417〉 - f419: 〈0;f418〉 - f420: 〈0;f419〉 - f421: 〈0;f420〉 - f422: 〈0;f421〉 - f423: 〈0;f422〉 - f424: 〈0;f423〉 - f425: 〈0;f424〉 - f426: 〈0;f425〉 - f427: 〈0;f426〉 - f428: 〈0;f427〉 - f429: 〈0;f428〉 - f430: 〈0;f429〉 - f431: 〈0;f430〉 - f432: 〈0;f431〉 - f433: 〈0;f432〉 - f434: 〈0;f433〉 - f435: 〈0;f434〉 - f436: 〈0;f435〉 - f437: 〈0;f436〉 - f438: 〈0;f437〉 - f439: 〈0;f438〉 - f440: 〈0;f439〉 - f441: 〈0;f440〉 - f442: 〈0;f441〉 - f443: 〈0;f442〉 - f444: 〈0;f443〉 - f445: 〈0;f444〉 - f446: 〈0;f445〉 - f447: 〈0;f446〉 - f448: 〈0;f447〉 - f449: 〈0;f448〉 - f450: 〈0;f449〉 - f451: 〈0;f450〉 - f452: 〈0;f451〉 - f453: 〈0;f452〉 - f454: 〈0;f453〉 - f455: 〈0;f454〉 - f456: 〈0;f455〉 - f457: 〈0;f456〉 - f458: 〈0;f457〉 - f459: 〈0;f458〉 - f460: 〈0;f459〉 - f461: 〈0;f460〉 - f462: 〈0;f461〉 - f463: 〈0;f462〉 - f464: 〈0;f463〉 - f465: 〈0;f464〉 - f466: 〈0;f465〉 - f467: 〈0;f466〉 - f468: 〈0;f467〉 - f469: 〈0;f468〉 - f470: 〈0;f469〉 - f471: 〈0;f470〉 - f472: 〈0;f471〉 - f473: 〈0;f472〉 - f474: 〈0;f473〉 - f475: 〈0;f474〉 - f476: 〈0;f475〉 - f477: 〈0;f476〉 - f478: 〈0;f477〉 - f479: 〈0;f478〉 - f480: 〈0;f479〉 - f481: 〈0;f480〉 - f482: 〈0;f481〉 - f483: 〈0;f482〉 - f484: 〈0;f483〉 - f485: 〈0;f484〉 - f486: 〈0;f485〉 - f487: 〈0;f486〉 - f488: 〈0;f487〉 - f489: 〈0;f488〉 - f490: 〈0;f489〉 - f491: 〈0;f490〉 - f492: 〈0;f491〉 - f493: 〈0;f492〉 - f494: 〈0;f493〉 - f495: 〈0;f494〉 - f496: 〈0;f495〉 - f497: 〈0;f496〉 - f498: 〈0;f497〉 - f499: 〈0;f498〉 - f500: 〈0;f499〉 - f501: 〈0;f500〉 - f502: 〈0;f501〉 - f503: 〈0;f502〉 - f504: 〈0;f503〉 - f505: 〈0;f504〉 - f506: 〈0;f505〉 - f507: 〈0;f506〉 - f508: 〈0;f507〉 - f509: 〈0;f508〉 - f510: 〈0;f509〉 - f511: 〈0;f510〉 - f512: 〈0;f511〉 - f513: 〈0;f512〉 - f514: 〈0;f513〉 - f515: 〈0;f514〉 - f516: 〈0;f515〉 - f517: 〈0;f516〉 - f518: 〈0;f517〉 - f519: 〈0;f518〉 - f520: 〈0;f519〉 - f521: 〈0;f520〉 - f522: 〈0;f521〉 - f523: 〈0;f522〉 - f524: 〈0;f523〉 - f525: 〈0;f524〉 - f526: 〈0;f525〉 - f527: 〈0;f526〉 - f528: 〈0;f527〉 - f529: 〈0;f528〉 - f530: 〈0;f529〉 - f531: 〈0;f530〉 - f532: 〈0;f531〉 - f533: 〈0;f532〉 - f534: 〈0;f533〉 - f535: 〈0;f534〉 - f536: 〈0;f535〉 - f537: 〈0;f536〉 - f538: 〈0;f537〉 - f539: 〈0;f538〉 - f540: 〈0;f539〉 - f541: 〈0;f540〉 - f542: 〈0;f541〉 - f543: 〈0;f542〉 - f544: 〈0;f543〉 - f545: 〈0;f544〉 - f546: 〈0;f545〉 - f547: 〈0;f546〉 - f548: 〈0;f547〉 - f549: 〈0;f548〉 - f550: 〈0;f549〉 - f551: 〈0;f550〉 - f552: 〈0;f551〉 - f553: 〈0;f552〉 - f554: 〈0;f553〉 - f555: 〈0;f554〉 - f556: 〈0;f555〉 - f557: 〈0;f556〉 - f558: 〈0;f557〉 - f559: 〈0;f558〉 - f560: 〈0;f559〉 - f561: 〈0;f560〉 - f562: 〈0;f561〉 - f563: 〈0;f562〉 - f564: 〈0;f563〉 - f565: 〈0;f564〉 - f566: 〈0;f565〉 - f567: 〈0;f566〉 - f568: 〈0;f567〉 - f569: 〈0;f568〉 - f570: 〈0;f569〉 - f571: 〈0;f570〉 - f572: 〈0;f571〉 - f573: 〈0;f572〉 - f574: 〈0;f573〉 - f575: 〈0;f574〉 - f576: 〈0;f575〉 - f577: 〈0;f576〉 - f578: 〈0;f577〉 - f579: 〈0;f578〉 - f580: 〈0;f579〉 - f581: 〈0;f580〉 - f582: 〈0;f581〉 - f583: 〈0;f582〉 - f584: 〈0;f583〉 - f585: 〈0;f584〉 - f586: 〈0;f585〉 - f587: 〈0;f586〉 - f588: 〈0;f587〉 - f589: 〈0;f588〉 - f590: 〈0;f589〉 - f591: 〈0;f590〉 - f592: 〈0;f591〉 - f593: 〈0;f592〉 - f594: 〈0;f593〉 - f595: 〈0;f594〉 - f596: 〈0;f595〉 - f597: 〈0;f596〉 - f598: 〈0;f597〉 - f599: 〈0;f598〉 - f600: 〈0;f599〉 - f601: 〈0;f600〉 - f602: 〈0;f601〉 - f603: 〈0;f602〉 - f604: 〈0;f603〉 - f605: 〈0;f604〉 - f606: 〈0;f605〉 - f607: 〈0;f606〉 - f608: 〈0;f607〉 - f609: 〈0;f608〉 - f610: 〈0;f609〉 - f611: 〈0;f610〉 - f612: 〈0;f611〉 - f613: 〈0;f612〉 - f614: 〈0;f613〉 - f615: 〈0;f614〉 - f616: 〈0;f615〉 - f617: 〈0;f616〉 - f618: 〈0;f617〉 - f619: 〈0;f618〉 - f620: 〈0;f619〉 - f621: 〈0;f620〉 - f622: 〈0;f621〉 - f623: 〈0;f622〉 - f624: 〈0;f623〉 - f625: 〈0;f624〉 - f626: 〈0;f625〉 - f627: 〈0;f626〉 - f628: 〈0;f627〉 - f629: 〈0;f628〉 - f630: 〈0;f629〉 - f631: 〈0;f630〉 - f632: 〈0;f631〉 - f633: 〈0;f632〉 - f634: 〈0;f633〉 - f635: 〈0;f634〉 - f636: 〈0;f635〉 - f637: 〈0;f636〉 - f638: 〈0;f637〉 - f639: 〈0;f638〉 - f640: 〈0;f639〉 - f641: 〈0;f640〉 - f642: 〈0;f641〉 - f643: 〈0;f642〉 - f644: 〈0;f643〉 - f645: 〈0;f644〉 - f646: 〈0;f645〉 - f647: 〈0;f646〉 - f648: 〈0;f647〉 - f649: 〈0;f648〉 - f650: 〈0;f649〉 - f651: 〈0;f650〉 - f652: 〈0;f651〉 - f653: 〈0;f652〉 - f654: 〈0;f653〉 - f655: 〈0;f654〉 - f656: 〈0;f655〉 - f657: 〈0;f656〉 - f658: 〈0;f657〉 - f659: 〈0;f658〉 - f660: 〈0;f659〉 - f661: 〈0;f660〉 - f662: 〈0;f661〉 - f663: 〈0;f662〉 - f664: 〈0;f663〉 - f665: 〈0;f664〉 - f666: 〈0;f665〉 - f667: 〈0;f666〉 - f668: 〈0;f667〉 - f669: 〈0;f668〉 - f670: 〈0;f669〉 - f671: 〈0;f670〉 - f672: 〈0;f671〉 - f673: 〈0;f672〉 - f674: 〈0;f673〉 - f675: 〈0;f674〉 - f676: 〈0;f675〉 - f677: 〈0;f676〉 - f678: 〈0;f677〉 - f679: 〈0;f678〉 - f680: 〈0;f679〉 - f681: 〈0;f680〉 - f682: 〈0;f681〉 - f683: 〈0;f682〉 - f684: 〈0;f683〉 - f685: 〈0;f684〉 - f686: 〈0;f685〉 - f687: 〈0;f686〉 - f688: 〈0;f687〉 - f689: 〈0;f688〉 - f690: 〈0;f689〉 - f691: 〈0;f690〉 - f692: 〈0;f691〉 - f693: 〈0;f692〉 - f694: 〈0;f693〉 - f695: 〈0;f694〉 - f696: 〈0;f695〉 - f697: 〈0;f696〉 - f698: 〈0;f697〉 - f699: 〈0;f698〉 - f700: 〈0;f699〉 - f701: 〈0;f700〉 - f702: 〈0;f701〉 - f703: 〈0;f702〉 - f704: 〈0;f703〉 - f705: 〈0;f704〉 - f706: 〈0;f705〉 - f707: 〈0;f706〉 - f708: 〈0;f707〉 - f709: 〈0;f708〉 - f710: 〈0;f709〉 - f711: 〈0;f710〉 - f712: 〈0;f711〉 - f713: 〈0;f712〉 - f714: 〈0;f713〉 - f715: 〈0;f714〉 - f716: 〈0;f715〉 - f717: 〈0;f716〉 - f718: 〈0;f717〉 - f719: 〈0;f718〉 - f720: 〈0;f719〉 - f721: 〈0;f720〉 - f722: 〈0;f721〉 - f723: 〈0;f722〉 - f724: 〈0;f723〉 - f725: 〈0;f724〉 - f726: 〈0;f725〉 - f727: 〈0;f726〉 - f728: 〈0;f727〉 - f729: 〈0;f728〉 - f730: 〈0;f729〉 - f731: 〈0;f730〉 - f732: 〈0;f731〉 - f733: 〈0;f732〉 - f734: 〈0;f733〉 - f735: 〈0;f734〉 - f736: 〈0;f735〉 - f737: 〈0;f736〉 - f738: 〈0;f737〉 - f739: 〈0;f738〉 - f740: 〈0;f739〉 - f741: 〈0;f740〉 - f742: 〈0;f741〉 - f743: 〈0;f742〉 - f744: 〈0;f743〉 - f745: 〈0;f744〉 - f746: 〈0;f745〉 - f747: 〈0;f746〉 - f748: 〈0;f747〉 - f749: 〈0;f748〉 - f750: 〈0;f749〉 - f751: 〈0;f750〉 - f752: 〈0;f751〉 - f753: 〈0;f752〉 - f754: 〈0;f753〉 - f755: 〈0;f754〉 - f756: 〈0;f755〉 - f757: 〈0;f756〉 - f758: 〈0;f757〉 - f759: 〈0;f758〉 - f760: 〈0;f759〉 - f761: 〈0;f760〉 - f762: 〈0;f761〉 - f763: 〈0;f762〉 - f764: 〈0;f763〉 - f765: 〈0;f764〉 - f766: 〈0;f765〉 - f767: 〈0;f766〉 - f768: 〈0;f767〉 - f769: 〈0;f768〉 - f770: 〈0;f769〉 - f771: 〈0;f770〉 - f772: 〈0;f771〉 - f773: 〈0;f772〉 - f774: 〈0;f773〉 - f775: 〈0;f774〉 - f776: 〈0;f775〉 - f777: 〈0;f776〉 - f778: 〈0;f777〉 - f779: 〈0;f778〉 - f780: 〈0;f779〉 - f781: 〈0;f780〉 - f782: 〈0;f781〉 - f783: 〈0;f782〉 - f784: 〈0;f783〉 - f785: 〈0;f784〉 - f786: 〈0;f785〉 - f787: 〈0;f786〉 - f788: 〈0;f787〉 - f789: 〈0;f788〉 - f790: 〈0;f789〉 - f791: 〈0;f790〉 - f792: 〈0;f791〉 - f793: 〈0;f792〉 - f794: 〈0;f793〉 - f795: 〈0;f794〉 - f796: 〈0;f795〉 - f797: 〈0;f796〉 - f798: 〈0;f797〉 - f799: 〈0;f798〉 - f800: 〈0;f799〉 - f801: 〈0;f800〉 - f802: 〈0;f801〉 - f803: 〈0;f802〉 - f804: 〈0;f803〉 - f805: 〈0;f804〉 - f806: 〈0;f805〉 - f807: 〈0;f806〉 - f808: 〈0;f807〉 - f809: 〈0;f808〉 - f810: 〈0;f809〉 - f811: 〈0;f810〉 - f812: 〈0;f811〉 - f813: 〈0;f812〉 - f814: 〈0;f813〉 - f815: 〈0;f814〉 - f816: 〈0;f815〉 - f817: 〈0;f816〉 - f818: 〈0;f817〉 - f819: 〈0;f818〉 - f820: 〈0;f819〉 - f821: 〈0;f820〉 - f822: 〈0;f821〉 - f823: 〈0;f822〉 - f824: 〈0;f823〉 - f825: 〈0;f824〉 - f826: 〈0;f825〉 - f827: 〈0;f826〉 - f828: 〈0;f827〉 - f829: 〈0;f828〉 - f830: 〈0;f829〉 - f831: 〈0;f830〉 - f832: 〈0;f831〉 - f833: 〈0;f832〉 - f834: 〈0;f833〉 - f835: 〈0;f834〉 - f836: 〈0;f835〉 - f837: 〈0;f836〉 - f838: 〈0;f837〉 - f839: 〈0;f838〉 - f840: 〈0;f839〉 - f841: 〈0;f840〉 - f842: 〈0;f841〉 - f843: 〈0;f842〉 - f844: 〈0;f843〉 - f845: 〈0;f844〉 - f846: 〈0;f845〉 - f847: 〈0;f846〉 - f848: 〈0;f847〉 - f849: 〈0;f848〉 - f850: 〈0;f849〉 - f851: 〈0;f850〉 - f852: 〈0;f851〉 - f853: 〈0;f852〉 - f854: 〈0;f853〉 - f855: 〈0;f854〉 - f856: 〈0;f855〉 - f857: 〈0;f856〉 - f858: 〈0;f857〉 - f859: 〈0;f858〉 - f860: 〈0;f859〉 - f861: 〈0;f860〉 - f862: 〈0;f861〉 - f863: 〈0;f862〉 - f864: 〈0;f863〉 - f865: 〈0;f864〉 - f866: 〈0;f865〉 - f867: 〈0;f866〉 - f868: 〈0;f867〉 - f869: 〈0;f868〉 - f870: 〈0;f869〉 - f871: 〈0;f870〉 - f872: 〈0;f871〉 - f873: 〈0;f872〉 - f874: 〈0;f873〉 - f875: 〈0;f874〉 - f876: 〈0;f875〉 - f877: 〈0;f876〉 - f878: 〈0;f877〉 - f879: 〈0;f878〉 - f880: 〈0;f879〉 - f881: 〈0;f880〉 - f882: 〈0;f881〉 - f883: 〈0;f882〉 - f884: 〈0;f883〉 - f885: 〈0;f884〉 - f886: 〈0;f885〉 - f887: 〈0;f886〉 - f888: 〈0;f887〉 - f889: 〈0;f888〉 - f890: 〈0;f889〉 - f891: 〈0;f890〉 - f892: 〈0;f891〉 - f893: 〈0;f892〉 - f894: 〈0;f893〉 - f895: 〈0;f894〉 - f896: 〈0;f895〉 - f897: 〈0;f896〉 - f898: 〈0;f897〉 - f899: 〈0;f898〉 - f900: 〈0;f899〉 - f901: 〈0;f900〉 - f902: 〈0;f901〉 - f903: 〈0;f902〉 - f904: 〈0;f903〉 - f905: 〈0;f904〉 - f906: 〈0;f905〉 - f907: 〈0;f906〉 - f908: 〈0;f907〉 - f909: 〈0;f908〉 - f910: 〈0;f909〉 - f911: 〈0;f910〉 - f912: 〈0;f911〉 - f913: 〈0;f912〉 - f914: 〈0;f913〉 - f915: 〈0;f914〉 - f916: 〈0;f915〉 - f917: 〈0;f916〉 - f918: 〈0;f917〉 - f919: 〈0;f918〉 - f920: 〈0;f919〉 - f921: 〈0;f920〉 - f922: 〈0;f921〉 - f923: 〈0;f922〉 - f924: 〈0;f923〉 - f925: 〈0;f924〉 - f926: 〈0;f925〉 - f927: 〈0;f926〉 - f928: 〈0;f927〉 - f929: 〈0;f928〉 - f930: 〈0;f929〉 - f931: 〈0;f930〉 - f932: 〈0;f931〉 - f933: 〈0;f932〉 - f934: 〈0;f933〉 - f935: 〈0;f934〉 - f936: 〈0;f935〉 - f937: 〈0;f936〉 - f938: 〈0;f937〉 - f939: 〈0;f938〉 - f940: 〈0;f939〉 - f941: 〈0;f940〉 - f942: 〈0;f941〉 - f943: 〈0;f942〉 - f944: 〈0;f943〉 - f945: 〈0;f944〉 - f946: 〈0;f945〉 - f947: 〈0;f946〉 - f948: 〈0;f947〉 - f949: 〈0;f948〉 - f950: 〈0;f949〉 - f951: 〈0;f950〉 - f952: 〈0;f951〉 - f953: 〈0;f952〉 - f954: 〈0;f953〉 - f955: 〈0;f954〉 - f956: 〈0;f955〉 - f957: 〈0;f956〉 - f958: 〈0;f957〉 - f959: 〈0;f958〉 - f960: 〈0;f959〉 - f961: 〈0;f960〉 - f962: 〈0;f961〉 - f963: 〈0;f962〉 - f964: 〈0;f963〉 - f965: 〈0;f964〉 - f966: 〈0;f965〉 - f967: 〈0;f966〉 - f968: 〈0;f967〉 - f969: 〈0;f968〉 - f970: 〈0;f969〉 - f971: 〈0;f970〉 - f972: 〈0;f971〉 - f973: 〈0;f972〉 - f974: 〈0;f973〉 - f975: 〈0;f974〉 - f976: 〈0;f975〉 - f977: 〈0;f976〉 - f978: 〈0;f977〉 - f979: 〈0;f978〉 - f980: 〈0;f979〉 - f981: 〈0;f980〉 - f982: 〈0;f981〉 - f983: 〈0;f982〉 - f984: 〈0;f983〉 - f985: 〈0;f984〉 - f986: 〈0;f985〉 - f987: 〈0;f986〉 - f988: 〈0;f987〉 - f989: 〈0;f988〉 - f990: 〈0;f989〉 - f991: 〈0;f990〉 - f992: 〈0;f991〉 - f993: 〈0;f992〉 - f994: 〈0;f993〉 - f995: 〈0;f994〉 - f996: 〈0;f995〉 - f997: 〈0;f996〉 - f998: 〈0;f997〉 - f999: 〈0;f998〉 - f1000: 〈0;f999〉 -} -- out/eval/stats -- Leaks: 0 Freed: 1001 diff --git a/cue/testdata/benchmarks/cycle.txtar b/cue/testdata/benchmarks/cycle.txtar index 2a9ae69c3..f67b7f8ad 100644 --- a/cue/testdata/benchmarks/cycle.txtar +++ b/cue/testdata/benchmarks/cycle.txtar @@ -20,29 +20,6 @@ sameValues: CmustBeA: { -- out/todo.txt -- v2 expanded S and C into independent copies; v3 uses structure sharing (S: ~(sameValues.SmustBeF.F), C: ~(sameValues.CmustBeA.A)). --- out/compile -- ---- in.cue -{ - sameValues: { - SmustBeF: { - T: (string|〈0;F〉) - F: { - x: 〈1;T〉 - } - S: 〈0;F〉 - } - } - sameValues: { - CmustBeA: { - A: { - x: [ - (string|〈2;A〉), - ] - } - C: 〈0;A〉 - } - } -} -- out/eval/stats -- Leaks: 2 Freed: 15 diff --git a/cue/testdata/benchmarks/cycleshare.txtar b/cue/testdata/benchmarks/cycleshare.txtar index fecc27201..650390533 100644 --- a/cue/testdata/benchmarks/cycleshare.txtar +++ b/cue/testdata/benchmarks/cycleshare.txtar @@ -201,80 +201,3 @@ NumCloseIDs: 1 root_2: ~(root) root_3: ~(root) } --- out/compile -- ---- in.cue -{ - #D1: ({ - a: 〈1;#D2〉 - }|{ - b: 〈1;#D2〉 - }|{ - c: 〈1;#D2〉 - }) - #D2: ({ - a: 〈1;#D3〉 - }|{ - b: 〈1;#D3〉 - }|{ - c: 〈1;#D3〉 - }) - #D3: { - one: ({ - a: int - }|{ - b: int - }|{ - c: int - }) - two: ({ - a: string - }|{ - b: string - }|{ - c: string - }) - three: ({ - a: bool - }|{ - b: bool - }|{ - c: bool - }) - } - root: { - y: (〈1;#D1〉|[ - 〈2;#D1〉, - ]|{ - x: 〈2;#D1〉 - }) - } - root: { - x: { - empty: {} - } - } - root: { - "0": { - data: 〈2;let root_0#1〉.x.empty - } - } - root: { - "1": { - data: 〈2;let root_1#2〉.x.empty - } - } - root: { - "2": { - data: 〈2;root_2〉.x.empty - } - } - root: { - "3": { - data: 〈2;root_3〉.x.empty - } - } - let root_0#1 = 〈0;root〉 - let root_1#2 = 〈0;root〉 - root_2: 〈0;root〉 - root_3: 〈0;root〉 -} diff --git a/cue/testdata/benchmarks/decimal.txtar b/cue/testdata/benchmarks/decimal.txtar index e1577a03f..6ff6fdb0d 100644 --- a/cue/testdata/benchmarks/decimal.txtar +++ b/cue/testdata/benchmarks/decimal.txtar @@ -24,21 +24,6 @@ out: [ 5.0, 0.3333333333333333333333333333333333 ]) --- out/compile -- ---- in.cue -{ - out: [ - (123.45 + 987.65), - (123.45 - 987.65), - (123.45 * 987.65), - (123.45 / 987.65), - (2 + 3), - (7 - 1), - (5 * 10), - (20 / 4), - (1 / 3), - ] -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/benchmarks/deduparc.txtar b/cue/testdata/benchmarks/deduparc.txtar index ad0f70b3e..4c2f057c6 100644 --- a/cue/testdata/benchmarks/deduparc.txtar +++ b/cue/testdata/benchmarks/deduparc.txtar @@ -36,30 +36,3 @@ Conjuncts: 28 Disjuncts: 4 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - #Value: ({ - type: "float" - }|{ - type: "string" - }) - foo: { - type: "string" - } - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 - foo: 〈0;#Value〉 -} diff --git a/cue/testdata/benchmarks/dedupelem.txtar b/cue/testdata/benchmarks/dedupelem.txtar index 9fa5e2199..95d83396b 100644 --- a/cue/testdata/benchmarks/dedupelem.txtar +++ b/cue/testdata/benchmarks/dedupelem.txtar @@ -33,84 +33,3 @@ Conjuncts: 59 Disjuncts: 3 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - #Value: ({ - type: "int" - }|{ - type: "float" - }|{ - type: "string" - }) - foo: ([ - { - type: "float" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "float" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "float" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "float" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "float" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "string" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "string" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "string" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "float" - }, - ] & [ - ...〈1;#Value〉, - ]) - foo: ([ - { - type: "float" - }, - ] & [ - ...〈1;#Value〉, - ]) -} diff --git a/cue/testdata/benchmarks/disjunctelim.txtar b/cue/testdata/benchmarks/disjunctelim.txtar index f8dbbc975..6a0e9f504 100644 --- a/cue/testdata/benchmarks/disjunctelim.txtar +++ b/cue/testdata/benchmarks/disjunctelim.txtar @@ -63,129 +63,3 @@ Disjuncts: 618 Notifications: 1 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - pat: ({ - [string]: 1 - }|{ - a: 2 - }) - list: ([ - 1, - ]|[ - 2, - ]|[ - 3, - ]|[ - 4, - ]) - list: ([ - 1, - ]|[ - 2, - ]|[ - 3, - ]|[ - 4, - ]) - list: ([ - 1, - ]|[ - 2, - ]|[ - 3, - ]|[ - 4, - ]) - list: ([ - 1, - ]|[ - 2, - ]|[ - 3, - ]|[ - 4, - ]) - list: ([ - 1, - ]|[ - 2, - ]|[ - 3, - ]|[ - 4, - ]) - list: ([ - 1, - ]|[ - 2, - ]|[ - 3, - ]|[ - 4, - ]) - list: ([ - 1, - ]|[ - 2, - ]|[ - 3, - ]|[ - 4, - ]) - issue3610: { - 〈0;#a〉 - #a: (<"a"|>"b"|string) - #a: (<"a"|>"b"|string) - #a: (<"a"|>"b"|string) - #a: (<"a"|>"b"|string) - #a: (<"a"|>"b"|string) - #a: (<"a"|>"b"|string) - } -} diff --git a/cue/testdata/benchmarks/disjunction.txtar b/cue/testdata/benchmarks/disjunction.txtar index c96653321..f40962465 100644 --- a/cue/testdata/benchmarks/disjunction.txtar +++ b/cue/testdata/benchmarks/disjunction.txtar @@ -27,116 +27,6 @@ x: { a0: {} @test(eq, {a0: {f: *1 | int}}) } --- out/compile -- ---- in.cue -{ - x: { - a0: {} - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - [_]: { - f: (*1|int) - } - } - x: { - a0: {} - } -} -- out/eval/stats -- Leaks: 0 Freed: 82 diff --git a/cue/testdata/benchmarks/inlinedisjunction.txtar b/cue/testdata/benchmarks/inlinedisjunction.txtar index a335fb8c8..16ed8d4d1 100644 --- a/cue/testdata/benchmarks/inlinedisjunction.txtar +++ b/cue/testdata/benchmarks/inlinedisjunction.txtar @@ -34,43 +34,3 @@ NumCloseIDs: 23 ConjunctInfos: 99 MaxConjunctInfos: 12 MaxReqSets: 12 --- out/compile -- ---- in.cue -{ - #def: { - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - c: string - }) - ({}|{ - a: string - }) - } - x: 〈0;#def〉 - x: { - c: "foo" - } -} diff --git a/cue/testdata/benchmarks/issue1684.txtar b/cue/testdata/benchmarks/issue1684.txtar index b0f82fef6..d22ee930a 100644 --- a/cue/testdata/benchmarks/issue1684.txtar +++ b/cue/testdata/benchmarks/issue1684.txtar @@ -75,115 +75,3 @@ Note that the old closedness implementation of V3 was able to reduce this to in some cases eliminate earlier than with a flat structure. So this may not be attainable with the current implementation. TODO(perf): investigate nonetheless. --- out/compile -- ---- in.cue -{ - #Secret: { - $secret: { - id: string - } - } - #secrets: (〈0;#Secret〉|{ - [string]: 〈1;#secrets〉 - }) - out: (〈0;#secrets〉 & { - FOO: { - $secret: { - id: "100" - } - } - ONE: { - TWO: { - THREE: { - $secret: { - id: "123" - } - } - } - } - }) - #Secret: { - $secret: { - _id: string - } - } - #secrets: (〈0;#Secret〉|{ - [string]: 〈1;#secrets〉 - }) - out: (〈0;#secrets〉 & { - FOO: { - $secret: { - _id: "100" - } - } - ONE: { - TWO: { - THREE: { - $secret: { - _id: "123" - } - } - } - } - }) -} ---- perf.cue -{ - nestedCross: { - closed: { - #D: ({ - id: string - }|{ - [string]: 〈1;#D〉 - }) - #D: ({ - id: string - }|{ - [string]: 〈1;#D〉 - }) - #D: ({ - id: string - }|{ - [string]: 〈1;#D〉 - }) - } - } - nestedCross: { - open: { - D: ({ - id: string - }|{ - [string]: 〈1;D〉 - }) - D: ({ - id: string - }|{ - [string]: 〈1;D〉 - }) - D: ({ - id: string - }|{ - [string]: 〈1;D〉 - }) - } - } - nestedClosed: { - passing: { - D: ({ - id: {} - }|{ - [string]: 〈1;D〉 - }) - D: ({ - id: {} - }|{ - [string]: 〈1;D〉 - }) - D: ({ - id: {} - }|{ - [string]: 〈1;D〉 - }) - } - } -} diff --git a/cue/testdata/benchmarks/issue2176.txtar b/cue/testdata/benchmarks/issue2176.txtar index fb37e8411..7ef2cc9d5 100644 --- a/cue/testdata/benchmarks/issue2176.txtar +++ b/cue/testdata/benchmarks/issue2176.txtar @@ -81,53 +81,5 @@ NumCloseIDs: 586 ConjunctInfos: 919 MaxConjunctInfos: 28 MaxReqSets: 26 --- out/compile -- ---- in.cue -{ - #Datastream: { - message: string - message: 〈import;strings〉.MinRunes(4) - marker: { - length: int - position: { - let characters#1 = 〈import;strings〉.Split(〈2;message〉, "") - let unique_combinations#2multi = { - for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { - let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) - if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { - "\((〈2;i〉 + 1))": 〈1;let combination#3〉 - } - } - } - [ - for i, _ in 〈1;let unique_combinations#2〉 { - 〈1;i〉 - }, - ][0] - } - } - } - input_short: "mjqjpqmgbljsphdztnvjfqwrcgsmlb" - input_long: "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" - input: (*〈0;input_short〉|〈0;input_long〉) - datastream: (〈0;#Datastream〉 & { - message: 〈1;input〉 - }) - output: { - [string]: string - } - output: { - "1": (〈1;datastream〉 & { - marker: { - length: 4 - } - }).marker.position - "2": (〈1;datastream〉 & { - marker: { - length: 14 - } - }).marker.position - } -} -- out/todo.txt -- let unique_combinations: not marked as multi in v3. Seems benign, but should be fixed. diff --git a/cue/testdata/benchmarks/issue3307.txtar b/cue/testdata/benchmarks/issue3307.txtar index 302c29582..eb35a75bd 100644 --- a/cue/testdata/benchmarks/issue3307.txtar +++ b/cue/testdata/benchmarks/issue3307.txtar @@ -41,31 +41,3 @@ Conjuncts: 3 Disjuncts: 0 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - if 〈0;_request〉.enabled { - r1: { - k1: 0 - k2: 0 - k3: 0 - k4: 0 - k5: 0 - k6: 0 - k7: 0 - k8: 0 - k9: 0 - k10: 0 - k11: 0 - k12: 0 - k13: 0 - k14: 0 - k15: 0 - k16: 0 - k17: 0 - } - } - _request: { - enabled: _ - } -} diff --git a/cue/testdata/benchmarks/issue3334.txtar b/cue/testdata/benchmarks/issue3334.txtar index 1ea339c75..d6b20a492 100644 --- a/cue/testdata/benchmarks/issue3334.txtar +++ b/cue/testdata/benchmarks/issue3334.txtar @@ -265,71 +265,3 @@ Conjuncts: 797 Disjuncts: 310 NumCloseIDs: 21 --- out/compile -- ---- in.cue -{ - x?: (null|〈0;Schema〉) - x: { - properties: { - disableSelfServiceScrape: {} - dnsConfig: { - properties: { - nameservers: {} - } - } - podDisruptionBudget: { - properties: { - maxUnavailable: {} - minAvailable: { - anyOf: [ - {}, - {}, - ] - } - labels: {} - } - } - } - } - Schema: { - title?: string - $ref?: (null|string) - enum?: [ - ..., - ] - required?: [ - ...string, - ] - items?: (null|_) - anyOf?: [ - ...〈2;Schema〉, - ] - allOf?: [ - ...〈2;Schema〉, - ] - oneOf?: [ - ...〈2;Schema〉, - ] - not?: (null|〈1;Schema〉) - properties?: { - [string]: 〈2;Schema〉 - } - additionalProperties?: (null|_) - patternProperties?: { - [string]: 〈2;Schema〉 - } - dependencies?: { - [string]: _ - } - additionalItems?: (null|_) - definitions?: { - [string]: _ - } - externalDocs?: (null|{ - description?: string - url?: string - }) - example?: (null|_) - nullable?: bool - } -} diff --git a/cue/testdata/benchmarks/issue3514.txtar b/cue/testdata/benchmarks/issue3514.txtar index 2010928d3..a55b469ee 100644 --- a/cue/testdata/benchmarks/issue3514.txtar +++ b/cue/testdata/benchmarks/issue3514.txtar @@ -54,53 +54,3 @@ Disjuncts: 1220 Notifications: 2 NumCloseIDs: 2876 --- out/compile -- ---- in.cue -{ - (〈0;_schema〉 & 〈0;_data〉) - _data: { - updates: [ - { - schedule: { - interval: "daily" - } - }, - ] - } - _schema: { - (matchIf((null|bool|number|string|[ - ..., - ]|{ - "enable-beta-ecosystems"!: true - }), _, (null|bool|number|string|[ - ..., - ]|{ - updates?: (null|bool|number|string|[ - ...(null|bool|number|string|[ - ..., - ]|{ - ... - }), - ]|{ - ... - }) - ... - })) & { - updates!: [ - ...〈2;#update〉, - ] - }) - #update: { - schedule!: { - timezone?: 〈2;#timezone〉 - ... - } - ... - } - #timezone: or([ - for _, i in 〈import;list〉.Range(0, 571, 1) { - "\(〈1;i〉)" - }, - ]) - } -} diff --git a/cue/testdata/benchmarks/issue3517.txtar b/cue/testdata/benchmarks/issue3517.txtar index ce7a17dc8..3fed0e99f 100644 --- a/cue/testdata/benchmarks/issue3517.txtar +++ b/cue/testdata/benchmarks/issue3517.txtar @@ -201,69 +201,6 @@ Conjuncts: 119 Disjuncts: 0 NumCloseIDs: 13 --- out/compile -- ---- main.cue -{ - #TimeSpan: { - start: float - duration: float - end: float - start: (〈0;end〉 - 〈0;duration〉) - duration: (〈0;end〉 - 〈0;start〉) - end: (〈0;start〉 + 〈0;duration〉) - start: <=〈0;end〉 - } - #Task: { - action: string - timeSpan: 〈1;#TimeSpan〉 - } - #TaskSet: { - action: string - #tasks: { - [string]: 〈2;#Task〉 - } - tasks: [ - for _, v in 〈1;#tasks〉 { - 〈1;v〉 - }, - ] - tasks: [ - ...〈2;#Task〉, - ] - timeSpan?: 〈1;#TimeSpan〉 - } - #T1: (〈0;#Task〉 & { - action: "Task 1" - timeSpan: (〈1;#TimeSpan〉 & { - duration: 4.2 - }) - }) - #T2: (〈0;#Task〉 & { - action: "Task 2" - timeSpan: (〈1;#TimeSpan〉 & { - duration: 120.0 - }) - }) - ts: 〈0;#TaskSet〉 - ts: { - action: "Task 1 and Task 2" - #tasks: { - t1: (〈2;#T1〉 & { - timeSpan: { - end: 〈4〉.#tasks.t2.timeSpan.start - } - }) - t2: (〈2;#T2〉 & { - timeSpan: { - end: 119 - } - }) - } - timeSpan: { - start: 〈2〉.#tasks.t1.timeSpan.start - } - } -} -- out/evalalpha -- Errors: ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): diff --git a/cue/testdata/benchmarks/issue3633.txtar b/cue/testdata/benchmarks/issue3633.txtar index edf5409a1..14be8933a 100644 --- a/cue/testdata/benchmarks/issue3633.txtar +++ b/cue/testdata/benchmarks/issue3633.txtar @@ -123,147 +123,3 @@ Conjuncts: 2081 Disjuncts: 1625 NumCloseIDs: 50 --- out/compile -- ---- in.cue -{ - reduced: { - #Schema: { - a?: (null|bool|string|int|〈1;#Schema〉) - b?: (null|bool|string|int|〈1;#Schema〉) - c?: (null|bool|string|int|〈1;#Schema〉) - d?: (null|bool|string|int|〈1;#Schema〉) - e?: (null|bool|string|int|〈1;#Schema〉) - f?: (null|bool|string|int|〈1;#Schema〉) - } - out: (〈0;#Schema〉 & { - 〈1;#Schema〉 - }) - } - full: { - #Schema: { - required?: [ - ...string, - ] - properties?: { - [string]: (null|bool|string|[ - ...int, - ]|〈2;#Schema〉) - } - foo00?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo01?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo02?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo03?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo04?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo05?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo06?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo07?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo08?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo09?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo10?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo11?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo12?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo13?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo14?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo15?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo16?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo17?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo18?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - foo19?: (null|bool|string|[ - ...int, - ]|{ - string: &(int, >=-2147483648, <=2147483647) - }) - } - out: ([ - ...〈1;#Schema〉, - ] & [ - { - 〈2;#Schema〉 - properties: { - foo: { - required: [ - "bar", - "baz", - ] - } - } - }, - ]) - } -} diff --git a/cue/testdata/benchmarks/issue572.txtar b/cue/testdata/benchmarks/issue572.txtar index 3474efcc3..f2db29d46 100644 --- a/cue/testdata/benchmarks/issue572.txtar +++ b/cue/testdata/benchmarks/issue572.txtar @@ -32,17 +32,3 @@ Conjuncts: 7498 Disjuncts: 0 NumCloseIDs: 4499 --- out/compile -- ---- in.cue -{ - _entries(:p): [ - for _, i in 〈import;list〉.Range(1, 1500, 1) { - 〈1;i〉 - }, - ] - unified: { - for _, entry in 〈1;_entries(:p)〉 { - "\(〈1;entry〉)": true - } - } -} diff --git a/cue/testdata/benchmarks/listdedup.txtar b/cue/testdata/benchmarks/listdedup.txtar index b6d312eb1..4ce896a18 100644 --- a/cue/testdata/benchmarks/listdedup.txtar +++ b/cue/testdata/benchmarks/listdedup.txtar @@ -142,40 +142,3 @@ ConjunctInfos: 70 MaxConjunctInfos: 6 MaxReqSets: 9 MaxRedirect: 2 --- out/compile -- ---- in.cue -{ - A: 〈0;#Task〉 - B: { - #steps: (〈1;#Script〉 & { - mount: [ - 〈3;A〉, - ] - }) - } - C: { - #steps: (〈1;#Script〉 & { - mount: [ - 〈3;B〉, - ] - }) - } - #Script: { - mount: [ - ...〈2;#Task〉, - ] - } - #Task: { - 〈1;#ref〉 - 〈1;#ref〉 - (_|{}) - (_|{}) - #steps: 〈1;#Script〉 - ... - } - #ref: ({ - a: 1 - }|{ - b: 2 - }) -} diff --git a/cue/testdata/benchmarks/listdisj.txtar b/cue/testdata/benchmarks/listdisj.txtar index 793f7386d..7dfb96591 100644 --- a/cue/testdata/benchmarks/listdisj.txtar +++ b/cue/testdata/benchmarks/listdisj.txtar @@ -19,32 +19,6 @@ v: #T @test(shareID=T) #X: z #X: v #X: #T --- out/compile -- ---- in.cue -{ - #T: ([ - "a", - 〈1;#T〉, - ]|[ - "b", - 〈1;#T〉, - ]|[ - "c", - 〈1;#T〉, - ]|[ - "d", - ...〈1;#T〉, - ]) - x: 〈0;#T〉 - y: 〈0;#T〉 - z: 〈0;#T〉 - v: 〈0;#T〉 - #X: 〈0;x〉 - #X: 〈0;y〉 - #X: 〈0;z〉 - #X: 〈0;v〉 - #X: 〈0;#T〉 -} -- out/eval/stats -- Leaks: 2 Freed: 16 diff --git a/cue/testdata/benchmarks/mergeddisjunction.txtar b/cue/testdata/benchmarks/mergeddisjunction.txtar index 0cee41ad6..c1c5824c7 100644 --- a/cue/testdata/benchmarks/mergeddisjunction.txtar +++ b/cue/testdata/benchmarks/mergeddisjunction.txtar @@ -45,59 +45,3 @@ NumCloseIDs: 35 ConjunctInfos: 194 MaxConjunctInfos: 32 MaxReqSets: 2 --- out/compile -- ---- in.cue -{ - list: [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - ] - a: { - [string]: { - text: (*"default"|string) - } - } - a: { - for _, i in 〈1;list〉 { - "\(〈1;i〉)": { - text: string - } - } - } - b: { - for _, x in 〈1;a〉 { - "\(〈1;x〉.text)": { - text: 〈2;x〉.text - } - } - } -} diff --git a/cue/testdata/benchmarks/share.txtar b/cue/testdata/benchmarks/share.txtar index d57aa2294..703777220 100644 --- a/cue/testdata/benchmarks/share.txtar +++ b/cue/testdata/benchmarks/share.txtar @@ -5,47 +5,6 @@ g: [h, h, h, h, h, h, h] @test(shareID=G) @test(shareID=H, at=0) @test(shareID=H h: [i, i, i, i, i, i, i] @test(shareID=H) @test(shareID=I, at=0) @test(shareID=I, at=3) @test(shareID=I, at=6) i: [j, j, j, j, j, j, j] @test(shareID=I) j: 1 --- out/compile -- ---- in.cue -{ - f: [ - 〈1;g〉, - 〈1;g〉, - 〈1;g〉, - 〈1;g〉, - 〈1;g〉, - 〈1;g〉, - 〈1;g〉, - ] - g: [ - 〈1;h〉, - 〈1;h〉, - 〈1;h〉, - 〈1;h〉, - 〈1;h〉, - 〈1;h〉, - 〈1;h〉, - ] - h: [ - 〈1;i〉, - 〈1;i〉, - 〈1;i〉, - 〈1;i〉, - 〈1;i〉, - 〈1;i〉, - 〈1;i〉, - ] - i: [ - 〈1;j〉, - 〈1;j〉, - 〈1;j〉, - 〈1;j〉, - 〈1;j〉, - 〈1;j〉, - 〈1;j〉, - ] - j: 1 -} -- out/eval/stats -- Leaks: 0 Freed: 34 diff --git a/cue/testdata/benchmarks/sharefg.txtar b/cue/testdata/benchmarks/sharefg.txtar index 60304cc61..d5e92db57 100644 --- a/cue/testdata/benchmarks/sharefg.txtar +++ b/cue/testdata/benchmarks/sharefg.txtar @@ -189,270 +189,6 @@ Conjuncts: 845 Disjuncts: 0 NumCloseIDs: 238 --- out/compile -- ---- in.cue -{ - binexpr: { - f1: { - out: { - x: 2 - } - } - f2: { - out: { - x: (〈2;f1〉.out.x + 1) - } - } - f3: { - out: { - x: (〈2;f2〉.out.x + 1) - } - } - f4: { - out: { - x: (〈2;f3〉.out.x + 1) - } - } - f5: { - out: { - x: (〈2;f4〉.out.x + 1) - } - } - f6: { - out: { - x: (〈2;f5〉.out.x + 1) - } - } - f7: { - out: { - x: (〈2;f6〉.out.x + 1) - } - } - f8: { - out: { - x: (〈2;f7〉.out.x + 1) - } - } - } - parenthesized: { - f1: { - out: { - x: 2 - } - } - f2: { - out: { - x: (〈2;f1〉.out.x + 1) - } - } - f3: { - out: { - x: (〈2;f2〉.out.x + 1) - } - } - f4: { - out: { - x: (〈2;f3〉.out.x + 1) - } - } - f5: { - out: { - x: (〈2;f4〉.out.x + 1) - } - } - f6: { - out: { - x: (〈2;f5〉.out.x + 1) - } - } - f7: { - out: { - x: (〈2;f6〉.out.x + 1) - } - } - f8: { - out: { - x: (〈2;f7〉.out.x + 1) - } - } - } - embedded: { - f1: { - out: { - x: 2 - } - } - f2: { - out: { - x: ({ - 〈3;f1〉.out - }.x + 1) - } - } - f3: { - out: { - x: ({ - 〈3;f2〉.out - }.x + 1) - } - } - f4: { - out: { - x: ({ - 〈3;f3〉.out - }.x + 1) - } - } - f5: { - out: { - x: ({ - 〈3;f4〉.out - }.x + 1) - } - } - f6: { - out: { - x: ({ - 〈3;f5〉.out - }.x + 1) - } - } - f7: { - out: { - x: ({ - 〈3;f6〉.out - }.x + 1) - } - } - f8: { - out: { - x: ({ - 〈3;f7〉.out - }.x + 1) - } - } - } - embeddedWithEmpty: { - f1: { - out: { - x: 2 - } - } - f2: { - out: { - x: ({ - (〈3;f1〉.out & {}) - }.x + 1) - } - } - f3: { - out: { - x: ({ - (〈3;f2〉.out & {}) - }.x + 1) - } - } - f4: { - out: { - x: ({ - (〈3;f3〉.out & {}) - }.x + 1) - } - } - f5: { - out: { - x: ({ - (〈3;f4〉.out & {}) - }.x + 1) - } - } - f6: { - out: { - x: ({ - (〈3;f5〉.out & {}) - }.x + 1) - } - } - f7: { - out: { - x: ({ - (〈3;f6〉.out & {}) - }.x + 1) - } - } - f8: { - out: { - x: ({ - (〈3;f7〉.out & {}) - }.x + 1) - } - } - } - weave: { - f: { - out: (〈0;in〉 + 1) - in: (〈1〉.ref.out + 1) - ref: (_ & {}) - } - f8: (〈0;f〉 & { - ref: 〈1;f7〉 - }) - f7: (〈0;f〉 & { - ref: 〈1;f6〉 - }) - f6: (〈0;f〉 & { - ref: 〈1;f5〉 - }) - f5: (〈0;f〉 & { - ref: 〈1;f4〉 - }) - f4: (〈0;f〉 & { - ref: 〈1;f3〉 - }) - f3: (〈0;f〉 & { - ref: 〈1;f2〉 - }) - f2: (〈0;f〉 & { - ref: 〈1;f1〉 - }) - f1: { - out: 2 - } - } - weaveExtraField: { - f: { - out: (〈0;in〉 + 1) - in: (〈1〉.ref.out + 1) - ref: { - y: 4 - } - } - f8: (〈0;f〉 & { - ref: 〈1;f7〉 - }) - f7: (〈0;f〉 & { - ref: 〈1;f6〉 - }) - f6: (〈0;f〉 & { - ref: 〈1;f5〉 - }) - f5: (〈0;f〉 & { - ref: 〈1;f4〉 - }) - f4: (〈0;f〉 & { - ref: 〈1;f3〉 - }) - f3: (〈0;f〉 & { - ref: 〈1;f2〉 - }) - f2: (〈0;f〉 & { - ref: 〈1;f1〉 - }) - f1: { - out: 2 - } - } -} -- out/todo.txt -- weave.f.out: v2 reports [cycle] error, v3 reports [incomplete] "undefined field: out". weaveExtraField.f.out: same v2/v3 difference as weave.f.out. diff --git a/cue/testdata/benchmarks/sort.txtar b/cue/testdata/benchmarks/sort.txtar index b888c90bf..2bff645f9 100644 --- a/cue/testdata/benchmarks/sort.txtar +++ b/cue/testdata/benchmarks/sort.txtar @@ -16,68 +16,6 @@ out: list.Sort(list.FlattenN(_c, 4), {x: _, y: _, less: x.name < y.name}) v2 expanded _b and _c elements into independent copies of the sublists; v3 uses structure sharing (_b elements: ~(_a), _c elements: ~(_b)). NOTE: this sharing is tested explicitly in share.txtar. --- out/compile -- ---- in.cue -{ - _a: [ - { - name: 1 - }, - { - name: 3 - }, - { - name: 4 - }, - { - name: 5 - }, - { - name: 6 - }, - { - name: 7 - }, - { - name: 8 - }, - { - name: 9 - }, - { - name: 0 - }, - ] - _b: [ - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - 〈1;_a〉, - ] - _c: [ - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - 〈1;_b〉, - ] - out: 〈import;list〉.Sort(〈import;list〉.FlattenN(〈0;_c〉, 4), { - x: _ - y: _ - less: (〈0;x〉.name < 〈0;y〉.name) - }) -} -- out/eval/stats -- Leaks: 0 Freed: 947 diff --git a/cue/testdata/benchmarks/typocheck.txtar b/cue/testdata/benchmarks/typocheck.txtar index 627ab8c15..9d9fa6d91 100644 --- a/cue/testdata/benchmarks/typocheck.txtar +++ b/cue/testdata/benchmarks/typocheck.txtar @@ -43,34 +43,3 @@ NumCloseIDs: 212 ConjunctInfos: 905 MaxConjunctInfos: 103 MaxReqSets: 104 --- out/compile -- ---- in.cue -{ - out: (〈0;#Output〉 & { - #input: 〈1;_input〉 - }) - _input: { - for _, n in 〈import;list〉.Range(1, 100, 1) { - "A\(〈1;n〉)": { - "B\(〈2;n〉)": { - name: "name\(〈3;n〉)" - } - } - } - } - #Embed: { - [string]: string - } - #Output: { - 〈1;#Embed〉 - #input: _ - for _, lvlA in 〈0;#input〉 { - for nameB, lvlB in 〈1;lvlA〉 { - 〈1;nameB〉: 〈1;lvlB〉.name - } - } - } - _checkB1: 〈0;out〉.B1 - _checkB50: 〈0;out〉.B50 - _checkB99: 〈0;out〉.B99 -} diff --git a/cue/testdata/builtins/056_issue314.txtar b/cue/testdata/builtins/056_issue314.txtar index 277757be4..2918b9456 100644 --- a/cue/testdata/builtins/056_issue314.txtar +++ b/cue/testdata/builtins/056_issue314.txtar @@ -60,29 +60,3 @@ NumCloseIDs: 3 -- out/diff-v2-v3.txt -- positions: v3 reports different position for some errors Verdict: worsening -- v3 reports different error positions. --- out/compile -- ---- in.cue -{ - x: { - s: "myname" - 〈1;#T〉 - } - #T: { - s: string - out: 〈import;"text/template"〉.Execute("{{.s}}", { - s: 〈1;s〉 - }) - } - #V: { - s: string - out: 〈import;"encoding/json"〉.Marshal({ - s: 〈1;s〉 - }) - } - #U: { - s: string - out: 〈import;"encoding/yaml"〉.Marshal({ - s: 〈1;s〉 - }) - } -} diff --git a/cue/testdata/builtins/all.txtar b/cue/testdata/builtins/all.txtar index 67b19d621..f29d1d211 100644 --- a/cue/testdata/builtins/all.txtar +++ b/cue/testdata/builtins/all.txtar @@ -57,41 +57,3 @@ NumCloseIDs: 3 ./in.cue:10:17 [incomplete] okIncompleteChild.x.a: undefined field: c: ./in.cue:18:16 --- out/compile -- ---- in.cue -{ - fatalArg: { - x: len(("eee" + 'eee')) - } - fatalChild: { - #b: {} - x: and([ - { - a: 〈2;#b〉.c - }, - ]) - } - okIncompleteChild: { - b: {} - x: and([ - { - a: 〈2;b〉.c - }, - { - b: 1 - }, - ]) - } -} ---- issue3412.cue -{ - andInPattern: { - out: { - [and(〈1;#constraints〉)]: _ - someKey: {} - } - #constraints: [ - =~"^.*$", - ] - } -} diff --git a/cue/testdata/builtins/and.txtar b/cue/testdata/builtins/and.txtar index 9c7be7a57..737fcd2d7 100644 --- a/cue/testdata/builtins/and.txtar +++ b/cue/testdata/builtins/and.txtar @@ -48,37 +48,3 @@ NumCloseIDs: 10 ./in.cue:11:28 [incomplete] issue3719._filledLater: undefined field: foo: ./in.cue:11:28 --- out/compile -- ---- in.cue -{ - merge: and([ - 1, - 1, - ]) - embed: and([ - { - 2 - #x: 1 - }, - { - 2 - #x: 2 - }, - ]) - issue3719: { - #openStruct: { - ... - } - _filledLater: 〈0;#openStruct〉.foo - withoutAnd: { - for k, v in 〈1;_filledLater〉.bar { - 〈1;k〉: 〈1;v〉 - } - } - withAnd: and([ - for k, v in 〈1;_filledLater〉.bar { - 〈1;k〉: 〈1;v〉 - }, - ]) - } -} diff --git a/cue/testdata/builtins/args.txtar b/cue/testdata/builtins/args.txtar index b7b522115..28a740d32 100644 --- a/cue/testdata/builtins/args.txtar +++ b/cue/testdata/builtins/args.txtar @@ -33,24 +33,3 @@ Retain: 0 Unifications: 10 Conjuncts: 16 Disjuncts: 4 --- out/compile -- ---- in.cue -{ - issue3584: { - reduced: { - t1: { - ref: 〈0;out〉 - trigger: (*1|2) - out: 〈import;strings〉.SliceRunes("ABC", 0, 〈0;trigger〉) - } - } - } - issue3584: { - reduced: { - t2: { - x: 〈import;math〉.Abs(〈0;y〉) - y: (*6|5) - } - } - } -} diff --git a/cue/testdata/builtins/closeall.txtar b/cue/testdata/builtins/closeall.txtar index 2f82f095d..74602c3e4 100644 --- a/cue/testdata/builtins/closeall.txtar +++ b/cue/testdata/builtins/closeall.txtar @@ -63,48 +63,3 @@ h: { ./in.cue:44:7 [eval] h.err: error in call to __closeAll: __closeAll may only be used when explicitopen is enabled: ./old.cue:3:7 --- out/compile -- ---- in.cue -{ - a: __closeAll({ - field1: 1 - nested: { - field2: "hello" - } - }) - b: { - err: (〈1;a〉 & { - extra: "not allowed" - }) - } - c: { - err: (〈1;a〉 & { - field1: 1 - nested: { - field2: "hello" - extra: "not allowed" - } - }) - } - d: { - err: __closeAll("not a struct") - } - e: __closeAll({}) - f: { - err: (〈1;e〉 & { - extra: "not allowed" - }) - } - #A: { - a: int - } - g: { - err: __closeAll(〈1;#A〉) - } -} ---- old.cue -{ - h: { - err: __closeAll({}) - } -} diff --git a/cue/testdata/builtins/closed.txtar b/cue/testdata/builtins/closed.txtar index 0f29dcfae..deecd299e 100644 --- a/cue/testdata/builtins/closed.txtar +++ b/cue/testdata/builtins/closed.txtar @@ -206,246 +206,3 @@ MaxRedirect: 2 Reordering Let differs. Verdict: cosmetic -- Field reordering; let binding differences. No semantic change. --- out/compile -- ---- embed.cue -{ - nestedEmbedded: { - base: { - close({ - foo?: close({ - foo?: _ - }) - }) - foo: { - allowed: 5 - } - } - } - nestedEmbedded: { - t1: { - { - close({ - foo?: close({ - foo?: _ - }) - }) - } - foo: { - allowed: 5 - } - } - } - nestedEmbedded: { - t2: { - { - { - close({ - foo?: close({ - foo?: _ - }) - }) - } - } - foo: { - allowed: 5 - } - } - } - unified: { - base: { - x: close({ - foo?: close({ - foo?: _ - }) - }) - x: { - foo: { - disallowed: 5 - } - } - } - } - unified: { - t1: { - x: { - close({ - foo?: close({ - foo?: _ - }) - }) - } - x: { - foo: { - disallowed: 5 - } - } - } - } - unified: { - t2: { - x: { - { - close({ - foo?: close({ - foo?: _ - }) - }) - } - } - x: { - foo: { - disallowed: 5 - } - } - } - } - nestedWithSelfReference: { - t1: { - _schema: close({ - foo?: 〈1;_schema〉 - }) - x: { - 〈1;_schema〉 - } - x: { - foo: { - disallowed: 5 - } - } - } - } - nestedWithSelfReference: { - t2: { - _schema: close({ - foo?: 〈1;_schema〉 - }) - x: { - { - 〈2;_schema〉 - } - } - x: { - foo: { - disallowed: 5 - } - } - } - } -} ---- in.cue -{ - a: close({ - a: { - b: int - } - }) - b: (〈0;a〉 & { - x: int - }) - c: (〈0;a〉 & { - a: { - c: int - } - }) - inDisjunctions: { - x: { - [string]: 〈1;#Def〉 - } - #Def: { - [string]: { - a: { - b: true - } - let X#1 = 〈0;a〉 - (close({ - uint: { - a: { - b: 〈3;let X#1〉.b - } - } - })|close({ - string: { - a: { - b: true - } - } - })) - } - } - x: { - socket: { - string: {} - } - } - x: { - syslog: 〈1;x〉.socket - } - x: { - syslog: { - xxx: {} - } - } - } - issue642: { - test: close(({ - a: _ - b: { - x: _ - } - } & { - [string]: { - y: _ - } - })) - test: { - a: { - x: _ - } - } - test: { - b: { - x: _ - } - } - } - withSubfields: { - test: close({ - a: _ - b: { - x: _ - } - [string]: { - y: _ - } - }) - test: { - a: { - x: _ - } - } - test: { - b: { - x: _ - } - } - } - issue3572: { - t1: (close({ - ... - }) & { - a: 5 - }) - e: close({ - ... - }) - t2: (〈0;e〉 & { - a: 5 - }) - } - issue3580: { - x: close({ - a: _ - b: 〈1;x〉.a - }) - } -} diff --git a/cue/testdata/builtins/default.txtar b/cue/testdata/builtins/default.txtar index e81102b1c..c24fa6bcc 100644 --- a/cue/testdata/builtins/default.txtar +++ b/cue/testdata/builtins/default.txtar @@ -7,28 +7,6 @@ Div: div(*5 | string, 2) @test(eq, 2) Mod: mod(*5 | string, 2) @test(eq, 1) Quo: quo(*5 | string, 2) @test(eq, 2) Rem: rem(*5 | string, 2) @test(eq, 1) --- out/compile -- ---- in.cue -{ - Len: len((*[ - 1, - 2, - 3, - ]|0)) - Close: close((*{}|0)) - And: and((*[ - 1, - 1, - ]|int)) - Or: or((*[ - 1, - 1, - ]|int)) - Div: div((*5|string), 2) - Mod: mod((*5|string), 2) - Quo: quo((*5|string), 2) - Rem: rem((*5|string), 2) -} -- out/eval/stats -- Leaks: 1 Freed: 42 diff --git a/cue/testdata/builtins/error.txtar b/cue/testdata/builtins/error.txtar index cf2c801d1..a12d245c9 100644 --- a/cue/testdata/builtins/error.txtar +++ b/cue/testdata/builtins/error.txtar @@ -170,69 +170,3 @@ issue3983.x: I wanted more than 10: ./self.cue:6:12 ./self.cue:7:5 ./self.cue:8:5 --- out/compile -- ---- in.cue -{ - selection: { - dropError: (1|error("drop me")) - useCustomError: ((1 & 2)|error("use me")) - twoCustomErrors: ((1 & 2)|error("error one")|error("error two")) - x: int - dropIncomplete: ((〈0;x〉 + 1)|error("user msg: x + 1 failed")) - } - interpolation: { - a: { - b: int - } - world: "world" - substituteAll: (〈0;a〉.notExist|error("hello \(〈0;world〉)")) - substituteFail: ((〈0;a〉.b + 1)|〈0;a〉.notExist|error("reference failed: \(〈0;a〉.b) | \(〈0;a〉.notExist)")) - errorNoInterpolation: ("a"|"b"|error("custom")) - errorNoInterpolation: "c" - errorStructInterpolation: ("a"|"b"|error("custom: \({ - x: 1 - })")) - errorStructInterpolation: "c" - errorBottomInterpolation: ("a"|"b"|error("custom: \((1 & 2))")) - errorBottomInterpolation: "c" - } - indirect: { - x: error - y: 〈0;x〉("msg") - } -} ---- incomplete.cue -{ - minFields: (〈import;struct〉.MinFields(2)|error("should remain incomplete")) - maxFields: { - a: 1 - } - multi: (〈import;struct〉.MinFields(2)|error("should remain incomplete")|error("second")) - multi: { - a: 1 - } -} ---- issues.cue -{ - issue4001: { - a: "b" - a: (int|error(("error: " + "a='\(〈0;a〉)'"))) - } - issue3983: { - x: (int|error("I wanted an integer")) - x: (>10|error("I wanted more than 10")) - x: (<20|error("I wanted less than 20")) - x: 3 - } - issue3984: { - v: ("a"|error("must be a")) - v: "b" - } -} ---- self.cue -{ - errorSelf: { - v: ("x"|"y"|error("bad: \(〈1〉)")) - v: "z" - } -} diff --git a/cue/testdata/builtins/export.txtar b/cue/testdata/builtins/export.txtar index c1776aff7..cfda0d901 100644 --- a/cue/testdata/builtins/export.txtar +++ b/cue/testdata/builtins/export.txtar @@ -37,36 +37,3 @@ Conjuncts: 18 Disjuncts: 0 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - issue3972: { - output: { - out0: "static" - } - input: { - inputStatic: "static" - } - if false { - input: { - inputNever: "never" - } - } - derived: { - derivedStatic: "static" - } - if false { - derived: { - derivedNever: 〈2;input〉.inputNever - } - } - _out1: [ - for svc, _ in 〈1;derived〉 { - 〈1;svc〉 - }, - ] - output: { - out1: 〈import;"encoding/yaml"〉.Marshal(〈1;_out1〉) - } - } -} diff --git a/cue/testdata/builtins/incomplete.txtar b/cue/testdata/builtins/incomplete.txtar index 2de18f541..1280adf34 100644 --- a/cue/testdata/builtins/incomplete.txtar +++ b/cue/testdata/builtins/incomplete.txtar @@ -185,102 +185,3 @@ NumCloseIDs: 7 [incomplete] multipleErrors.#T.out: error in call to text/template.Execute: cannot convert non-concrete value string: ./in.cue:106:8 ./in.cue:103:4 --- out/compile -- ---- in.cue -{ - list1: { - Out1: 〈import;list〉.FlattenN(〈0;Top〉, 1) - Out2: ([ - ..., - ] & 〈import;list〉.FlattenN(〈0;Top〉, 1)) - Out3: (〈import;list〉.FlattenN(〈0;Top〉, 1) & [ - ..., - ]) - Top: [ - [ - for _, F in 〈2;_Sub〉 { - 〈1;F〉 - }, - ], - ] - _Sub: 〈0;a〉.b - a: {} - } - list2: { - Out1: 〈import;list〉.FlattenN(〈0;_Top〉, 1) - Out2: ([ - ..., - ] & 〈import;list〉.FlattenN(〈0;_Top〉, 1)) - Out3: (〈import;list〉.FlattenN(〈0;_Top〉, 1) & [ - ..., - ]) - _Top: [ - for _, F in 〈1;#Sub〉 { - 〈1;F〉 - }, - ] - #Sub: 〈0;a〉.b - a: {} - } - value1: { - a: len(('sf'|'dd')) - } - value2: { - len(('sf'|'dd')) - } - incompleteArgDecimalList: { - a: (〈0;#a〉 & { - param: 123 - }) - #a: { - param: int - transformed: +〈0;param〉 - max: 〈import;list〉.Max([ - 〈1;transformed〉, - ]) - } - } - incompleteArgStringList: { - a: (〈0;#a〉 & { - param: "123" - }) - #a: { - param: string - transformed: (〈0;param〉 + "") - joined: 〈import;strings〉.Join([ - 〈1;transformed〉, - ], "-") - } - } - incompleteList: { - x: _ - decimal: 〈import;list〉.Max(〈0;x〉) - str: 〈import;strings〉.Join(〈0;x〉, "") - } - incompleteListError: { - x: (〈0;y〉 + []) - y: _ - decimal: 〈import;list〉.Max(〈0;x〉) - str: 〈import;strings〉.Join(〈0;x〉, "") - } - badListType: { - x: 2 - decimal: 〈import;list〉.Max(〈0;x〉) - str: 〈import;strings〉.Join(〈0;x〉, "") - } - badListError: { - x: (2 + 〈0;y〉) - y: "foo" - decimal: 〈import;list〉.Max(〈0;x〉) - str: 〈import;strings〉.Join(〈0;x〉, "") - } - multipleErrors: { - #T: { - params: { - x: string - y: string - } - out: 〈import;"text/template"〉.Execute("{{.x}} {{.y}}", 〈0;params〉) - } - } -} diff --git a/cue/testdata/builtins/intdiv.txtar b/cue/testdata/builtins/intdiv.txtar index 9558dd1f0..1b599ffda 100644 --- a/cue/testdata/builtins/intdiv.txtar +++ b/cue/testdata/builtins/intdiv.txtar @@ -73,35 +73,3 @@ Disjuncts: 0 ./in.cue:38:20 [eval] modTypeError2: cannot use 1.0 (type float) as int in argument 2 to mod: ./in.cue:39:23 --- out/compile -- ---- in.cue -{ - quo1: quo(5, 2) - quo2: quo(5, -2) - quo3: quo(-5, 2) - quo4: quo(-5, -2) - quoDivByZero: quo(2, 0) - quoTypeError1: quo(2.0, 1) - quoTypeError2: quo(2, 1.0) - rem1: rem(5, 2) - rem2: rem(5, -2) - rem3: rem(-5, 2) - rem4: rem(-5, -2) - remDivByZero: rem(2, 0) - remTypeError1: rem(2.0, 1) - remTypeError2: rem(2, 1.0) - div1: div(5, 2) - div2: div(5, -2) - div3: div(-5, 2) - div4: div(-5, -2) - divDivByZero: div(2, 0) - divTypeError1: div(2.0, 1) - divTypeError2: div(2, 1.0) - mod1: mod(5, 2) - mod2: mod(5, -2) - mod3: mod(-5, 2) - mod4: mod(-5, -2) - modDivByZero: mod(2, 0) - modTypeError1: mod(2.0, 1) - modTypeError2: mod(2, 1.0) -} diff --git a/cue/testdata/builtins/issue299.txtar b/cue/testdata/builtins/issue299.txtar index 9c91c6029..eaa9d5967 100644 --- a/cue/testdata/builtins/issue299.txtar +++ b/cue/testdata/builtins/issue299.txtar @@ -24,16 +24,3 @@ NumCloseIDs: 1 ./in.cue:3:4 ./in.cue:4:4 ./in.cue:5:4 --- out/compile -- ---- in.cue -{ - x: 〈import;list〉.UniqueItems - x: [ - string, - ...string, - ] - x: [ - "x", - "x", - ] -} diff --git a/cue/testdata/builtins/issue4208.txtar b/cue/testdata/builtins/issue4208.txtar index 2df35cb65..d1264eb7a 100644 --- a/cue/testdata/builtins/issue4208.txtar +++ b/cue/testdata/builtins/issue4208.txtar @@ -38,19 +38,3 @@ invalid: foo: {} @test(err, code=eval, contains="field not allowed", incorrect) -- out/errors.txt -- [eval] invalid.foo: field not allowed: ./in.cue:10:10 --- out/compile -- ---- in.cue -{ - #Environment: ("sbx"|"stg"|"pro"|error("Must specify a valid environment")) - #Envs: { - [〈1;#Environment〉]: {} - } - valid: 〈0;#Envs〉 - valid: { - sbx: {} - } - invalid: 〈0;#Envs〉 - invalid: { - foo: {} - } -} diff --git a/cue/testdata/builtins/issue490.txtar b/cue/testdata/builtins/issue490.txtar index 018d64f5e..1795d55d3 100644 --- a/cue/testdata/builtins/issue490.txtar +++ b/cue/testdata/builtins/issue490.txtar @@ -48,14 +48,3 @@ NumCloseIDs: 3 positions Reordering Verdict: worsening -- v3 reports different error positions; field reordering. --- out/compile -- ---- test.cue -{ - A: close({ - a: 1 - b: 2 - }) - B: (〈0;A〉 & { - c: 3 - }) -} diff --git a/cue/testdata/builtins/issue_3567.txtar b/cue/testdata/builtins/issue_3567.txtar index 2e0f04fcd..30cb0d7fa 100644 --- a/cue/testdata/builtins/issue_3567.txtar +++ b/cue/testdata/builtins/issue_3567.txtar @@ -2,16 +2,6 @@ import "strings" a: strings.Join( [ strings.Join(["1"]), "2" ], "\n") @test(err, code=eval, contains="not enough arguments in call to strings.Join", pos=[0:4, 0:20]) --- out/compile -- ---- in.cue -{ - a: 〈import;strings〉.Join([ - 〈import;strings〉.Join([ - "1", - ]), - "2", - ], "\n") -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/builtins/list/issue332.txtar b/cue/testdata/builtins/list/issue332.txtar index 55a20918a..a14bd0295 100644 --- a/cue/testdata/builtins/list/issue332.txtar +++ b/cue/testdata/builtins/list/issue332.txtar @@ -28,22 +28,3 @@ Conjuncts: 44 Disjuncts: 0 NumCloseIDs: 15 --- out/compile -- ---- in.cue -{ - #d: { - #x: string - result: [ - 〈1;#x〉, - ] - } - #foo: { - #x: _ - y: 〈import;list〉.FlattenN((〈1;#d〉 & { - #x: 〈1;#x〉 - }).result, 1) - } - r: (〈0;#foo〉 & { - #x: "hello" - }) -} diff --git a/cue/testdata/builtins/list/sort.txtar b/cue/testdata/builtins/list/sort.txtar index 662073e51..b6f89d04f 100644 --- a/cue/testdata/builtins/list/sort.txtar +++ b/cue/testdata/builtins/list/sort.txtar @@ -14,17 +14,3 @@ Conjuncts: 20 Disjuncts: 0 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - a: 〈import;list〉.Sort([ - 2, - 3, - 1, - 4, - ], { - x: _ - y: _ - less: (〈0;x〉 < 〈0;y〉) - }) -} diff --git a/cue/testdata/builtins/matchif.txtar b/cue/testdata/builtins/matchif.txtar index c07c6f88c..87f05f740 100644 --- a/cue/testdata/builtins/matchif.txtar +++ b/cue/testdata/builtins/matchif.txtar @@ -46,48 +46,3 @@ Conjuncts: 154 Disjuncts: 0 NumCloseIDs: 48 --- out/compile -- ---- in.cue -{ - regularFields: { - [_]: matchIf({ - x!: >2 - }, { - y!: 5 - }, { - y!: 1 - }) - ok1: { - x: 10 - y: 5 - } - ok2: { - x: 11 - y: 5 - } - ok3: { - x: 2 - y: 1 - } - ok4: { - x: 1 - y: 1 - } - err1: { - x: 10 - y: 6 - } - err2: { - x: 11 - y: 6 - } - err3: { - x: 2 - y: 5 - } - err4: { - x: 1 - y: 2 - } - } -} diff --git a/cue/testdata/builtins/matchn.txtar b/cue/testdata/builtins/matchn.txtar index ab426a7c0..7bd7919f7 100644 --- a/cue/testdata/builtins/matchn.txtar +++ b/cue/testdata/builtins/matchn.txtar @@ -796,650 +796,3 @@ v2/v3 differences: - explicitClose.err1.out.a.baz: v2 reports extra position info that v3 does not - issue3389.x: position differences - issue3694: position differences (2-line comment at top of file shifts line numbers) --- out/compile -- ---- closedness.cue -{ - ellipsis: { - ok: { - out: (〈0;#Schema〉 & { - field: { - shouldBeAllowed: 123 - } - }) - #Schema: { - field?: 〈0;#anything〉 - #anything: matchN(1, [ - { - ... - }, - ]) - } - } - } - openArguments: { - ok1: { - #Schema: { - { - a: matchN(1, [ - "all", - { - foo: "bar" - }, - ]) - } - } - out: (〈0;#Schema〉 & { - a: { - baz: "allowed" - } - }) - } - } - openArguments: { - err2: { - #Schema: { - { - a?: matchN(1, [ - null, - { - [string]: string - }, - { - b: { - ... - } - }, - ]) - } - } - out: (〈0;#Schema〉 & { - a: { - allowed: "once" - } - }) - } - } - explicitClose: { - err1: { - #Schema: { - { - a: matchN(1, [ - "all", - close({ - foo: "bar" - }), - ]) - } - } - out: (〈0;#Schema〉 & { - a: { - baz: "notAllowed" - } - }) - } - } - explicitClose: { - ok2: { - #Schema: { - { - a?: matchN(1, [ - null, - close({ - [string]: string - }), - close({ - b: { - ... - } - }), - ]) - } - } - out: (〈0;#Schema〉 & { - a: { - allowed: "once" - } - }) - } - } - mixed: { - ok3: { - #Schema: { - exports?: matchN(1, [ - close({ - never?: _ - }), - 〈1;#exportsObject〉, - ]) - #exports: matchN(1, [ - string, - 〈1;#exportsObject〉, - ]) - #exportsObject: { - exp1?: 〈1;#exports〉 - } - } - out: (〈0;#Schema〉 & { - exports: { - exp1: "./main-module.js" - } - }) - } - } - closedByDefinition: { - ok4: { - #Schema: { - exports?: matchN(1, [ - string, - 〈1;#exportsObject〉, - ]) - #exports: matchN(1, [ - string, - 〈1;#exportsObject〉, - ]) - #exportsObject: { - exp1?: 〈1;#exports〉 - } - } - out: (〈0;#Schema〉 & { - exports: { - exp1: "./main-module.js" - } - }) - } - } - closedByDefinition: { - err5: { - #Schema: { - exports?: matchN(1, [ - null, - 〈1;#exportsObject〉, - ]) - #exports: matchN(1, [ - null, - 〈1;#exportsObject〉, - ]) - #exportsObject: { - exp1?: 〈1;#exports〉 - } - } - out: (〈0;#Schema〉 & { - exports: { - exp1: "./main-module.js" - } - }) - } - } -} ---- in.cue -{ - #Foo: { - a: int - } - match: { - [=~"^single"]: matchN(1, [ - 〈2;#Foo〉, - ]) - singleOK: { - a: 2 - } - singleErr: { - a: "foo" - } - [=~"^incomplete"]: matchN(1, [ - 〈2;#Foo〉, - ]) - incompleteOK: { - a: int - } - incompleteErr: { - a: string - } - #A: { - a: int - b: _ - ... - } - defaults: { - [=~"^pickTop"]: matchN(1, [ - 2, - ]) - pickTopOK1: (*2|int) - pickTopOK2: int - pickTopErr: (*3|int) - [=~"^pickNested1"]: matchN(1, [ - { - a: 2 - }, - ]) - pickNested1OK1: { - a: (*2|int) - } - pickNested1OK2: { - a: int - } - pickNested1Err: { - a: (*3|int) - } - [=~"^pickNested2"]: matchN(1, [ - { - a: <=2 - }, - ]) - pickNested2OK1: { - a: (*2|int) - } - pickNested2OK2: { - a: int - } - pickNested2Err: { - a: (*3|int) - } - } - nestedOK: { - matchN(4, [ - 〈2;#A〉, - 〈2;#A〉, - 〈2;#A〉, - 〈2;#A〉, - ]) - a: 2 - b: { - matchN(4, [ - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - ]) - a: 3 - b: matchN(4, [ - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - ]) - b: { - a: 4 - } - c: matchN(4, [ - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - ]) - c: { - a: 5 - } - } - c: { - matchN(4, [ - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - ]) - a: 3 - b: matchN(4, [ - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - ]) - b: { - a: 4 - } - c: matchN(4, [ - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - 〈3;#A〉, - ]) - c: { - a: 5 - } - } - } - } - not: { - [=~"^single"]: matchN(0, [ - 〈2;#Foo〉, - ]) - singleOK: { - a: "foo" - } - singleErr: { - a: 2 - } - [=~"^double"]: matchN(0, [ - matchN(0, [ - 〈3;#Foo〉, - ]), - ]) - doubleOK: { - a: 2 - } - doubleErr: { - a: "foo" - } - } - oneOf: { - [=~"^multiple1"]: matchN(1, [ - 〈import;math〉.MultipleOf(3), - 〈import;math〉.MultipleOf(5), - ]) - multiple1Err1: 1 - multiple1OK1: 3 - multiple1OK2: 5 - multiple1Err2: 15 - } - anyOf: { - [=~"^multiple1"]: matchN(>0, [ - 〈import;math〉.MultipleOf(3), - 〈import;math〉.MultipleOf(5), - ]) - multiple1Err1: 1 - multiple1OK1: 3 - multiple1OK2: 5 - multiple1OK3: 15 - } - allOf: { - [=~"^multiple1"]: matchN(2, [ - 〈import;math〉.MultipleOf(3), - 〈import;math〉.MultipleOf(5), - ]) - multiple1Err1: 1 - multiple1Err2: 3 - multiple1Err3: 5 - multiple1OK1: 15 - } - bare: { - embed: { - t1: { - a: { - matchN(1, [ - >10, - ]) - } - b: { - 〈1;a〉 - } - } - } - embed: { - t2: { - b: { - 〈1;a〉 - } - a: { - matchN(1, [ - >10, - ]) - } - } - } - direct: { - t1: { - a: matchN(1, [ - >10, - ]) - b: 〈0;a〉 - } - } - direct: { - t2: { - b: 〈0;a〉 - a: matchN(1, [ - >10, - ]) - } - } - } - required: { - ok1: { - x: matchN(0, [ - { - foo!: string - }, - ]) - x: { - bar: 2 - } - } - ok2: { - x: matchN(0, [ - { - foo!: string - }, - ]) - } - ok3: { - x: matchN(0, [ - { - bar!: string - }, - ]) - x: { - bar: 2 - } - } - } - issue3575: { - test1: { - #x: matchN(1, [ - [ - {}, - ], - ]) - x: 〈0;#x〉 - x: [ - { - a: 1 - }, - ] - } - test2: { - #x: matchN(1, [ - {}, - ]) - x: 〈0;#x〉 - x: { - a: 1 - } - } - } -} ---- incomplete.cue -{ - incomplete: { - incomplete1: { - x: matchN(1, [ - { - foo!: string - }, - ]) - x: { - bar: 2 - } - } - incomplete2: { - x: matchN(1, [ - { - foo!: string - }, - ]) - } - incomplete3: { - x: matchN(〈import;math〉.MultipleOf(2), [ - { - bar!: int - }, - { - foo!: int - }, - ]) - x: { - bar: 2 - } - } - incomplete4: { - x: matchN(〈import;math〉.MultipleOf(2), [ - { - bar!: int - }, - { - foo!: int - }, - { - baz!: int - }, - ]) - x: { - bar: 2 - } - } - incomplete5: { - x: matchN((>1 & <=3), [ - { - bar!: int - }, - { - foo!: int - }, - { - baz!: int - }, - ]) - x: { - bar: 2 - } - } - incomplete6: { - x: matchN((2|3), [ - { - bar!: int - }, - { - foo!: int - }, - { - baz!: int - }, - ]) - x: { - bar: 2 - } - } - err1: { - x: matchN(1, [ - { - bar!: string - }, - ]) - x: { - bar: 2 - } - } - err2: { - x: matchN(0, [ - { - bar!: int - }, - { - foo!: int - }, - ]) - x: { - bar: 2 - } - } - err3: { - x: matchN(2, [ - { - bar!: string - }, - { - foo!: string - }, - ]) - x: { - bar: 2 - } - } - err4: { - x: matchN(>1, [ - { - bar!: string - }, - { - foo!: string - }, - ]) - x: { - bar: 2 - } - } - err5: { - x: matchN(<1, [ - { - bar!: int - }, - { - foo!: int - }, - ]) - x: { - bar: 2 - } - } - } - issue3389: { - x: { - bar: 2 - } - x: matchN(1, [ - { - bar: 3 - }, - { - bar: 2 - foo!: int - }, - ]) - } -} ---- issue3694.cue -{ - issue3694: { - full: { - #step: matchN(1, [ - { - uses!: _ - ... - }, - { - run!: _ - ... - }, - ]) - #step: close({ - uses?: string - run?: string - }) - s: (〈0;#step〉 & { - run: "echo hello world" - }) - } - } - issue3694: { - simple: { - #step: matchN(1, [ - { - uses!: _ - }, - ]) - #step: close({ - uses?: string - }) - } - } -} diff --git a/cue/testdata/builtins/or.txtar b/cue/testdata/builtins/or.txtar index 247da0619..1b289434e 100644 --- a/cue/testdata/builtins/or.txtar +++ b/cue/testdata/builtins/or.txtar @@ -9,39 +9,3 @@ unique2: or([{a: 1}, {a: 1}, {a: 2}]) @test(eq, {a: 1} | {a: 2}) // do not unique embedded scalars with differing values for child definitions. embed1: or([{2, #x: 1}, {2, #x: 2}]) @test(eq, {2, #x: 1} | {2, #x: 2}) --- out/compile -- ---- in.cue -{ - unwrap: or([ - 1, - 1, - 1, - ]) - unique1: or([ - 2, - 1, - 1, - 2, - ]) - unique2: or([ - { - a: 1 - }, - { - a: 1 - }, - { - a: 2 - }, - ]) - embed1: or([ - { - 2 - #x: 1 - }, - { - 2 - #x: 2 - }, - ]) -} diff --git a/cue/testdata/builtins/reclose.txtar b/cue/testdata/builtins/reclose.txtar index eb11591d2..2376d9241 100644 --- a/cue/testdata/builtins/reclose.txtar +++ b/cue/testdata/builtins/reclose.txtar @@ -159,196 +159,3 @@ retro: { ./in.cue:125:15 [eval] retro.t1.err: error in call to __reclose: __reclose may only be used when explicitopen is enabled: ./old.cue:3:11 --- out/compile -- ---- in.cue -{ - noClose: { - foo: { - a: int - } - a: __reclose({ - 〈1;foo〉... - }) - t1: { - ok: (〈1;a〉 & { - b: 1 - }) - } - } - recursive: { - #x: { - foo: int - } - a: __reclose({ - 〈1;#x〉... - nested: { - field2: int - } - }) - t1: { - err: (〈1;a〉 & { - extra: "not allowed" - }) - } - t2: { - ok: (〈1;a〉 & { - nested: { - field2: 5 - } - }) - } - t3: { - ok: (〈1;a〉 & { - foo: 5 - }) - } - t4: { - err: (〈1;a〉 & { - nested: { - field2: 1 - extra: "not allowed" - } - }) - } - e: __reclose({}) - t5: { - err: (〈1;e〉 & { - extra: "not allowed" - }) - } - } - nonRecursive: { - x: __reclose({ - close({ - b: int - })... - c: int - d: { - e: int - } - }) - y: { - err: (〈1;x〉 & { - f: int - }) - } - z: { - ok: (〈1;x〉 & { - d: { - f: int - } - }) - } - } - nonRecursiveDetect: { - foo: close({ - b: {} - }) - a: __reclose({ - 〈1;foo〉... - }) - t1: { - err: (〈1;a〉 & { - f: int - }) - } - t2: { - ok: (〈1;a〉 & { - b: { - c: 1 - } - }) - } - } - mixedClose: { - #D: { - x: { - y: int - } - } - foo: close({ - b: {} - }) - a: __reclose({ - 〈1;#D〉... - 〈1;foo〉... - }) - t1: { - err: (〈1;a〉 & { - f: int - }) - } - t2: { - ok: (〈1;a〉 & { - x: { - y: 5 - } - b: { - c: 1 - } - }) - } - } - recloseWrapsClose: { - #def: { - a: { - b: int - } - } - a: __reclose(close({ - 〈1;#def〉... - })) - t1: { - err: (〈1;a〉 & { - f: int - }) - } - t2: { - err: (〈1;a〉 & { - a: { - c: 1 - } - }) - } - t3: { - ok: (〈1;a〉 & { - a: { - b: 5 - } - }) - } - } - nonStructLiterals: { - t1: { - err: __reclose("not a struct") - } - #A: { - a: int - } - t4: { - err: __reclose(〈1;#A〉) - } - } - nonStructDefinitions: { - #Def: 1 - a: __reclose({ - 〈1;#Def〉... - }) - t1: { - ok: (〈1;a〉 & 1) - } - t2: { - err: (〈1;a〉 & { - b: 1 - }) - } - } -} ---- old.cue -{ - retro: { - t1: { - err: __reclose({}) - } - } -} diff --git a/cue/testdata/builtins/validators.txtar b/cue/testdata/builtins/validators.txtar index f8b971b54..f6437d819 100644 --- a/cue/testdata/builtins/validators.txtar +++ b/cue/testdata/builtins/validators.txtar @@ -366,317 +366,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 76 --- out/compile -- ---- in.cue -{ - incompleteError1: { - MyType: { - kv: 〈import;struct〉.MinFields(1) - } - foo: (〈0;MyType〉 & { - kv: { - joel: "testing" - } - }) - } - incompleteError2: { - MyType: { - kv: { - [string]: string - } - kv: 〈import;struct〉.MinFields(1) - } - foo: (〈0;MyType〉 & { - kv: { - joel: "testing" - } - }) - } - incompleteError3: { - t: string - t: 〈import;"encoding/json"〉.Validate(string) - } - uniqueConstrains1: { - t: string - t: 〈import;"encoding/json"〉.Validate(string) - t: 〈import;"encoding/json"〉.Validate(string) - } - uniqueConstrains2: { - t: 〈import;struct〉.MaxFields(1) - t: 〈import;struct〉.MaxFields(1) - } - violation: { - #MyType: { - kv: { - [string]: string - } - kv: 〈import;struct〉.MinFields(1) - } - foo: (〈0;#MyType〉 & { - kv: { - joel: "testing" - } - kv: { - tony: "testing" - } - }) - } - conjuncts: { - kv: 〈import;struct〉.MinFields(1) - kv: 〈import;struct〉.MaxFields(3) - } - bareBuiltin: { - a: 〈import;"encoding/json"〉.Valid - a: 〈import;"encoding/json"〉.Valid - } - bareBuiltinCheck: { - a: 〈import;"encoding/json"〉.Valid - a: "3" - } - builtinValidator: { - a: 〈import;"encoding/json"〉.Valid() - a: 〈import;"encoding/json"〉.Valid() - } - builtinValidatorCheck: { - a: 〈import;"encoding/json"〉.Valid() - a: "3" - } - callOfCallToValidator: { - a: 〈import;"encoding/json"〉.Valid - b: 〈0;a〉() - e: 〈0;b〉() - e: "5" - } - validatorAsFunction: { - a: 〈import;"encoding/json"〉.Valid - b: 〈0;a〉("3") - c: 〈import;"encoding/json"〉.Valid("3") - } - issue2098: { - ok1: { - _a: [ - 1, - ..., - ] - _a: 〈import;list〉.MinItems(1) - 〈0;_a〉[0] - } - } - issue2098: { - incomplete1: { - _a: [ - ..., - ] - _a: 〈import;list〉.MinItems(1) - 〈0;_a〉[0] - } - } -} ---- issue3418.cue -{ - issue3418: { - t1: (("foo" & matchN(1, [ - (1 & 2), - ])) & matchN(1, [ - _, - ])) - } - issue3418: { - t2: (("foo" & matchN(1, [ - _, - ])) & matchN(1, [ - (1 & 2), - ])) - } - issue3418: { - t3: { - x: "foo" - x: matchN(1, [ - _, - ]) - x: matchN(1, [ - (1 & 2), - ]) - } - } - issue3418: { - t4: { - x: "foo" - x: matchN(1, [ - (1 & 2), - ]) - x: matchN(1, [ - _, - ]) - } - } -} ---- issue3474.cue -{ - issue3474: { - structValidator: { - ok: { - A: 〈import;struct〉.MinFields(1) - A: { - if true { - B: true - } - } - } - } - } - issue3474: { - structValidator: { - failAfter: { - A: 〈import;struct〉.MaxFields(1) - A: { - C: true - if true { - B: true - } - } - } - } - } - issue3474: { - structValidator: { - incomplete: { - A: 〈import;struct〉.MinFields(1) - A: { - if true {} - } - } - } - } - issue3474: { - structValidator: { - failClosed: { - #A: 〈import;struct〉.MinFields(1) - #A: { - if true {} - } - } - } - } - issue3474: { - topValidator: { - ok: { - A: matchN(1, [ - >10, - ]) - A: { - if true { - 100 - } - } - } - } - } - issue3474: { - topValidator: { - fail: { - A: matchN(1, [ - >10, - ]) - A: { - if true { - 1 - } - } - } - } - } - issue3474: { - topValidator: { - incomplete: { - A: matchN(1, [ - >10, - ]) - A: { - if true { - int - } - } - } - } - } - issue3474: { - topValidator: { - failType: { - A: matchN(1, [ - >10, - ]) - A: { - if true { - C: 1 - } - } - } - } - } -} ---- validator_is_top.cue -{ - issue3639: { - a: ({ - 〈1;#X〉 - } & 〈0;#X〉) - a: { - b: 1 - } - #X: matchN(1, [ - { - b: int - }, - ]) - } - issue3661: { - #X: matchN(1, [ - { - b!: int - }, - ]) - a: { - b: 1 - } - a: 〈0;#X〉 - ["a"]: 〈0;#X〉 - } - issue3678: { - #X: matchN(1, [ - { - a!: string - }, - { - c!: string - }, - ]) - x: { - c: "c" - } - y: 〈0;#X〉 - y: 〈0;x〉 - x: 〈0;#X〉 - } - issue3981: { - matchWithClose: { - out: { - close({ - f1: matchN(1, [ - 〈2;#openStruct〉, - ]) - }) - #openStruct: { - ... - } - } - out: { - f1: { - foo: [ - "bar", - ] - } - } - } - } -} diff --git a/cue/testdata/builtins/versionchk.txtar b/cue/testdata/builtins/versionchk.txtar index ab4eb5650..c62095f63 100644 --- a/cue/testdata/builtins/versionchk.txtar +++ b/cue/testdata/builtins/versionchk.txtar @@ -9,10 +9,3 @@ a: error("msg") -- out/evalalpha -- a: builtin "error" is not available in version v0.8.0; it was added in version "v0.14.0": ./in.cue:2:4 --- out/compile -- -a: builtin "error" is not available in version v0.8.0; it was added in version "v0.14.0": - ./in.cue:2:4 ---- in.cue -{ - a: _|_(builtin "error" is not available in version v0.8.0; it was added in version "v0.14.0")("msg") -} diff --git a/cue/testdata/choosedefault/000_pick_first.txtar b/cue/testdata/choosedefault/000_pick_first.txtar index 61a0a3cdd..c27205042 100644 --- a/cue/testdata/choosedefault/000_pick_first.txtar +++ b/cue/testdata/choosedefault/000_pick_first.txtar @@ -5,18 +5,6 @@ b: c: *{ } | { a: 3 } @test(eq, *{a: 2} | {a: 3}) --- out/compile -- ---- in.cue -{ - a: (*5|"a"|true) - b: { - c: (*{ - a: 2 - }|{ - a: 3 - }) - } -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/choosedefault/001_simple_disambiguation_conflict.txtar b/cue/testdata/choosedefault/001_simple_disambiguation_conflict.txtar index f9a5e2888..32db20e3a 100644 --- a/cue/testdata/choosedefault/001_simple_disambiguation_conflict.txtar +++ b/cue/testdata/choosedefault/001_simple_disambiguation_conflict.txtar @@ -2,13 +2,6 @@ a: *"a" | "b" @test(eq, *"a" | "b") b: *"b" | "a" @test(eq, *"b" | "a") c: a & b @test(eq, "a" | "b") --- out/compile -- ---- in.cue -{ - a: (*"a"|"b") - b: (*"b"|"a") - c: (〈0;a〉 & 〈0;b〉) -} -- out/eval/stats -- Leaks: 0 Freed: 14 diff --git a/cue/testdata/choosedefault/002_associativity_of_defaults.txtar b/cue/testdata/choosedefault/002_associativity_of_defaults.txtar index b54641322..5c98b508f 100644 --- a/cue/testdata/choosedefault/002_associativity_of_defaults.txtar +++ b/cue/testdata/choosedefault/002_associativity_of_defaults.txtar @@ -82,74 +82,3 @@ Conjuncts: 466 Disjuncts: 278 NumCloseIDs: 101 --- out/compile -- ---- complex.cue -{ - t1: { - va: { - a: 1 - b: 2 - } - vb1: { - c: 3 - } - vb2: { - c: 4 - } - vc: { - c: 4 - } - vd: string - A: (〈0;va〉|〈0;vd〉) - B: (*〈0;vb1〉|〈0;vb2〉|〈0;vd〉) - C: (*〈0;vc〉|〈0;vd〉) - p1: ((〈0;A〉 & 〈0;B〉) & 〈0;C〉) - p2: (〈0;A〉 & (〈0;B〉 & 〈0;C〉)) - } - t2: { - va: (0|1|2) - vb1: (2|3) - vb2: (0|1|4) - vc: (0|3|4) - vd: string - A: (〈0;va〉|〈0;vd〉) - B: (*〈0;vb1〉|〈0;vb2〉|〈0;vd〉) - C: (*〈0;vc〉|〈0;vd〉) - p1: ((〈0;A〉 & 〈0;B〉) & 〈0;C〉) - p2: (〈0;A〉 & (〈0;B〉 & 〈0;C〉)) - } -} ---- in.cue -{ - a: (*"a"|("b"|"c")) - b: ((*"a"|"b")|"c") - c: (*"a"|(*"b"|"c")) - x: (〈0;a〉 & 〈0;b〉) - y: (〈0;b〉 & 〈0;c〉) - s1: (*1|((*2|3) & (2|*3))) - s2: (*1|((*2|3) & (*2|3))) - s3: (*1|((*2|3) & 3)) - s4: (*1|((*2|3) & 2)) - s5: (*1|*(*2|3)) - e1: (*(1 & 2)|(*"x"|string)) - e2: ((*"x"|string)|*(1 & 2)) -} ---- issue3908.cue -{ - issue3908: { - reduced: { - (string|*null) - (string|*"str") - } - } - issue3908: { - full: { - out: (〈0;#Schema〉 & { - field: (string|*"dataDefault") - }) - #Schema: { - field: (string|*null) - } - } - } -} diff --git a/cue/testdata/compile/alias.txtar b/cue/testdata/compile/alias.txtar index 636b69f42..28a2f590b 100644 --- a/cue/testdata/compile/alias.txtar +++ b/cue/testdata/compile/alias.txtar @@ -7,15 +7,6 @@ dynamic: { a: "name" @test(eq, {x: 1, a: "name", name: 1}) } --- out/compile -- ---- in.cue -{ - dynamic: { - 〈0;a〉: 1 - x: 〈0;(〈0;a〉)〉 - a: "name" - } -} -- out/eval/stats -- Leaks: 0 Freed: 10 diff --git a/cue/testdata/compile/err_top.txtar b/cue/testdata/compile/err_top.txtar index 67ec7c419..c0edc66c5 100644 --- a/cue/testdata/compile/err_top.txtar +++ b/cue/testdata/compile/err_top.txtar @@ -26,47 +26,6 @@ nested: "_": _: 1 nested: "_foo": _: 1 nested: "#foo": _: 1 --- out/compile -- -disallowTopAsAlias: cannot use _ as alias or let clause: - ./in.cue:2:2 -disallowTopAsLet: cannot use _ as alias or let clause: - ./in.cue:6:6 -disallowTopAsLabel: cannot use _ as label: - ./in.cue:10:2 -nested."_": cannot use _ as label: - ./in.cue:23:14 -nested."_foo": cannot use _ as label: - ./in.cue:24:17 -nested."#foo": cannot use _ as label: - ./in.cue:25:17 ---- in.cue -{ - disallowTopAsAlias: { - X: 1 - } - disallowTopAsLet: { - let _ = 1 - } - disallowTopAsLabel: { - _|_(cannot use _ as label) - a: _ - } - nested: { - "_": { - _|_(cannot use _ as label) - } - } - nested: { - "_foo": { - _|_(cannot use _ as label) - } - } - nested: { - "#foo": { - _|_(cannot use _ as label) - } - } -} -- out/evalalpha -- disallowTopAsAlias: cannot use _ as alias or let clause: ./in.cue:2:2 diff --git a/cue/testdata/compile/erralias.txtar b/cue/testdata/compile/erralias.txtar index 4c4b1ec3e..043616c8a 100644 --- a/cue/testdata/compile/erralias.txtar +++ b/cue/testdata/compile/erralias.txtar @@ -10,24 +10,6 @@ c: {} for x in c {a: E} Z1=[Z2=string]: Z1 + Z2 --- out/compile -- -unreferenced alias or let clause X: - ./in.cue:1:2 -a: reference "Y" not found: - ./in.cue:4:12 -for[].a: reference "E" not found: - ./in.cue:7:16 ---- in.cue -{ - let X#1 = {} - ["foo"]: 3 - a: _|_(reference "Y" not found) - c: {} - for _, x in 〈0;c〉 { - a: _|_(reference "E" not found) - } - [string]: (〈0;(〈0;-〉)〉 + 〈0;-〉) -} -- out/evalalpha -- unreferenced alias or let clause X: ./in.cue:1:2 diff --git a/cue/testdata/compile/experiment.txtar b/cue/testdata/compile/experiment.txtar index d16fa94c5..b3e6261ac 100644 --- a/cue/testdata/compile/experiment.txtar +++ b/cue/testdata/compile/experiment.txtar @@ -12,15 +12,6 @@ on: __test_experiment("on") @test(eq, "on") -- out/errors.txt -- [eval] off: error in call to testExperiment: testing experiment disabled: ./off.cue:1:6 --- out/compile -- ---- off.cue -{ - off: testExperiment("off") -} ---- on.cue -{ - on: testExperiment("on") -} -- out/eval/stats -- Leaks: 0 Freed: 3 diff --git a/cue/testdata/compile/fields.txtar b/cue/testdata/compile/fields.txtar index 635ebb0a1..378cad2c5 100644 --- a/cue/testdata/compile/fields.txtar +++ b/cue/testdata/compile/fields.txtar @@ -3,14 +3,6 @@ "#dev": int @test(eq, int) _dev: int @test(eq, int) _#dev: int @test(eq, int) --- out/compile -- ---- in.cue -{ - #dev: int - "#dev": int - _dev: int - _#dev: int -} -- out/eval/stats -- Leaks: 0 Freed: 5 diff --git a/cue/testdata/compile/files.txtar b/cue/testdata/compile/files.txtar index 3529880d0..829b7d186 100644 --- a/cue/testdata/compile/files.txtar +++ b/cue/testdata/compile/files.txtar @@ -10,24 +10,6 @@ package repro x: {for a in a {}} @test(eq, {}) y: {{{for a in a {}}}} @test(eq, {}) --- out/compile -- ---- in.cue -{ - a: [] -} ---- out.cue -{ - x: { - for _, a in 〈1;a〉 {} - } - y: { - { - { - for _, a in 〈3;a〉 {} - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/compile/json.txtar b/cue/testdata/compile/json.txtar index 5b323bdf2..8ba5913c2 100644 --- a/cue/testdata/compile/json.txtar +++ b/cue/testdata/compile/json.txtar @@ -26,22 +26,6 @@ a } b: [0, 1, 2, 3, 4, 5] }) --- out/compile -- ---- in.cue -{ - a: { - key: "value" - key2: "value2" - } - b: [ - 0, - 1, - 2, - 3, - 4, - 5, - ] -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/compile/labels.txtar b/cue/testdata/compile/labels.txtar index 930dfd927..142d64609 100644 --- a/cue/testdata/compile/labels.txtar +++ b/cue/testdata/compile/labels.txtar @@ -30,66 +30,6 @@ saneReferencesInComprehensions: { a: _ // Should not compile to a reference. } } --- out/compile -- -bad1: comprehension values not allowed in this position: - ./in.cue:24:8 ---- in.cue -{ - dis1: ("dev"|"prd") - dis2: (*"dev"|"prd") - con1: string - let con2#1 = string - ok0: { - [string]: string - } - ok1: { - [string]: string - } - ok2: { - [〈1;con1〉]: string - } - ok3: { - [〈1;let con2#1〉]: string - } - ok4: { - ["foo"]: string - } - ok5: { - [1]: string - } - ok6: { - [1]: string - } - ok7: { - [〈1;dis1〉]: string - } - ok8: { - [〈1;dis2〉]: string - } - ok9: { - [〈1;dis2〉]: string - } - ok10: { - [{ - foo: "bar" - }]: string - } - ok11: { - [〈import;list〉.FlattenN([ - string, - ], 1)]: string - } - bad1: { - [_|_(comprehension values not allowed in this position)]: string - } - saneReferencesInComprehensions: { - for _, _ in [ - 1, - ] { - a: _ - } - } -} -- out/evalalpha -- bad1: comprehension values not allowed in this position: ./in.cue:24:8 diff --git a/cue/testdata/compile/let.txtar b/cue/testdata/compile/let.txtar index 00cb5b97a..e29f3a65c 100644 --- a/cue/testdata/compile/let.txtar +++ b/cue/testdata/compile/let.txtar @@ -71,133 +71,6 @@ issue4051: reduced: { let N = x x: "s" } --- out/compile -- -b.let[]: cyclic references in let clause or alias: - ./in.cue:10:10 ---- alignstack.cue -{ - issue4051: { - full: { - #app: { - name: "foo" - } - let N#1 = 〈0;#app〉.name - out: { - 〈1;let N#1〉=>〈0;#app〉.name: [ - { - f1: { - f2: 〈4;let N#1〉=>〈0;#app〉.name - } - }, - ] - } - } - } - issue4051: { - reduced: { - 〈0;let N#2〉=>〈0;x〉: [ - { - f1: { - f2: 〈3;let N#2〉=>〈0;x〉 - } - }, - ] - let N#2 = 〈0;x〉 - x: "s" - } - } -} ---- in.cue -{ - a: { - let X#3 = 〈0;let Y#4〉=>〈0;c〉 - let Y#4 = 〈0;c〉 - b: 〈0;let X#3〉=>〈0;let Y#4〉=>〈0;c〉 - c: 5 - } - b: { - let X#5 = 〈0;let Y#6〉=>〈0;let X#5〉=>〈0;let Y#6〉=>_|_(cyclic references in let clause or alias) - let Y#6 = 〈0;let X#5〉=>〈0;let Y#6〉=>_|_(cyclic references in let clause or alias) - b: 〈0;let X#5〉=>〈0;let Y#6〉=>_|_(cyclic references in let clause or alias) - c: 5 - } - fieldOffset: { - a: { - p1: { - let X#7 = { - value: 〈1;let Y#8〉=>2 - } - let Y#8 = 2 - x: 〈0;let X#7〉=>{ - value: 〈1;let Y#8〉=>2 - } - } - p2: { - x: 〈0;let X#A〉=>{ - value: 〈1;let Y#9〉=>2 - } - let Y#9 = 2 - let X#A = { - value: 〈1;let Y#9〉=>2 - } - } - } - b: { - p1: { - let X#B = { - x: { - y: 〈2;let Y#C〉=>2 - } - } - let Y#C = 2 - x: 〈0;let X#B〉=>{ - x: { - y: 〈2;let Y#C〉=>2 - } - } - } - p2: { - x: 〈0;let X#E〉=>{ - x: { - y: 〈2;let Y#D〉=>2 - } - } - let Y#D = 2 - let X#E = { - x: { - y: 〈2;let Y#D〉=>2 - } - } - } - } - } - issue767: { - #Foo: { - let _#bar#F = { - value: "" - } - let _#volmnts#10 = { - x: 〈1;let _#baz#11〉=>{ - 〈1;let _#bar#F〉=>{ - value: "" - } - }.value - } - let _#baz#11 = { - 〈1;let _#bar#F〉=>{ - value: "" - } - } - out: 〈0;let _#volmnts#10〉=>{ - x: 〈1;let _#baz#11〉=>{ - 〈1;let _#bar#F〉=>{ - value: "" - } - }.value - } - } - } -} -- out/evalalpha -- b.let[]: cyclic references in let clause or alias: ./in.cue:10:10 diff --git a/cue/testdata/compile/postfixexpr.txtar b/cue/testdata/compile/postfixexpr.txtar index 11cdd6400..d816635d7 100644 --- a/cue/testdata/compile/postfixexpr.txtar +++ b/cue/testdata/compile/postfixexpr.txtar @@ -35,21 +35,3 @@ fn: _ @test(eq, _) ./with_experiment.cue:11:8 [incomplete] d: cannot call non-concrete value fn (type _): ./with_experiment.cue:17:4 --- out/compile -- ---- with_experiment.cue -{ - #Base: { - x: int - } - a: 〈0;#Base〉... - b: 〈0;foo〉.bar... - c: (〈0;x〉 & 〈0;y〉)... - d: 〈0;fn〉()... - e: (〈0;#Base〉... & { - y: int - }) - foo: {} - x: _ - y: _ - fn: _ -} diff --git a/cue/testdata/compile/scope.txtar b/cue/testdata/compile/scope.txtar index d4deea7ae..e966efc2d 100644 --- a/cue/testdata/compile/scope.txtar +++ b/cue/testdata/compile/scope.txtar @@ -46,51 +46,6 @@ schema: { let _schema_1 = schema -- out/errors.txt -- [structural_cycle] schema.next: structural cycle --- out/compile -- ---- in.cue -{ - a: { - { - { - 〈3;b〉 - 〈2;c〉 - d: 〈3;b〉 - e: 〈2;c〉 - } - } - c: {} - } - b: {} - s: "foo" - c: 〈0;s〉 - d: { - [〈1;s〉]: 3 - } - e: {} - (〈0;e〉 & { - e: {} - }) - p: { - { - ["foo"]: { - b: (〈1;(〈0;-〉)〉|null) - } - } - { - ["bar"]: { - b: 〈1;-〉 - } - } - } - let B#1 = { - open: int - } - f: 〈0;let B#1〉 - schema: { - next: 〈1;let _schema_1#2〉 - } - let _schema_1#2 = 〈0;schema〉 -} -- out/eval/stats -- Leaks: 1 Freed: 17 diff --git a/cue/testdata/comprehensions/015_list_comprehension.txtar b/cue/testdata/comprehensions/015_list_comprehension.txtar index 22e3540e0..80e74070a 100644 --- a/cue/testdata/comprehensions/015_list_comprehension.txtar +++ b/cue/testdata/comprehensions/015_list_comprehension.txtar @@ -12,33 +12,6 @@ c: { @test(eq, [1, 1, 1, 2, 2, 3]) } d: [for x, _ in a {x}] @test(eq, [0, 1]) --- out/compile -- ---- in.cue -{ - b: { - a: 1 - b: 2 - c: 3 - d: 4 - } - a: [ - for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { - 〈1;k〉 - }, - ] - c: { - [ - for _, x in 〈2;b〉 for _, y in 〈3;b〉 if (〈1;x〉 < 〈0;y〉) { - 〈2;x〉 - }, - ] - } - d: [ - for x, _ in 〈1;a〉 { - 〈1;x〉 - }, - ] -} -- out/eval/stats -- Leaks: 0 Freed: 19 diff --git a/cue/testdata/comprehensions/045_comprehension_and_skipped_field.txtar b/cue/testdata/comprehensions/045_comprehension_and_skipped_field.txtar index 8e7e95672..f9541292a 100644 --- a/cue/testdata/comprehensions/045_comprehension_and_skipped_field.txtar +++ b/cue/testdata/comprehensions/045_comprehension_and_skipped_field.txtar @@ -13,24 +13,6 @@ for key, value in {x: v: 1} { } } @test(eq, {x: {v: {"1": 2}, _p: 3}}) --- out/compile -- ---- in.cue -{ - for key, value in { - x: { - v: 1 - } - } { - "\(〈1;key〉)": { - v: (*{ - for pod, _ in 〈3;value〉.v {} - }|{ - "\(〈3;value〉.v)": 2 - }) - _p: 3 - } - } -} -- out/eval/stats -- Leaks: 2 Freed: 8 diff --git a/cue/testdata/comprehensions/checkdefined.txtar b/cue/testdata/comprehensions/checkdefined.txtar index 6b9951b38..d9e4af0ad 100644 --- a/cue/testdata/comprehensions/checkdefined.txtar +++ b/cue/testdata/comprehensions/checkdefined.txtar @@ -141,195 +141,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 29 --- out/compile -- ---- in.cue -{ - xc: close({ - field: {} - }) - xo: { - field: {} - } - okc0: { - if (〈1;xc〉.undefined == _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - oko0: { - if (〈1;xo〉.undefined == _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - okc1: { - if (〈1;xc〉.undefined != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - oko1: { - if (〈1;xo〉.undefined != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - okc2: { - if (({} & { - s: [ - for _, y in 〈3;xc〉.undefined {}, - ] - }) != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - oko2: { - if (({} & { - s: [ - for _, y in 〈3;xo〉.undefined {}, - ] - }) != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - okc3: { - if ({ - s: [ - for _, y in 〈3;xc〉.undefined {}, - ] - } != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - oko3: { - if ({ - s: [ - for _, y in 〈3;xo〉.undefined {}, - ] - } != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - issue1969: { - okc: { - let X#1 = 〈2;xc〉.undefined - let Y#2 = ({} & { - s: [ - for _, y in 〈import;list〉.Range(0, 〈2;let X#1〉, 1) {}, - ] - }) - if (〈0;let Y#2〉 != _|_(explicit error (_|_ literal) in source)) { - 〈1;let Y#2〉 - } - } - } - issue1969: { - oko: { - let X#3 = 〈2;xo〉.undefined - let Y#4 = ({} & { - s: [ - for _, y in 〈import;list〉.Range(0, 〈2;let X#3〉, 1) {}, - ] - }) - if (〈0;let Y#4〉 != _|_(explicit error (_|_ literal) in source)) { - 〈1;let Y#4〉 - } - } - } -} ---- incomplete.cue -{ - checkIncomplete: { - t1: { - f: { - [string]: { - if (〈0;a〉 != _|_(explicit error (_|_ literal) in source)) { - b: "d\(〈1;a〉)" - } - a: string - } - } - f: { - blah: {} - } - } - } -} ---- issue2245.cue -{ - yo: { - f: int - g: (〈0;f〉 < 10) - } - okyo: { - if (〈1;yo〉 != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } - okyog: { - if (〈1;yo〉.g != _|_(explicit error (_|_ literal) in source)) { - a: 1 - } - } -} ---- structs.cue -{ - structs: { - bare: { - t1: (({ - y: 2 - } & { - x: 3 - }) != _|_(explicit error (_|_ literal) in source)) - } - bare: { - f2: (({ - y: 2 - } & { - x: 3 - }) == _|_(explicit error (_|_ literal) in source)) - } - bare: { - f3: (({ - x: 1 - y: 2 - } & { - x: 3 - }) != _|_(explicit error (_|_ literal) in source)) - } - bare: { - t4: (({ - x: 1 - y: 2 - } & { - x: 3 - }) == _|_(explicit error (_|_ literal) in source)) - } - select: { - t1: (({ - y: 2 - } & { - x: 3 - }).y != _|_(explicit error (_|_ literal) in source)) - } - select: { - f2: (({ - y: 2 - } & { - x: 3 - }).y == _|_(explicit error (_|_ literal) in source)) - } - select: { - f3: (({ - x: 1 - y: 2 - } & { - x: 3 - }).y != _|_(explicit error (_|_ literal) in source)) - } - select: { - t4: (({ - x: 1 - y: 2 - } & { - x: 3 - }).y == _|_(explicit error (_|_ literal) in source)) - } - } -} diff --git a/cue/testdata/comprehensions/closed.txtar b/cue/testdata/comprehensions/closed.txtar index ab5b74e13..823870f49 100644 --- a/cue/testdata/comprehensions/closed.txtar +++ b/cue/testdata/comprehensions/closed.txtar @@ -164,133 +164,3 @@ Conjuncts: 125 Disjuncts: 14 NumCloseIDs: 46 --- out/compile -- ---- in.cue -{ - dynamicTop: { - #D: { - for k, v in { - foo: 123 - } { - 〈1;k〉: 〈1;v〉 - } - } - } - dynamicDepth1: { - #D: { - a: { - foo: 123 - } - b: { - for k, v in 〈1;a〉 { - 〈1;k〉: 〈1;v〉 - } - } - } - } - allowed: { - #D: { - if true { - d: int - } - } - vErr: (〈0;#D〉 & { - d: 5 - }) - } - disallowed: { - #D: { - if false { - d: int - } - } - vErr: (〈0;#D〉 & { - d: 5 - }) - } - comprehensionIsEmbed: { - #A: { - size: (int|*1) - } - #B: { - kind: string - if true { - 〈2;#A〉 - } - } - x: (〈0;#B〉 & { - kind: "A" - }) - } - noEraseDefinition: { - #Foo: [ - if true { - a: int - }, - ] - a: { - (〈1;#Foo〉 & [ - { - b: 2 - }, - ]) - } - } - issue1956: { - #Details: { - size: (int|*1) - } - #Thing: { - kind: ("KindA"|"KindB") - if (〈0;kind〉 == "KindA") { - 〈2;#Details〉 - } - } - x: (〈0;#Thing〉 & { - kind: "KindA" - }) - } - dedupTodo: { - #sub: { - c: _ - if (〈0;c〉.n == "c") { - X: { - test: 〈2;c〉 - } - } - } - out: 〈0;#sub〉 - out: { - c: { - n: "c" - } - c: { - n: string - } - } - } -} ---- v3issues.cue -{ - issue3483: { - #Schema: { - schemaField: int - } - out1: { - out2: (〈1;#Schema〉 & { - if false { - schemaField: 3 - } - }) - } - } - issue3486: { - #schema: {} - if true { - out: { - 〈2;#schema〉 - extra: "foo" - } - } - } -} diff --git a/cue/testdata/comprehensions/deferfieldsetknown.txtar b/cue/testdata/comprehensions/deferfieldsetknown.txtar index d5d5b1d75..06e0a1bf3 100644 --- a/cue/testdata/comprehensions/deferfieldsetknown.txtar +++ b/cue/testdata/comprehensions/deferfieldsetknown.txtar @@ -13,31 +13,3 @@ out: ({ cfg: resources: _ out: {for n, _ in cfg.resources {(n): "x"}} } & {cfg: result}).out @test(eq, {x: "x"}) --- out/compile -- ---- in.cue -{ - #PDB: { - y: int - } - result: { - resources: { - if true { - x: (〈3;#PDB〉 & { - y: 1 - }) - } - } - } - out: ({ - cfg: { - resources: _ - } - out: { - for n, _ in 〈1;cfg〉.resources { - 〈1;n〉: "x" - } - } - } & { - cfg: 〈1;result〉 - }).out -} diff --git a/cue/testdata/comprehensions/else.txtar b/cue/testdata/comprehensions/else.txtar index 817920085..b527881b5 100644 --- a/cue/testdata/comprehensions/else.txtar +++ b/cue/testdata/comprehensions/else.txtar @@ -196,291 +196,3 @@ Conjuncts: 180 Disjuncts: 0 NumCloseIDs: 69 --- out/compile -- ---- in.cue -{ - ifTrue: { - if true { - a: 1 - } else { - b: 2 - } - } - ifFalse: { - if false { - a: 1 - } else { - b: 2 - } - } - forNonEmpty: { - for _, x in [ - 1, - 2, - ] { - "\(〈1;x〉)": 〈1;x〉 - } else { - empty: true - } - } - forEmpty: { - for _, x in [] { - "\(〈1;x〉)": 〈1;x〉 - } else { - empty: true - } - } - forFilteredAll: { - for _, x in [ - 1, - 2, - 3, - ] if (〈0;x〉 > 10) { - "\(〈1;x〉)": 〈1;x〉 - } else { - empty: true - } - } - forFilteredSome: { - for _, x in [ - 1, - 2, - 3, - ] if (〈0;x〉 > 1) { - "\(〈1;x〉)": 〈1;x〉 - } else { - empty: true - } - } - ifTrueForEmpty: { - if true for _, x in [] { - "\(〈1;x〉)": 〈1;x〉 - } else { - empty: true - } - } - ifFalseForNonEmpty: { - if false for _, x in [ - 1, - 2, - ] { - "\(〈1;x〉)": 〈1;x〉 - } else { - empty: true - } - } - ifTrueForNonEmpty: { - if true for _, x in [ - 1, - 2, - ] { - "\(〈1;x〉)": 〈1;x〉 - } else { - empty: true - } - } - ifIfBothTrue: { - if true if true { - a: 1 - } else { - b: 2 - } - } - ifIfFirstFalse: { - if false if true { - a: 1 - } else { - b: 2 - } - } - ifIfSecondFalse: { - if true if false { - a: 1 - } else { - b: 2 - } - } - tryTryBothSucceed: { - a: 1 - b: 2 - try x = 〈0;a〉? try y = 〈1;b〉? { - result: (〈2;x〉 + 〈1;y〉) - } else { - default: 0 - } - } - missing?: int - tryTryFirstFails: { - b: 2 - try x = 〈1;missing〉? try y = 〈1;b〉? { - result: (〈2;x〉 + 〈1;y〉) - } else { - default: -1 - } - } - tryTrySecondFails: { - a: 1 - try x = 〈0;a〉? try y = 〈2;missing〉? { - result: (〈2;x〉 + 〈1;y〉) - } else { - default: -2 - } - } - listIfTrue: [ - if true { - 1 - } else { - 2 - }, - ] - listIfFalse: [ - if false { - 1 - } else { - 2 - }, - ] - listForEmpty: [ - for _, x in [] { - 〈1;x〉 - } else { - 0 - }, - ] - listForNonEmpty: [ - for _, x in [ - 1, - 2, - ] { - (〈1;x〉 * 2) - } else { - 0 - }, - ] - elseMultipleFields: { - if false { - a: 1 - } else { - b: 2 - c: 3 - } - } - elseEmbeds: { - existing: 1 - if false { - added: 2 - } else { - fallback: 3 - } - } - outerScope: { - let threshold#1 = 10 - for _, x in [] { - 〈1;x〉 - } else { - fallbackField: 〈1;let threshold#1〉 - } - } - ifNestedBody: { - if false { - a: { - b: 1 - } - } else { - c: 2 - } - } - ifNestedElse: { - if false { - a: 1 - } else { - b: { - c: 2 - } - } - } - ifNestedBoth: { - if false { - a: { - b: 1 - } - } else { - c: { - d: 2 - } - } - } - ifDeeplyNested: { - if false { - a: { - b: { - c: 1 - } - } - } else { - a: { - b: { - c: 2 - } - } - } - } - forNestedEmpty: { - for _, x in [] { - a: { - b: { - 〈3;x〉: 〈3;x〉 - } - } - } else { - a: { - b: { - none: true - } - } - } - } - forNestedNonEmpty: { - for _, x in [ - 1, - ] { - a: { - b: { - "\(〈3;x〉)": 〈3;x〉 - } - } - } else { - a: { - b: { - none: true - } - } - } - } - nestedOuterFallback: { - for _, x in [] { - for _, y in [ - 1, - ] { - 〈1;y〉 - } else { - inner: true - } - } else { - outer: true - } - } - nestedInnerFallback: { - for _, x in [ - 1, - ] { - for _, y in [] { - 〈1;y〉 - } else { - inner: true - } - } else { - outer: true - } - } -} diff --git a/cue/testdata/comprehensions/else_compile_errors.txtar b/cue/testdata/comprehensions/else_compile_errors.txtar index 3dbcd24f6..91fd4ec54 100644 --- a/cue/testdata/comprehensions/else_compile_errors.txtar +++ b/cue/testdata/comprehensions/else_compile_errors.txtar @@ -38,33 +38,3 @@ forVarInElse.bad: reference "i" not found: ./in.cue:5:49 letVarInElse.bad: reference "y" not found: ./in.cue:10:61 --- out/compile -- -forVarInElse.bad: reference "i" not found: - ./in.cue:5:49 -letVarInElse.bad: reference "y" not found: - ./in.cue:10:61 ---- in.cue -{ - forVarInElse: { - for _, i in [ - 1, - 2, - 3, - ] { - "\(〈1;i〉)": 〈1;i〉 - } else { - bad: _|_(reference "i" not found) - } - } - letVarInElse: { - for _, x in [ - 1, - 2, - 3, - ] let y = (〈0;x〉 * 2) { - "\(〈2;x〉)": 〈1;y〉 - } else { - bad: _|_(reference "y" not found) - } - } -} diff --git a/cue/testdata/comprehensions/else_on_error.txtar b/cue/testdata/comprehensions/else_on_error.txtar index f38bf32cf..d7e883f5c 100644 --- a/cue/testdata/comprehensions/else_on_error.txtar +++ b/cue/testdata/comprehensions/else_on_error.txtar @@ -29,28 +29,3 @@ forSourceBottom: { ./in.cue:15:14 [user] explicit error (_|_ literal) in source: ./in.cue:21:11 --- out/compile -- ---- in.cue -{ - forSourceError: { - for _, x in "not-a-list" { - "\(〈1;x〉)": 〈1;x〉 - } else { - fallbackField: true - } - } - ifConditionError: { - if ("not" + 1) { - a: 1 - } else { - b: 2 - } - } - forSourceBottom: { - for _, x in _|_(explicit error (_|_ literal) in source) { - "\(〈1;x〉)": 〈1;x〉 - } else { - fallbackField: true - } - } -} diff --git a/cue/testdata/comprehensions/errors.txtar b/cue/testdata/comprehensions/errors.txtar index 9f77a304b..eaa4f65e2 100644 --- a/cue/testdata/comprehensions/errors.txtar +++ b/cue/testdata/comprehensions/errors.txtar @@ -84,42 +84,3 @@ Conjuncts: 32 Disjuncts: 6 NumCloseIDs: 12 --- out/compile -- ---- in.cue -{ - circularIf: { - #list: { - tail: (〈1;#list〉|*null) - if (〈0;tail〉 != null) {} - } - } - circularFor: { - #list: { - tail: (〈1;#list〉|*null) - for _, x in (〈0;tail〉 != null) {} - } - } - userError: { - a: (string|*_|_(explicit error (_|_ literal) in source)) - if (〈0;a〉 != "") {} - } - intField: { - for i, _ in [ - 1, - 2, - ] { - 〈1;i〉: {} - } - } - conflictRangingOverSelf: { - x: { - name: string - age: int - } - x: { - for k, _ in 〈1;x〉 { - 〈1;k〉: 〈1;k〉 - } - } - } -} diff --git a/cue/testdata/comprehensions/fields.txtar b/cue/testdata/comprehensions/fields.txtar index bf654a6ca..ee6b6a660 100644 --- a/cue/testdata/comprehensions/fields.txtar +++ b/cue/testdata/comprehensions/fields.txtar @@ -104,54 +104,3 @@ Conjuncts: 37 Disjuncts: 0 NumCloseIDs: 12 --- out/compile -- ---- in.cue -{ - dynamic: { - for _, s in [ - "foo", - ] { - 〈1;s〉: 1 - "\(〈1;s〉)bar": 2 - } - } - ignoreOptional: { - #x: { - a?: string - b?: string - c: string - } - y: { - for k, v in 〈1;#x〉 { - 〈1;k〉: "exists" - } - } - } - missingRequiredError: { - #x: { - a!: string - b?: string - c: string - } - y: { - for k, v in 〈1;#x〉 { - 〈1;k〉: "exists" - } - } - } - issue560: { - #User: { - tags_str: string - tags_map: { - for k, v in 〈import;strings〉.Split(〈1;tags_str〉, " ") { - "\(〈1;v〉)": string - } - "{a}": string - } - } - user: { - 〈1;#User〉 - tags_str: "b {c}" - } - } -} diff --git a/cue/testdata/comprehensions/for.txtar b/cue/testdata/comprehensions/for.txtar index 0ba4cf872..a7fed95be 100644 --- a/cue/testdata/comprehensions/for.txtar +++ b/cue/testdata/comprehensions/for.txtar @@ -30,44 +30,3 @@ Disjuncts: 21 MisalignedConjunct: 1 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - b: { - for k, v in 〈1;a〉 { - "\(〈1;k〉)": (〈1;v〉 + 1) - } - } - a: { - b: 1 - c: 2 - } - x: { - for k, v in 〈1;y〉 { - "\(〈1;k〉)": 〈1;v〉 - } - } - y: {} - k: { - for _, v in 〈1;e〉 { - 〈1;v〉 - } - } - e: int - comprehensionBinds: { - a: { - for _, _ in [ - 1, - ] { - a: _ - } - } - b: { - for _, _ in [ - 1, - ] { - a: _ - } - } - } -} diff --git a/cue/testdata/comprehensions/iferror.txtar b/cue/testdata/comprehensions/iferror.txtar index 43e87a23d..2a8f15798 100644 --- a/cue/testdata/comprehensions/iferror.txtar +++ b/cue/testdata/comprehensions/iferror.txtar @@ -137,104 +137,6 @@ issue1972: { ./in.cue:105:8 ./in.cue:107:11 ./in.cue:108:3 --- out/compile -- ---- in.cue -{ - a: { - b: 2 - c: int - } - wrongConcreteType: { - if 〈1;a〉.b { - 2 - } - } - wrongType: { - if 〈1;a〉.c { - 2 - } - } - incomplete: { - err1: { - if 〈2;a〉.d { - 2 - } - } - } - incomplete: { - err2: { - list: [ - 1, - 2, - 3, - ] - for _, x in 〈0;list〉 if 〈3;a〉.d { - 〈1;x〉 - } - } - } - useDefault: { - a: { - x: (*"foo"|string) - if (〈0;x〉 != _|_(explicit error (_|_ literal) in source)) { - y: 〈1;x〉 - } - } - issue809: { - #A: { - a: string - b: (*〈0;a〉|string) - } - s: { - [string]: (〈1;#A〉 & { - a: 〈1;-〉 - }) - } - s: { - bar: _ - } - foo: [ - for _, a in 〈1;s〉 if (〈0;a〉.b != _|_(explicit error (_|_ literal) in source)) { - 〈1;a〉 - }, - ] - } - } - issue1972: { - err1: { - #patchs: [] - 〈0;#patchs〉 - #someCondition: _ - if 〈0;#someCondition〉 {} - } - err1: { - someCondition: _ - patchs: [ - ...{}, - ] - 〈0;patchs〉 - if 〈0;someCondition〉 { - patchs: _ - } - } - err2: { - #patchs: [] - 〈0;#patchs〉 - #someCondition: _ - if 〈0;#someCondition〉 {} - } - err3: { - someCondition: _ - patchs: [ - ...{}, - ] - 〈0;patchs〉 - if 〈0;someCondition〉 { - patchs: _ - } - } - } -} -- out/eval/stats -- Leaks: 1 Freed: 40 diff --git a/cue/testdata/comprehensions/incomplete.txtar b/cue/testdata/comprehensions/incomplete.txtar index 8d56a6502..b295ac44e 100644 --- a/cue/testdata/comprehensions/incomplete.txtar +++ b/cue/testdata/comprehensions/incomplete.txtar @@ -24,19 +24,3 @@ Conjuncts: 7 Disjuncts: 7 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - cond: bool - src: {} - top: _ - a: [ - if 〈1;cond〉 {}, - ] - b: [ - for _, x in 〈1;src〉.foo {}, - ] - c: { - for _, x in 〈1;top〉 {} - } -} diff --git a/cue/testdata/comprehensions/issue1732.txtar b/cue/testdata/comprehensions/issue1732.txtar index a88869243..27b75b105 100644 --- a/cue/testdata/comprehensions/issue1732.txtar +++ b/cue/testdata/comprehensions/issue1732.txtar @@ -241,142 +241,3 @@ Disjuncts: 6 Notifications: 1 NumCloseIDs: 38 --- out/compile -- ---- in.cue -{ - networkingv1: { - metav1: { - #LabelSelector: { - matchLabels: { - [string]: string - } - } - } - #NetworkPolicy: { - spec: 〈1;#NetworkPolicySpec〉 - } - #NetworkPolicySpec: { - ingress: [ - ...〈2;#NetworkPolicyIngressRule〉, - ] - egress: [ - ...〈2;#NetworkPolicyEgressRule〉, - ] - } - #NetworkPolicyIngressRule: { - from: [ - ...〈2;#NetworkPolicyPeer〉, - ] - } - #NetworkPolicyEgressRule: { - to: [ - ...〈2;#NetworkPolicyPeer〉, - ] - } - #NetworkPolicyPeer: { - namespaceSelector: (null|〈1;metav1〉.#LabelSelector) - } - } - global_config: { - #GlobalConfig: { - auth0: { - enabled: bool - } - } - } - common: { - #SomeConfig: { - enabled: bool - if 〈0;enabled〉 { - foo: string - } - } - } - foo: { - #Values: { - global: 〈2;global_config〉.#GlobalConfig - } - } - #Config: { - tenant: { - id: string - } - auth0: (〈1;common〉.#SomeConfig & { - enabled: bool - if 〈0;enabled〉 { - foo: "\(〈2;tenant〉.id)-value" - } - }) - charts: { - foo: (〈2;foo〉.#Values & { - global: 〈3〉.global - }) - } - global: (〈1;global_config〉.#GlobalConfig & { - auth0: { - enabled: 〈3〉.auth0.enabled - } - }) - } - #NetworkPolicy: 〈0;networkingv1〉.#NetworkPolicy - #Flux: { - 〈1;#Config〉 - charts: _ - formatOutput: { - ... - } - _outputs(:config): { - ... - } - for _chartName, _chartValues in 〈0;charts〉 { - _outputs(:config): { - "\(〈2;_chartName(:config)〉)": {} - } - } - _outputs(:config): { - for _, ns in [ - "ns", - ] { - "\(〈1;ns〉)/network": (〈4;#NetworkPolicy〉 & { - spec: { - ingress: [ - { - from: [ - { - namespaceSelector: { - matchLabels: { - tenant: 〈12〉.tenant.id - } - } - }, - ] - }, - ] - egress: [ - { - to: [ - { - namespaceSelector: { - matchLabels: { - tenant: 〈12〉.tenant.id - } - } - }, - ] - }, - ] - } - }) - } - } - for _, ns in [ - "ns", - ] { - for k, v in 〈2;_outputs(:config)〉 { - formatOutput: { - "\(〈2;k〉)": 〈2;v〉 - } - } - } - } -} diff --git a/cue/testdata/comprehensions/issue2171.txtar b/cue/testdata/comprehensions/issue2171.txtar index 7fce79569..d2eb92212 100644 --- a/cue/testdata/comprehensions/issue2171.txtar +++ b/cue/testdata/comprehensions/issue2171.txtar @@ -9,18 +9,6 @@ do: { for k, v in do {do: (k): v} @test(eq, {do: hello: {}}) --- out/compile -- ---- in.cue -{ - do: { - hello: {} - } - for k, v in 〈0;do〉 { - do: { - 〈2;k〉: 〈2;v〉 - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 3 diff --git a/cue/testdata/comprehensions/issue2481.txtar b/cue/testdata/comprehensions/issue2481.txtar index ea30c21b1..f405b5541 100644 --- a/cue/testdata/comprehensions/issue2481.txtar +++ b/cue/testdata/comprehensions/issue2481.txtar @@ -101,55 +101,3 @@ Conjuncts: 54 Disjuncts: 0 NumCloseIDs: 22 --- out/compile -- ---- in.cue -{ - out: { - for _, k in 〈1;keys〉 { - if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { - val: 〈2;k〉 - if (〈0;val〉 != _|_(explicit error (_|_ literal) in source)) { - 〈3;k〉 - } - } - } - } - multiLets: { - for _, k in 〈1;keys〉 { - if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { - let val#1multi = 〈2;k〉 - if (〈0;let val#1〉 != _|_(explicit error (_|_ literal) in source)) { - 〈3;k〉 - } - } - } - } - keys: [ - "a", - "b", - ] - values: { - b: "member" - c: "foo" - } - full: { - out: { - for k, _ in 〈1;#github_team_membership〉 { - if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { - let val#2multi = 〈4;values〉[〈2;k〉] - if ((〈0;let val#2〉 != null) && ((〈0;let val#2〉 & string) != _|_(explicit error (_|_ literal) in source))) { - 〈3;k〉: 〈1;let val#2〉 - } - } - } - } - #github_team_membership: { - team_id: string - role: string - } - values: { - role: "member" - username: "foo" - } - } -} diff --git a/cue/testdata/comprehensions/issue287.txtar b/cue/testdata/comprehensions/issue287.txtar index d55678c4b..40aef050e 100644 --- a/cue/testdata/comprehensions/issue287.txtar +++ b/cue/testdata/comprehensions/issue287.txtar @@ -23,23 +23,3 @@ Disjuncts: 5 MisalignedConjunct: 1 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - if (〈0;#E〉["x"] != _|_(explicit error (_|_ literal) in source)) { - #E: { - y: true - } - } - if (〈0;#E〉["y"] != _|_(explicit error (_|_ literal) in source)) { - z: true - } - #E: { - [_]: bool - } - #E: { - x: true - } - #E: _ - z: _ -} diff --git a/cue/testdata/comprehensions/issue293.txtar b/cue/testdata/comprehensions/issue293.txtar index 2a3387bb3..325fe1e86 100644 --- a/cue/testdata/comprehensions/issue293.txtar +++ b/cue/testdata/comprehensions/issue293.txtar @@ -66,41 +66,3 @@ Conjuncts: 40 Disjuncts: 0 NumCloseIDs: 15 --- out/compile -- ---- in.cue -{ - #T: { - if true { - x: close({ - f1: int - }) - } - x: _ - } - z: (〈0;#T〉 & { - x: { - f1: 99 - f2: "i want to disallow this" - } - }) - t: 〈0;#C〉 - #C: { - if true { - p: _ - } - } - t: { - p: "foo" - } -} ---- variant1.cue -{ - #V1: { - x: close({ - f1: int - }) - x: { - f2: 2 - } - } -} diff --git a/cue/testdata/comprehensions/issue3762.txtar b/cue/testdata/comprehensions/issue3762.txtar index 2b5d8b445..eda884282 100644 --- a/cue/testdata/comprehensions/issue3762.txtar +++ b/cue/testdata/comprehensions/issue3762.txtar @@ -134,118 +134,3 @@ Disjuncts: 0 Notifications: 8 NumCloseIDs: 25 --- out/compile -- ---- in.cue -{ - full: { - kube: { - node: { - n1: { - _CL: "l" - _cs: { - 〈1;_CL〉: 〈4;_a〉[〈1;_CL〉] - } - _cs: { - 〈1;_CL〉: { - opts: {} - } - } - } - } - } - _a: { - l: { - _ba?: string - opts: { - if (〈1;_ba〉 != _|_(explicit error (_|_ literal) in source)) { - b: 〈2;_ba〉 - } - } - } - } - for k, _ in (〈0;_a〉 & 〈0;_b〉) { - x: 5 - } - _a: { - [_]: { - vms: [ - { - name: "hello" - }, - ] - } - } - _b: { - [_]: { - vms: [ - { - name: "again" - }, - ] - } - } - } - reduced: { - p1: { - _cs: (〈0;_a〉.l & { - opts: {} - }) - _a: { - l: { - _ba?: string - opts: { - if (〈1;_ba〉 != _|_(explicit error (_|_ literal) in source)) { - b: 〈2;_ba〉 - } - } - vms: "hello" - } - } - _b: { - l: { - vms: "again" - } - } - for k, _ in (〈0;_a〉 & 〈0;_b〉) { - x: 5 - } - } - } - reduced: { - p2: { - for k, _ in (〈0;_a〉 & 〈0;_b〉) { - x: 5 - } - _cs: (〈0;_a〉.l & { - opts: {} - }) - _a: { - l: { - _ba?: string - opts: { - if (〈1;_ba〉 != _|_(explicit error (_|_ literal) in source)) { - b: 〈2;_ba〉 - } - } - vms: "hello" - } - } - _b: { - l: { - vms: "again" - } - } - } - } - reference: { - _x: { - f: true - } - _y: { - f: false - } - for k, _ in (〈0;_x〉 & 〈0;_y〉) { - ok: true - } - } -} diff --git a/cue/testdata/comprehensions/issue3763.txtar b/cue/testdata/comprehensions/issue3763.txtar index 8ca820c15..3ef9e2c84 100644 --- a/cue/testdata/comprehensions/issue3763.txtar +++ b/cue/testdata/comprehensions/issue3763.txtar @@ -114,93 +114,3 @@ Conjuncts: 126 Disjuncts: 0 NumCloseIDs: 38 --- out/compile -- ---- full.cue -{ - full: { - _core_v1: { - #cp: { - hostPort?: &(int, >=-2147483648, <=2147483647) - cp: &(int, >=-2147483648, <=2147483647) - } - } - k: { - n: { - n1: { - _CL: "l" - } - } - } - let nc#1 = { - _ports: { - [_]: 〈2;_core_v1〉.#cp - } - } - _cl: { - [_]: (〈1;let nc#1〉 & { - _ports: { - "1": {} - "2": {} - "3": {} - } - }) - } - k: { - n: { - [_]: { - _CL: string - _cs: { - 〈1;_CL〉: 〈4;_cl〉[〈1;_CL〉] - } - } - } - } - for _, n in 〈0;k〉.n { - let cps#2multi = [ - for _, c in 〈2;n〉._cs for _, cps in 〈0;c〉._ports { - 〈1;cps〉 - }, - ] - ports: [ - for _, cp in 〈1;let cps#2〉 if (〈0;cp〉.hostPort != _|_(explicit error (_|_ literal) in source)) { - port: "\(〈1;cp〉.hostPort)" - }, - ] - } - _cl: { - l: {} - } - } -} ---- reduced.cue -{ - reduced: { - A: { - x1: { - y?: int - } - } - A: { - x2: { - y?: int - } - } - A: { - x3: { - y?: int - } - } - if true { - let Z#3 = [ - for _, x in 〈2;A〉 { - 〈1;x〉 - }, - ] - B: [ - for _, z in 〈1;let Z#3〉 if (〈0;z〉.y != _|_(explicit error (_|_ literal) in source)) { - b: 1 - }, - ] - } - } -} diff --git a/cue/testdata/comprehensions/issue3929.txtar b/cue/testdata/comprehensions/issue3929.txtar index efcf00d38..eb2620531 100644 --- a/cue/testdata/comprehensions/issue3929.txtar +++ b/cue/testdata/comprehensions/issue3929.txtar @@ -224,107 +224,3 @@ ConjunctInfos: 166 MaxConjunctInfos: 8 MaxReqSets: 15 MaxRedirect: 3 --- out/compile -- ---- in.cue -{ - reduced: { - #Input: { - name: string - age: ("one"|"two") - if (〈0;name〉 != _|_(explicit error (_|_ literal) in source)) { - if true { - age: "one" - } - } - } - #def1: { - _in(:main): _ - def1: (〈1;#def2〉 & { - _in(:main): 〈1;_in(:main)〉 - }) - } - #def2: { - _in(:main): _ - def2: (〈1;#def3〉 & { - _in(:main): 〈1;_in(:main)〉 - }) - } - #def3: { - _in(:main): 〈1;#Input〉 - def3: 〈0;_in(:main)〉.age - } - in: { - name: "foobar" - } - out: (〈0;#def1〉 & { - _in(:main): 〈1;in〉 - }).def1 - } - full: { - cronjob: { - [string]: 〈1;#CronjobConfig〉 - } - #CronjobConfig: { - 〈1;#PodConfig〉 - } - #PodConfig: { - 〈1;#ContainerConfig〉 - } - #ContainerConfig: { - image: string - imagePullPolicy: ("IfNotPresent"|"Always"|"Never") - if (〈0;image〉 != _|_(explicit error (_|_ literal) in source)) { - if (〈import;strings〉.HasSuffix(〈1;image〉, ":latest") == true) { - imagePullPolicy: ("IfNotPresent"|*"Always"|"Never") - } - if (〈import;strings〉.HasSuffix(〈1;image〉, ":latest") != true) { - imagePullPolicy: (*"IfNotPresent"|"Always"|"Never") - } - } - } - _#cronjob(:main): { - _config(:main): 〈1;#CronjobConfig〉 - out: { - spec: { - jobTemplate: { - spec: { - template: (〈5;_#pod(:main)〉 & { - _config(:main): 〈5;_config(:main)〉 - }) - } - } - } - } - } - _#pod(:main): { - _config(:main): 〈1;#PodConfig〉 - spec: { - containers: [ - { - (〈4;_#container(:main)〉 & { - _config(:main): 〈4;_config(:main)〉 - }) - }, - ] - } - } - _#container(:main): { - _config(:main): 〈1;#ContainerConfig〉 - imagePullPolicy: 〈0;_config(:main)〉.imagePullPolicy - } - cronjob: { - foobar: { - image: "foobar:latest" - } - } - for k, v in 〈0;cronjob〉 { - objects: { - cronjob: { - "\(〈3;k〉)": (〈4;_#cronjob(:main)〉 & { - _config(:main): 〈4;v〉 - }).out - } - } - } - } -} diff --git a/cue/testdata/comprehensions/issue436.txtar b/cue/testdata/comprehensions/issue436.txtar index 7b47eb01e..98ac4adca 100644 --- a/cue/testdata/comprehensions/issue436.txtar +++ b/cue/testdata/comprehensions/issue436.txtar @@ -36,24 +36,3 @@ Conjuncts: 47 Disjuncts: 12 NumCloseIDs: 11 --- out/compile -- ---- in.cue -{ - #a: { - val: string - result: string - } - a: (〈0;#a〉 & { - val: (*"default"|string) - result: (*"not-matched"|string) - if (〈0;val〉 == "match") { - result: "matched" - } - }) - match: (〈0;a〉 & { - val: "match" - }) - not: (〈0;a〉 & { - val: "other" - }) -} diff --git a/cue/testdata/comprehensions/issue507.txtar b/cue/testdata/comprehensions/issue507.txtar index 71f32f009..f5827ceb8 100644 --- a/cue/testdata/comprehensions/issue507.txtar +++ b/cue/testdata/comprehensions/issue507.txtar @@ -39,33 +39,3 @@ Conjuncts: 17 Disjuncts: 4 NumCloseIDs: 4 --- out/compile -- ---- in.cue -{ - somelist: ([ - ...string, - ]|*[]) - foo: [ - for _, e in 〈1;somelist〉 { - "hello foo: \(〈1;e〉)" - }, - ] - otherlist: [ - "something", - ] - z: [ - for _, e in 〈1;otherlist〉 { - "hello z: \(〈1;e〉)" - }, - ] - extlist: ([ - ...string, - ]|*[ - "something", - ]) - bar: [ - for _, e in 〈1;extlist〉 { - "hello bar: \(〈1;e〉)" - }, - ] -} diff --git a/cue/testdata/comprehensions/issue837.txtar b/cue/testdata/comprehensions/issue837.txtar index 76e385d08..1b31b4a73 100644 --- a/cue/testdata/comprehensions/issue837.txtar +++ b/cue/testdata/comprehensions/issue837.txtar @@ -108,83 +108,3 @@ Conjuncts: 97 Disjuncts: 8 NumCloseIDs: 17 --- out/compile -- ---- in.cue -{ - #DeploymentManifest: (〈0;#Manifest〉 & { - ref: { - kind: "deployment" - } - }) - #Manifest: { - ref: 〈1;#ManifestRef〉 - description: 〈1;#KumoriKinds〉[〈0;ref〉.kind] - } - #ManifestRef: { - kind: 〈1;#KindsNames〉 - } - #KindsNames: ("service"|"deployment") - #KumoriKinds: { - deployment: 〈1;#Deployment〉 - } - #KumoriKinds: { - [string]: { - ... - } - } - #DoDeploy: { - _params: { - manifest: 〈2;#DeploymentManifest〉 - } - deployment: { - description: { - let dep#1 = 〈2;_params〉.manifest.description - service: (〈3;#Configure〉 & { - _params: { - hsize: 〈2;let dep#1〉.hsize - } - }).service - } - } - } - #Configure: { - _params: { - hsize: { - [string]: 〈3;#RoleSize〉 - } - } - service: { - description: { - let configed#2 = (〈3;#RelabelService〉 & { - _params: { - hsize: 〈4;_params〉.hsize - } - role: "admin" - }).out - role: 〈0;let configed#2〉.role - } - } - } - #RelabelService: { - _params: { - hsize: 〈2;#RoleSize〉 - } - out: { - labstr: 〈1;_params〉.label - } - } - #RoleSize: { - $_instances: (>=0|*1) - } - #Deployment: { - service: 〈1;#ServiceManifest〉 - hsize: { - [〈1;service〉.description.#roles]: 〈2;#RoleSize〉 - } - } - #ServiceManifest: (〈0;#Manifest〉 & { - ref: { - kind: "service" - } - }) -} diff --git a/cue/testdata/comprehensions/issue843.txtar b/cue/testdata/comprehensions/issue843.txtar index 34dc1d9c8..1a2dae7dd 100644 --- a/cue/testdata/comprehensions/issue843.txtar +++ b/cue/testdata/comprehensions/issue843.txtar @@ -86,52 +86,3 @@ Conjuncts: 103 Disjuncts: 12 NumCloseIDs: 24 --- out/compile -- ---- in.cue -{ - #d1: { - as: [ - ...string, - ] - #c: [ - (〈2;#f1〉 & { - as: 〈import;list〉.Concat([ - [ - "go", - ], - 〈3;as〉, - ]) - }), - ] - } - #d2: { - p: (*"."|string) - #c: [ - (〈2;#f2〉 & { - from: (〈3;#d1〉 & { - as: [ - 〈4;p〉, - ] - }) - }), - ] - } - #c1: { - #c: [ - ...〈2;#o〉, - ] - _ - ... - } - #o: (〈0;#f1〉|〈0;#f2〉) - #f1: { - do: "f1" - as: [ - ...string, - ] - } - #f2: { - do: "f2" - from: 〈1;#c1〉 - } -} diff --git a/cue/testdata/comprehensions/lists.txtar b/cue/testdata/comprehensions/lists.txtar index 5aa294197..1c8db4fc6 100644 --- a/cue/testdata/comprehensions/lists.txtar +++ b/cue/testdata/comprehensions/lists.txtar @@ -19,20 +19,3 @@ Retain: 0 Unifications: 7 Conjuncts: 8 Disjuncts: 7 --- out/compile -- ---- in.cue -{ - a: [ - { - a: 1 - }, - { - b: (2 & 3) - }, - ] - b: [ - for _, x in 〈1;a〉 { - 〈1;x〉 - }, - ] -} diff --git a/cue/testdata/comprehensions/multi.txtar b/cue/testdata/comprehensions/multi.txtar index 76f2a058e..418b537c1 100644 --- a/cue/testdata/comprehensions/multi.txtar +++ b/cue/testdata/comprehensions/multi.txtar @@ -42,49 +42,3 @@ Conjuncts: 37 Disjuncts: 0 NumCloseIDs: 21 --- out/compile -- ---- in.cue -{ - list: [ - 2, - 3, - ] - a: [ - 3, - for _, x in 〈1;list〉 { - 〈1;x〉 - }, - for _, x in 〈1;list〉 { - 〈1;x〉 - }, - ] - b: [ - 3, - if true { - 3 - }, - for _, x in 〈1;list〉 if (〈0;x〉 > 2) { - 〈1;x〉 - }, - ] - issue574: { - greet: true - bye: true - message1: [ - if 〈1;greet〉 { - "hello" - }, - "how are you doing?", - "bye", - ] - message2: [ - if !〈1;greet〉 { - "hello" - }, - "how are you doing?", - if 〈1;bye〉 { - "bye" - }, - ] - } -} diff --git a/cue/testdata/comprehensions/nested.txtar b/cue/testdata/comprehensions/nested.txtar index dc9b6cac3..76afaf8ba 100644 --- a/cue/testdata/comprehensions/nested.txtar +++ b/cue/testdata/comprehensions/nested.txtar @@ -116,108 +116,3 @@ Conjuncts: 89 Disjuncts: 10 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - service: { - "node-exporter": { - spec: { - ports: [ - { - name: "metrics" - port: 9100 - protocol: "TCP" - }, - ] - } - } - } - deployment: { - "node-exporter": { - spec: { - template: { - spec: { - containers: [ - { - ports: [ - { - containerPort: 9100 - name: "scrape" - }, - ] - }, - ] - } - } - } - } - } - service: { - [string]: { - spec: { - ports: [ - ...{ - port: int - protocol: (*"TCP"|"UDP") - name: (string|*"client") - }, - ] - } - } - } - deployment: { - [string]: {} - } - deployment: { - [_]: (〈1;_spec(:kube)〉 & {}) - } - _spec(:kube): { - _name(:kube): string - spec: { - template: { - spec: { - containers: [ - { - name: 〈5;_name(:kube)〉 - }, - ] - } - } - } - } - _spec(:kube): { - spec: { - template: { - spec: { - containers: [ - ...{ - ports: [ - ...{ - _export(:kube): (*true|false) - }, - ] - }, - ] - } - } - } - } - for k, v in 〈0;deployment〉 { - service: { - "\(〈2;k〉)": { - spec: { - selector: 〈4;v〉.spec.template.metadata.labels - } - spec: { - ports: [ - for _, c in 〈5;v〉.spec.template.spec.containers for _, p in 〈0;c〉.ports if 〈0;p〉._export(:kube) { - let Port#1 = 〈1;p〉.containerPort - port: (*〈0;let Port#1〉|int) - targetPort: (*〈0;let Port#1〉|int) - }, - ] - } - } - } - } -} diff --git a/cue/testdata/comprehensions/nested2.txtar b/cue/testdata/comprehensions/nested2.txtar index 56db3c1b8..0c9595903 100644 --- a/cue/testdata/comprehensions/nested2.txtar +++ b/cue/testdata/comprehensions/nested2.txtar @@ -548,370 +548,3 @@ Disjuncts: 0 Notifications: 5 NumCloseIDs: 217 --- out/compile -- ---- in.cue -{ - given: { - INC: { - USD: 2.0 - } - USD: { - GBP: 3.0 - } - } - hydrated: { - for k, v in 〈1;given〉 { - for k1, r in 〈1;v〉 { - "\(〈3;k〉)": { - "\(〈4;k〉)": 1.0 - } - "\(〈1;k1〉)": { - "\(〈2;k1〉)": 1.0 - } - "\(〈3;k〉)": { - "\(〈2;k1〉)": 〈2;r〉 - } - "\(〈1;k1〉)": { - "\(〈4;k〉)": number - } - } - } - } - foo: { - a: 10 - if (〈0;a〉 < 20) { - if (〈1;a〉 < 50) { - b: 20 - } - } - } - indirectlyNested: { - a: true - if true { - b: { - if 〈2;a〉 { - 〈3;a〉 - } - } - } - } - directlyNestedEmpty: { - a: true - if true { - if 〈1;a〉 {} - } - } - directlyDoublyNestedEmpty: { - a: true - if true { - if 〈1;a〉 {} - } - } - indirectlyDoublyNestedEmpty: { - a: true - b: { - if true { - if 〈2;a〉 { - if 〈3;a〉 { - 〈4;a〉 - } - } - if 〈2;a〉 { - 〈3;a〉 - } - } - } - } - indirectlyDoublyNested: { - a: true - if true { - if 〈1;a〉 { - if 〈2;a〉 { - b: 1 - } - } - if 〈1;a〉 { - c: 1 - } - } - } - issue1974: { - X: { - foo: { - bar: "" - baz: "" - } - } - out: { - for k, v in 〈1;X〉 for vk, vv in 〈0;v〉 { - "\(〈2;k〉)": { - "\(〈2;vk〉)": 〈2;vv〉 - } - } - } - } -} ---- issue3940.cue -{ - issue3940: { - reduced1: { - 〈0;X〉 - a: { - b: 〈1;X〉 - } - a: { - b: { - a: { - b: { - y: 〈4;X〉 - } - } - } - } - X: { - a: {} - objects: { - for _, v in 〈1;a〉 for _, _ in ({} & 〈0;v〉).objects {} - } - } - } - } - issue3940: { - reduced2: { - 〈0;X〉 - a: { - b: 〈1;X〉 - } - a: { - b: { - a: { - b: { - y: 〈4;X〉 - } - } - } - } - X: { - a: {} - objects: { - for _, v in 〈1;a〉 for _, _ in ({} & 〈0;v〉).objects {} - } - } - } - } - issue3940: { - reduced3: { - a: 〈0;E〉 - a: { - i: { - x: 〈2;E〉 - } - } - a: { - i: { - x: { - i: { - x: 〈4;E〉 - } - } - } - } - E: { - i: {} - o: [ - for _, m in 〈1;i〉 for _, v in ({} & 〈0;m〉).o {}, - ] - } - } - } - issue3940: { - reduced4: { - out: (〈0;Exporter〉 & { - _imports: [ - { - objects: { - ... - } - #export: (〈3;Exporter〉 & { - _imports: [ - { - #export: 〈6;Exporter〉 - }, - ] - }) - }, - ] - }) - Exporter: { - _imports: [ - ..., - ] - objects: [ - for _, v in 〈1;_imports〉 for _, obj in ({} & 〈0;v〉.#export).objects { - 〈1;obj〉 - }, - ] - } - } - } - issue3940: { - let: { - 〈0;X〉 - a: { - b: 〈1;X〉 - } - a: { - b: { - a: { - b: { - y: 〈4;X〉 - } - } - } - } - X: { - a: {} - objects: { - for _, v in 〈1;a〉 let x = ({} & 〈0;v〉) for _, _ in 〈0;x〉.objects {} - } - } - } - } - issue3940: { - full: { - out: (〈0;#Exporter〉 & { - _imports: [ - 〈2;_branch〉, - ] - #conf: { - global: { - region: "Europe" - } - } - }) - _branch: { - objects: { - branch: { - #conf: { - ... - } - region: 〈0;#conf〉.global.region - } - } - imports: [ - 〈2;_leaf〉, - ] - #export: (〈1;#Exporter〉 & { - _objects: 〈1;objects〉 - _imports: 〈1;imports〉 - }) - } - _leaf: { - objects: { - leaf: { - #conf: { - ... - } - region: 〈0;#conf〉.global.region - } - } - #export: (〈1;#Exporter〉 & { - _objects: 〈1;objects〉 - }) - } - #Exporter: { - #conf: { - ... - } - _objects: { - ... - } - _imports: [ - ..., - ] - objects: [ - for name, obj in (〈1;_objects〉 & { - [string]: { - #conf: 〈3;#conf〉 - } - }) { - 〈1;name〉: 〈1;obj〉 - }, - for _, import in 〈1;_imports〉 for _, obj in ({ - #conf: 〈3;#conf〉 - } & 〈0;import〉.#export).objects { - 〈1;obj〉 - }, - ] - } - } - } -} ---- issue3990.cue -{ - issue3990: { - _imports: [ - 〈1;_noVolumes〉, - 〈1;_someVolumes〉, - ] - _noVolumes: { - name: "noVolumes" - exportObjs: { - deployment: (〈2;_Deployment〉 & { - volumes: [] - }) - } - } - _someVolumes: { - name: "someVolumes" - exportObjs: { - deployment: (〈2;_Deployment〉 & { - volumes: [ - { - name: "data" - }, - ] - }) - } - } - for _, import in 〈0;_imports〉 for _, obj in ({ - extra: "unused" - } & 〈0;import〉).exportObjs { - 〈2;import〉.name: 〈1;obj〉 - } - _Deployment: { - _names: { - for _, v in 〈2〉.volumes { - 〈1;v〉.name: 〈1;v〉.name - } - } - if (len(〈0;_names〉) > 0) { - volumeNames: [ - for _, v in 〈2;_names〉 { - 〈1;v〉 - }, - ] - } - } - } -} ---- pending.cue -{ - T: int - for _, C in 〈0;Y〉 { - let X#1multi = 〈1;C〉.M - T: 〈0;let X#1〉.V - } - Y: { - x: { - M: { - V: 1 - } - for _, _ in 〈0;M〉 { - if true { - M: {} - } - } - } - } -} diff --git a/cue/testdata/comprehensions/nestembed.txtar b/cue/testdata/comprehensions/nestembed.txtar index ce9928135..50640fcec 100644 --- a/cue/testdata/comprehensions/nestembed.txtar +++ b/cue/testdata/comprehensions/nestembed.txtar @@ -35,32 +35,3 @@ Conjuncts: 22 Disjuncts: 0 NumCloseIDs: 6 --- out/compile -- ---- in.cue -{ - DeleteThis: [ - "this", - "that", - ] - useful_infra: { - gcp: { - cluters: 10 - } - aws: { - clusters: 20 - } - this: { - clusters: 1 - } - that: { - clusters: 2 - } - } - New_infra: { - for k, v in 〈1;useful_infra〉 { - if !〈import;list〉.Contains(〈3;DeleteThis〉, 〈1;k〉) { - "\(〈2;k〉)": 〈2;v〉 - } - } - } -} diff --git a/cue/testdata/comprehensions/open_iter_writeback.txtar b/cue/testdata/comprehensions/open_iter_writeback.txtar index 0511ecc66..a6cfc4851 100644 --- a/cue/testdata/comprehensions/open_iter_writeback.txtar +++ b/cue/testdata/comprehensions/open_iter_writeback.txtar @@ -40,38 +40,3 @@ defOpen: { keys: ["b", "a"] }) } --- out/compile -- ---- in.cue -{ - openIter: { - src: { - a: 1 - b: 2 - ... - if true { - c: 3 - } - } - keys: [ - for k, _ in 〈1;src〉 { - 〈1;k〉 - }, - ] - } - defOpen: { - #T: { - [string]: int - if true { - a: 1 - } - } - inst: (〈0;#T〉 & { - b: 2 - }) - keys: [ - for k, _ in 〈1;inst〉 { - 〈1;k〉 - }, - ] - } -} diff --git a/cue/testdata/comprehensions/optional_ref_yield.txtar b/cue/testdata/comprehensions/optional_ref_yield.txtar index 014631da5..9ff8a8726 100644 --- a/cue/testdata/comprehensions/optional_ref_yield.txtar +++ b/cue/testdata/comprehensions/optional_ref_yield.txtar @@ -56,39 +56,3 @@ pendingBecomesMember: { -- out/errors.txt -- [incomplete] optionalStaysOptional.x.bar: cannot reference optional field: foo: ./in.cue:22:11 --- out/compile -- ---- in.cue -{ - optionalUpgradesViaSiblingComp: { - x: { - bar: 〈1;x〉.foo - foo?: int - if true { - foo: 5 - } - } - x: { - bar: int - } - } - optionalStaysOptional: { - x: { - bar: 〈1;x〉.foo - foo?: int - } - x: { - bar: _ - } - } - pendingBecomesMember: { - x: { - bar: 〈1;x〉.foo - if true { - foo: 5 - } - } - x: { - bar: int - } - } -} diff --git a/cue/testdata/comprehensions/pushdown.txtar b/cue/testdata/comprehensions/pushdown.txtar index 6f1cef748..a2fd30662 100644 --- a/cue/testdata/comprehensions/pushdown.txtar +++ b/cue/testdata/comprehensions/pushdown.txtar @@ -1543,1447 +1543,3 @@ Conjuncts: 904 Disjuncts: 44 NumCloseIDs: 264 --- out/compile -- ---- in.cue -{ - linkChildren: { - w: 1 - v: { - x: 1 - if true { - y: 1 - if true { - z: 1 - rw: 〈3;w〉 - rx: 〈2;x〉 - ry: 〈1;y〉 - rz: 〈0;z〉 - n1a: { - na: [ - 〈5;w〉, - 〈4;x〉, - 〈3;y〉, - 〈2;z〉, - ] - } - n2a: { - n1a: { - na: [ - 〈6;w〉, - 〈5;x〉, - 〈4;y〉, - 〈3;z〉, - ] - } - } - n2z: { - n1z: { - nz: 〈2;z〉 - } - } - } - } - } - } - fail: { - a: { - if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { - b: 1 - } - } - } - embed: { - fail1: 〈0;#C1〉 - #C1: { - if false { - p: _ - } - } - fail1: { - p: "foo" - } - success2: 〈0;#C2〉 - #C2: { - if true { - p: _ - } - } - success2: { - p: "foo" - } - success3: 〈0;#C3〉 - #C3: {} - success3: { - if false { - p: { - q: 1 - } - } - } - success4: { - #X: { - y: string - } - x: { - y: string - } - x: { - for _, _ in [ - "iter-once", - ] { - 〈3;#X〉 - if false { - y: "foo" - } - } - } - } - fail4: 〈0;#C4〉 - #C4: {} - fail4: { - if true { - p: { - q: 1 - } - } - } - incomplete5: { - a: bool - if 〈0;a〉 { - p: { - q: 1 - } - } - } - incomplete6: { - if false { - p: 1 - } - p: (〈0;q〉 + 1) - q: int - } - incomplete7: { - p: (〈0;q〉 + 1) - q: int - if false { - q: 1 - } - } - } - mixedFieldsSuccess: { - a: { - for _, s in [ - "foo", - ] { - "\(〈1;s〉)": 1 - X: 1 - } - } - b: { - #Def: { - for _, s in [ - "foo", - ] { - "\(〈1;s〉)": 1 - X: 1 - } - } - } - b: { - x: 〈1;b〉.#Def - } - b: { - x: { - X: _ - } - } - b: { - x: { - foo: _ - } - } - c: { - #Def: { - X: int - foo: int - } - } - c: { - x: 〈1;c〉.#Def - } - c: { - x: { - for _, s in [ - "foo", - ] { - "\(〈1;s〉)": 1 - X: 1 - } - } - } - } - fieldMismatch: { - a: { - 2 - if true { - x: 3 - } - } - } - noStackOverflowStructCycle: { - #list: { - tail: 〈1;#list〉 - if (〈0;tail〉 != null) { - sum: 〈1;tail〉.sum - } - } - list: { - tail: 〈1;list〉 - if (〈0;tail〉 != null) { - sum: 〈1;tail〉.sum - } - } - } - provideIncompleteSuccess: { - t1: { - #a: { - if 〈0;b〉 { - c: 4 - } - b: bool - } - x: ((〈0;#a〉 & { - b: true - }) & { - c: 4 - }) - y: 〈0;x〉 - } - t2: { - #a: { - if 〈0;b〉 { - c: 4 - } - b: true - } - #c: {} - a: { - if 〈0;b〉 { - c: { - d: 4 - } - } - b: true - c: 〈1;#c〉 - } - } - } - voidArcs: { - scopes: { - x: 1 - a: { - y: 2 - if true { - b: 〈2;x〉 - c: { - d: 〈3;x〉 - } - e: 〈1;y〉 - f: { - g: 〈2;y〉 - } - } - } - } - drop: { - x: 1 - a: { - y: 2 - if false { - b: 〈2;x〉 - c: { - d: 〈3;x〉 - } - e: 〈1;y〉 - f: { - g: 〈2;y〉 - } - } - } - } - } - cyclicError: { - a: { - x: bool - y: bool - if 〈1;a〉.x { - y: true - } - if 〈1;a〉.y { - x: true - } - b: {} - } - c: 〈0;a〉.b - } - midwayReferences: { - a: { - for i, j in { - a: 1 - b: 2 - } { - x: { - y: { - z: { - 〈4;i〉: 〈4;j〉 - } - } - } - } - x: { - y: {} - } - } - b: 〈0;a〉.x - c: 〈0;a〉.x.y - d: 〈0;a〉.x.y.z - } - closedCheck: { - success1: { - a: { - b: { - [string]: 〈2;#D〉 - } - } - #D: { - d: string - if (〈0;d〉 != "c") { - e: string - } - } - a: { - b: { - c: { - d: "d" - e: "ok" - } - } - } - } - } - closedCheck: { - success2: { - a: { - b: { - [string]: 〈2;#D〉 - } - } - #D: { - d: string - if (〈0;d〉 != "c") { - ("foo" + "bar"): string - } - } - a: { - b: { - c: { - d: "d" - foobar: "ok" - } - } - } - } - } - closedCheck: { - success3: { - a: { - b: { - [string]: 〈2;#D〉 - } - } - #D: { - d: string - e: { - if (〈1;d〉 != "c") { - string - } - } - } - a: { - b: { - c: { - d: "d" - e: "ok" - } - } - } - } - } - emptyComprehensionIncomplete: { - a: {} - b: { - if 〈1;a〉.b {} - } - } - voidEliminationSuccess: { - t1: { - [string]: { - b: bool - if !〈0;b〉 {} - } - if false { - a: { - b: true - } - } - } - } - voidEliminationSuccess: { - t2: { - components: { - sinks: { - [string]: (〈1;#C〉 & { - kind: string - configuration: { - if (〈1;kind〉 != "source") { - inputs: { - required: true - } - } - } - }) - } - #C: { - kind: string - configuration: { - [string]: { - required: bool - if !〈0;required〉 { - common: bool - } - } - } - } - } - components: { - sinks: { - blah: { - kind: "source" - } - } - } - } - } - voidEliminationSuccess: { - derefRef1: { - a: { - [string]: { - c: { - [string]: 〈3;E〉 - } - } - } - a: { - b: { - c: { - if false { - d: { - e: true - } - } - } - } - } - E: { - e: bool - f: !〈0;e〉 - } - } - } - voidEliminationSuccess: { - derefRef2: { - a: { - [string]: { - c: { - [string]: 〈3;E〉 - } - } - } - a: { - b: { - c: { - if false { - d: { - e: true - } - } - } - } - } - E: 〈0;#F〉 - #F: { - e: bool - f: !〈0;e〉 - } - } - } - voidEliminationSuccess: { - derefDisj1: { - a: { - [string]: { - c: { - [string]: 〈3;E〉 - } - } - } - a: { - b: { - c: { - if false { - d: { - e: true - } - } - } - } - } - E: ({ - e: bool - f: !〈0;e〉 - }|{ - g: bool - h: !〈0;g〉 - }) - } - } - voidEliminationSuccess: { - derefDisj2: { - a: { - [string]: { - c: { - [string]: (〈3;E〉 & 〈3;E〉) - } - } - } - a: { - b: { - c: { - if false { - d: { - e: true - } - } - } - } - } - E: ({ - e: bool - f: !〈0;e〉 - }|{ - g: bool - h: !〈0;g〉 - }) - } - } - voidEliminationSuccess: { - bulk1: { - a: { - b: {} - } - a: { - [string]: { - c: { - e: string - if false { - e: "" - } - } - d: 〈0;c〉.e - } - } - } - } - voidEliminationSuccess: { - opt1: { - a: { - b: {} - } - a: { - b?: { - c: { - e: string - if false { - e: "" - } - } - d: 〈0;c〉.e - } - } - } - } - voidEliminationSuccess: { - noCycle1: { - _x: 〈0;a〉.b - a: { - c: { - h: "stream" - } - b: { - if (〈1;c〉.g != _|_(explicit error (_|_ literal) in source)) {} - } - c: { - if false { - g: _ - } - } - } - } - } - voidEliminationSuccess: { - noCycle2: { - a: { - c: { - h: "stream" - } - b: { - if (〈1;c〉.g != _|_(explicit error (_|_ literal) in source)) {} - } - c: { - if false { - g: _ - } - } - } - _x: 〈0;a〉.b - } - } - voidLookup: { - a: { - x: { - z: 〈2;a〉.y.z.void - } - } - a: { - y: { - c: _ - z: {} - } - } - a: { - [string]: { - c: { - for k, v in 〈1;z〉 { - 〈1;k〉: null - } - } - z: { - if false { - err: {} - } - } - } - } - } - topElimination: { - a: int - _ - if true { - x: (〈1;a〉 + 1) - } - } - voidEliminationSuccess: { - drop1: { - t: { - #ok: (*true|bool) - if 〈0;#ok〉 { - x: int - } - } - s: (〈0;t〉 & { - #ok: false - }) - } - } - explicitDefaultError: { - a: (string|*_|_(explicit error (_|_ literal) in source)) - if (〈0;a〉 != "") {} - } - allArcsSuccess: { - p1: { - x: { - for k, _ in 〈1;y〉 { - 〈1;k〉: null - } - } - y: { - if false { - x: {} - } - } - } - } - allArcsSuccess: { - p2: { - y: { - if false { - x: {} - } - } - x: { - for k, _ in 〈1;y〉 { - 〈1;k〉: null - } - } - } - } - structShare: { - ok1: { - a: { - [string]: 〈1;E〉 - } - E: {} - a: { - if true { - d: { - e: true - } - } - } - } - } - structShare: { - err1: { - x: { - [string]: 〈1;x〉.#E - } - x: { - #E: {} - } - if true { - x: { - d: { - e: true - } - } - } - } - } -} ---- issue1759.cue -{ - unity: { - success1: { - #Config: { - name: string - type: string - } - #AnyConfig: { - 〈1;#Config〉 - ... - } - #Env: { - name: string - configurations: { - [string]: 〈2;#AnyConfig〉 - } - } - envs: { - e1: (〈1;#Env〉 & { - configurations: { - c1: 〈3;#Config〉 - } - }) - } - envs: { - [string]: { - configurations: { - [string]: { - type: "foo" - if (〈0;type〉 == "terraform") { - backend: { - type: "s3" - } - } - } - } - } - } - } - } - issue1759: { - _ports_map: {} - if (len(〈0;_ports_map〉) > 0) { - port: 〈1;_ports_map〉.a.port - } - if true { - _ports_map: { - a: { - port: "80" - } - } - } - } - arcAlignment: { - t1: { - [string]: { - if true {} - } - if false { - c: _ - } - } - } -} ---- issue2111.cue -{ - letPushdown: { - _c: { - y: 1 - } - a: { - for k, v in 〈1;_c〉 { - let x#1multi = 〈1;v〉 - if (〈0;let x#1〉 != _|_(explicit error (_|_ literal) in source)) {} - } - } - } -} ---- issue2113.cue -{ - nestedWithEmbeddingOK: { - c: [ - 1, - ] - a: { - for k, v in 〈1;c〉 { - { - x: 1 - } - if (〈3;a〉.x != _|_(explicit error (_|_ literal) in source)) {} - } - } - } - nestedWithDynamicFieldOK: { - _c: { - y: 1 - } - a: { - for k, v in 〈1;_c〉 { - if (〈0;("\(〈1;k〉)")〉 != _|_(explicit error (_|_ literal) in source)) {} - "\(〈1;k〉)": 1 - } - } - } - errorPropagation: { - deployment: _ - for k, v in 〈0;deployment〉 { - for k1, v2 in 〈1;v〉.env2 { - deployment: { - 〈4;k〉: { - x1: 1 - } - } - } - } - for _, id in [ - "elem", - ] { - deployment: { - 〈2;id〉: { - x2: 2 - } - } - } - } -} ---- issue2131.cue -{ - issue2131: { - tests: { - windows: { - eg1: { - in: "c:\\d" - } - eg2: { - in: "c:\\test" - } - eg3: { - in: "c:\\test\\d" - } - } - for os, examples in 〈1;tests〉 for k, v in 〈0;examples〉 { - 〈2;os〉: { - 〈2;k〉: { - out: "test" - } - } - } - } - } -} ---- issue2208.cue -{ - voidErrorIncomplete: { - #Schema: { - [string]: { - required: bool - if !〈0;required〉 {} - } - } - root: 〈0;#Schema〉 - root: { - if false { - child: { - required: false - } - } - } - } -} ---- issue3533.cue -{ - issue3533: { - #ObjectMeta: { - namespace?: string - } - out: { - for i, _ in [ - "iter-once", - ] { - metadata: 〈3;#ObjectMeta〉 - if false { - metadata: { - namespace: "foo" - } - } - } - } - out: { - metadata: { - namespace: (*"default"|string) - } - } - } -} ---- issue3535.cue -{ - issue3535: { - hidden: { - #X: { - kind: string - output: {} - } - foo: (〈0;#X〉 & { - kind: string - if (〈0;kind〉 == "foo") { - _hidden: {} - } - }) - foo: { - kind: "foo" - } - } - } - issue3535: { - regular: { - #X: { - kind: string - output: {} - } - foo: (〈0;#X〉 & { - kind: string - if (〈0;kind〉 == "foo") { - regular: {} - } - }) - foo: { - kind: "foo" - } - } - } - issue3535: { - def: { - #X: { - kind: string - output: {} - } - foo: (〈0;#X〉 & { - kind: string - if (〈0;kind〉 == "foo") { - #def: {} - } - }) - foo: { - kind: "foo" - } - } - } -} ---- issue3621.cue -{ - issue3621: { - reduced: { - t1: { - if true { - a: 〈0;b1〉.b2.b3 - b1: { - b2: { - b3: "Foo" - } - } - } - } - } - } - issue3621: { - reduced: { - t2: { - outer: {} - if true { - inner: { - inner2: { - name: "Foo" - } - } - outer: { - b: 〈1;inner〉.inner2.name - } - } - } - } - } - issue3621: { - full: { - hello: "world" - outer: { - [string]: { - name: 〈1;-〉 - } - } - if true { - inner: { - inner2: { - name: "Employees" - description: "All employees" - privacy: "secret" - create_default: false - } - } - outer: { - outer2: { - bar: 〈2;inner〉.inner2.name - } - } - } - } - } -} ---- issue3708.cue -{ - issue3708: { - out: 〈0;people〉.bob.kind - people: { - [string]: { - kind: "person" - name?: string - } - } - if true { - people: { - bob: { - name: "Bob" - } - } - } - } -} ---- issue3729.cue -{ - issue3729: { - withDisjunction: { - #Root: { - sub1?: { - #sub2?: bool - } - } - root?: (null|〈0;#Root〉) - if true { - root: { - sub1?: { - #sub2: true - } - } - } - } - } - issue3729: { - withoutDisjunction: { - root?: null - if true { - root: { - #sub1?: { - #sub2: true - } - } - } - } - } - issue3729: { - withoutDisjunctionWithEmbed: { - root?: null - if true { - root: { - _ - #sub1?: { - #sub2: true - } - } - } - } - } - issue3729: { - definitionsOnly: { - #Root: { - #sub1?: { - #sub2?: bool - } - } - root?: (null|〈0;#Root〉) - if true { - root: { - #sub1?: { - #sub2: true - } - } - } - } - } - issue3729: { - withEmbed: { - incomplete: { - #Root: { - #sub1?: { - #sub2?: bool - } - } - root?: (null|〈0;#Root〉) - if true { - root: { - _ - #sub1?: { - #sub2: true - } - } - } - } - } - } - issue3729: { - full: { - #Application: { - spec: 〈1;#ApplicationSpec〉 - } - #ApplicationSpec: { - syncPolicy?: (null|〈1;#SyncPolicy〉) - } - #SyncPolicy: { - automated?: (null|〈1;#SyncPolicyAutomated〉) - } - #SyncPolicyAutomated: { - prune?: bool - selfHeal?: bool - } - argoApp: (〈0;#Application〉 & { - spec: { - if true { - syncPolicy: { - automated: { - prune: true - selfHeal: true - } - } - } - } - }) - argoApp: { - spec: { - _syncpolicy: "selfhealprune" - } - } - } - } -} ---- issue3935.cue -{ - issue3935: { - reduced: { - out: (〈0;#A〉|〈0;#B〉) - out: (〈0;#B〉 & { - y: { - x: "bar" - } - }) - #A: { - y: { - other: int - } - } - #B: { - if true { - x: 〈1;y〉.x - } - y!: { - x!: _ - } - } - } - } - issue3935: { - full: { - out: (〈0;#SchemaOther〉|〈0;#SchemaSelected〉) - out: (〈0;#SchemaSelected〉 & { - spec: { - name: "foo" - config: { - namespace: "bar" - } - } - }) - #SchemaOther: { - spec: { - otherOptional?: int - otherRegular: int - otherRequired!: int - } - } - #SchemaSelected: { - spec!: { - name!: string - config!: _ - } - if true { - namespace: 〈1;_specConfig〉.namespace - } - _specConfig: 〈0;spec〉.config - } - } - } -} ---- pending.cue -{ - arcTypeAcrossTwo: { - a?: { - b?: ({ - c?: (null|{}) - }|null) - } - if true { - a: { - b: { - c: { - d: true - } - } - } - } - } - issue3894: { - reduced: { - p1: { - ({ - a: string - }|{ - b: { - value: string - } - }) - if true { - b: { - value: "true" - } - } - } - } - } - issue3894: { - reduced: { - p2: { - ({ - b: { - value: string - } - }|{ - a: string - }) - if true { - b: { - value: "true" - } - } - } - } - } - issue3894: { - full: { - #Output: ({ - a?: string - }|{ - b?: { - value: string - } - }) - out: 〈0;#Output〉 - out: { - if (true == true) { - b: { - value: "true" - } - } - } - } - } -} ---- reflect.cue -{ - unifyDynamicReflectSuccess: { - for _, s in [ - "foo", - ] { - X: { - ... - } - "\(〈1;s〉)": { - X: { - ... - } - Y: 〈import;"encoding/json"〉.Marshal(〈0;X〉) - } - } - [string]: { - X: { - if true { - x: { - y: {} - } - } - } - } - } -} ---- rework.cue -{ - regression1: { - #Primary: { - _Y: _ - let _X#2 = 〈0;_Y〉 - if (len(〈0;let _X#2〉.spec.command) > 0) { - command: 〈1;let _X#2〉.spec.command - } - } - #Rollout: { - _X: _ - out: ((〈1;#Primary〉 & { - _Y: 〈1;_X〉 - }) & 〈0;_X〉.patch) - } - x: { - spec: { - command: [ - "a", - ] - } - patch: {} - } - out: (〈0;#Rollout〉 & { - _X: 〈1;x〉 - }) - } - regression2: { - #Primary: { - _Y: _ - if (len(〈0;_Y〉.spec.command) > 0) { - command: 〈1;_Y〉.spec.command - } - } - #Rollout: { - _X: _ - out: ((〈1;#Primary〉 & { - _Y: 〈1;_X〉 - }) & 〈0;_X〉.patch) - } - x: { - spec: { - command: [ - "a", - ] - } - patch: {} - } - out: (〈0;#Rollout〉 & { - _X: 〈1;x〉 - }) - } - letCycleSelf: { - #X: { - let this#3 = 〈1〉 - hosts: { - [string]: _ - } - for h, _ in 〈0;let this#3〉.hosts { - out: { - 〈2;h〉: 1 - } - } - for h, _ in 〈0;let this#3〉.hosts { - out: { - 〈2;h〉: 2 - } - } - } - x: { - [string]: 〈1;#X〉 - } - x: { - a: {} - } - } -} ---- rework2.cue -{ - letCycleSelfKeyword: { - #E: { - let s#4 = 〈1〉 - hosts: _ - for _, hv in 〈0;let s#4〉.hosts { - out: { - 〈2;hv〉.x: "a" - } - } - } - env: (〈0;#E〉 & { - hosts: { - h1: { - x: "k" - } - } - }) - } - letCycleSelfKeyword2: { - #E: { - let s#5 = 〈1〉 - ... - for _, hv in 〈0;let s#5〉.hosts { - let n#6 = 〈2;let s#5〉.networks - a: 〈0;let n#6〉 - } - } - env: (〈0;#E〉 & { - hosts: { - h1: 1 - } - networks: { - n1: "x" - } - }) - } -} diff --git a/cue/testdata/comprehensions/try.txtar b/cue/testdata/comprehensions/try.txtar index 08d6be219..a8f7996a2 100644 --- a/cue/testdata/comprehensions/try.txtar +++ b/cue/testdata/comprehensions/try.txtar @@ -605,552 +605,3 @@ Conjuncts: 507 Disjuncts: 0 NumCloseIDs: 173 --- out/compile -- ---- in.cue -{ - a: 1 - b: 2 - c?: int - incomplete: int - success: { - try { - result: (〈2;a〉? + 〈2;b〉?) - } - } - single: { - x: 5 - try { - y: (〈1;x〉? * 2) - } - } - fallbackDef: 42 - elseNotTriggered: { - try { - v: 〈2;fallbackDef〉? - } else { - fallback: 0 - } - } - elseTriggered: { - try { - v: 〈2;c〉? - } else { - fallback: -1 - } - } - elseMultiField: { - try { - x: 〈2;c〉? - y: 〈2;c〉? - } else { - fallback: true - } - } - emptyOnFail: { - try { - z: (〈2;c〉? + 1) - } - } - mixedRefs: { - try { - x: 〈2;a〉? - y: 〈2;c〉? - } else { - fallback: true - } - } - incompleteOK: { - try { - x: 〈2;incomplete〉? - } else { - fallback: 23 - } - } - incompleteNestedBody: { - try { - x: { - y: 〈3;incomplete〉? - } - } else { - fallback: 23 - } - } - requiredUnfilled: { - a!: _ - try { - x: 〈1;a〉? - } else { - fallback: 23 - } - } - requiredFilled: { - a!: _ - a: 5 - try { - x: 〈1;a〉? - } else { - fallback: 23 - } - } - requiredWithType: { - a!: int - try { - x: 〈1;a〉? - } else { - fallback: 23 - } - } - forWithDefinedSource: { - try { - for _, x in [ - 〈3;b〉?, - ] { - val: 〈1;x〉 - } - } - } - forWithUndefinedSource: { - try { - for _, x in [ - 〈3;c〉?, - ] { - val: 〈1;x〉 - } - } else { - empty: true - } - } - nested: { - outer: { - try { - inner: 〈3;a〉? - } - } - multi: { - try { - first: 〈3;a〉? - } - try { - second: 〈3;b〉? - } - } - deepNested: { - try { - level1: { - level2: 〈4;a〉? - } - } - } - } - complexExpr: { - binOp: { - try { - sum: (〈3;a〉? + 〈3;b〉?) - prod: (〈3;a〉? * 〈3;b〉?) - } - } - list: { - try { - items: [ - 〈4;a〉?, - 〈4;b〉?, - (〈4;a〉? + 〈4;b〉?), - ] - } - } - } - selectorTests: { - data: { - nested: { - value: 100 - } - } - definedSelector: { - try { - v: 〈2;data〉.nested.value? - } - } - } - closedness: { - #Def: { - f: int - } - d: 〈0;#Def〉 - exists: { - try { - v: 〈2;#Def〉.f? - } - } - notExistsDef: { - try { - v: 〈2;#Def〉.g? - } - } - notExistsValue: { - try { - v: 〈2;d〉.g? - } - } - } - indexTests: { - closedList: [ - 10, - 20, - 30, - ] - openList: [ - 10, - 20, - 30, - ..., - ] - definedIndex: { - try { - v: 〈2;closedList〉[0]? - } - } - middleIndex: { - try { - v: 〈2;closedList〉[1]? - } - } - outOfRangeClosed: { - try { - v: 〈2;closedList〉[10]? - } else { - fallback: -1 - } - } - outOfRangeClosedNoElse: { - try { - v: 〈2;closedList〉[100]? - } - } - outOfRangeOpen: { - try { - v: 〈2;openList〉[10]? - } else { - fallback: -1 - } - } - outOfRangeOpenNoElse: { - try { - v: 〈2;openList〉[100]? - } - } - multipleIndex: { - try { - x: 〈2;closedList〉[0]? - y: 〈2;closedList〉[1]? - z: 〈2;closedList〉[2]? - } - } - } - edgeCases: { - emptyBody: { - try {} - } - literalOnly: { - try { - x: 42 - } - } - firstFails: { - try { - x: 〈3;c〉? - y: 〈3;a〉? - } else { - skipped: true - } - } - secondFails: { - try { - x: 〈3;a〉? - y: 〈3;c〉? - } else { - skipped: true - } - } - referenceError: { - a: (1 / 0) - a: { - _b: 2 - } - direct: { - try { - v: 〈2;a〉? - } else { - skipped: true - } - } - dontSkipError1: { - try { - 〈2;a〉._b? - } else { - skipped: true - } - } - dontSkipError2: { - try { - 〈2;a〉?._b? - } else { - skipped: true - } - } - } - } - refIntoTry: { - source: { - try { - val: 〈3;a〉? - } - } - ref: 〈0;source〉.val - nestedSource: { - try { - inner: { - try { - deep: 〈5;b〉? - } - } - } - } - nestedRef: 〈0;nestedSource〉.inner.deep - nestedSkipped?: { - try { - 〈3;c〉? - } - } - mixedSource: { - try { - foo: 〈2;nestedSkipped〉? - } - bar?: 1 - baz: 1 - } - skippedRef: { - try { - v: 〈2;mixedSource〉.foo? - } else { - missing: true - } - } - failedRef1: { - try { - v: 〈2;mixedSource〉.foo - } else { - missing: true - } - } - failedRef2: { - try { - v: 〈2;mixedSource〉.foo - } else { - missing: true - } - } - successRef: { - try { - v: 〈2;mixedSource〉.baz? - } else { - missing: true - } - } - } - errorPrecedence: { - typeErrorDefined: { - try { - v: (〈3;a〉? + "string") - } else { - fallback: "ok" - } - } - typeErrorUndefined: { - try { - v: (〈3;c〉? + "string") - } else { - fallback: "ok" - } - } - divByZero: { - try { - v: (〈3;a〉? / 0) - } else { - fallback: "ok" - } - } - conflictError: { - try { - v: (〈3;a〉? & "notanint") - } else { - fallback: "ok" - } - } - mixedError: { - try { - x: 〈3;c〉? - y: (1 / 0) - } else { - fallback: "ok" - } - } - mixedErrorMultiple: { - try { - x: 〈3;a〉? - y: 〈3;c〉? - z: (〈3;a〉? / 0) - } else { - fallback: "ok" - } - } - } - assignmentForm: { - basicDefined: { - try x = 〈2;a〉? { - result: 〈1;x〉 - } - } - basicUndefined: { - try x = 〈2;c〉? { - result: 〈1;x〉 - } else { - fallback: 0 - } - } - noElseUndefined: { - try x = 〈2;c〉? { - result: 〈1;x〉 - } - } - withExpression: { - try sum = (〈2;a〉? + 〈2;b〉?) { - result: 〈1;sum〉 - } - } - withFailingExpr: { - try sum = (〈2;a〉? + 〈2;c〉?) { - result: 〈1;sum〉 - } else { - fallback: -1 - } - } - chained: { - try x = 〈2;a〉? try y = 〈3;b〉? { - result: (〈2;x〉 + 〈1;y〉) - } - } - withSelector: { - data: { - inner: 42 - } - try v = 〈0;data〉.inner? { - result: 〈1;v〉 - } - } - withIndex: { - list: [ - 10, - 20, - 30, - ] - try v = 〈0;list〉[1]? { - result: 〈1;v〉 - } - } - withOutOfRangeIndex: { - list: [ - 10, - 20, - 30, - ] - try v = 〈0;list〉[10]? { - result: 〈1;v〉 - } else { - fallback: -1 - } - } - withOutOfRangeIndexOpen: { - list: [ - 10, - 20, - 30, - ..., - ] - try v = 〈0;list〉[10]? { - result: 〈1;v〉 - } else { - fallback: -1 - } - } - nestedUse: { - try x = 〈2;a〉? { - inner: { - value: (〈2;x〉 * 2) - } - } - } - chainedOneFails: { - try x = 〈2;a〉? try y = 〈3;c〉? { - result: (〈2;x〉 + 〈1;y〉) - } - } - withRealError: { - try x = (〈2;a〉? / 0) { - result: 〈1;x〉 - } else { - fallback: "ok" - } - } - withFor: { - try x = 〈2;b〉? for i, v in [ - 1, - 2, - ] { - "\(〈1;i〉)": (〈2;x〉 + 〈1;v〉) - } - } - withIf: { - try x = 〈2;a〉? if (〈0;x〉 > 0) { - positive: 〈1;x〉 - } - } - withLet: { - try x = 〈2;a〉? let y = (〈0;x〉 * 2) { - doubled: 〈1;y〉 - } - } - } - recursive: { - t1: { - try { - for _, x in [ - 〈4;b〉?, - ] { - 〈1;x〉 - } - } - } - } - recursive: { - t2: { - try { - { - x: 〈4;b〉? - y: 〈4;c〉? - } - } - } - } - recursive: { - t3: { - try { - { - x: 〈4;b〉? - y: 〈4;c〉? - } - } else { - z: 23 - } - } - } -} diff --git a/cue/testdata/comprehensions/try_compile_errors.txtar b/cue/testdata/comprehensions/try_compile_errors.txtar index d6656fb5a..72f738b79 100644 --- a/cue/testdata/comprehensions/try_compile_errors.txtar +++ b/cue/testdata/comprehensions/try_compile_errors.txtar @@ -76,48 +76,3 @@ optionalOutsideTry.b: optional marker (?) is only valid within a try clause: ./in.cue:11:8 optionalInForSource: optional marker (?) is only valid within a try clause: ./in.cue:16:14 --- out/compile -- -structFormNotLast: struct-form try clause must be the last clause in a comprehension: - ./in.cue:5:5 -optionalOutsideTry.b: optional marker (?) is only valid within a try clause: - ./in.cue:11:8 -optionalInForSource: optional marker (?) is only valid within a try clause: - ./in.cue:17:14 -optionalInAssignmentBody.try[].x: optional marker (?) is only valid within a try clause: - ./in.cue:24:21 -invalidUseOfOptional.x: reference "c" not found: - ./in.cue:29:14 ---- in.cue -{ - structFormNotLast: { - _|_(struct-form try clause must be the last clause in a comprehension) - } - optionalOutsideTry: { - a: 1 - b: 〈0;a〉? - } - optionalInForSource: { - a?: [ - 1, - 2, - 3, - ] - for _, x in 〈0;a〉? { - "\(〈1;x〉)": 〈1;x〉 - } - } - optionalInAssignmentBody: { - a: 1 - b: 2 - try y = 〈0;a〉? { - x: 〈2;b〉? - } else { - fallback: 23 - } - } - invalidUseOfOptional: { - try { - x: _|_(reference "c" not found) - } - } -} diff --git a/cue/testdata/cycle/015_reference_across_tuples_and_back.txtar b/cue/testdata/cycle/015_reference_across_tuples_and_back.txtar index 517d319ab..e78ec7e7c 100644 --- a/cue/testdata/cycle/015_reference_across_tuples_and_back.txtar +++ b/cue/testdata/cycle/015_reference_across_tuples_and_back.txtar @@ -7,20 +7,6 @@ t1: { b: {e: 3, f: 3} }) } --- out/compile -- ---- in.cue -{ - t1: { - a: { - c: 〈1;b〉.e - d: 〈1;b〉.f - } - b: { - e: 3 - f: 〈1;a〉.c - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/cycle/021_delayed_constraint_failure.txtar b/cue/testdata/cycle/021_delayed_constraint_failure.txtar index 4e7d7e6f5..04b068c30 100644 --- a/cue/testdata/cycle/021_delayed_constraint_failure.txtar +++ b/cue/testdata/cycle/021_delayed_constraint_failure.txtar @@ -16,15 +16,6 @@ x: x + 1 @test(err, code=eval, pos=[-1:4, 0:4]) [eval] x: conflicting values 101 and 100: ./in.cue:5:4 ./in.cue:6:4 --- out/compile -- ---- in.cue -{ - a: (〈0;b〉 - 100) - b: (〈0;a〉 + 110) - b: 200 - x: 100 - x: (〈0;x〉 + 1) -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/cycle/023_reentrance.txtar b/cue/testdata/cycle/023_reentrance.txtar index e1e2b14ee..81014ef3f 100644 --- a/cue/testdata/cycle/023_reentrance.txtar +++ b/cue/testdata/cycle/023_reentrance.txtar @@ -63,41 +63,3 @@ Conjuncts: 306 Disjuncts: 0 NumCloseIDs: 117 --- out/compile -- ---- in.cue -{ - fibRec: { - nn: int - out: (〈1;fib〉 & { - n: 〈1;nn〉 - }).out - } - fib: { - n: int - if (〈0;n〉 >= 2) { - out: ((〈2;fibRec〉 & { - nn: (〈2;n〉 - 2) - }).out + (〈2;fibRec〉 & { - nn: (〈2;n〉 - 1) - }).out) - } - if (〈0;n〉 < 2) { - out: 〈1;n〉 - } - } - fib1: (〈0;fib〉 & { - n: 1 - }).out - fib2: (〈0;fib〉 & { - n: 2 - }).out - fib3: (〈0;fib〉 & { - n: 3 - }).out - fib7: (〈0;fib〉 & { - n: 7 - }).out - fib12: (〈0;fib〉 & { - n: 12 - }).out -} diff --git a/cue/testdata/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar b/cue/testdata/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar index 27925c2a2..0314e2396 100644 --- a/cue/testdata/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar +++ b/cue/testdata/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar @@ -25,27 +25,6 @@ a1: 2 errors in empty disjunction:: ./in.cue:4:10 a2: unresolved disjunction: a1: ./in.cue:4:10 --- out/compile -- ---- in.cue -{ - a1: (*0|1) - a1: (〈0;a3〉 - 〈0;a2〉) - a2: (*0|1) - a2: (〈0;a3〉 - 〈0;a1〉) - a3: 1 - b1: ((*0|1) & 〈0;b2〉) - b2: ((0|*1) & 〈0;b1〉) - c1: ((*{ - a: 1 - }|{ - b: 1 - }) & 〈0;c2〉) - c2: ((*{ - a: 2 - }|{ - b: 2 - }) & 〈0;c1〉) -} -- out/eval/stats -- Leaks: 0 Freed: 52 diff --git a/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar b/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar index 0d8f86c53..daedbef02 100644 --- a/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar +++ b/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar @@ -10,17 +10,6 @@ a: x: "hey" @test(err, code=eval, contains="conflicting values", pos=[-3:5, 0:7] [eval] a.x: conflicting values "hey!?" and "hey": ./in.cue:2:5 ./in.cue:5:7 --- out/compile -- ---- in.cue -{ - a: { - x: (〈0;y〉 + "?") - y: (〈0;x〉 + "!") - } - a: { - x: "hey" - } -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar b/cue/testdata/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar index 47d5cbe6e..88955335f 100644 --- a/cue/testdata/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar +++ b/cue/testdata/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar @@ -10,25 +10,6 @@ c: a & {y: 3} | {z: 3} // {x:1,y:3,z:2} | {z:3} b: {x: 2} | {z: 2, y: 3, x: 1} c: {y: 3, x: 1, z: 2} | {z: 3} }) --- out/compile -- ---- in.cue -{ - a: ((〈0;b〉 & { - x: 1 - })|{ - y: 1 - }) - b: ({ - x: 2 - }|(〈0;c〉 & { - z: 2 - })) - c: ((〈0;a〉 & { - y: 3 - })|{ - z: 3 - }) -} -- out/eval/stats -- Leaks: 6 Freed: 46 diff --git a/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar b/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar index 83ba96d52..e418cfd6e 100644 --- a/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar +++ b/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar @@ -158,40 +158,3 @@ Conjuncts: 95 Disjuncts: 21 NumCloseIDs: 17 --- out/compile -- ---- in.cue -{ - xa1: ((〈0;xa2〉 & 8)|(〈0;xa4〉 & 9)) - xa2: (〈0;xa3〉 + 2) - xa3: (6 & (〈0;xa1〉 - 2)) - xa4: (〈0;xa2〉 + 2) - xb1: ((〈0;xb2〉 & 8)|(〈0;xb4〉 & 9)) - xb2: (〈0;xb3〉 + 2) - xb3: ((6 & (〈0;xb1〉 - 2))|(〈0;xb4〉 & 9)) - xb4: (〈0;xb2〉 + 2) - xc1: ((〈0;xc2〉 & 8)|(〈0;xc4〉 & 9)|(〈0;xc5〉 & 9)) - xc2: (〈0;xc3〉 + 2) - xc3: (6 & (〈0;xc1〉 - 2)) - xc4: (〈0;xc2〉 + 1) - xc5: (〈0;xc2〉 + 2) - xd1: ((〈0;xd2〉 & 8)|(〈0;xd4〉 & 9)|(〈0;xd5〉 & 9)) - xd2: (〈0;xd3〉 + 2) - xd3: (6 & (〈0;xd1〉 - 2)) - xd4: (〈0;xd2〉 + 1) - xd5: (〈0;xd2〉 + 2) - xd1: 8 - xe1: ((〈0;xe2〉 & 8)|(〈0;xe4〉 & 9)|(〈0;xe5〉 & 9)) - xe2: (〈0;xe3〉 + 2) - xe3: (6 & (〈0;xe1〉 - 2)) - xe4: (〈0;xe2〉 + 1) - xe5: (〈0;xe2〉 + 2) - xe1: 9 - xf1: ((〈0;xf2〉 & 8)|(〈0;xf4〉 & 9)) - xf2: (〈0;xf3〉 + 2) - xf3: ((6 & (〈0;xf1〉 - 2))|(〈0;xf4〉 & 9)) - xf4: (〈0;xf2〉 + 2) - z1: ((〈0;z2〉 + 1)|(〈0;z3〉 + 5)) - z2: (〈0;z3〉 + 2) - z3: (〈0;z1〉 - 3) - z3: 8 -} diff --git a/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar b/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar index c4b9555eb..89137a467 100644 --- a/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar +++ b/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar @@ -100,35 +100,3 @@ Conjuncts: 79 Disjuncts: 17 NumCloseIDs: 14 --- out/compile -- ---- in.cue -{ - xa1: ((〈0;xa2〉 & 8)|*(〈0;xa4〉 & 9)) - xa2: (〈0;xa3〉 + 2) - xa3: (6 & (〈0;xa1〉 - 2)) - xa4: (〈0;xa2〉 + 2) - xb1: (*(〈0;xb2〉 & 8)|(〈0;xb4〉 & 9)) - xb2: (〈0;xb3〉 + 2) - xb3: (*(6 & (〈0;xb1〉 - 2))|(〈0;xb4〉 & 9)) - xb4: (〈0;xb2〉 + 2) - xc1: (*(〈0;xc2〉 & 8)|(〈0;xc4〉 & 9)|(〈0;xc5〉 & 9)) - xc2: (〈0;xc3〉 + 2) - xc3: (6 & (〈0;xc1〉 - 2)) - xc4: (〈0;xc2〉 + 1) - xc5: (〈0;xc2〉 + 2) - xd1: (*(〈0;xd2〉 & 8)|(〈0;xd4〉 & 9)|(〈0;xd5〉 & 9)) - xd2: (〈0;xd3〉 + 2) - xd3: (6 & (〈0;xd1〉 - 2)) - xd4: (〈0;xd2〉 + 1) - xd5: (〈0;xd2〉 + 2) - xe1: (*(〈0;xe2〉 & 8)|(〈0;xe4〉 & 9)|(〈0;xe5〉 & 9)) - xe2: (〈0;xe3〉 + 2) - xe3: (6 & (〈0;xe1〉 - 2)) - xe4: (〈0;xe2〉 + 1) - xe5: (〈0;xe2〉 + 2) - xe1: 9 - z1: (*(〈0;z2〉 + 1)|(〈0;z3〉 + 5)) - z2: (〈0;z3〉 + 2) - z3: (〈0;z1〉 - 3) - z3: 8 -} diff --git a/cue/testdata/cycle/builtins.txtar b/cue/testdata/cycle/builtins.txtar index fd9f884f3..a5011cffd 100644 --- a/cue/testdata/cycle/builtins.txtar +++ b/cue/testdata/cycle/builtins.txtar @@ -469,413 +469,3 @@ selfCycle.t1.c.d.d.d: structural cycle: [structural_cycle] selfCycle.yamlValidatePartial.x.y: invalid value "{}" (does not satisfy encoding/yaml.ValidatePartial): structural cycle: ./yamlcycle.cue:60:8 ./yamlcycle.cue:61:8 --- out/compile -- ---- cycle.cue -{ - noCycle: { - t1: { - 〈0;_s〉 - _s: { - #x: matchN(1, [ - 〈2;_s〉, - ]) - #x: {} - } - } - } - issue3649: { - noCycle: { - t1: { - data: 〈0;#c〉 - data: { - a: { - b: "foo" - } - } - #c: { - b?: string - a?: matchN(1, [ - 〈2;#c〉, - ]) - } - } - } - } - issue3649: { - noCycle: { - t2: { - x: 〈0;c〉 - x: { - y: { - a: { - d: { - b: "foo" - } - } - } - } - c: { - b?: string - y: { - a?: matchN(1, [ - { - d: 〈4;c〉 - }, - ]) - } - } - } - } - } - issue3649: { - cycle: { - t1: { - data: 〈0;#c〉 - data: { - a: { - b: "foo" - } - } - #c: { - b: string - a: matchN(1, [ - 〈2;#c〉, - ]) - } - } - } - } - issue4037: { - cycle: { - _intlike: matchN(1, [ - 〈import;strconv〉.Atoi(〈1〉), - ]) - f: ("1233" & 〈0;_intlike〉) - } - } -} ---- in.cue -{ - builtinCyclePerm: { - X: "mod.test" - Y: { - #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) - host: 〈0;#components〉.host - } - X: 〈0;Y〉.host - } -} ---- issue3634.cue -{ - issue3634: { - full: { - #Schema: { - required?: [ - ...string, - ] - properties?: { - [string]: (null|〈2;#Schema〉) - } - } - out: len(([ - ...〈1;#Schema〉, - ] & 〈import;list〉.Repeat([ - { - 〈2;#Schema〉 - properties: { - foo: { - required: [ - "bar", - "baz", - ] - } - } - }, - ], 3))) - } - } - issue3634: { - reduced: { - #D: { - b?: int - a?: 〈1;#D〉 - } - out: len((〈0;#D〉 & 〈import;list〉.Repeat([ - (〈1;#D〉 & { - a: { - b: 1 - } - }), - ], 1)[0])) - } - } -} ---- issue3743.cue -{ - issue3743: { - #transform: { - in: _ - out: [ - if false { - 〈2;out〉 - }, - 〈1;in〉, - ] - } - docs: [ - (〈1;#transform〉 & { - in: "x" - }).out, - ] - out: 〈import;"encoding/yaml"〉.MarshalStream(〈0;docs〉) - } -} ---- jsoncycle.cue -{ - jsonCycle: { - t1: { - x: { - y: 〈import;"encoding/json"〉.Validate(〈1;x〉) - } - x: { - y: "{}" - } - } - } -} ---- listmatchncycle.cue -{ - listMatchN: { - structCycle: { - x: { - y: 〈import;list〉.MatchN(1, 〈1;x〉) - } - x: { - y: [ - {}, - ] - } - } - } - listMatchN: { - ok: { - x: { - y?: 〈import;list〉.MatchN(1, 〈1;x〉) - } - z: 〈0;x〉 - z: { - y: [ - {}, - ] - } - } - } -} ---- matchn.cue -{ - issue3410: { - 〈0;_s〉 - _s: { - #x: matchN(1, [ - 〈2;_s〉, - [ - ...〈3;_s〉, - ], - ]) - } - } - issue3420: { - matches1: { - #S: matchN(1, [ - _, - _|_(explicit error (_|_ literal) in source), - ]) - s: 2 - } - } - issue3443: { - matchIf: { - #S: 〈1;matchIf〉({ - x?: "b" - }, { - n?: (〈1;#S〉 & (int|{})) - }, _) - } - noCycle: { - #S: matchN(1, [ - { - n?: (〈2;#S〉 & (int|{})) - }, - ]) - noHang: { - s: 〈1;#S〉 - s: { - n: { - n: _ - } - } - } - } - noCycle2: { - #S: matchN(1, [ - { - n?: (int|〈2;#S〉) - }, - ]) - } - cycle1: { - #S: matchN(1, [ - { - n: 〈2;#S〉 - }, - ]) - ok: { - s: 〈1;#S〉 - s: _ - } - cycle: { - s: 〈1;#S〉 - s: { - n: { - n: _ - } - } - } - } - cycle2: { - fail: { - #S: (matchN(1, [ - { - n: 〈2;#S〉 - }, - ]) & { - n: { - n: { - n: _ - } - } - }) - } - } - } - issue3633: { - final: { - data: ({} & 〈0;#s〉) - #s: matchN(1, [ - matchN(1, [ - { - a!: _ - }, - ]), - ]) - } - } - issue3842: { - reduced: { - #recursive: [ - ...(matchIf({ - source?: "multi" - }, 〈1;#recursive〉, _) & { - source?: string - }), - ] - } - } -} ---- yamlcycle.cue -{ - yamlNoCycle: { - #c: { - b?: string - a?: 〈import;"encoding/yaml"〉.Validate(〈1;#c〉) - } - data: 〈0;#c〉 - data: { - a: "{a: \"b: foo\"}" - } - } - selfCycle: { - t1: { - c: matchN(1, [ - { - d: 〈2;c〉 - }, - ]) - c: { - d: {} - } - } - } - selfCycle: { - t2: { - c: matchN(1, [ - { - d: 〈2;c〉 - }, - ]) - c: {} - } - } - selfCycle: { - yamlVal: { - t1: { - x: { - y: 〈import;"encoding/yaml"〉.Validate(〈1;x〉) - } - x: { - y: "{}" - } - } - } - } - selfCycle: { - yamlVal: { - t2: { - x: { - y: 〈import;"encoding/yaml"〉.Validate(〈1;x〉) - } - x: { - y: "{}" - } - x: { - y: 〈import;"encoding/yaml"〉.Validate(〈1;x〉) - } - x: { - y: "{}" - } - } - } - } - selfCycle: { - yamlFun: { - t1: { - x: { - y?: 〈import;"encoding/yaml"〉.Validate("{}", 〈1;x〉) - } - } - } - } - selfCycle: { - yamlFun: { - t2: { - z: (〈0;x〉 & _|_(no sharing)) - z: { - y: "{}" - } - x: { - y: 〈import;"encoding/yaml"〉.Validate("{}", 〈1;x〉) - } - } - } - } - selfCycle: { - yamlValidatePartial: { - x: { - y: 〈import;"encoding/yaml"〉.ValidatePartial(〈1;x〉) - } - x: { - y: "{}" - } - } - } -} diff --git a/cue/testdata/cycle/chain.txtar b/cue/testdata/cycle/chain.txtar index 13aa5b96e..6e5abcda2 100644 --- a/cue/testdata/cycle/chain.txtar +++ b/cue/testdata/cycle/chain.txtar @@ -512,298 +512,3 @@ Disjuncts: 729 Notifications: 3 NumCloseIDs: 1501 --- out/compile -- ---- in.cue -{ - chain: { - t1: { - #maxiter: 2 - x: 〈0;a〉.x0 - a: { - for k, _ in [ - 0, - 1, - ] { - "x\(〈1;k〉)": (〈3;#DepthF〉 & { - #in: 〈4;a〉["x\((〈2;k〉 + 1))"] - }).#out - } - } - a: { - x2: null - } - #DepthF: { - #in: _ - #out: {} - } - } - } - chain: { - t2: { - p1: { - X: 1 - for _, v in 〈import;list〉.Concat([ - [ - 0, - 〈2;X〉, - ], - [], - ]) { - x: { - "x\(〈2;v〉)": {} - } - } - x: _ - 〈0;x〉.x0 - } - } - } - chain: { - t2: { - p2: { - for _, v in 〈import;list〉.Concat([ - [ - 0, - 〈2;X〉, - ], - [], - ]) { - x: { - "x\(〈2;v〉)": {} - } - } - x: _ - 〈0;x〉.x0 - X: 1 - } - } - } - chain: { - t3: { - p1: { - X: 1 - for _, v in 〈import;list〉.Range(0, 〈0;X〉, 1) { - x: { - "x\(〈2;v〉)": {} - } - } - x: _ - 〈0;x〉.x0 - } - } - } - chain: { - t3: { - p1: { - for _, v in 〈import;list〉.Range(0, 〈0;X〉, 1) { - x: { - "x\(〈2;v〉)": {} - } - } - x: _ - 〈0;x〉.x0 - X: 1 - } - } - } -} ---- issue2052.cue -{ - issue2052: { - reduced: { - t1: { - A: { - a: _ - } - Depth: { - #maxiter: 1 - if (〈import;math〉.Abs(〈0;#maxiter〉) == 1) { - funcs: { - "\(0)": 〈3;A〉 - } - } - funcs: {} - 〈0;funcs〉["0"] - } - } - } - } - issue2052: { - reduced: { - t2: { - A: { - a: _ - } - Depth: { - maxiter: 1 - for k, v in 〈import;list〉.Range(0, 〈0;maxiter〉, 1) { - funcs: { - "\(0)": 〈4;A〉 - } - } - funcs: {} - 〈0;funcs〉["0"] - } - } - } - } - issue2052: { - medium: { - t1: { - #Depth: { - #maxiter: 4 - for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { - #funcs: { - "\(〈2;k〉)": (〈4;#DepthF〉 & { - #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] - }).#func - } - } - #funcs: { - "\(〈1;#maxiter〉)": null - } - 〈0;#funcs〉["0"] - } - #DepthF: { - #next: _ - #func: { - #in: _ - #basic: (string|null) - out: { - if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { - 1 - } - if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { - (〈import;list〉.Max([ - for k, v in 〈3;#in〉 { - (〈6;#next〉 & { - #in: 〈2;v〉 - }).out - }, - ]) + 1) - } - } - } - } - tree: "bar" - d: (〈0;#Depth〉 & { - #in: 〈1;tree〉 - }) - } - } - } - issue2052: { - medium: { - t2: { - #Depth: { - #maxiter: 4 - for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { - #funcs: { - "\(〈2;k〉)": (〈4;#DepthF〉 & { - #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] - }).#func - } - } - #funcs: { - for k, v in 〈import;list〉.Range(0, 〈1;#maxiter〉, 1) { - "\(〈1;k〉)": (〈4;#DepthF〉 & { - #next: 〈4;#funcs〉["\((〈2;k〉 + 1))"] - }).#func - } - } - #funcs: { - "\(〈1;#maxiter〉)": null - } - 〈0;#funcs〉["0"] - } - #DepthF: { - #next: _ - #func: { - #in: _ - #basic: (string|null) - out: { - if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { - 1 - } - if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { - (〈import;list〉.Max([ - for k, v in 〈3;#in〉 { - (〈6;#next〉 & { - #in: 〈2;v〉 - }).out - }, - ]) + 1) - } - } - } - } - tree: "bar" - d: (〈0;#Depth〉 & { - #in: 〈1;tree〉 - }) - } - } - } - issue2052: { - full: { - #RecurseN: { - #maxiter: (&(int, >=0)|*4) - #funcFactory: { - #next: _ - #func: _ - } - for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { - #funcs: { - "\(〈2;k〉)": (〈3;#funcFactory〉 & { - #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] - }).#func - } - } - #funcs: { - "\(〈1;#maxiter〉)": null - } - 〈0;#funcs〉["0"] - } - #DepthF: { - #next: _ - #func: { - #in: _ - #basic: (int|number|string|bytes|null) - out: { - if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { - 1 - } - if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { - let depths#1 = [ - for k, v in 〈3;#in〉 { - (〈6;#next〉 & { - #in: 〈2;v〉 - }).out - }, - ] - (〈import;list〉.Max(〈0;let depths#1〉) + 1) - } - } - } - } - #Depth: (〈0;#RecurseN〉 & { - #maxiter: 11 - #funcFactory: 〈1;#DepthF〉 - }) - tree: { - a: { - foo: "bar" - a: { - b: { - c: "d" - } - } - } - cow: "moo" - } - d: (〈0;#Depth〉 & { - #in: 〈1;tree〉 - }) - } - } -} diff --git a/cue/testdata/cycle/compbottom.txtar b/cue/testdata/cycle/compbottom.txtar index 0ac42834a..d559b124a 100644 --- a/cue/testdata/cycle/compbottom.txtar +++ b/cue/testdata/cycle/compbottom.txtar @@ -114,49 +114,3 @@ Conjuncts: 177 Disjuncts: 0 NumCloseIDs: 72 --- out/compile -- ---- in.cue -{ - simple: { - #message: "^(message: (?P.*))?$" - p1: { - X: "message: hello" - #aux: { - if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { - message: "" - } - if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { - message: ("message: " + 〈2;Y〉.message) - } - } - Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) - X: 〈0;#aux〉.message - } - } - medium: { - #userHostPort: "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)$" - p1: { - Y: { - userinfo: "user" - host: "mod.test" - } - X: (〈0;#X〉.userinfo + 〈0;#X〉.host) - #X: { - if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { - userinfo: "" - } - if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { - userinfo: (〈2;Y〉.userinfo + "@") - } - host: 〈1;Y〉.host - } - Y: { - if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { - userinfo: 〈2;#Y〉.userinfo - } - host: 〈1;#Y〉.host - } - #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) - } - } -} diff --git a/cue/testdata/cycle/compbottom2.txtar b/cue/testdata/cycle/compbottom2.txtar index 05f0a2a86..5c828e4d1 100644 --- a/cue/testdata/cycle/compbottom2.txtar +++ b/cue/testdata/cycle/compbottom2.txtar @@ -417,444 +417,3 @@ Disjuncts: 16 Notifications: 2 NumCloseIDs: 112 --- out/compile -- ---- in.cue -{ - self: { - fail: { - a: { - if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { - b: 1 - } - } - } - isConcreteFail: { - t1: { - a: { - if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { - b: 1 - } - b: int - } - } - } - isConcreteFail: { - t2: { - a: { - if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { - b: 1 - } - b?: int - } - } - } - isNotConcrete: { - t1: { - a: { - if (〈1;a〉.b != _|_(explicit error (_|_ literal) in source)) { - b: 1 - } - b: int - } - } - } - isNotConcrete: { - t2: { - a: { - if (〈1;a〉.b != _|_(explicit error (_|_ literal) in source)) { - b: 1 - } - b?: int - } - } - } - } -} ---- issue3836.cue -{ - issue3836: { - hidden: { - _Value: { - foo?: _ - bar?: _ - if ((〈0;foo〉|〈0;bar〉) == _|_(explicit error (_|_ literal) in source)) { - bar: { - type: "bar" - } - } - out: [ - if (〈1;bar〉 != _|_(explicit error (_|_ literal) in source)) { - "bar is set" - }, - ] - } - 〈0;_Value〉.out - } - } - issue3836: { - exposed: { - foo?: _ - bar?: _ - if ((〈0;foo〉|〈0;bar〉) == _|_(explicit error (_|_ literal) in source)) { - bar: { - type: "bar" - } - } - out: [ - if (〈1;bar〉 != _|_(explicit error (_|_ literal) in source)) { - "bar is set" - }, - ] - } - } -} ---- issue3838.cue -{ - issue3838: { - #T: { - subject: { - in: { - opt?: { - foo: int - } - } - out: [ - if (〈1;in〉.opt != _|_(explicit error (_|_ literal) in source)) { - 〈2;in〉.opt.foo - }, - 0, - ][0] - } - _test: { - assert: { - pass: bool - } - assert: ({ - notOk: _ - pass: false - }|{ - invoke: _ - res: 〈2;subject〉.out - pass: true - }) - } - results: 〈0;_test〉.assert.pass - } - (〈0;#T〉 & { - _test: { - assert: { - invoke: "foo" - } - } - }).results - } -} ---- mutual.cue -{ - mutual: { - noConflicts: { - a: { - if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { - new: "" - } - } - b: { - if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { - new: "" - } - } - } - mutualCycleFail: { - b: { - if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { - foo: "" - } - } - a: { - if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { - bar: "" - } - } - } - brokenCycleSuccess: { - a: { - if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { - foo: "" - } - } - b: { - if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { - bar: "" - } - } - a: { - bar: "" - } - } - allowOneDirectionalDependency: { - p1: { - a: { - if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { - bar: "" - } - } - b: { - if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { - new: "" - } - } - } - p2: { - a: { - if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { - new: "" - } - } - b: { - if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { - foo: "" - } - } - } - } - oneDirectionalBrokenConflictSuccess: { - b: { - foo: "" - } - a: { - if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { - bar: "" - } - } - b: { - if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { - new: "" - } - } - } - } -} ---- mutualsamestruct.cue -{ - sameStruct: { - chainSuccess: { - a: { - raises?: {} - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - ret?: {} - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - foo: { - a: 1 - } - } - } - } - chainSuccess: { - b: { - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - foo: { - a: 1 - } - } - raises?: {} - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - ret?: {} - } - } - cycleFail: { - t1: { - p1: { - raises?: {} - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - ret?: {} - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - raises: { - a: 1 - } - } - } - } - } - cycleFail: { - t1: { - p2: { - ret?: {} - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - raises: { - a: 1 - } - } - raises?: {} - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - } - } - } - cycleFail: { - t2: { - p1: { - raises: {} - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - ret: {} - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - raises: { - a: 1 - } - } - } - } - } - cycleFail: { - t2: { - p2: { - ret: {} - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - raises: { - a: 1 - } - } - raises: {} - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - } - } - } - cycleFail: { - t3: { - p1: { - raises: _ - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - ret: _ - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - raises: { - a: 1 - } - } - } - } - } - cycleFail: { - t3: { - p2: { - ret: _ - if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { - raises: { - a: 1 - } - } - raises: _ - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret: { - a: 1 - } - } - } - } - } - defCloseSuccess: { - #Example: { - raises?: { - runtime?: string - } - if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { - ret?: _ - } - } - expr: (〈0;#Example〉 & { - ret: 2 - }) - } - } -} ---- nestedchain.cue -{ - nestedChain: { - cycleFail: { - if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { - #E: { - y: true - } - } - if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { - #E: { - x: true - } - } - #E: { - [_]: bool - } - } - brokenCycleSuccess: { - if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { - #E: { - y: true - } - } - if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { - #E: { - x: true - } - } - #E: { - [_]: bool - } - #E: { - x: true - } - } - doubleAddfail: { - if (〈0;#E〉.x == _|_(explicit error (_|_ literal) in source)) { - #E: { - y: true - } - } - if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { - #E: { - x: true - } - } - #E: { - [_]: bool - } - } - trippleSuccess: { - if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { - #E: { - y: true - } - } - if (〈0;#E〉.y != _|_(explicit error (_|_ literal) in source)) { - z: true - } - #E: { - x: true - } - } - } -} diff --git a/cue/testdata/cycle/compbottomnofinal.txtar b/cue/testdata/cycle/compbottomnofinal.txtar index 2215144b0..30c29ff2f 100644 --- a/cue/testdata/cycle/compbottomnofinal.txtar +++ b/cue/testdata/cycle/compbottomnofinal.txtar @@ -186,87 +186,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 76 --- out/compile -- ---- in.cue -{ - minimal: { - a: { - if (〈1;b〉.port == _|_(explicit error (_|_ literal) in source)) { - port: "" - } - } - b: { - if (〈1;a〉.port == _|_(explicit error (_|_ literal) in source)) { - port: "" - } - } - } - small: { - #userHostPort: "^(:(?P\\d+))?$" - p1: { - #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) - #X: { - if (〈1;#Y〉.port == _|_(explicit error (_|_ literal) in source)) { - port: "" - } - if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { - port: (":" + 〈import;strconv〉.FormatInt(〈2;#Y〉.port, 10)) - } - } - } - } - medium: { - #userHostPort: "^(:(?P\\d+))?$" - p1: { - #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) - Y: { - if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { - port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) - } - } - #X: { - if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { - port: "" - } - if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { - port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) - } - } - } - } - large: { - #userHostPort: "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\\d+))?$" - p1: { - Y: { - userinfo: "user" - host: "mod.test" - } - X: ((〈0;#X〉.userinfo + 〈0;#X〉.host) + 〈0;#X〉.port) - #X: { - if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { - userinfo: "" - } - if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { - userinfo: (〈2;Y〉.userinfo + "@") - } - host: 〈1;Y〉.host - if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { - port: "" - } - if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { - port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) - } - } - Y: { - if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { - userinfo: 〈2;#Y〉.userinfo - } - host: 〈1;#Y〉.host - if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { - port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) - } - } - #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) - } - } -} diff --git a/cue/testdata/cycle/comprehension.txtar b/cue/testdata/cycle/comprehension.txtar index 3031f1763..6599425fd 100644 --- a/cue/testdata/cycle/comprehension.txtar +++ b/cue/testdata/cycle/comprehension.txtar @@ -829,732 +829,3 @@ MaxRedirect: 1 ./issue2229.cue:16:28 structural cycle: ./issue2229.cue:16:24 --- out/compile -- ---- in.cue -{ - A: { - a: { - parent: "" - children: [ - for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { - 〈1;k〉 - }, - ] - } - b: { - parent: "a" - children: [ - for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { - 〈1;k〉 - }, - ] - } - } - B: { - a: { - parent: "" - children: [ - for k, v in 〈3;B〉 for _, w in 〈0;v〉.children { - 〈2;k〉 - }, - ] - } - } - Issue486: { - A: { - a: { - parent: "" - children: [ - ...string, - ] - } - b: { - parent: "a" - children: [ - ...string, - ] - } - c: { - parent: "b" - children: [ - ...string, - ] - } - } - A: { - [string]: { - children: [ - for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈3;-〉) { - 〈1;k〉 - }, - ] - } - } - } - issue1666: { - #E: { - f1: { - [string]: (〈2;#E〉|[ - ...〈3;#E〉, - ]) - } - f2: { - [string]: { - t: 〈3;#E〉 - } - } - } - _e: 〈0;#E〉 - _e: { - f2: { - a: _ - } - } - e: (〈0;_e〉 & { - f1: { - for fk, s in 〈2;_e〉.f2 { - 〈1;fk〉: 〈1;s〉.t - } - } - }) - } - issue779: { - X: 〈0;Y〉.message - STATE: { - for k, v in 〈1;Y〉 { - if (〈1;k〉 != "message") { - "\(〈2;k〉)": 〈2;v〉 - } - } - } - Y: (〈0;STATE〉 & { - message: 〈1;X〉 - }) - X: "test" - STATE: { - code: 101 - } - } - selfReferential: { - T1: { - S: { - d: "bar" - } - T: { - e: { - S: { - a: "foo" - } - } - } - for s, v in 〈0;S〉 for t, _ in 〈1;T〉 { - T: { - 〈2;t〉: { - S: { - 〈5;s〉: 〈5;v〉 - } - } - } - } - } - } - selfReferential: { - list: { - panels: [ - for i, _ in 〈1;panels〉 { - id: 〈1;i〉 - }, - ] - panels: [ - {}, - {}, - {}, - ] - } - } - selfReferential: { - insertionError: { - A: { - foo: 1 - for _, x in 〈1;A〉 { - "foo3": 1 - } - } - } - } - selfReferential: { - acrossOr: { - t1: { - p1: { - o: (〈0;#Output〉 & { - retry: { - reject: "ok" - } - }) - #AllOutputs: { - reject: string - resource: string - retry: 〈1;#Output〉 - } - #Output: or([ - for name, config in 〈1;#AllOutputs〉 { - 〈1;name〉: 〈1;config〉 - }, - ]) - } - } - } - } - selfReferential: { - acrossOr: { - t1: { - p2: { - #Output: or([ - for name, config in 〈1;#AllOutputs〉 { - 〈1;name〉: 〈1;config〉 - }, - ]) - o: (〈0;#Output〉 & { - retry: { - reject: "ok" - } - }) - #AllOutputs: { - reject: string - resource: string - retry: 〈1;#Output〉 - } - } - } - } - } - selfReferential: { - acrossOr: { - t1: { - p3: { - #Output: or([ - for name, config in 〈1;#AllOutputs〉 { - 〈1;name〉: 〈1;config〉 - }, - ]) - #AllOutputs: { - reject: string - resource: string - retry: 〈1;#Output〉 - } - o: (〈0;#Output〉 & { - retry: { - reject: "ok" - } - }) - } - } - } - } - selfReferential: { - acrossOr: { - t2: { - p1: { - d: or([ - for x, y in 〈1;#A〉 { - 〈1;y〉 - }, - ]) - o: (〈0;d〉 & { - b: 2 - }) - #A: { - d1: int - d2: string - d3: { - b: 〈2;d〉 - } - } - } - } - } - } - selfReferential: { - acrossOr: { - t2: { - p2: { - o: (〈0;d〉 & { - b: 2 - }) - d: or([ - for x, y in 〈1;#A〉 { - 〈1;y〉 - }, - ]) - #A: { - d1: int - d2: string - d3: { - b: 〈2;d〉 - } - } - } - } - } - } - selfReferential: { - acrossOr: { - t2: { - p3: { - o: (〈0;d〉 & { - b: 2 - }) - #A: { - d1: int - d2: string - d3: { - b: 〈2;d〉 - } - } - d: or([ - for x, y in 〈1;#A〉 { - 〈1;y〉 - }, - ]) - } - } - } - } - issue1881: { - p1: { - o: (〈0;#Output〉 & { - retry: { - output: { - reject: "ok" - } - } - }) - #AllOutputs: { - reject: string - resource: string - retry: { - output: 〈2;#Output〉 - } - } - #Output: or([ - for name, config in 〈1;#AllOutputs〉 { - 〈1;name〉: 〈1;config〉 - }, - ]) - } - } - issue1881: { - p2: { - #AllOutputs: { - reject: string - resource: string - retry: { - output: 〈2;#Output〉 - } - } - o: (〈0;#Output〉 & { - retry: { - output: { - reject: "ok" - } - } - }) - #Output: or([ - for name, config in 〈1;#AllOutputs〉 { - 〈1;name〉: 〈1;config〉 - }, - ]) - } - } - issue1881: { - p3: { - #AllOutputs: { - reject: string - resource: string - retry: { - output: 〈2;#Output〉 - } - } - #Output: or([ - for name, config in 〈1;#AllOutputs〉 { - 〈1;name〉: 〈1;config〉 - }, - ]) - o: (〈0;#Output〉 & { - retry: { - output: { - reject: "ok" - } - } - }) - } - } - siblingInsertion: { - t1: { - p1: { - D: { - logging: _ - } - deployment: _ - for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { - deployment: { - 〈3;k〉: { - env: { - 〈4;k1〉: 〈4;v2〉 - } - } - } - } - for id, v in 〈0;D〉 { - deployment: { - 〈2;id〉: { - env2: { - ENV: "True" - } - } - } - } - } - } - } - siblingInsertion: { - t1: { - p2: { - D: { - logging: _ - } - deployment: _ - for id, v in 〈0;D〉 { - deployment: { - 〈2;id〉: { - env2: { - ENV: "True" - } - } - } - } - for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { - deployment: { - 〈3;k〉: { - env: { - 〈4;k1〉: 〈4;v2〉 - } - } - } - } - } - } - } - siblingInsertion: { - t2: { - p1: { - D: { - logging: _ - } - deployment: _ - for k, v in 〈0;deployment〉 { - for k1, v2 in 〈1;v〉.env2 { - deployment: { - 〈4;k〉: { - env: { - 〈4;k1〉: 〈4;v2〉 - } - } - } - } - } - for id, v in 〈0;D〉 { - deployment: { - 〈2;id〉: { - env2: { - ENV: "True" - } - } - } - } - } - } - } - siblingInsertion: { - t2: { - p2: { - D: { - logging: _ - } - deployment: _ - for k, v in 〈0;deployment〉 { - for k1, v2 in 〈1;v〉.env2 { - deployment: { - 〈4;k〉: { - env: { - 〈4;k1〉: 〈4;v2〉 - } - } - } - } - } - for id, v in 〈0;D〉 { - deployment: { - 〈2;id〉: { - env2: { - ENV: "True" - } - } - } - } - } - } - } - selfReferential: { - fail: { - a: {} - b: (〈0;a〉.x != "") - if 〈0;b〉 {} - } - } - issue2367: { - a: _ - for _, x in [ - 〈1;a〉, - ] { - a: 〈1;x〉 - } - } - issue2310: { - original: { - #s: { - #_1: string - #_2: string - #_3: string - 〈import;strings〉.Replace(〈0;#_1〉, 〈0;#_2〉, 〈0;#_3〉, -1) - } - #sub: { - #a: string - _#X: [ - 〈1;#a〉, - for _, i in 〈import;list〉.Range(0, len(〈2;#subs〉), 1) { - (〈4;#subs〉[〈1;i〉] & { - #_1: 〈4;_#X〉[〈2;i〉] - _ - }) - }, - ] - 〈0;_#X〉[(len(〈0;_#X〉) - 1)] - } - res: (〈0;#sub〉 & { - #a: "aaa" - _ - }) - #subs: [ - (〈1;#s〉 & { - #_2: "a" - #_3: "b" - _ - }), - (〈1;#s〉 & { - #_2: "c" - #_3: "d" - _ - }), - (〈1;#s〉 & { - #_2: "e" - #_3: "f" - _ - }), - ] - } - } - issue2310: { - reduced: { - res: { - 〈0;#X〉[3] - #X: [ - "X", - for i, _ in 〈2;#subs〉 { - 〈4;#s〉 - #str: 〈3;#X〉[〈1;i〉] - }, - ] - } - #s: { - #str: string - (〈0;#str〉 + "a") - } - #subs: [ - 0, - 1, - 2, - ] - } - } -} ---- issue2229.cue -{ - issue2229: { - full_ok: { - build: (bool|*true) - test: (bool|*true) - make: [ - for k, v in 〈2〉 if ((〈0;v〉 & true) != _|_(explicit error (_|_ literal) in source)) { - 〈1;k〉 - }, - ] - } - } - issue2229: { - reduced_fail: { - x: true - y: [ - for _, v in 〈2〉 if (〈0;v〉 & true) { - _ - }, - ] - } - } -} ---- issue2405.cue -{ - issue2405: { - #Copy: ({ - param: { - ... - } - result: { - for k, v in 〈1;param〉 { - 〈1;k〉: (〈4;#Copy〉 & { - param: 〈2;v〉 - }).result - } - } - }|{ - param: [ - ..., - ] - result: [ - for _, v in 〈1;param〉 { - (〈4;#Copy〉 & { - param: 〈2;v〉 - }).result - }, - ] - }|{ - param: number - result: 〈0;param〉 - }) - foo: 〈0;#Copy〉 - foo: { - param: { - a: [ - { - b: 134 - }, - ] - } - } - } -} ---- issue3903.cue -{ - issue3903: { - reduced: { - s1: 〈0;#Schema〉 - s1: { - _deps: [ - 〈2;#Schema〉, - ] - } - #Schema: { - _deps: [ - ..., - ] - objs: [ - for _, dep in 〈1;_deps〉 for _, obj in (〈0;dep〉 & {}).objs { - 〈1;obj〉 - }, - ] - } - } - } - issue3903: { - full: { - s1: (〈0;#Schema〉 & { - _deps: [ - 〈2;s2〉, - ] - _local: [ - "s1 local", - ] - }) - s2: (〈0;#Schema〉 & { - _local: [ - "s2 local", - ] - }) - #Schema: { - _local: [ - ...string, - ] - _deps: [ - ..., - ] - objs: [ - for _, obj in 〈1;_local〉 { - 〈1;obj〉 - }, - for _, dep in 〈1;_deps〉 for _, obj in (〈0;dep〉 & {}).objs { - 〈1;obj〉 - }, - ] - } - } - } -} ---- issue3941.cue -{ - issue3941: { - full: { - #Metadata: { - name: string - } - #Resource: { - metadata: 〈1;#Metadata〉 - } - out: { - _metadata: { - name: "foo" - } - resource: { - [string]: { - [string]: 〈3;#Resource〉 - } - } - _names: [ - 〈1;_metadata〉.name, - ] - for _, name in 〈0;_names〉 { - resource: { - level1: { - 〈3;name〉: { - metadata: 〈5;_metadata〉 - } - } - } - } - } - } - } -} ---- issue4100.cue -{ - issue4100: { - a: { - let l#1 = [ - 0, - ] - if (〈0;let l#1〉 != _|_(explicit error (_|_ literal) in source)) { - 〈1;let l#1〉[:] - } - } - for _, _ in 〈0;a〉 {} - } -} diff --git a/cue/testdata/cycle/constraints.txtar b/cue/testdata/cycle/constraints.txtar index 39fb85c09..755f61a39 100644 --- a/cue/testdata/cycle/constraints.txtar +++ b/cue/testdata/cycle/constraints.txtar @@ -306,389 +306,6 @@ noCancelSelfInvoke.t1.x.c.b.b.b in v2). Structure sharing in v3 means some field appear as ~(...) references rather than expanded structs (cyclicRing.t1.D.a, selfTriggerCycle.t1.a, brokenRing.t1.p1.D.a?, brokenRing.t1.p2.T.b). v2 additionally reports cyclicRing.t1.D.a.b as structural cycle. --- out/compile -- ---- in.cue -{ - safeCycle: { - simple2: { - y: { - [string]: { - b: { - c: 〈3;y〉 - } - } - } - x: 〈0;y〉 - x: { - c: 〈1;y〉 - } - } - } - safeCycle: { - long1: { - y: { - [string]: { - b: 〈2;y〉 - } - } - x: 〈0;y〉 - x: { - c: { - b: { - e: { - b: { - c: _ - } - } - } - } - } - } - } - safeCycle: { - long2: { - a: { - [string]: { - b: 〈2;a〉 - } - } - x: 〈0;a〉 - x: { - c: { - b: { - c: { - b: { - c: {} - } - } - } - } - } - } - } - noCyclePattern: _ - noCyclePattern: { - t1: { - #D: { - [string]: 〈1;#D〉 - } - a: {} - [string]: 〈0;#D〉 - [string]: { - b: { - c: {} - } - } - } - } - noCyclePattern: { - t2: { - #D: { - [string]: { - x: 〈2;#D〉 - } - } - a: {} - [string]: 〈0;#D〉 - [string]: { - b: { - x: { - c: {} - } - } - } - } - } - noCyclePattern: { - t3: { - _D: { - [string]: 〈1;_T〉 - } - _T: { - x: 〈1;_D〉 - } - [string]: 〈0;_D〉 - [string]: { - b: { - x: { - c: {} - } - } - } - a: {} - } - } - noCyclePattern: { - t4: { - _D: { - [string]: { - x: 〈2;_T〉 - } - } - _T: { - y: 〈1;_D〉 - } - [string]: 〈0;_D〉 - [string]: { - b: { - x: {} - } - } - a: {} - } - } - noCyclePattern: { - t5: { - _D: { - [string]: { - x: 〈2;_T〉 - } - } - _T: { - y: 〈1;_D〉 - } - [string]: 〈0;_D〉 - [string]: { - b: { - x: { - y: { - c: { - x: {} - } - } - } - } - } - a: {} - } - } - noCyclePattern: { - t6: { - #D: { - [string]: 〈1;#E〉 - } - #E: { - t: 〈1;#T〉 - } - #T: { - { - object: 〈2;#S〉 - } - } - #S: { - y: 〈1;#D〉 - } - [string]: { - x: 〈1;#D〉 - } - [string]: { - x: { - r: { - t: { - object: { - y: { - foo: { - t: { - object: {} - } - } - } - } - } - } - } - } - bar: {} - } - } - noCancelSelfInvoke: { - t1: { - y: { - [string]: { - b: 〈2;y〉 - } - } - x: 〈0;y〉 - x: { - c: 〈1;x〉 - } - } - } - selfTriggerCycle: _ - selfTriggerCycle: { - t1: { - a: 〈0;#T〉 - #T: { - [string]: 〈1;#T〉 - b: {} - } - } - } - selfTriggerCycle: { - t2: { - #T: { - [string]: { - a: 〈1〉 - } - } - b: 〈0;#T〉 - b: { - c: {} - } - } - } - selfTriggerCycle: { - long1: { - a: { - [string]: { - b: 〈2;a〉 - } - } - a: { - c: { - b: { - c: { - b: { - c: {} - } - } - } - } - } - } - } - selfTriggerCycle: { - issue1503: { - a: (〈0;#T〉 & { - a: { - one: { - link: { - a: { - two: {} - } - } - } - } - }) - #T: { - a: { - [string]: { - link: 〈3;#T〉 - } - } - a: { - b: {} - } - } - } - } - mutuallyTriggeringCycle: { - t1: { - y: { - [string]: { - b: 〈2;y〉 - } - } - x: 〈0;y〉 - x: { - c: 〈1;y〉 - } - } - } -} ---- issue3476.cue -{ - issue3476: { - #a: (〈0;#b〉 & { - x: _ - }).x - #b: { - x?: 〈0;#c〉 - #c: { - [string]: 〈1;#c〉 - } - } - } -} ---- issue3509.cue -{ - issue3509: { - out: (〈0;#job〉.step & "foo") - #job: (〈0;#Workflow〉 & { - job: _ - }).job - #Workflow: { - job: { - step: string - } - #matrixConfig: ([ - ...〈1;#matrixConfig〉, - ]|string) - matrix?: { - [string]: [ - ...〈2;#matrixConfig〉, - ] - } - } - } -} ---- ring.cue -{ - brokenRing: { - t1: { - p1: { - D: { - a?: 〈1;T〉 - } - T: { - b: 〈1;D〉 - } - } - p2: { - T: { - b: 〈1;D〉 - } - D: { - a?: 〈1;T〉 - } - } - } - } - brokenRing: { - t2: { - p1: { - D: { - [string]: 〈1;T〉 - } - T: { - b: 〈1;D〉 - } - } - } - } - brokenRing: { - t2: { - p2: { - T: { - b: 〈1;D〉 - } - D: { - [string]: 〈1;T〉 - } - } - } - } - cyclicRing: { - t1: { - D: { - a: 〈1;T〉 - } - T: { - b: 〈1;D〉 - } - } - } -} -- out/eval/stats -- Leaks: 4 Freed: 190 diff --git a/cue/testdata/cycle/cycle_with_bounds.txtar b/cue/testdata/cycle/cycle_with_bounds.txtar index 3c61b7335..1c61d20f3 100644 --- a/cue/testdata/cycle/cycle_with_bounds.txtar +++ b/cue/testdata/cycle/cycle_with_bounds.txtar @@ -8,17 +8,6 @@ bar: !=foo bar: 0 @test(eq, 0) foo: 1 @test(eq, 1) --- out/compile -- ---- in.cue -{ - #Value: int - foo: 〈0;#Value〉 - foo: !=〈0;bar〉 - bar: 〈0;#Value〉 - bar: !=〈0;foo〉 - bar: 0 - foo: 1 -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/cycle/disjunction.txtar b/cue/testdata/cycle/disjunction.txtar index 078420f67..f442df540 100644 --- a/cue/testdata/cycle/disjunction.txtar +++ b/cue/testdata/cycle/disjunction.txtar @@ -109,71 +109,3 @@ Conjuncts: 159 Disjuncts: 73 NumCloseIDs: 20 --- out/compile -- ---- in.cue -{ - cycle: { - a: 〈1;cycle〉 - } - r1a: (〈0;cycle〉|int) - r1b: (int|〈0;cycle〉) - r2a: (〈0;cycle〉|1) - r2b: (1|〈0;cycle〉) - r3a: (〈0;cycle〉|null) - r3b: (null|〈0;cycle〉) - r4a: (〈0;cycle〉|{}) - r4b: ({}|〈0;cycle〉) - r5a: (〈0;cycle〉|[]) - r5b: ([]|〈0;cycle〉) - s1a: { - x: (〈1;s1a〉|int) - } - s1b: { - x: (int|〈1;s1b〉) - } - s2a: { - x: (〈1;s2a〉|1) - } - s2b: { - x: (1|〈1;s2b〉) - } - s3a: { - x: (〈1;s3a〉|null) - } - s3b: { - x: (null|〈1;s3b〉) - } - s4a: { - x: (〈1;s4a〉|{}) - } - s4b: { - x: ({}|〈1;s4b〉) - } - s5a: { - x: (〈1;s5a〉|[]) - } - s5b: { - x: ([]|〈1;s5b〉) - } -} ---- issue3042.cue -{ - issue3042: { - #foo: =~"^foo" - #nesting: (string|{ - name?: 〈1;#foo〉 - [string]: 〈1;#nesting〉 - }|[ - ...〈1;#nesting〉, - ]) - data: (〈0;#nesting〉 & { - secret: { - infra: [ - { - name: "bar1" - }, - ] - } - }) - } -} diff --git a/cue/testdata/cycle/evaluate.txtar b/cue/testdata/cycle/evaluate.txtar index e37be306d..7fd4443fe 100644 --- a/cue/testdata/cycle/evaluate.txtar +++ b/cue/testdata/cycle/evaluate.txtar @@ -202,148 +202,3 @@ Conjuncts: 150 Disjuncts: 4 NumCloseIDs: 47 --- out/compile -- ---- in.cue -{ - letCycleOK: { - t1: { - b: 〈0;c〉 - let X#1 = 〈0;b〉 - c: 〈0;let X#1〉 - } - } - letCycleOK: { - t2: { - a: { - b: 1 - let X#2 = 〈1;a〉 - c: 〈0;let X#2〉.b - } - } - } - letCycleFail: { - t1: { - a: { - b: 1 - let X#3 = 〈1;a〉 - c: 〈0;let X#3〉 - } - } - } - letCycleFail: { - t2: { - a: { - let X#4 = 〈1;a〉 - if (〈0;let X#4〉 == _|_(explicit error (_|_ literal) in source)) {} - x: { - y: "" - } - } - } - } - listCycleOK: { - a: 〈0;b〉 - b: and([ - 〈1;c〉, - ]) - c: 〈0;a〉 - } - disjunctionCycle: { - a: 〈0;b〉 - b: and((1|〈0;c〉)) - c: 〈0;a〉 - } - forCycle: { - #A: { - a: 〈1;#B〉 - } - #B: or([ - for _, x in 〈1;#A〉 { - b: 〈1;x〉 - }, - ]) - } - letCycleWithAnd: { - a: { - d: 〈1;b〉 - } - b: and([ - for _, x in 〈1;a〉 let y = 〈0;x〉 { - 〈1;y〉 - }, - ]) - c: 〈0;a〉 - } - closeCycle: { - a: 〈0;b〉 - b: close({ - d: 〈1;c〉 - }) - c: 〈0;a〉 - } - structCycle: { - a: 〈0;b〉 - b: and([ - { - d: 〈2;c〉 - }, - ]) - c: 〈0;a〉 - } - embedCycle: { - a: 〈0;b〉 - b: close({ - 〈1;c〉 - }) - c: 〈0;a〉 - } - listAddCycle: { - a: 〈0;b〉 - b: 〈import;list〉.Concat([ - [ - 〈2;c〉, - ], - [ - 〈2;c〉, - ], - ]) - c: 〈0;a〉 - } - listMulCycle: { - a: 〈0;b〉 - b: 〈import;list〉.Repeat([ - { - a: { - b: 〈3;c〉 - } - }, - ], 3) - c: 〈0;a〉 - } - closeFail: { - #T: { - [_]: _ - } - #T: close({ - a: string - }) - x: 〈0;#T〉 - x: { - b: "foo" - } - } - printCycle: { - a: { - X: 〈1;a〉 - if 〈0;X〉 {} - } - } -} ---- self.cue -{ - issue3978: { - a: { - if (〈1〉.missing != _|_(explicit error (_|_ literal) in source)) {} - } - } -} diff --git a/cue/testdata/cycle/expression.txtar b/cue/testdata/cycle/expression.txtar index 7b82cb603..010325468 100644 --- a/cue/testdata/cycle/expression.txtar +++ b/cue/testdata/cycle/expression.txtar @@ -121,106 +121,3 @@ Conjuncts: 168 Disjuncts: 0 NumCloseIDs: 34 --- out/compile -- ---- in.cue -{ - t1: { - a: { - a1: (〈0;a0〉 + 2) - b1: (〈0;a1〉 - 2) - a0: 〈0;X〉 - X: 〈0;b1〉 - X: 5.0 - } - } - t1: { - b: { - X: 5.0 - a1: (〈0;a0〉 + 2) - b1: (〈0;a1〉 - 2) - a0: 〈0;X〉 - X: 〈0;b1〉 - } - } - t1: { - c: { - a1: (〈0;a0〉 + 2) - b1: (〈0;a1〉 - 2) - X: 5.0 - a0: 〈0;X〉 - X: 〈0;b1〉 - } - } - t1: { - c: { - b1: (〈0;a1〉 - 2) - a1: (〈0;a0〉 + 2) - X: 5.0 - a0: 〈0;X〉 - X: 〈0;b1〉 - } - } - t1: { - c: { - b1: (〈0;a1〉 - 2) - X: 5.0 - a1: (〈0;a0〉 + 2) - a0: 〈0;X〉 - X: 〈0;b1〉 - } - } - t1total: { - for _, v in 〈1;t1〉 { - 〈1;v〉 - } - } - t2: { - a: { - a0: 〈0;X〉 - a1: (〈0;a0〉 * 2) - Y: 〈0;a1〉 - b0: 〈0;Y〉 - b1: (〈0;b0〉 / 2) - X: 〈0;b1〉 - X: 5.0 - } - } - t2: { - b: { - b0: 〈0;Y〉 - b1: (〈0;b0〉 / 2) - X: 〈0;b1〉 - a0: 〈0;X〉 - a1: (〈0;a0〉 * 2) - Y: 〈0;a1〉 - X: 5.0 - } - } - t2: { - c: { - b0: 〈0;Y〉 - b1: (〈0;b0〉 / 2) - X: 〈0;b1〉 - X: 5.0 - a0: 〈0;X〉 - a1: (〈0;a0〉 * 2) - Y: 〈0;a1〉 - } - } - t2: { - d: { - b0: 〈0;Y〉 - b1: (〈0;b0〉 / 2) - X: 〈0;b1〉 - a0: 〈0;X〉 - a1: (〈0;a0〉 * 2) - Y: 〈0;a1〉 - X: 5.0 - } - } - t2total: { - for _, v in 〈1;t2〉 { - 〈1;v〉 - } - } -} diff --git a/cue/testdata/cycle/freeze.txtar b/cue/testdata/cycle/freeze.txtar index c6025a1ae..d0570b577 100644 --- a/cue/testdata/cycle/freeze.txtar +++ b/cue/testdata/cycle/freeze.txtar @@ -125,147 +125,3 @@ Conjuncts: 193 Disjuncts: 0 NumCloseIDs: 54 --- out/compile -- ---- comprehension.cue -{ - comprehension: { - t1: _ - } - comprehension: { - t1: { - ok: { - x: { - y: {} - } - for _, _ in 〈0;x〉 { - if true { - x: { - z: { - a: {} - } - } - } - } - if true { - if true { - x: { - z: { - a: {} - } - } - } - } - } - } - } - comprehension: { - t2: { - err: { - a: { - x: 1 - for k, v in 〈1;a〉 { - (〈1;k〉 + "q"): 〈1;v〉 - } - } - } - } - } - comprehension: { - t3: { - err: { - a: { - x: 1 - } - b: { - y: 1 - } - a: { - for k, v in 〈1;b〉 { - (〈1;k〉 + "q"): 〈1;v〉 - } - } - b: { - for k, v in 〈1;a〉 { - 〈1;k〉: 〈1;v〉 - } - } - } - } - } - comprehension: { - t4: { - ok: { - x: { - y: {} - } - for _, _ in 〈0;x〉 { - if true { - x: { - y: { - a: {} - } - } - } - } - } - } - } - comprehension: { - moreSpecific: { - ok: { - a: { - x: int - for k, v in 〈1;a〉 { - 〈1;k〉: 1 - } - } - } - } - } - comprehension: { - moreSpecific: { - err: { - a: { - x: { - y: 1 - } - for k, v in 〈1;a〉 if (len(〈0;v〉) > 0) { - 〈1;k〉: { - z: 1 - } - } - } - } - } - } -} ---- in.cue -{ - freezing: { - t1: { - ok: { - #a: { - x: "a" - } - len(〈0;#a〉) - } - } - } -} ---- issue3178.cue -{ - issue3178: { - input: [ - "Value", - ] - output: { - ... - } - for _, name in 〈0;input〉 { - output: { - "\(〈2;name〉)": true - } - } - for name, v in 〈0;output〉 {} - } -} diff --git a/cue/testdata/cycle/inline.txtar b/cue/testdata/cycle/inline.txtar index e5d155ce3..52f9e3be2 100644 --- a/cue/testdata/cycle/inline.txtar +++ b/cue/testdata/cycle/inline.txtar @@ -261,249 +261,3 @@ Conjuncts: 623 Disjuncts: 0 NumCloseIDs: 202 --- out/compile -- ---- inlineexpand.cue -{ - inlined: { - X: { - input: { - a: _ - } - output: 〈0;input〉.a - } - root: { - a: (〈1;X〉 & { - input: 〈2;root〉 - }).output - } - } - expanded1: { - hasCycle: { - X: { - input: { - a: _ - } - output: 〈0;input〉.a - } - root: { - a: 〈0;_a〉.output - _a: (〈1;X〉 & { - input: 〈2;root〉 - }) - } - } - } - expanded2: { - noCycle: { - X: { - input: { - a: _ - } - output: 〈0;input〉.a - } - root: { - a: 〈1;_a〉.output - } - _a: (〈0;X〉 & { - input: 〈1;root〉 - }) - } - } - issue3731: { - reduced: { - #lookup: { - input: { - ... - } - output: [ - for _, v in 〈1;input〉 if (〈0;v〉.show != _|_(explicit error (_|_ literal) in source)) { - 〈1;v〉 - }, - ] - } - root: { - self: { - show: true - } - others: (〈1;#lookup〉 & { - input: 〈2;root〉 - }).output - } - } - } - issue3731: { - expanded: { - #lookup: { - input: { - ... - } - output: [ - for _, v in 〈1;input〉 if (〈0;v〉.show != _|_(explicit error (_|_ literal) in source)) { - 〈1;v〉 - }, - ] - } - root: { - self: { - show: true - } - others: 〈0;_others〉.output - _others: (〈1;#lookup〉 & { - input: 〈2;root〉 - }) - } - } - } - issue3731: { - full: { - #Workspace: { - workspaceA?: {} - workspaceB?: {} - } - #AccountConfig: { - workspaces: 〈1;#Workspace〉 - siblings?: [ - ...string, - ] - } - #AccountConfigSub1: { - 〈1;#AccountConfig〉 - workspaces: { - workspaceA: {} - } - } - #AccountConfigSub2: { - 〈1;#AccountConfig〉 - workspaces: { - workspaceB: {} - } - } - tree: { - env1: { - region1: { - "env1-r1-account-sub1": 〈3;#AccountConfigSub1〉 - "env1-r1-account-sub2-1": 〈3;#AccountConfigSub2〉 - } - } - } - #lookupSiblings: { - envtree: { - ... - } - out: [ - for region, v in 〈1;envtree〉 for account, config in 〈0;v〉 if (〈0;config〉.workspaces.workspaceB != _|_(explicit error (_|_ literal) in source)) { - 〈1;account〉 - }, - ] - } - tree: { - env1: { - [_]: { - [_]: (〈3;#AccountConfig〉 & { - siblings: (〈4;#lookupSiblings〉 & { - envtree: 〈4;env1〉 - }).out - }) - } - } - } - } - } -} ---- x.cue -{ - inline: { - small: { - f: { - n: int - out: (〈1;f〉 & { - n: (〈1;n〉 - 1) - }).out - } - } - } - inline: { - medium: { - f2: (〈0;f〉 & { - n: 2 - }).out - fRec: { - nn: int - out: (〈1;f〉 & { - n: 〈1;nn〉 - }).out - } - f: { - n: int - out: (〈1;fRec〉 & { - nn: (〈1;n〉 - 1) - }).out - } - } - } - inline: { - patterns: { - f: { - n: (〈1;f〉 & { - n: {} - }).n - } - f: { - n: {} - } - [string]: { - n: {} - } - f: { - [string]: {} - } - f: {} - } - } - inline: { - acrossFields: { - fail1: { - f: { - in: number - out: (〈0;in〉 + 1) - } - k00: 0 - k10: (〈0;f〉 & { - in: 〈1;k00〉 - }).out - k20: (〈0;f〉 & { - in: 〈1;k10〉 - }).out - k30: (〈0;f〉 & { - in: 〈1;k20〉 - }).out - k10: (〈0;f〉 & { - in: 〈1;k30〉 - }).out - } - } - } - inline: { - acrossFields: { - ok1: { - f: { - in: number - out: 〈0;in〉 - } - k00: 0 - k10: (〈0;f〉 & { - in: 〈1;k00〉 - }).out - k20: (〈0;f〉 & { - in: 〈1;k10〉 - }).out - k30: (〈0;f〉 & { - in: 〈1;k20〉 - }).out - k10: (〈0;f〉 & { - in: 〈1;k30〉 - }).out - } - } - } -} diff --git a/cue/testdata/cycle/inline_non_recursive.txtar b/cue/testdata/cycle/inline_non_recursive.txtar index 9bd8a4570..1d4a4d4db 100644 --- a/cue/testdata/cycle/inline_non_recursive.txtar +++ b/cue/testdata/cycle/inline_non_recursive.txtar @@ -188,187 +188,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 169 --- out/compile -- ---- in.cue -{ - ok1: { - f: { - in: number - out: 〈0;in〉 - } - k00: 0 - k10: (〈0;f〉 & { - in: 〈1;k00〉 - }).out - k20: (〈0;f〉 & { - in: 〈1;k10〉 - }).out - k30: (〈0;f〉 & { - in: 〈1;k20〉 - }).out - } - ok2: { - f: { - in: number - out: 〈0;in〉 - } - k00: 0 - k10: { - (〈1;f〉 & { - in: 〈2;k00〉 - }).out - } - k20: { - (〈1;f〉 & { - in: 〈2;k10〉 - }).out - } - k30: { - (〈1;f〉 & { - in: 〈2;k20〉 - }).out - } - } - ok3: { - f: { - in: number - out: 〈0;in〉 - } - k00: 0 - k10: { - close((〈1;f〉 & { - in: 〈2;k00〉 - })).out - } - k20: { - close((〈1;f〉 & { - in: 〈2;k10〉 - })).out - } - k30: { - close((〈1;f〉 & { - in: 〈2;k20〉 - })).out - } - } - ok4: { - f: { - in: number - out: 〈0;in〉 - } - k00: 0 - k10: { - out: { - (〈2;f〉 & { - in: 〈3;k00〉 - }).out - } - }.out - k20: { - out: { - (〈2;f〉 & { - in: 〈3;k10〉 - }).out - } - }.out - k30: { - out: { - (〈2;f〉 & { - in: 〈3;k20〉 - }).out - } - }.out - } - issue1708: { - #add10: { - in: number - a10: { - i: 〈1;in〉 - o: (〈0;i〉 + 10) - } - out: 〈0;a10〉.o - } - k00: 0 - k10: (〈0;#add10〉 & { - in: 〈1;k00〉 - }).out - k20: (〈0;#add10〉 & { - in: 〈1;k10〉 - }).out - k30: (〈0;#add10〉 & { - in: 〈1;k20〉 - }).out - } -} ---- issue3182.cue -{ - issue3182: { - first: { - t1: { - x: { - a: 〈1;x〉 - }.a - } - } - first: { - t2: { - x: { - a: { - b: 〈2;x〉 - } - }.a - } - } - second: { - { - t: 〈1;x〉 - }.t.y - x: { - y: { - x: { - y: { - a: 1 - } - } - } - } - } - third: { - { - p: { - x: 〈1;p〉 - y: 1 - } - }.p.x.y - } - } -} ---- select.cue -{ - select: { - direct: { - #Step: (〈0;#Job〉 & { - opt: _ - }).opt - #Job: matchN(1, [ - 〈3;#NormalJob〉, - ]) - } - } - select: { - indirect: { - #Step: 〈0;#Job〉.opt - #Job: (matchN(1, [ - 〈3;#NormalJob〉, - ]) & { - opt: _ - }) - } - } - #NormalJob: { - req!: int - opt?: { - run?: string - } - } -} diff --git a/cue/testdata/cycle/issue1960.txtar b/cue/testdata/cycle/issue1960.txtar index 1625809fb..e07ff8c9d 100644 --- a/cue/testdata/cycle/issue1960.txtar +++ b/cue/testdata/cycle/issue1960.txtar @@ -77,101 +77,3 @@ t3: { -- out/evalalpha -- t2.z.hello: unreferenced alias or let clause q: ./issue1960.cue:18:3 --- out/compile -- -t2.z.hello: unreferenced alias or let clause q: - ./issue1960.cue:18:3 ---- issue1960.cue -{ - t1: { - z: { - blah: { - s: [ - for _, z in 〈3;z〉 {}, - ] - } - } - z: { - hello: { - for _, x in 〈0;p〉 {} - let q#1 = 〈2;z〉.blah - p: 〈0;let q#1〉.r - p: { - t: 1 - } - } - } - } - t2: { - z: { - blah: { - s: [ - for _, z in 〈3;z〉 {}, - ] - } - } - z: { - hello: { - for _, x in 〈0;p〉 {} - let q#2 = 〈2;z〉.blah - p: { - t: 1 - } - } - } - } - t3: { - #z: { - n: string - p: { - t: "e" - } - s: [ - ...string, - ] - _p: { - n: string - e: { - p: {} - } - } - r: 〈0;_p〉[〈0;p〉.t] - for _, pl in 〈0;r〉.p { - if 〈1;pl〉.blah {} - } - } - #i: { - 〈1;#z〉 - t: "i" - r: { - e: {} - } - } - #c: { - 〈1;#z〉 - t: "c" - n: string - } - z: { - [=~"^b"]: (〈1;#i〉 & { - s: [ - for n, z in 〈3;z〉 if (〈0;z〉.t == "c") if (〈0;z〉.n == 〈3;-〉) { - 〈1;n〉 - }, - ] - }) - } - z: { - [=~"^h"]: (〈1;#c〉 & { - n: string - let q#3 = 〈2;z〉[〈0;n〉] - p: 〈0;let q#3〉.r.e - }) - } - z: { - blah: {} - hello: { - n: "blah" - } - } - } -} diff --git a/cue/testdata/cycle/issue241.txtar b/cue/testdata/cycle/issue241.txtar index b343cbc0f..dacd84bea 100644 --- a/cue/testdata/cycle/issue241.txtar +++ b/cue/testdata/cycle/issue241.txtar @@ -44,38 +44,3 @@ Conjuncts: 66 Disjuncts: 32 NumCloseIDs: 4 --- out/compile -- ---- in.cue -{ - #Value: (0|1) - foo: 〈0;#Value〉 - foo: !=〈0;bar〉 - bar: 〈0;#Value〉 - bar: !=〈0;foo〉 - #Value: (0|1) - Foo: 〈0;#Value〉 - Foo: !=〈0;Bar〉 - Bar: 〈0;#Value〉 - Bar: !=〈0;Foo〉 - Bar: 0 - cell: { - a: (0|1) - } - cell: { - a: !=〈1;cell〉.b - } - cell: { - b: (0|1) - } - cell: { - b: !=〈1;cell〉.a - } - cell: { - a: 0 - } - cell: { - b: _ - } - a: 〈0;cell〉.a - b: 〈0;cell〉.b -} diff --git a/cue/testdata/cycle/issue242.txtar b/cue/testdata/cycle/issue242.txtar index c271a3738..9f8731df0 100644 --- a/cue/testdata/cycle/issue242.txtar +++ b/cue/testdata/cycle/issue242.txtar @@ -108,201 +108,3 @@ Conjuncts: 191 Disjuncts: 52 NumCloseIDs: 8 --- out/compile -- ---- in.cue -{ - #size: 2 - #CellValue: (0|1|2|3) - cell: { - "0": { - "0": 〈2;#CellValue〉 - } - } - cell: { - "0": { - "0": !=〈2;cell〉["0"]["1"] - } - } - cell: { - "0": { - "0": !=〈2;cell〉["1"]["0"] - } - } - cell: { - "0": { - "0": !=〈2;cell〉["1"]["1"] - } - } - cell: { - "0": { - "1": 〈2;#CellValue〉 - } - } - cell: { - "0": { - "1": !=〈2;cell〉["0"]["0"] - } - } - cell: { - "0": { - "1": !=〈2;cell〉["1"]["0"] - } - } - cell: { - "0": { - "1": !=〈2;cell〉["1"]["1"] - } - } - cell: { - "1": { - "0": 〈2;#CellValue〉 - } - } - cell: { - "1": { - "0": !=〈2;cell〉["0"]["0"] - } - } - cell: { - "1": { - "0": !=〈2;cell〉["0"]["1"] - } - } - cell: { - "1": { - "0": !=〈2;cell〉["1"]["1"] - } - } - cell: { - "1": { - "1": 〈2;#CellValue〉 - } - } - cell: { - "1": { - "1": !=〈2;cell〉["0"]["0"] - } - } - cell: { - "1": { - "1": !=〈2;cell〉["0"]["1"] - } - } - cell: { - "1": { - "1": !=〈2;cell〉["1"]["0"] - } - } - cell: { - "0": { - "0": 0 - } - } - cell: { - "0": { - "1": 1 - } - } - cell: { - "1": { - "0": 2 - } - } - cell: { - "1": { - "1": 3 - } - } - cell2: { - a: (0|1) - } - cell2: { - a: !=〈1;cell2〉.b - } - cell2: { - b: (0|1) - } - cell2: { - b: !=〈1;cell2〉.a - } - cell2: { - a: _ - } - cell2: { - b: 1 - } - cell3: { - a: (0|1) - } - cell3: { - a: !=〈1;cell3〉.b - } - cell3: { - b: (0|1) - } - cell3: { - b: !=〈1;cell3〉.a - } - cell3: { - a: 0 - } - cell3: { - b: _ - } - cell4: { - a: (0|1) - } - cell4: { - a: !=〈1;cell4〉.b - } - cell4: { - b: (0|1) - } - cell4: { - b: !=〈1;cell4〉.a - } - cell4: { - b: _ - } - cell4: { - a: 0 - } - cell5: { - b: (0|1) - } - cell5: { - b: !=〈1;cell5〉.a - } - cell5: { - a: (0|1) - } - cell5: { - a: !=〈1;cell5〉.b - } - cell5: { - b: _ - } - cell5: { - a: 0 - } - a: 〈0;#CellValue〉 - a: !=〈0;b〉 - a: !=〈0;c〉 - a: !=〈0;d〉 - b: 〈0;#CellValue〉 - b: !=〈0;a〉 - b: !=〈0;c〉 - b: !=〈0;d〉 - c: 〈0;#CellValue〉 - c: !=〈0;a〉 - c: !=〈0;b〉 - c: !=〈0;d〉 - d: 〈0;#CellValue〉 - d: !=〈0;a〉 - d: !=〈0;b〉 - d: !=〈0;c〉 - a: 0 - b: 1 - c: 2 - d: 3 -} diff --git a/cue/testdata/cycle/issue2526.txtar b/cue/testdata/cycle/issue2526.txtar index 088aff2b7..3e9444978 100644 --- a/cue/testdata/cycle/issue2526.txtar +++ b/cue/testdata/cycle/issue2526.txtar @@ -10,12 +10,3 @@ x: { @test(err, code=structural_cycle, path=x.y, contains="structural cycle", pos=[]) -- out/errors.txt -- [structural_cycle] x.y: structural cycle --- out/compile -- ---- in.cue -{ - 〈0;x〉 - x: { - 〈0;y〉 - y: 〈1;x〉 - } -} \ No newline at end of file diff --git a/cue/testdata/cycle/issue306.txtar b/cue/testdata/cycle/issue306.txtar index 4ee753451..462fcf778 100644 --- a/cue/testdata/cycle/issue306.txtar +++ b/cue/testdata/cycle/issue306.txtar @@ -18,13 +18,3 @@ Retain: 0 Unifications: 5 Conjuncts: 5 Disjuncts: 0 --- out/compile -- ---- in.cue -{ - a: 12 - #Controller: { - settings: { - controller: 〈2;#Controller〉 - } - } -} diff --git a/cue/testdata/cycle/issue3118.txtar b/cue/testdata/cycle/issue3118.txtar index 1de60a72e..8f2643ec3 100644 --- a/cue/testdata/cycle/issue3118.txtar +++ b/cue/testdata/cycle/issue3118.txtar @@ -112,35 +112,3 @@ Conjuncts: 47 Disjuncts: 0 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - #TimeSpan: { - start: float - duration: float - end: float - start: (〈0;end〉 - 〈0;duration〉) - duration: (〈0;end〉 - 〈0;start〉) - end: (〈0;start〉 + 〈0;duration〉) - start: <=〈0;end〉 - } - examples: { - [string]: 〈1;#TimeSpan〉 - } - examples: { - eg1: { - start: 10.0 - duration: 2.1 - } - } - examples: { - eg2: { - start: 10.0 - } - } - examples: { - eg3: { - end: 10.0 - } - } -} diff --git a/cue/testdata/cycle/issue3527.txtar b/cue/testdata/cycle/issue3527.txtar index 1eb03a58a..ee2b8eafa 100644 --- a/cue/testdata/cycle/issue3527.txtar +++ b/cue/testdata/cycle/issue3527.txtar @@ -237,35 +237,3 @@ diff old new self?: (_){ _ } } } --- out/compile -- ---- in.cue -{ - _taxPayer(:p): { - self: {} - } - let sam#1 = { - taxPayer: 〈1;_taxPayer(:p)〉 - } - assert: { - invoke: 〈1;let sam#1〉 - invoke: _ - res: (〈1;subject〉 & { - in: 〈1;invoke〉 - }) - } - subject: { - in: 〈1;#ReturnData〉 - _computed(:p): (〈1;#computeF1040〉 & { - in: 〈1;in〉 - }) - } - #computeF1040: { - in: 〈1;#ReturnData〉 - } - #ReturnData: { - taxPayer?: 〈1;#TaxPayer〉 - } - #TaxPayer: { - self?: _ - } -} diff --git a/cue/testdata/cycle/issue3570.txtar b/cue/testdata/cycle/issue3570.txtar index 10bbf1699..24219aee9 100644 --- a/cue/testdata/cycle/issue3570.txtar +++ b/cue/testdata/cycle/issue3570.txtar @@ -16,12 +16,3 @@ conflicting values {foo:{foo:(25|44)},foo,foo:foo} and 44 (mismatched types stru ./in.cue:2:1 2 errors in empty disjunction:: ./in.cue:3:6 --- out/compile -- ---- in.cue -{ - foo: { - foo: (25|44) - } - 〈0;foo〉 - foo: 〈0;foo〉 -} diff --git a/cue/testdata/cycle/issue3571.txtar b/cue/testdata/cycle/issue3571.txtar index 03a42c6da..eca89f008 100644 --- a/cue/testdata/cycle/issue3571.txtar +++ b/cue/testdata/cycle/issue3571.txtar @@ -76,51 +76,3 @@ underlying vertex. Specifically, in `simplified`, v2 expands `in` and `x` with their full #T contents, while v3 represents them as ~(simplified.#T). Similarly in `issue3571.a`, v2 expands `in` and `#in` fully, while v3 uses shared references like ~(issue3571.a.in.g.#in) and ~(issue3571.a.#in.g.#in). --- out/compile -- ---- in.cue -{ - simplified: { - 〈0;#T〉 - in: _ - x: 〈0;#T〉 - x: { - x: 〈1;#T〉 - } - #T: { - in: 〈0;x〉 - x: _ - } - } - issue3571: { - a: 〈0;#T〉 - a: { - in: { - f: true - } - } - a: { - #in: { - g: 〈2;#T〉 - g: { - #in: { - f: 〈4;#T〉 - } - } - g: { - #in: { - f: { - #in: { - x: true - } - } - } - } - f?: _ - } - } - #T: { - in: 〈0;#in〉 - #in: _ - } - } -} diff --git a/cue/testdata/cycle/issue3827.txtar b/cue/testdata/cycle/issue3827.txtar index b560d6994..06f1cdf42 100644 --- a/cue/testdata/cycle/issue3827.txtar +++ b/cue/testdata/cycle/issue3827.txtar @@ -50,41 +50,3 @@ Disjuncts: 4 Notifications: 2 NumCloseIDs: 7 --- out/compile -- ---- in.cue -{ - reduced: { - A: { - b: (〈1;A〉.c & {}).x - } - A: (null|{ - c: { - x: 1 - } - }) - } - full: { - out: (〈0;#Workflow〉.#Step & { - uses: "actions/upload-artifact@v3" - with: { - name: "foo" - path: "bar" - } - }) - #Workflow: { - #Step: (〈1;#Workflow〉.steps & { - x: {} - }).x - } - #Workflow: (null|{ - steps: { - [string]: { - uses?: string - with?: { - [string]: string - } - } - } - }) - } -} diff --git a/cue/testdata/cycle/issue4203.txtar b/cue/testdata/cycle/issue4203.txtar index e021688ce..dc51b109d 100644 --- a/cue/testdata/cycle/issue4203.txtar +++ b/cue/testdata/cycle/issue4203.txtar @@ -49,43 +49,3 @@ if true { variable: "{kind1}" }] }) --- out/compile -- ---- in.cue -{ - _listBuilder: { - kind: "kind1" - _deps: [ - ..., - ] - _kindJoin: { - _objs: [ - ..., - ] - _out: 〈import;strings〉.Join([ - for _, d in 〈1;_objs〉 { - 〈1;d〉.kind - }, - ], ",") - } - _depKinds: { - (〈1;_kindJoin〉 & { - _objs: 〈2;_deps〉 - }) - }._out - variable: (("{" + 〈0;_depKinds〉) + "}") - } - output: _ - if true { - _input: [ - { - 〈3;_listBuilder〉 - _deps: [ - { - 〈5;_listBuilder〉 - }, - ] - }, - ] - output: 〈0;_input〉[0].variable - } -} diff --git a/cue/testdata/cycle/issue4210.txtar b/cue/testdata/cycle/issue4210.txtar index fc2a5d921..a1eb3f5fa 100644 --- a/cue/testdata/cycle/issue4210.txtar +++ b/cue/testdata/cycle/issue4210.txtar @@ -27,46 +27,3 @@ t4: { [structural_cycle] t2.a.b.c.c: structural cycle [structural_cycle] t3.a.b.c.d.d: structural cycle [structural_cycle] t4.x.y.z.z: structural cycle --- out/compile -- ---- in.cue -{ - t1: { - a: { - b: { - c: { - 〈3;a〉 - }.b - } - } - } - t2: { - a: { - b: { - c: { - (〈3;a〉 & _) - }.b - } - } - } - t3: { - a: { - b: { - c: { - d: { - 〈4;a〉.b - }.c - } - } - } - } - t4: { - x: { - y: { - z: { - 〈3;a〉 - }.y - } - } - a: 〈0;x〉 - } -} diff --git a/cue/testdata/cycle/issue4228.txtar b/cue/testdata/cycle/issue4228.txtar index e9c372ad9..c05435506 100644 --- a/cue/testdata/cycle/issue4228.txtar +++ b/cue/testdata/cycle/issue4228.txtar @@ -378,104 +378,3 @@ Result: } } -- out/eval -- --- out/compile -- ---- export.cue -{ - let _globalScope#1 = 〈1〉 - #export: { - #entries: [ - ..., - ] - manifests: [ - for _, _entry in 〈1;#entries〉 for _, _ns in 〈0;_entry(:main)〉 for _kind, _objs in 〈0;_ns(:main)〉 for _name, _obj in 〈0;_objs(:main)〉 { - 〈1;_obj(:main)〉.k8s - }, - ] - yamlStream: 〈import;"encoding/yaml"〉.MarshalStream(〈0;manifests〉) - } - #manifests: { - 〈1;#export〉 - #entries: [ - 〈2;let _globalScope#1〉, - ] - }.yamlStream -} ---- in.cue -{ - _objectBase(:main): { - name: string - k8s: { - metadata: { - name: 〈3〉.name - } - } - } - _namespacedResource(:main): { - 〈1;_objectBase(:main)〉 - namespace: string - k8s: { - metadata: { - namespace: 〈3〉.namespace - } - } - } - _allValuesAreValidStructs(:main): { - [_]: { - (*{}|error("<- invalid \(〈1〉)")) - } - } - _setTypeMeta(:main): { - #apiVersion!: string - #kind!: string - #template: { - k8s: { - apiVersion: 〈3〉.#apiVersion - kind: 〈3〉.#kind - } - } - } - _resourceKindsBase(:main): { - _base(:main)!: _ - [string]: { - 〈2;_allValuesAreValidStructs(:main)〉 - 〈2;_setTypeMeta(:main)〉 - #resourceSchema: _ - #template: { - 〈2;_base(:main)〉 - k8s: 〈1;#resourceSchema〉 - } - [_]: 〈0;#template〉 - } - } - _namespacedResourceKinds(:main): { - 〈1;_resourceKindsBase(:main)〉 - _base(:main): 〈1;_namespacedResource(:main)〉 - [string]: { - [string]: { - namespace: string - } - } - app: { - #apiVersion: "argoproj.io/v1alpha1" - #kind: "Application" - #resourceSchema: { - spec?: { - revisionHistoryLimit?: int - } - } - #template: { - revisionHistoryLimit: (*3|int) - k8s: { - spec: { - revisionHistoryLimit: 〈3〉.revisionHistoryLimit - } - } - } - } - } - argocd: (〈0;_namespacedResourceKinds(:main)〉 & { - app: { - apps: {} - } - }) -} diff --git a/cue/testdata/cycle/issue4230.txtar b/cue/testdata/cycle/issue4230.txtar index b04c574ee..422a92cfd 100644 --- a/cue/testdata/cycle/issue4230.txtar +++ b/cue/testdata/cycle/issue4230.txtar @@ -21,28 +21,3 @@ x: X={ regions: ["west"] app: {region: "west"} }) --- out/compile -- ---- in.cue -{ - #transform: { - _input: { - ... - } - _output: [ - if (〈1;_input〉.app != _|_(explicit error (_|_ literal) in source)) { - 〈2;_input〉.app.region - }, - ] - } - x: { - regions: (〈1;#transform〉 & { - _input: 〈2〉 - })._output - app: { - region: (or([ - "west", - "east", - ]) & "west") - } - } -} diff --git a/cue/testdata/cycle/issue4244.txtar b/cue/testdata/cycle/issue4244.txtar index 12c3f5146..ba7e7e1c3 100644 --- a/cue/testdata/cycle/issue4244.txtar +++ b/cue/testdata/cycle/issue4244.txtar @@ -48,23 +48,3 @@ case2: #schema & { [incomplete] #schema.prefix: invalid interpolation: index out of range [0] with length 1: ./in.cue:8:12 ./in.cue:5:22 --- out/compile -- ---- in.cue -{ - #schema: { - let splits#1 = 〈import;strings〉.Split(〈0;id〉, "_never_") - let prefix#2 = 〈0;let splits#1〉[0] - #ID: =~"^\(〈0;let prefix#2〉)$" - #SubID: =~"^\(〈0;let prefix#2〉):sub$" - id: 〈0;#ID〉 - subid: 〈0;#SubID〉 - } - case1: (〈0;#schema〉 & { - id: "foo" - subid: "foo:sub" - }) - case2: (〈0;#schema〉 & { - subid: "foo:sub" - id: "foo" - }) -} diff --git a/cue/testdata/cycle/issue4253.txtar b/cue/testdata/cycle/issue4253.txtar index dd54161e8..d88ae7fa7 100644 --- a/cue/testdata/cycle/issue4253.txtar +++ b/cue/testdata/cycle/issue4253.txtar @@ -24,28 +24,3 @@ x: { gateway: whoami2: {} } @test(eq, at=gateway.whoami2, {foo: 1, k8s: {foo: 1}}) --- out/compile -- ---- in.cue -{ - x: { - #tmpl: { - let _self#1 = 〈1〉 - foo: 1 - k8s: { - foo: 〈1;let _self#1〉.foo - } - } - #allowed: =~"^[a-z0-9]+$" - [string]: { - [string]: { - 〈2;#tmpl〉 - if ((〈2;#allowed〉 & 〈1;-〉) == _|_(explicit error (_|_ literal) in source)) { - error("bad: \(〈2;-〉)") - } - } - } - gateway: { - whoami2: {} - } - } -} diff --git a/cue/testdata/cycle/issue429.txtar b/cue/testdata/cycle/issue429.txtar index e91cc1f4e..0fcb74153 100644 --- a/cue/testdata/cycle/issue429.txtar +++ b/cue/testdata/cycle/issue429.txtar @@ -123,51 +123,6 @@ er3.min: conflicting values 1 and 5: er3.min: invalid value 5 (out of bound <5): ./in.cue:46:7 ./in.cue:64:7 --- out/compile -- ---- in.cue -{ - #Size: { - res: (&(int, >=0)|*0) - min: (>〈0;res〉|*(1 + 〈0;res〉)) - max: (>〈0;min〉|*〈0;min〉) - } - s0: (〈0;#Size〉 & { - res: 1 - }) - s1: (〈0;#Size〉 & { - min: 5 - }) - s2: (〈0;#Size〉 & { - max: 5 - }) - s3: (〈0;#Size〉 & { - min: 5 - max: 10 - }) - es3: (〈0;#Size〉 & { - min: 10 - max: 5 - }) - #nonEmptyRange: { - min: (*1|int) - min: <〈0;max〉 - max: >〈0;min〉 - } - r1: (〈0;#nonEmptyRange〉 & { - min: 3 - }) - r2: (〈0;#nonEmptyRange〉 & { - max: 5 - }) - r3: (〈0;#nonEmptyRange〉 & { - min: 3 - max: 6 - }) - er3: (〈0;#nonEmptyRange〉 & { - min: 5 - max: 5 - }) -} -- out/eval/stats -- Leaks: 23 Freed: 75 diff --git a/cue/testdata/cycle/issue494.txtar b/cue/testdata/cycle/issue494.txtar index 54a5bc89f..3ef52c052 100644 --- a/cue/testdata/cycle/issue494.txtar +++ b/cue/testdata/cycle/issue494.txtar @@ -45,82 +45,3 @@ Retain: 0 Unifications: 36 Conjuncts: 59 Disjuncts: 0 --- out/compile -- ---- in.cue -{ - _Q: [ - { - pos: 0 - }, - { - pos: 1 - }, - ] - a: { - [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] - } - a: { - ben: [ - {}, - ] - } - b: { - [string]: 〈1;_Q〉[0:1] - } - b: { - ben: [ - {}, - ] - } - c: { - [string]: [ - ...{ - l: len(〈3;a〉[〈2;-〉]) - }, - ] - } - c: { - ben: [ - {}, - ] - } - #d: { - [string]: ([ - ...{ - pos: &(int, >=0) - }, - ] & 〈1;_Q〉[0:len(〈1;#d〉[〈0;-〉])]) - } - #d: { - ben: [ - {}, - ] - } - d: 〈0;#d〉 - e: { - [string]: 〈1;_Q〉[0:(len(〈1;a〉[〈0;-〉]) + 1)] - } - e: { - ben: [ - {}, - ..., - ] - } - f: { - [string]: 〈1;_Q〉[0:(len(〈1;a〉[〈0;-〉]) + 1)] - } - f: { - ben: [ - {}, - ] - } - g: { - [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] - } - g: { - ben: [ - {}, - {}, - ] - } -} diff --git a/cue/testdata/cycle/issue502.txtar b/cue/testdata/cycle/issue502.txtar index f75621701..746b4aa43 100644 --- a/cue/testdata/cycle/issue502.txtar +++ b/cue/testdata/cycle/issue502.txtar @@ -105,86 +105,3 @@ NumCloseIDs: 45 -- out/errors.txt -- [structural_cycle] reduced.t1.#T.x.y.z.x.y.z: structural cycle [structural_cycle] reduced.t1.a.x.y.z.x.y.z.x.y.z: structural cycle --- out/compile -- ---- in.cue -{ - #T: { - config: _ - body: _ - mas: { - [string]: { - cfg: _ - _link: 〈3;#T〉 - link: (〈0;_link〉 & { - config: 〈1;cfg〉 - }) - } - } - } - #a: (〈0;#T〉 & { - config: { - a: int - } - body: 〈0;config〉.a - mas: { - one: { - cfg: { - b: 〈3;config〉.a - } - _link: { - config: { - b: int - } - body: 〈0;config〉.b - mas: { - two: { - cfg: { - c: 〈3;config〉.b - } - _link: { - config: { - c: int - } - body: 〈0;config〉.c - } - } - } - } - } - } - }) - a: (〈0;#a〉 & { - config: { - a: 34 - } - }) -} ---- reduced.cue -{ - reduced: { - t1: { - #T: { - x: { - y?: { - V: _ - z: ((〈3;#T〉 & 〈0;V〉) & {}) - } - } - } - a: 〈0;#T〉 - a: { - x: { - y: { - V: { - x: { - y: { - V: {} - } - } - } - } - } - } - } - } -} diff --git a/cue/testdata/cycle/issue990.txtar b/cue/testdata/cycle/issue990.txtar index 07d660a6a..eb69d456d 100644 --- a/cue/testdata/cycle/issue990.txtar +++ b/cue/testdata/cycle/issue990.txtar @@ -205,98 +205,3 @@ ConjunctInfos: 1021 MaxConjunctInfos: 6 MaxReqSets: 19 MaxRedirect: 4 --- out/compile -- ---- in.cue -{ - #AC: { - k: "simple" - d: 〈1;#C〉 - } - #AS: { - k: "complex" - d: 〈1;#S〉 - } - #R: { - a: (〈1;#AC〉|〈1;#AS〉) - } - #S: { - n: string - r: { - [string]: 〈2;#R〉 - } - } - #C: { - n: string - } - #sub: { - #p: 〈1;#AS〉 - dict: { - [string]: _ - } - for rn, rd in 〈0;#p〉.d.r if (〈0;rd〉.a.k == "complex") { - let subs#1multi = (〈3;#sub〉 & { - #p: 〈2;rd〉.a - }) - for sn, sd in 〈0;let subs#1〉.dict { - dict: { - "\(〈4;rn〉)_\(〈2;sn〉)": 〈2;sd〉 - } - } - } - for rn, rd in 〈0;#p〉.d.r if (〈0;rd〉.a.k == "simple") { - dict: { - "\(〈2;rn〉)": 〈2;rd〉 - } - } - } - _test: { - c1: 〈1;#AC〉 - c1: { - d: { - n: "c1" - } - } - s3: 〈1;#AS〉 - s3: { - d: { - n: "s3" - r: { - r1: { - a: 〈4;c1〉 - } - } - } - } - s2: 〈1;#AS〉 - s2: { - d: { - n: "s2" - r: { - r1: { - a: 〈4;c1〉 - } - r2: { - a: 〈4;s3〉 - } - } - } - } - s1: 〈1;#AS〉 - s1: { - d: { - n: "s1" - r: { - r1: { - a: 〈4;c1〉 - } - r2: { - a: 〈4;s2〉 - } - } - } - } - } - out: (〈0;#sub〉 & { - #p: 〈1;_test〉.s1 - }) -} diff --git a/cue/testdata/cycle/patterns.txtar b/cue/testdata/cycle/patterns.txtar index 3404f58c1..cc8d06e2c 100644 --- a/cue/testdata/cycle/patterns.txtar +++ b/cue/testdata/cycle/patterns.txtar @@ -40,37 +40,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 7 --- out/compile -- ---- in.cue -{ - [!~"^[.]"]: 〈0;c〉 - a: 〈0;b〉 - b: { - [string]: int - } - c: { - a: int - } - [string]: 〈0;c〉 - a: 〈0;b〉 - b: { - [string]: int - } - c: { - a: int - } -} ---- issue3326.cue -{ - issue3326: { - _self: { - x: [ - ...and(〈1;x〉), - ] - } - 〈0;_self〉 - x: [ - 1, - ] - } -} diff --git a/cue/testdata/cycle/self.txtar b/cue/testdata/cycle/self.txtar index d4018963d..b939694e0 100644 --- a/cue/testdata/cycle/self.txtar +++ b/cue/testdata/cycle/self.txtar @@ -383,491 +383,3 @@ Conjuncts: 435 Disjuncts: 100 NumCloseIDs: 86 --- out/compile -- ---- in.cue -{ - expr: { - error1: { - a: 3 - a: (〈0;a〉 + 1) - } - } - expr: { - error2: { - a: (〈0;a〉 + 1) - a: 3 - } - } - listConcat: { - error1: { - a: [ - "1", - "2", - ] - a: 〈import;list〉.Concat([ - 〈1;a〉, - [ - "3", - ], - ]) - } - } - listConcat: { - error2: { - a: 〈import;list〉.Concat([ - [ - "3", - ], - 〈1;a〉, - ]) - a: [ - "1", - "2", - ] - } - } - selfEmbed: { - ok1: { - a: 〈0;x〉 - Y: 〈0;x〉 - x: { - 〈1;Y〉 - } - } - } - selfEmbed: { - ok2: { - Y: 〈0;x〉.b - a: 〈0;x〉 - x: { - b: { - 〈2;Y〉 - } - } - } - } - selfEmbed: { - ok3: { - Y: 〈0;x〉 - a: 〈0;x〉 - x: { - 〈1;Y〉 - } - } - } - selfEmbed: { - ok4: { - a: 〈0;x〉 - x: { - 〈1;Y〉 - } - Y: 〈0;x〉 - } - } - selfEmbed: { - ok5: { - x: { - 〈1;Y〉 - } - a: 〈0;x〉 - Y: 〈0;x〉 - } - } - selfEmbed: { - ok6: { - x: { - b: { - 〈2;Y〉 - } - } - Y: 〈0;x〉.b - a: 〈0;x〉 - } - } - disjSelf: { - ok1: { - #A: (string|〈0;#A〉) - x: 〈0;#A〉 - } - } - disjSelf: { - ok2: { - x: 〈0;#A〉 - #A: (string|〈0;#A〉) - } - } - disjSelf: { - ok3: { - #A: (〈0;#A〉|string) - x: 〈0;#A〉 - } - } - disjSelf: { - ok4: { - x: 〈0;#A〉 - #A: (〈0;#A〉|string) - } - } - disjEmbed: { - ok1: { - #A: (string|{ - 〈1;#A〉 - }) - x: 〈0;#A〉 - } - } - disjEmbed: { - ok2: { - x: 〈0;#A〉 - #A: (string|{ - 〈1;#A〉 - }) - } - } - disjEmbed: { - ok3: { - #A: ({ - 〈1;#A〉 - }|string) - x: 〈0;#A〉 - } - } - disjEmbed: { - ok4: { - x: 〈0;#A〉 - #A: ({ - 〈1;#A〉 - }|string) - } - } - disjList: _ - disjList: { - ok1: { - #A: (string|[ - 〈1;#A〉, - ]) - x: 〈0;#A〉 - y: 〈0;x〉 - y: [ - [ - [ - [ - string, - ], - ], - ], - ] - } - } - disjList: { - ok2: { - x: 〈0;#A〉 - #A: (string|[ - 〈1;#A〉, - ]) - } - } - disjList: { - ok3: { - #A: ([ - 〈1;#A〉, - ]|string) - x: 〈0;#A〉 - } - } - disjList: { - ok4: { - x: 〈0;#A〉 - #A: ([ - 〈1;#A〉, - ]|string) - } - } -} ---- old.cue -{ - name: "foo" - dynamicSelf: { - ok1: { - 〈2;name〉: (string|〈0;(〈2;name〉)〉) - x: 〈0;(〈2;name〉)〉 - } - } - dynamicSelf: { - ok2: { - x: 〈0;(〈2;name〉)〉 - 〈2;name〉: (string|〈0;(〈2;name〉)〉) - } - } - dynamicSelf: { - ok3: { - 〈2;name〉: (〈0;(〈2;name〉)〉|string) - x: 〈0;(〈2;name〉)〉 - } - } - dynamicSelf: { - ok4: { - x: 〈0;(〈2;name〉)〉 - 〈2;name〉: (〈0;(〈2;name〉)〉|string) - } - } - dynamicEmbed: { - ok1: { - 〈2;name〉: (string|{ - 〈1;(〈2;name〉)〉 - }) - x: 〈0;(〈2;name〉)〉 - } - } - dynamicEmbed: { - ok2: { - x: 〈0;(〈2;name〉)〉 - 〈2;name〉: (string|{ - 〈1;(〈2;name〉)〉 - }) - } - } - dynamicEmbed: { - ok3: { - 〈2;name〉: ({ - 〈1;(〈2;name〉)〉 - }|string) - x: 〈0;(〈2;name〉)〉 - } - } - dynamicEmbed: { - ok4: { - x: 〈0;(〈2;name〉)〉 - 〈2;name〉: ({ - 〈1;(〈2;name〉)〉 - }|string) - } - } - dynamicList: _ - dynamicList: { - ok1: { - 〈2;name〉: (string|[ - 〈1;(〈2;name〉)〉, - ]) - x: 〈0;(〈2;name〉)〉 - y: 〈0;x〉 - y: [ - [ - [ - [ - string, - ], - ], - ], - ] - } - } - dynamicList: { - ok2: { - x: 〈0;(〈2;name〉)〉 - 〈2;name〉: (string|[ - 〈1;(〈2;name〉)〉, - ]) - } - } - dynamicList: { - ok3: { - 〈2;name〉: ([ - 〈1;(〈2;name〉)〉, - ]|string) - x: 〈0;(〈2;name〉)〉 - } - } - dynamicList: { - ok4: { - x: 〈0;(〈2;name〉)〉 - 〈2;name〉: ([ - 〈1;(〈2;name〉)〉, - ]|string) - } - } - dynamicPatternSelf: { - ok1: { - [string]: (string|〈0;(〈0;-〉)〉) - } - } - dynamicPatternSelf: { - ok2: { - [string]: (〈0;(〈0;-〉)〉|string) - } - } - dynamicPatternEmbed: { - ok1: { - [string]: (string|{ - 〈1;(〈0;-〉)〉 - }) - } - } - dynamicPatternEmbed: { - ok2: { - [string]: ({ - 〈1;(〈0;-〉)〉 - }|string) - } - } - dynamicPatternList: { - ok1: { - [string]: (string|[ - 〈1;(〈0;-〉)〉, - ]) - } - } - dynamicPatternList: { - ok2: { - [string]: ([ - 〈1;(〈0;-〉)〉, - ]|string) - } - } - valueSelf: { - ok1: { - y: { - (string|〈1〉) - } - x: 〈0;y〉 - } - } - valueSelf: { - ok2: { - x: 〈0;y〉 - y: { - (string|〈1〉) - } - } - } - valueSelf: { - ok3: { - y: { - (〈1〉|string) - } - x: 〈0;y〉 - } - } - valueSelf: { - ok4: { - x: 〈0;y〉 - y: { - (〈1〉|string) - } - } - } - valueEmbed: { - ok1: { - y: { - (string|{ - 〈2〉 - }) - } - x: 〈0;y〉 - } - } - valueEmbed: { - ok2: { - x: 〈0;y〉 - y: { - (string|{ - 〈2〉 - }) - } - } - } - valueEmbed: { - ok3: { - y: { - ({ - 〈2〉 - }|string) - } - x: 〈0;y〉 - } - } - valueEmbed: { - ok4: { - x: 〈0;y〉 - y: { - ({ - 〈2〉 - }|string) - } - } - } - valueList: { - ok1: { - y: { - (string|[ - 〈2〉, - ]) - } - x: 〈0;y〉 - } - } - valueList: { - ok2: { - x: 〈0;y〉 - y: { - (string|[ - 〈2〉, - ]) - } - } - } - valueList: { - ok3: { - y: { - ([ - 〈2〉, - ]|string) - } - x: 〈0;y〉 - } - } - valueList: { - ok4: { - x: 〈0;y〉 - y: { - ([ - 〈2〉, - ]|string) - } - } - } - issue1729: { - t1: { - #x: { - (〈1;#x〉|{}) - } - x: (〈0;#x〉 & {}) - } - } - issue1729: { - t2: { - x: (〈0;#x〉 & {}) - #x: { - (〈1;#x〉|{}) - } - } - } -} ---- selfnew.cue -{ - issue4125: { - t1_self: { - let Root#1 = 〈1〉 - a: 〈0;let Root#1〉.a - } - } -} ---- selfold.cue -{ - issue4125: { - t2_alias: { - let Y#2 = 〈1〉 - b: 〈0;let Y#2〉.b - } - } -} diff --git a/cue/testdata/cycle/structural.txtar b/cue/testdata/cycle/structural.txtar index e5ffcf9b5..277e8c451 100644 --- a/cue/testdata/cycle/structural.txtar +++ b/cue/testdata/cycle/structural.txtar @@ -1004,838 +1004,3 @@ Conjuncts: 998 Disjuncts: 149 NumCloseIDs: 172 --- out/compile -- ---- edge.cue -{ - resolveToAncestor: { - t1: { - X: { - a: 〈0;b〉.a - b: 〈1;X〉 - } - } - t2: { - X: { - b: 〈1;X〉 - a: 〈0;b〉.a - } - } - } -} ---- in.cue -{ - a1: { - f: [ - 〈1;f〉, - ] - } - a2: { - f: 〈0;f〉 - } - a3: { - f: { - g: 〈1;f〉 - } - } - a4: { - a: [ - (〈1;a〉|int), - ] - } - a5: { - a: { - b: (〈1;a〉|int) - } - } - a6: { - a: (〈0;a〉|int) - } - a7: { - a: 〈0;c〉.x - b: { - x: 〈1;c〉 - y: "foo" - } - c: { - x: 〈1;b〉.y - y: 3 - } - } - b1: { - b: (〈0;a〉 & [ - 1, - ]) - a: [ - (〈1;a〉|int), - ] - } - b2: { - a: [ - (〈1;a〉|int), - ] - b: (〈0;a〉 & [ - 1, - ]) - } - b3: { - x: { - a: [ - (〈1;a〉|int), - ] - } - b: (〈0;x〉 & { - a: [ - 1, - ] - }) - } - b4: { - b: (〈0;x〉.y & [ - 1, - ]) - x: { - y: [ - 〈1;y〉, - ] - } - } - b4: { - cond1: { - b: (〈0;x〉.y & { - _z: false - [ - 1, - ] - }) - x: { - y: { - _z: (*true|bool) - if 〈0;_z〉 { - [ - 〈3;y〉, - ] - } - } - } - } - } - b4: { - cond2: { - x: { - y: { - _z: (*true|bool) - if 〈0;_z〉 { - [ - 〈3;y〉, - ] - } - } - } - b: (〈0;x〉.y & { - _z: false - [ - 1, - ] - }) - } - } - b5: { - b: (〈0;x〉.y & { - a: [ - 1, - ] - }) - x: { - y: { - a: [ - (〈1;a〉|int), - ] - } - } - } - b6: { - b: (〈0;x〉 & { - a: [ - 1, - ] - }) - x: { - a: [ - 〈1;a〉, - ] - } - } - b7: { - b: (〈0;a〉 & [ - [ - 1, - ], - ]) - a: [ - 〈1;a〉, - ] - } - b8: { - x: 〈0;a〉 - a: { - f: 〈1;b〉 - } - b: (〈0;a〉|string) - } - b9: { - #a: (string|〈0;#b〉|〈0;#ref〉) - #b: { - c: [ - 〈2;#a〉, - 〈2;#a〉, - 〈2;#a〉, - ] - } - #ref: { - ref: string - } - x: (〈0;#b〉|〈0;#ref〉) - } - b10: { - a: close({ - b: (string|〈1;a〉|〈1;c〉) - }) - c: close({ - d: (string|〈1;a〉) - }) - d: { - d: { - b: string - } - } - } - b11: { - #list: { - tail: (〈1;#list〉|*null) - if (〈0;tail〉 != null) {} - } - } - b12: { - #list: { - value: int - tail: (〈1;#list〉|*null) - if (〈0;tail〉 != null) { - sum: (〈1;value〉 + 〈1;tail〉.sum) - } - if (〈0;tail〉 == null) { - sum: 〈1;value〉 - } - } - list1: 〈0;#list〉 - list1: { - value: 1 - tail: { - value: 2 - tail: { - value: 3 - tail: { - value: 4 - } - } - } - } - } - b12b: { - #list: { - tail: 〈1;#list〉 - if (〈0;tail〉 != null) { - sum: 〈1;tail〉.sum - } - } - list1: 〈0;#list〉 - list1: { - tail: { - tail: {} - } - } - } - b13: { - root: { - a: [ - for _, x in 〈2;root〉 { - 〈1;x〉 - }, - ] - } - } - b14: { - root: { - a: [ - ...int, - ] - for _, x in 〈0;a〉 { - "\(〈1;x〉)": {} - } - b: [ - for _, x in 〈2;root〉 { - 〈1;x〉 - }, - ] - } - } - b15: { - root: { - a: { - for _, x in 〈2;root〉 { - 〈1;x〉 - } - } - } - } - p1: { - #T: { - a: { - [string]: { - link: 〈3;#T〉 - } - } - } - a: (〈0;#T〉 & { - a: { - one: { - link: { - a: { - two: {} - } - } - } - } - }) - } - p2: { - #T: { - a: { - [string]: { - link: 〈3;#T〉 - } - } - a: { - b: {} - } - } - a: (〈0;#T〉 & { - a: { - one: { - link: { - a: { - two: {} - } - } - } - } - }) - } - p3: { - #S: { - #T: { - a: { - [string]: { - link: 〈3;#T〉 - } - } - } - } - #U: { - 〈1;#S〉 - #T: { - a: { - b: {} - } - } - } - a: (〈0;#U〉.#T & { - a: { - one: { - link: { - a: { - two: {} - } - } - } - } - }) - } - p4: { - #T: { - a: [ - ...{ - link: 〈3;#T〉 - }, - ] - } - a: (〈0;#T〉 & { - a: [ - { - link: { - a: [ - {}, - ] - } - }, - ] - }) - } - p5: { - #T: { - a: [ - ...{ - link: 〈3;#T〉 - }, - ] - a: [ - {}, - ] - } - a: (〈0;#T〉 & { - a: [ - { - link: { - a: [ - {}, - ] - } - }, - ] - }) - } - p6: { - #S: { - #T: { - a: [ - ...{ - link: 〈3;#T〉 - }, - ] - } - } - #U: { - 〈1;#S〉 - #T: { - a: [ - {}, - ] - } - } - a: (〈0;#U〉.#T & { - a: [ - { - link: { - a: [ - {}, - ] - } - }, - ] - }) - } - c1: { - a: { - b: {} - c: (〈1;a〉 & 〈0;b〉) - } - } - d1: { - a: { - b: { - c: { - d: { - h: int - t: 〈4;r〉 - } - } - } - } - r: 〈0;a〉.b - x: 〈0;a〉.b.c - } - d2: { - x: 〈0;a〉.b.c - r: 〈0;a〉.b - a: { - b: { - c: { - d: { - h: int - t: 〈4;r〉 - } - } - } - } - } - d3: { - config: { - a: { - b: { - c: 〈2;indirect〉 - } - } - indirect: [ - 〈1;a〉.b, - null, - ][〈0;i〉] - i: (int|*1) - } - x: (〈0;config〉 & { - i: 0 - }) - } - shortPathFail: _ - shortPathFail: { - doubleRef: { - a: 〈0;#List〉 - #List: { - Next: (〈1;#List〉|*null) - } - } - } - shortPathFail: { - elipsis: { - t1: { - #Foo: { - ref: (null|〈1;#Foo〉) - } - #Foo: { - ... - } - } - t2: { - Foo: { - ref: 〈1;Foo〉 - } - Foo: { - ... - } - } - } - } - patternFail: { - issue2374: { - [string]: { - b: 〈1;(〈0;-〉)〉 - } - a: { - r: 0 - } - } - } - shortPathFail: { - comprehension: { - #list: { - tail: (〈1;#list〉|*null) - if (〈0;tail〉 != null) {} - } - } - } - withLetFail: { - schema: { - next: 〈1;let _schema_1#1〉 - } - let _schema_1#1 = 〈0;schema〉 - } - fieldsSumInfinite: { - issue3310: { - cheeseburger: 3.00 - fries: 2.00 - sprite: 1.00 - total: 〈import;list〉.Sum([ - for _, v in 〈2;issue3310〉 { - 〈1;v〉 - }, - ]) - } - } - listOptOK: { - list: { - head: int - tail?: 〈1;list〉 - } - a: (〈0;list〉 & { - head: 3 - tail: { - head: 2 - } - }) - } - issue2545: { - #A: { - B?: 〈1;#B〉 - } - #B: { - A: 〈1;#A〉 - } - } - e1: { - a: 〈0;a〉 - a: { - c: 〈1;a〉 - } - b: { - c: 〈1;b〉 - } - b: 〈0;b〉 - } - e2: { - a: { - 〈1;a〉 - } - a: { - c: 〈1;a〉 - } - b: { - c: 〈1;b〉 - } - b: { - 〈1;b〉 - } - } - e3: { - a: [ - 〈1;a〉, - ] - a: { - c: 〈1;a〉 - } - b: [ - 〈1;b〉, - ] - b: { - c: 〈1;b〉 - } - } - e4: { - a: [ - (〈1;a〉|{}), - ] - a: [ - [ - { - c: 1 - }, - ], - ] - b: [ - [ - { - c: 1 - }, - ], - ] - b: [ - (〈1;b〉|{}), - ] - } - e5: { - a: { - c: (〈1;a〉|int) - } - a: (〈0;a〉|int) - b: (〈0;b〉|int) - b: { - c: (〈1;b〉|int) - } - } - nestedList: { - v1e: { - x: [ - (〈1;x〉|int), - 1, - ] - y: (〈0;x〉 & [ - [ - [ - 2, - ], - 1, - ], - 1, - ]) - } - v2e: { - y: (〈0;x〉 & [ - [ - [ - 2, - ], - 1, - ], - 1, - ]) - x: [ - (〈1;x〉|int), - 1, - ] - } - v1: { - x: [ - (〈1;x〉|int), - 1, - ] - y: (〈0;x〉 & [ - [ - [ - 2, - 1, - ], - 1, - ], - 1, - ]) - } - v2: { - y: (〈0;x〉 & [ - [ - [ - 2, - 1, - ], - 1, - ], - 1, - ]) - x: [ - (〈1;x〉|int), - 1, - ] - } - } - v3: { - list: { - head: int - tail: (〈1;list〉|null) - } - myList: 〈0;list〉 - myList: { - head: 2 - tail: { - head: 3 - tail: { - head: 4 - } - } - } - } - v4: { - list: { - head: int - tail: (〈1;list〉|1) - } - myList: 〈0;list〉 - myList: { - head: 2 - tail: { - head: 3 - } - } - } - v5: { - list: { - head: int - tail: (〈1;list〉|{}) - } - myList: 〈0;list〉 - myList: { - head: 2 - tail: { - head: 3 - } - } - } - z1: { - y: { - f: { - h: 〈1;g〉 - } - g: _ - } - x: { - f: _ - g: 〈0;f〉 - } - z: (〈0;x〉 & 〈0;y〉) - } - crossRefNoCycle: { - t1: { - T: { - x: _ - y: 〈0;x〉 - } - C: ({ - x: 〈1;T〉 - } & 〈0;T〉) - } - } - crossRefNoCycle: { - t2: { - T: { - x: _ - y: 〈0;x〉 - } - C: (〈0;T〉 & { - x: 〈1;T〉 - }) - } - } - crossRefNoCycle: { - t3: { - T: { - x: _ - y: 〈0;x〉 - z: 〈0;y〉 - } - C: (〈0;T〉 & { - x: 〈1;T〉 - }) - } - } - crossRefNoCycle: { - t4: { - T: { - x: _ - y: 〈0;x〉 - z: 〈0;y〉 - } - C: (〈0;T〉 & { - x: (〈1;T〉 & { - x: 〈2;T〉 - }) - }) - } - } - crossRefNoCycle: { - t5: { - T: { - y: 〈1〉.x - } - C: (〈0;T〉 & { - x: 〈1;T〉 - }) - } - } - n1: { - a: { - b: int - } - } - n2: { - 〈1;n1〉 - a: 〈1;n1〉 - } - n3: { - 〈1;n1〉 - } - n4: { - 〈1;n1〉 - x: { - 〈2;n1〉 - y: { - 〈3;n1〉 - z: int - } - } - } -} diff --git a/cue/testdata/cycle/with_defaults.txtar b/cue/testdata/cycle/with_defaults.txtar index 4a3dbb037..a3b3c51a0 100644 --- a/cue/testdata/cycle/with_defaults.txtar +++ b/cue/testdata/cycle/with_defaults.txtar @@ -31,20 +31,3 @@ Conjuncts: 22 Disjuncts: 6 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - range1: { - min: (*1|int) - range: >〈0;min〉 - range: 8 - } - range2: { - min: (*1|int) - max: (int & >〈0;min〉) - } - rg: 〈0;range2〉 - rg: { - max: 8 - } -} diff --git a/cue/testdata/definitions/026_combined_definitions.txtar b/cue/testdata/definitions/026_combined_definitions.txtar index 8abc3559e..615e13273 100644 --- a/cue/testdata/definitions/026_combined_definitions.txtar +++ b/cue/testdata/definitions/026_combined_definitions.txtar @@ -31,54 +31,6 @@ d1: #D1 & {env: c: "C" } @test(err, at=env.c, code=eval, contains="field not all ./in.cue:8:17 [eval] #D4.env.b: field not allowed: ./in.cue:23:7 --- out/compile -- ---- in.cue -{ - #D1: { - env: { - a: "A" - } - env: { - b: "B" - } - #def: { - a: "A" - } - #def: { - b: "B" - } - } - d1: (〈0;#D1〉 & { - env: { - c: "C" - } - }) - #D2: { - a: int - } - #D2: { - b: int - } - #D3: { - env: { - a: "A" - } - } - #D3: { - env: { - b: "B" - } - } - #D4: { - env: 〈1;#DC〉 - env: { - b: int - } - } - #DC: { - a: int - } -} -- out/eval/stats -- Leaks: 0 Freed: 29 diff --git a/cue/testdata/definitions/028_recursive_closing_starting_at_non-definition.txtar b/cue/testdata/definitions/028_recursive_closing_starting_at_non-definition.txtar index 8b0550e6e..7bb2bc193 100644 --- a/cue/testdata/definitions/028_recursive_closing_starting_at_non-definition.txtar +++ b/cue/testdata/definitions/028_recursive_closing_starting_at_non-definition.txtar @@ -9,31 +9,6 @@ z: a: { } } A: z & {a: {#B: {c: e: 2}}} @test(eq, {a: #B: c: {e: 2, d: 1, f: 1}}) --- out/compile -- ---- in.cue -{ - z: { - a: { - #B: { - c: { - d: 1 - } - c: { - f: 1 - } - } - } - } - A: (〈0;z〉 & { - a: { - #B: { - c: { - e: 2 - } - } - } - }) -} -- out/eval/stats -- Leaks: 0 Freed: 14 diff --git a/cue/testdata/definitions/032_definitions_with_embedding.txtar b/cue/testdata/definitions/032_definitions_with_embedding.txtar index f0cf82219..0d9419f85 100644 --- a/cue/testdata/definitions/032_definitions_with_embedding.txtar +++ b/cue/testdata/definitions/032_definitions_with_embedding.txtar @@ -33,32 +33,6 @@ Conjuncts: 36 Disjuncts: 0 NumCloseIDs: 11 --- out/compile -- ---- in.cue -{ - #E: { - a: { - b: int - } - } - #S: { - 〈1;#E〉 - a: { - c: int - } - b: 3 - } - #e1: (〈0;#S〉 & { - a: { - d: 4 - } - }) - #v1: (〈0;#S〉 & { - a: { - c: 4 - } - }) -} -- out/diff-v2-v3.txt -- Reordering / missing positions. Verdict: worsening -- v3 reports fewer error positions; field reordering. diff --git a/cue/testdata/definitions/033_Issue_#153.txtar b/cue/testdata/definitions/033_Issue_#153.txtar index 7908d81db..81314217b 100644 --- a/cue/testdata/definitions/033_Issue_#153.txtar +++ b/cue/testdata/definitions/033_Issue_#153.txtar @@ -45,30 +45,6 @@ Conjuncts: 22 Disjuncts: 4 Notifications: 1 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - Foo: { - listOfCloseds: [ - ...〈2;#Closed〉, - ] - } - #Closed: { - a: (int|*0) - } - Junk: { - b: 2 - } - (〈0;Foo〉 & { - listOfCloseds: [ - { - for k, v in 〈3;Junk〉 { - "\(〈1;k〉)": 〈1;v〉 - } - }, - ] - }) -} -- out/diff-v2-v3.txt -- missing error positions: v3 reports fewer positions than v2. listOfCloseds.0.b: field not allowed: diff --git a/cue/testdata/definitions/036_closing_with_failed_optional.txtar b/cue/testdata/definitions/036_closing_with_failed_optional.txtar index ce0f680e4..3ae14305c 100644 --- a/cue/testdata/definitions/036_closing_with_failed_optional.txtar +++ b/cue/testdata/definitions/036_closing_with_failed_optional.txtar @@ -53,39 +53,3 @@ Conjuncts: 41 Disjuncts: 4 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - #k1: ({ - a: int - b?: int - } & 〈0;#A〉) - #k2: (〈0;#A〉 & { - a: int - b?: int - }) - o1: ({ - a?: 3 - } & { - a?: 4 - }) - #o2: ({ - a?: 3 - } & { - a?: 4 - }) - #d1: ({ - a?: 2 - b: 4 - }|{ - a?: 3 - c: 5 - }) - v1: (〈0;#d1〉 & { - a?: 3 - b: 4 - }) - #A: { - a: int - } -} diff --git a/cue/testdata/definitions/036_optionals_in_open_structs.txtar b/cue/testdata/definitions/036_optionals_in_open_structs.txtar index 4418aebf3..4837cd15d 100644 --- a/cue/testdata/definitions/036_optionals_in_open_structs.txtar +++ b/cue/testdata/definitions/036_optionals_in_open_structs.txtar @@ -11,22 +11,6 @@ c: #C & {aaa: 3} @test(eq, { [=~"^[m-z]*$"]: int aaa: 3 }) --- out/compile -- ---- in.cue -{ - A: { - [=~"^[a-s]*$"]: int - } - B: { - [=~"^[m-z]*$"]: int - } - #C: { - (〈1;A〉 & 〈1;B〉) - } - c: (〈0;#C〉 & { - aaa: 3 - }) -} -- out/eval/stats -- Leaks: 0 Freed: 6 diff --git a/cue/testdata/definitions/037_closing_with_comprehensions.txtar b/cue/testdata/definitions/037_closing_with_comprehensions.txtar index 3f7ba34a1..8a60ca19e 100644 --- a/cue/testdata/definitions/037_closing_with_comprehensions.txtar +++ b/cue/testdata/definitions/037_closing_with_comprehensions.txtar @@ -38,51 +38,6 @@ for k, v in {f3: int} { ./in.cue:4:11 [eval] #E.f3: field not allowed: ./in.cue:30:3 --- out/compile -- ---- in.cue -{ - #A: { - f1: int - f2: int - } - for k, v in { - f3: int - } { - a: (〈2;#A〉 & { - "\(〈2;k〉)": 〈2;v〉 - }) - } - #B: { - for k, v in { - f1: int - } { - "\(〈1;k〉)": 〈1;v〉 - } - } - #C: { - f1: _ - for k, v in { - f1: int - } { - "\(〈1;k〉)": 〈1;v〉 - } - } - #D: { - for k, v in { - f1: int - } { - "\(〈1;k〉)": 〈1;v〉 - } - ... - } - #E: (〈0;#A〉 & { - for k, v in { - f3: int - } { - "\(〈1;k〉)": 〈1;v〉 - } - }) -} -- out/eval/stats -- Leaks: 0 Freed: 28 diff --git a/cue/testdata/definitions/037_conjunction_of_optional_sets.txtar b/cue/testdata/definitions/037_conjunction_of_optional_sets.txtar index dc88055af..90609570f 100644 --- a/cue/testdata/definitions/037_conjunction_of_optional_sets.txtar +++ b/cue/testdata/definitions/037_conjunction_of_optional_sets.txtar @@ -39,27 +39,5 @@ Conjuncts: 29 Disjuncts: 0 NumCloseIDs: 14 --- out/compile -- ---- in.cue -{ - #A: { - [=~"^[a-s]*$"]: int - } - #B: { - [=~"^[m-z]*$"]: int - } - #C: (〈0;#A〉 & 〈0;#B〉) - c: 〈0;#C〉 - c: { - aaa: 3 - } - #D: { - (〈1;#A〉 & 〈1;#B〉) - } - d: 〈0;#D〉 - d: { - aaa: 3 - } -} -- out/diff-v2-v3.txt -- Missing positions: v3 reports fewer positions than v2 for the "field not allowed" errors. diff --git a/cue/testdata/definitions/038_continue_recursive_closing_for_optionals.txtar b/cue/testdata/definitions/038_continue_recursive_closing_for_optionals.txtar index 89f7121ae..016d4872a 100644 --- a/cue/testdata/definitions/038_continue_recursive_closing_for_optionals.txtar +++ b/cue/testdata/definitions/038_continue_recursive_closing_for_optionals.txtar @@ -20,20 +20,6 @@ Conjuncts: 9 Disjuncts: 0 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - #S: { - [string]: { - a: int - } - } - a: (〈0;#S〉 & { - v: { - b: int - } - }) -} -- out/diff-v2-v3.txt -- Missing positions: v3 reports fewer positions than v2 for the "field not allowed" error. a.v.b: field not allowed: diff --git a/cue/testdata/definitions/039_augment_closed_optionals.txtar b/cue/testdata/definitions/039_augment_closed_optionals.txtar index fa5a9b0b1..eb47e3e70 100644 --- a/cue/testdata/definitions/039_augment_closed_optionals.txtar +++ b/cue/testdata/definitions/039_augment_closed_optionals.txtar @@ -16,32 +16,6 @@ c: #C & {QQ: 3} @test(eq, {QQ: 3}) #B } d: #D & {aaa: 4} @test(eq, {aaa: 4}) --- out/compile -- ---- in.cue -{ - #A: { - [=~"^[a-s]*$"]: int - } - #B: { - [=~"^[m-z]*?"]: int - } - #C: { - (〈1;#A〉 & 〈1;#B〉) - { - [=~"^Q*$"]: int - } - } - c: (〈0;#C〉 & { - QQ: 3 - }) - #D: { - 〈1;#A〉 - 〈1;#B〉 - } - d: (〈0;#D〉 & { - aaa: 4 - }) -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/definitions/comprehensions.txtar b/cue/testdata/definitions/comprehensions.txtar index c7696358a..fce191be5 100644 --- a/cue/testdata/definitions/comprehensions.txtar +++ b/cue/testdata/definitions/comprehensions.txtar @@ -29,18 +29,3 @@ Conjuncts: 7 Disjuncts: 0 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - issue595: { - #cfgs: [ - { - name: "foo" - }, - ] - _name: 〈0;#cfgs〉[0].name - for _, cfg in 〈0;#cfgs〉 { - files: 〈1;cfg〉.nam - } - } -} diff --git a/cue/testdata/definitions/defembed.txtar b/cue/testdata/definitions/defembed.txtar index f16f660ac..ff987ffd4 100644 --- a/cue/testdata/definitions/defembed.txtar +++ b/cue/testdata/definitions/defembed.txtar @@ -35,25 +35,6 @@ Conjuncts: 16 Disjuncts: 0 NumCloseIDs: 6 --- out/compile -- ---- in.cue -{ - a: { - 〈1;#A〉 - } - a: { - c: 1 - } - #A: { - b: 1 - } - b: { - 〈1;#A〉 - leaf: "leaf value" - interpolation: "more \(〈0;leaf_ref〉)" - leaf_ref: 〈0;leaf〉 - } -} -- out/diff-v2-v3.txt -- Positions: v3 reports fewer positions than v2 for the "field not allowed" error. Reordering. diff --git a/cue/testdata/definitions/dynamic.txtar b/cue/testdata/definitions/dynamic.txtar index 321396be3..419000fee 100644 --- a/cue/testdata/definitions/dynamic.txtar +++ b/cue/testdata/definitions/dynamic.txtar @@ -56,40 +56,3 @@ Disjuncts: 4 NumCloseIDs: 2 -- out/diff-v2-v3.txt -- Disjunctions with defaults: needs @test(final) for x.a.b.c field. --- out/compile -- ---- evalv3regress.cue -{ - chained: { - x: { - 〈0;a〉.b: "foo" - 〈1;x〉.hello: "true" - a: { - b: "hello" - } - } - } -} ---- in.cue -{ - #A: { - a: "foo" - "\(〈0;a〉)": 3 - } - #B: { - a: { - b: { - c: string - d: 2 - } - } - } - #C: { - a: { - b: { - c: (*"d"|string) - 〈0;c〉: 2 - } - } - } - x: (〈0;#B〉 & 〈0;#C〉) -} diff --git a/cue/testdata/definitions/embed.txtar b/cue/testdata/definitions/embed.txtar index 90374077a..2aa7fd7f8 100644 --- a/cue/testdata/definitions/embed.txtar +++ b/cue/testdata/definitions/embed.txtar @@ -100,90 +100,6 @@ ConjunctInfos: 85 MaxConjunctInfos: 7 MaxReqSets: 12 MaxRedirect: 2 --- out/compile -- ---- in.cue -{ - deployment: { - [string]: 〈1;#Deployment〉 - } - deployment: { - foo: { - spec: { - replicas: 1 - } - } - } - #Deployment: { - 〈1;#TypeMeta〉 - spec: 〈1;#Spec〉 - } - #Spec: { - replicas: int - } - #TypeMeta: {} - recloseSimple: { - #foo: {} - a: ({ - 〈1;#foo〉 - } & { - b: int - }) - } - reclose1: { - #D: { - x: int - y: int - } - #a: { - 〈1;#D〉 - b: { - c: int - } - } - z: 〈0;#a〉.b - z: { - d: 3 - } - } - reclose2: { - #D: { - x: int - y: int - } - a: { - 〈1;#D〉 - b: { - c: int - } - } - z: 〈0;a〉.b - z: { - d: 3 - } - } - reclose3: { - #Step: { - (〈1;#A〉|〈1;#B〉) - 〈1;#Common〉 - } - #Common: { - Name: string - } - #A: { - 〈1;#Common〉 - Something: int - } - #B: { - 〈1;#Common〉 - Else: int - } - x: 〈0;#Step〉 - x: (〈0;#A〉 & { - Name: "a" - Something: 4 - }) - } -} -- out/diff-v2-v3.txt -- Reordering. Missing error positions: v3 reports fewer positions than v2. diff --git a/cue/testdata/definitions/exclude.txtar b/cue/testdata/definitions/exclude.txtar index 5d16e5a98..ebd78c3b9 100644 --- a/cue/testdata/definitions/exclude.txtar +++ b/cue/testdata/definitions/exclude.txtar @@ -115,103 +115,3 @@ Conjuncts: 115 Disjuncts: 0 NumCloseIDs: 18 --- out/compile -- ---- in.cue -{ - excludeLet: { - #D: { - let X#1 = {} - #foo: 〈0;let X#1〉 - f: _ - } - a: 〈0;#D〉 - a: { - let X#2 = { - a: 1 - } - f: 〈0;let X#2〉 - } - } - definition: { - err1: { - #D: { - #foo: { - a: int - } - } - a: 〈0;#D〉 - a: { - #foo: { - b: int - } - } - } - ok1: { - #D: {} - a: 〈0;#D〉 - a: { - #foo: { - b: int - } - } - } - } - hidden: { - err1: { - #D: { - _foo(:p): { - a: int - } - } - a: 〈0;#D〉 - a: { - _foo(:p): { - b: int - } - } - } - ok1: { - #D: {} - a: 〈0;#D〉 - a: { - _foo(:p): { - b: int - } - } - } - } -} ---- regress.cue -{ - definition: { - ok2: { - #Tree: { - #Leaf: { - leaf: string - } - #Branch: { - branch?: 〈1;#Leaf〉 - } - root: 〈0;#Branch〉 - } - out: 〈import;"encoding/json"〉.Marshal((〈0;#Tree〉 & { - root: {} - })) - } - } - hidden: { - ok2: { - out: (〈0;#Workflow〉 & { - _hidden(:p): (〈1;#step〉 & { - run: "foo bar" - }) - }) - #Workflow: {} - #step: matchN(1, [ - { - run!: _ - }, - ]) - } - } -} diff --git a/cue/testdata/definitions/explicitopen.txtar b/cue/testdata/definitions/explicitopen.txtar index 9c00332fd..71cd3bd2a 100644 --- a/cue/testdata/definitions/explicitopen.txtar +++ b/cue/testdata/definitions/explicitopen.txtar @@ -295,562 +295,3 @@ issue4150: { f9: combinenew.f9.ok is in error because two f9 declarations conflict. f14/f15: combinenew.f14.err and f15.err are NOT in error (v3 allows these). Structure sharing: NewOpen2: ~(#A), combinenew.f4.ok ~(NewClosed1), combinenew.f18.ok ~(NewClosed1). --- out/compile -- ---- issues.cue -{ - issue4150: { - #Def: { - a: int - } - x: (〈0;#Def〉... & { - a: 42 - b: 42 - }) - foo: { - a: int - } - bar: { - b: int - } - y: (〈0;foo〉... & 〈0;bar〉...) - z: 1... - } -} ---- new.cue -{ - NewClosed1: { - 〈1;#A〉 - } - #NewClosed2: { - 〈1;#A〉... - b: 1 - } - NewOpen1: { - 〈1;#A〉... - b: 1 - } - NewOpen2: 〈0;#A〉... - useOld1: { - t1: { - err: (〈2;Old1〉 & { - c: 3 - }) - } - t2: { - err: { - 〈3;Old1〉 - c: 3 - } - } - t3: { - ok: { - 〈3;Old1〉... - c: 3 - } - } - } - useOld2: { - t1: { - err: (〈2;#Old2〉 & { - c: 3 - }) - } - t2: { - err: { - 〈3;#Old2〉 - c: 3 - } - } - t3: { - ok: { - 〈3;#Old2〉... - c: 3 - } - } - } - combinenew: { - a0: { - ok: (〈2;#A〉 & 〈2;NewClosed1〉) - } - a1: { - ok: { - 〈3;#A〉 - 〈3;NewClosed1〉 - } - } - a2: { - ok: (〈2;NewClosed1〉 & 〈2;NewOpen2〉) - } - a3: { - ok: { - 〈3;NewClosed1〉 - 〈3;NewOpen2〉 - } - } - a4: { - ok: { - 〈3;NewClosed1〉... - 〈3;NewOpen2〉 - } - } - a5: { - ok: (〈2;NewOpen2〉 & 〈2;NewClosed1〉) - } - a6: { - ok: { - 〈3;NewOpen2〉 - 〈3;NewClosed1〉 - } - } - a7: { - ok: { - 〈3;NewOpen2〉... - 〈3;NewClosed1〉 - } - } - b0: { - ok: (〈2;Old1〉 & 〈2;#NewClosed2〉) - } - b1: { - ok: (〈2;#Old2〉 & 〈2;#NewClosed2〉) - } - b2: { - ok: (〈2;#NewClosed2〉 & 〈2;Old1〉) - } - b3: { - ok: (〈2;#NewClosed2〉 & 〈2;#Old2〉) - } - c1: { - ok: { - 〈3;#NewClosed2〉 - 〈3;Old1〉 - } - } - c2: { - ok: { - 〈3;#NewClosed2〉 - 〈3;#Old2〉 - } - } - c3: { - ok: { - 〈3;Old1〉 - 〈3;#NewClosed2〉 - } - } - c4: { - ok: { - 〈3;#Old2〉 - 〈3;#NewClosed2〉 - } - } - d0: { - ok: { - 〈3;#NewClosed2〉 - 〈3;Old1〉... - } - } - d1: { - ok: { - 〈3;#NewClosed2〉 - 〈3;#Old2〉... - } - } - d2: { - ok: { - 〈3;#NewClosed2〉... - 〈3;Old1〉 - } - } - d3: { - ok: { - 〈3;#NewClosed2〉... - 〈3;#Old2〉 - } - } - d4: { - ok: { - 〈3;#NewClosed2〉... - 〈3;Old1〉... - } - } - d5: { - ok: { - 〈3;#NewClosed2〉... - 〈3;#Old2〉... - } - } - d6: { - ok: { - 〈3;Old1〉... - 〈3;#NewClosed2〉 - } - } - d7: { - ok: { - 〈3;#Old2〉... - 〈3;#NewClosed2〉 - } - } - d8: { - ok: { - 〈3;Old1〉 - 〈3;#NewClosed2〉... - } - } - d9: { - ok: { - 〈3;#Old2〉 - 〈3;#NewClosed2〉... - } - } - d10: { - ok: { - 〈3;Old1〉... - 〈3;#NewClosed2〉... - } - } - d11: { - ok: { - 〈3;#Old2〉... - 〈3;#NewClosed2〉... - } - } - e0: { - err: (〈2;#A〉 & 〈2;Old1〉) - } - e1: { - err: (〈2;#A〉 & 〈2;#Old2〉) - } - e2: { - err: (〈2;#A〉 & 〈2;#NewClosed2〉) - } - e3: { - err: (〈2;#A〉 & 〈2;NewOpen1〉) - } - e4: { - err: { - 〈3;#A〉 - 〈3;Old1〉 - } - } - e5: { - err: { - 〈3;#A〉 - 〈3;#Old2〉 - } - } - e6: { - err: { - 〈3;#A〉 - 〈3;#NewClosed2〉 - } - } - e7: { - err: { - 〈3;#A〉 - 〈3;NewOpen1〉 - } - } - e8: { - ok: { - 〈3;#A〉... - 〈3;Old1〉 - } - } - e9: { - ok: { - 〈3;#A〉... - 〈3;#Old2〉 - } - } - e10: { - ok: { - 〈3;#A〉... - 〈3;#NewClosed2〉 - } - } - e11: { - ok: { - 〈3;#A〉... - 〈3;NewOpen1〉 - } - } - f0: { - err: (〈2;NewClosed1〉 & 〈2;Old1〉) - } - f1: { - err: (〈2;NewClosed1〉 & 〈2;#Old2〉) - } - f2: { - err: (〈2;NewClosed1〉 & 〈2;#NewClosed2〉) - } - f3: { - err: (〈2;NewClosed1〉 & 〈2;NewOpen1〉) - } - f4: { - ok: (〈2;NewClosed1〉 & 〈2;NewClosed1〉) - } - f5: { - err: { - 〈3;NewClosed1〉 - 〈3;Old1〉 - } - } - f6: { - err: { - 〈3;NewClosed1〉 - 〈3;#Old2〉 - } - } - f7: { - err: { - 〈3;NewClosed1〉 - 〈3;#NewClosed2〉 - } - } - f8: { - err: { - 〈3;NewClosed1〉 - 〈3;NewOpen1〉 - } - } - f9: { - ok: { - 〈3;NewClosed1〉 - 〈3;NewClosed1〉 - } - } - f9: { - ok: { - 〈3;NewClosed1〉... - 〈3;Old1〉 - } - } - f10: { - ok: { - 〈3;NewClosed1〉... - 〈3;#Old2〉 - } - } - f11: { - ok: { - 〈3;NewClosed1〉... - 〈3;NewClosed1〉 - } - } - f12: { - ok: { - 〈3;NewClosed1〉... - 〈3;#NewClosed2〉 - } - } - f13: { - ok: { - 〈3;NewClosed1〉... - 〈3;NewOpen1〉 - } - } - f14: { - err: (〈2;Old1〉 & 〈2;NewClosed1〉) - } - f15: { - err: (〈2;#Old2〉 & 〈2;NewClosed1〉) - } - f16: { - err: (〈2;#NewClosed2〉 & 〈2;NewClosed1〉) - } - f17: { - err: (〈2;NewOpen1〉 & 〈2;NewClosed1〉) - } - f18: { - ok: (〈2;NewClosed1〉 & 〈2;NewClosed1〉) - } - } -} ---- old.cue -{ - #A: { - a: 1 - } - Old1: { - { - 〈2;#A〉 - b: 1 - } - } - #Old2: { - { - 〈2;#A〉 - b: 1 - } - } - useNewClosed1: { - t1: { - err: (〈2;NewClosed1〉 & { - c: 3 - }) - } - t2: { - ok: { - 〈3;NewClosed1〉 - c: 3 - } - } - } - useNewClosed2: { - t1: { - err: (〈2;#NewClosed2〉 & { - c: 3 - }) - } - t2: { - ok: { - 〈3;#NewClosed2〉 - c: 3 - } - } - } - useNewOpen1: { - t1: { - ok: (〈2;NewOpen1〉 & { - c: 3 - }) - } - t2: { - ok: { - 〈3;NewOpen1〉 - c: 3 - } - } - } - useNewOpen2: { - t1: { - ok: (〈2;NewOpen2〉 & { - c: 3 - }) - } - t2: { - ok: { - 〈3;NewOpen2〉 - c: 3 - } - } - } - combineold: { - a0: { - ok: (〈2;#A〉 & 〈2;NewClosed1〉) - } - a1: { - ok: { - 〈3;#A〉 - 〈3;NewClosed1〉 - } - } - a2: { - ok: (〈2;NewClosed1〉 & 〈2;NewOpen2〉) - } - a3: { - ok: { - 〈3;NewClosed1〉 - 〈3;NewOpen2〉 - } - } - b0: { - ok: (〈2;Old1〉 & 〈2;#NewClosed2〉) - } - b1: { - ok: (〈2;#Old2〉 & 〈2;#NewClosed2〉) - } - c1: { - ok: { - 〈3;#NewClosed2〉 - 〈3;Old1〉 - } - } - c2: { - ok: { - 〈3;#NewClosed2〉 - 〈3;#Old2〉 - } - } - e0: { - err: (〈2;#A〉 & 〈2;Old1〉) - } - e1: { - err: (〈2;#A〉 & 〈2;#Old2〉) - } - e2: { - err: (〈2;#A〉 & 〈2;#NewClosed2〉) - } - e3: { - err: (〈2;#A〉 & 〈2;NewOpen1〉) - } - e4: { - ok: { - 〈3;#A〉 - 〈3;Old1〉 - } - } - e5: { - ok: { - 〈3;#A〉 - 〈3;#Old2〉 - } - } - e6: { - ok: { - 〈3;#A〉 - 〈3;#NewClosed2〉 - } - } - e7: { - ok: { - 〈3;#A〉 - 〈3;NewOpen1〉 - } - } - f0: { - err: (〈2;NewClosed1〉 & 〈2;Old1〉) - } - f1: { - err: (〈2;NewClosed1〉 & 〈2;#Old2〉) - } - f2: { - err: (〈2;NewClosed1〉 & 〈2;#NewClosed2〉) - } - f3: { - err: (〈2;NewClosed1〉 & 〈2;NewOpen1〉) - } - f4: { - ok: { - 〈3;NewClosed1〉 - 〈3;Old1〉 - } - } - f5: { - ok: { - 〈3;NewClosed1〉 - 〈3;#Old2〉 - } - } - f6: { - ok: { - 〈3;NewClosed1〉 - 〈3;NewClosed1〉 - } - } - f7: { - ok: { - 〈3;NewClosed1〉 - 〈3;#NewClosed2〉 - } - } - f8: { - ok: { - 〈3;NewClosed1〉 - 〈3;NewOpen1〉 - } - } - } -} diff --git a/cue/testdata/definitions/fields.txtar b/cue/testdata/definitions/fields.txtar index 775a6b113..a76dac677 100644 --- a/cue/testdata/definitions/fields.txtar +++ b/cue/testdata/definitions/fields.txtar @@ -419,447 +419,3 @@ NumCloseIDs: 122 Error positions: v3 reports fewer positions than v2. Field reordering differences between v2 and v3. Verdict: worsening -- v3 reports fewer error positions than v2; field reordering. --- out/compile -- ---- in.cue -{ - ok: { - t1: { - c: 〈0;#R〉 - c: [ - { - b: int - }, - ] - #R: [ - ..., - ] - } - } - ok: { - t2: { - #A: _ - l: 〈0;#A〉 - l: { - f: "hi" - } - } - } - ok: { - t3: { - #A: { - f: { - ... - } - } - #A1: { - 〈1;#A〉 - } - s: { - [string]: 〈1;#A1〉 - } - s: { - foo: { - f: { - d: { - foo: 1 - } - } - } - } - } - } - ok: { - t4: { - #T: { - a: { - b: 1 - } - } - W: { - { - 〈2;#T〉 - } - b: { - c: 2 - } - } - } - } - ok: { - t5: { - #A: { - 〈1;Common〉 - _ - } - Common: {} - x: 〈0;#A〉 - x: { - c: int - } - } - } - ok: { - t6: { - #A: { - 〈1;Common〉 - ... - } - Common: {} - x: 〈0;#A〉 - x: { - c: int - } - } - } - ok: { - t7: { - a: { - 〈1;#A〉 - 〈1;#B〉 - } - #A: { - b: { - f: 1 - } - } - #B: { - b: { - g: 1 - } - } - } - } - ok: { - t8: { - foo: 〈0;#X〉 - #X: { - a: { - b: { - c: { - C: 1 - } - } - } - for k, _ in 〈0;a〉 { - a: { - 〈2;k〉: { - c: { - D: 2 - } - } - } - } - } - } - } - ok: { - t9: { - c: 〈0;#R〉 - c: [ - { - b: int - }, - ] - #R: [ - ..., - ] - } - } - ok: { - t10: { - #A: _ - l: 〈0;#A〉 - l: { - f: "hi" - } - } - } - ok: { - t11: { - #A: { - f: { - ... - } - } - #A1: { - 〈1;#A〉 - } - s: { - [string]: 〈1;#A1〉 - } - s: { - foo: { - f: { - d: { - foo: "bar" - } - } - } - } - } - } - ok: { - t12: { - #T: { - a: { - b: 1 - } - } - W: { - { - 〈2;#T〉 - } - b: { - c: 2 - } - } - } - } - ok: { - t13: { - #A: { - 〈1;Common〉 - _ - } - Common: {} - x: 〈0;#A〉 - x: { - c: int - } - } - } - ok: { - t14: { - #A: { - 〈1;Common〉 - ... - } - Common: {} - x: 〈0;#A〉 - x: { - c: int - } - } - } - err: { - t1: { - #D: (_ & { - a: 2 - }) - a: 〈0;#D〉 - a: { - disallowed: 1 - } - } - } - err: { - t2: { - #S: { - { - c: { - d: 1 - } - } - } - V: 〈0;#S〉 - V: { - c: { - e: 1 - } - } - } - } - err: { - t3: { - #D: {} - a: 〈0;#D〉 - a: { - c: "C" - } - } - } - err: { - t4: { - a: 〈0;#A〉 - #A: { - b: { - f: 1 - } - } - a: { - b: { - h: 1 - } - } - } - } - err: { - t5: { - a: { - 〈1;#A〉 - 〈1;#B〉 - } - #A: { - b: { - f: 1 - } - } - #B: { - b: { - g: 1 - } - } - b: 〈0;a〉 - b: { - b: { - h: 1 - } - } - } - } - err: { - t6: { - a: { - 〈1;#A〉 - 〈1;#B〉 - } - #A: { - b: { - c: { - d: { - e: { - f: 1 - } - } - } - } - } - #B: { - b: { - c: { - d: { - e: { - g: 1 - } - } - } - } - } - b: 〈0;a〉 - b: { - b: { - c: { - d: { - e: { - h: 1 - } - } - } - } - } - } - } - err: { - t7: { - #D: (_ & { - a: 2 - }) - a: 〈0;#D〉 - a: { - b: 1 - } - } - } - err: { - t8: { - #S: { - { - c: { - d: 1 - } - } - } - V: 〈0;#S〉 - V: { - c: { - e: 1 - } - } - } - } -} ---- issue1830.cue -{ - issue1830: { - #x: { - y: { - z?: { - name: string - } - } - } - egs: { - x1: ((〈1;#x〉 & { - y: { - z: _ - } - }).y.z & { - name: "blah" - age1: 5 - }) - x2: ((〈1;#x〉.y & { - z: _ - }).z & { - name: "blah" - age2: 5 - }) - } - } -} ---- issue3491.cue -{ - issue3491: { - #Schema: { - field?: {} - } - a: (〈0;#Schema〉 & { - field: {} - }) - a: 〈0;b〉 - b: { - #Extra: {} - } - } -} ---- validators.cue -{ - validator: { - open: { - #Schema: { - matchN(1, [ - 〈1;#x〉, - ]) - #x: { - trailingComma?: "all" - } - } - data: { - trailingComma: "all" - } - data: 〈0;#Schema〉 - } - } - validator: { - keepClosed: { - #X: { - 〈import;struct〉.MaxFields(1) - a?: int - b?: int - } - x: 〈0;#X〉 - x: { - c: 1 - } - } - } -} diff --git a/cue/testdata/definitions/files.txtar b/cue/testdata/definitions/files.txtar index 82cc91a57..94bd07b3e 100644 --- a/cue/testdata/definitions/files.txtar +++ b/cue/testdata/definitions/files.txtar @@ -45,31 +45,6 @@ Disjuncts: 4 Notifications: 1 NumCloseIDs: 13 --- out/compile -- ---- box.cue -{ - (〈0;#Config〉 & { - console: 〈1;dark〉 - }) -} ---- in.cue -{ - #theme: { - color: string - ctermbg: string - } - dark: (〈0;#theme〉 & { - color: "dark" - ctermbg: "239" - }) - light: (〈0;#theme〉 & { - color: "light" - ctermbg: "254" - }) - #Config: { - console: (〈1;dark〉|*〈1;light〉) - } -} -- out/diff-v2-v3.txt -- Reordering. Disjunctions with defaults: needs @test(final) for console field. diff --git a/cue/testdata/definitions/hidden.txtar b/cue/testdata/definitions/hidden.txtar index fa68e1164..39d1ba376 100644 --- a/cue/testdata/definitions/hidden.txtar +++ b/cue/testdata/definitions/hidden.txtar @@ -58,34 +58,3 @@ NumCloseIDs: 4 -- out/diff-v2-v3.txt -- g: v2 evaluator expands g to {f: 4}; v3 uses structure sharing (~(f._val(:foo))). Verdict: improvement -- v3 uses structure sharing for g; more efficient. --- out/compile -- ---- in.cue -{ - #def: { - _name(:foo): { - d: int - } - } - d: (〈import;"mod.test/pkg"〉.#D & { - _name(:foo): { - d: int - } - _val(:foo): { - f: 4 - } - }) - e: ((〈import;"mod.test/pkg"〉.#D & 〈0;#def〉) & { - _name(:foo): { - c: int - } - _val(:foo): { - g: int - } - }) - f: (〈import;"mod.test/pkg"〉.#D & { - _val(:foo): { - f: 4 - } - }) - g: 〈0;f〉._val(:foo) -} diff --git a/cue/testdata/definitions/issue271.txtar b/cue/testdata/definitions/issue271.txtar index 4180fa8eb..47b2df850 100644 --- a/cue/testdata/definitions/issue271.txtar +++ b/cue/testdata/definitions/issue271.txtar @@ -24,21 +24,6 @@ Unifications: 10 Conjuncts: 20 Disjuncts: 0 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - #T: { - [_]: _ - } - #T: close({ - a: string - }) - x: 〈0;#T〉 - x: { - a: "hello" - b: "foo" - } -} -- out/diff-v2-v3.txt -- Positions: v3 reports fewer positions than v2 for the "field not allowed" error. x.b: field not allowed: @@ -47,4 +32,4 @@ x.b: field not allowed: - ./in.cue:3:5 ./in.cue:6:2 -No newline at end of right file. \ No newline at end of file +No newline at end of right file. diff --git a/cue/testdata/definitions/issue317.txtar b/cue/testdata/definitions/issue317.txtar index 5093926e8..c9aa83431 100644 --- a/cue/testdata/definitions/issue317.txtar +++ b/cue/testdata/definitions/issue317.txtar @@ -68,60 +68,3 @@ Unifications: 46 Conjuncts: 96 Disjuncts: 6 NumCloseIDs: 21 --- out/compile -- ---- in.cue -{ - #T: { - #Schema: { - [_]: 〈2;#D〉 - } - concrete: 〈0;#Schema〉 - } - #D: { - fieldWithDefault: (*0|int) - ... - } - s: (〈0;#T〉 & { - #Schema: { - foo: { - otherField: string - } - } - concrete: { - foo: { - otherField: "hello" - } - } - }) - #Container: { - Env: { - [string]: { - name: string - value: string - } - } - } - #Deployment: { - #Containers: { - [string]: 〈2;#Container〉 - } - containers: [ - for _, c in 〈1;#Containers〉 { - 〈1;c〉 - }, - ] - } - Something: { - 〈1;#Deployment〉 - #Containers: { - "a thing": { - Env: { - foobar: { - value: "foo" - } - } - } - } - } - x: (〈0;Something〉 & 〈0;#Deployment〉) -} diff --git a/cue/testdata/definitions/issue320.txtar b/cue/testdata/definitions/issue320.txtar index 3604cc52b..eac61e137 100644 --- a/cue/testdata/definitions/issue320.txtar +++ b/cue/testdata/definitions/issue320.txtar @@ -30,21 +30,6 @@ Unifications: 7 Conjuncts: 14 Disjuncts: 0 NumCloseIDs: 7 --- out/compile -- ---- in.cue -{ - #Foo: { - x: string - 〈1;#More〉 - } - #More: { - [=~"^x-"]: _ - } - foo: (〈0;#Foo〉 & { - x: "hello" - y: "goodbye" - }) -} -- out/diff-v2-v3.txt -- Positions: v3 reports fewer positions than v2 for the "field not allowed" error. Verdict: worsening -- v3 reports fewer error positions than v2. diff --git a/cue/testdata/definitions/issue342.txtar b/cue/testdata/definitions/issue342.txtar index d5f8c6dfd..43206338c 100644 --- a/cue/testdata/definitions/issue342.txtar +++ b/cue/testdata/definitions/issue342.txtar @@ -38,30 +38,6 @@ X: { } Z: X.test_3_bar.ref @test(eq, "FOO") --- out/compile -- ---- in.cue -{ - X: { - #Simple: { - ref: string - } - #Complex: { - ({ - ref: string - }|{ - local: string - }) - } - var: "bar" - test_1: 〈0;#Complex〉 - "test_2_\(〈0;var〉)": 〈0;#Simple〉 - "test_3_\(〈0;var〉)": 〈0;#Complex〉 - test_3_bar: { - ref: "FOO" - } - } - Z: 〈0;X〉.test_3_bar.ref -} -- out/eval/stats -- Leaks: 2 Freed: 18 diff --git a/cue/testdata/definitions/issue359.txtar b/cue/testdata/definitions/issue359.txtar index aa126aa94..b5792db69 100644 --- a/cue/testdata/definitions/issue359.txtar +++ b/cue/testdata/definitions/issue359.txtar @@ -81,60 +81,6 @@ notbad: many & { } } }) --- out/compile -- ---- in.cue -{ - #simple: { - peso: (*1|int) - edad: (*2|int) - } - good: (〈0;#simple〉 & { - peso: 4 - }) - #complex: { - things: { - [string]: 〈2;#simple〉 - } - } - #many: (〈0;#complex〉 & { - things: { - hola: { - peso: 2 - } - } - things: { - sol: { - peso: 3 - } - } - }) - bad: (〈0;#many〉 & { - things: { - hola: { - peso: 2 - } - } - }) - many: (〈0;#complex〉 & { - things: { - hola: { - peso: 2 - } - } - things: { - sol: { - peso: 3 - } - } - }) - notbad: (〈0;many〉 & { - things: { - hola: { - peso: 2 - } - } - }) -} -- out/eval/stats -- Leaks: 9 Freed: 72 diff --git a/cue/testdata/definitions/issue367.txtar b/cue/testdata/definitions/issue367.txtar index af657f0fd..2302ed95f 100644 --- a/cue/testdata/definitions/issue367.txtar +++ b/cue/testdata/definitions/issue367.txtar @@ -7,32 +7,6 @@ } }) instance: #special1 & {l1: l2: l3: 34} @test(eq, {l1: {l2: {l3: 34, l4: 26}}}) --- out/compile -- ---- in.cue -{ - #def1: { - l1: { - ["l2"]: { - l3: int - l4: 26 - } - } - } - #special1: (〈0;#def1〉 & { - l1: { - l2: { - l3: <100 - } - } - }) - instance: (〈0;#special1〉 & { - l1: { - l2: { - l3: 34 - } - } - }) -} -- out/eval/stats -- Leaks: 0 Freed: 13 diff --git a/cue/testdata/definitions/issue370.txtar b/cue/testdata/definitions/issue370.txtar index 86c6c4aff..b408a0d82 100644 --- a/cue/testdata/definitions/issue370.txtar +++ b/cue/testdata/definitions/issue370.txtar @@ -21,24 +21,6 @@ c2: #C2 & { c1 age: 5 } @test(eq, {age: 5, name: "cueckoo"}) --- out/compile -- ---- x.cue -{ - #C1: { - name: string - } - #C2: { - 〈1;#C1〉 - age: int - } - c1: (〈0;#C1〉 & { - name: "cueckoo" - }) - c2: (〈0;#C2〉 & { - 〈1;c1〉 - age: 5 - }) -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/definitions/issue3834.txtar b/cue/testdata/definitions/issue3834.txtar index d6d42a6a8..1181d8f1c 100644 --- a/cue/testdata/definitions/issue3834.txtar +++ b/cue/testdata/definitions/issue3834.txtar @@ -163,124 +163,3 @@ NumCloseIDs: 69 -- out/diff-v2-v3.txt -- Disjunction handling: _a: _ | close({y!: z?: _}) uses disjunction; needs @test(final) for precise testing. Verdict: cosmetic -- Disjunction with @test(final) annotation artifact. No semantic change. --- out/compile -- ---- in.cue -{ - X: { - _a: { - foo: true - } - _a: (_|close({ - y!: { - z?: _ - } - })) - _b: (〈0;_a〉 & { - y: {} - }) - concrete: 〈0;_b〉.y - isTrue: (〈0;concrete〉 != _|_(explicit error (_|_ literal) in source)) - } - { - 〈1;X〉 - } - sub: { - t1: { - X: { - _a: { - foo: true - } - _a: (_|close({ - y!: { - z?: _ - } - })) - _b: (〈0;_a〉 & { - y: {} - }) - concrete: 〈0;_b〉.y - } - { - 〈1;X〉 - } - } - } - sub: { - t2: { - X: { - _a: { - foo: true - } - _a: (_|close({ - y!: { - z?: _ - } - })) - _b: (〈0;_a〉 & { - y: {} - }) - concrete: 〈0;_b〉.y - } - 〈0;X〉 - } - } - sub: { - t3: { - #X: { - _a: { - foo: true - } - _a: (_|close({ - y!: { - z?: _ - } - })) - _b: (〈0;_a〉 & { - y: {} - }) - concrete: 〈0;_b〉.y - } - { - 〈1;#X〉 - } - } - } - sub: { - t4: { - #X: { - _a: { - foo: true - } - _a: (_|close({ - y!: { - z?: _ - } - })) - _b: (〈0;_a〉 & { - y: {} - }) - concrete: 〈0;_b〉.y - } - 〈0;#X〉 - } - } - full: { - #Foo: { - _data: { - Foo: true - } - _data: (_|close({ - Extra!: { - optional?: _ - } - })) - _dataWithExtra: (〈0;_data〉 & { - Extra: {} - }) - out: (〈0;_dataWithExtra〉.Extra != _|_(explicit error (_|_ literal) in source)) - } - { - 〈1;#Foo〉 - } - } -} diff --git a/cue/testdata/definitions/issue3851.txtar b/cue/testdata/definitions/issue3851.txtar index 8cc5d59d0..df4f55fd8 100644 --- a/cue/testdata/definitions/issue3851.txtar +++ b/cue/testdata/definitions/issue3851.txtar @@ -30,31 +30,6 @@ Disjuncts: 14 Notifications: 2 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - #App: { - name?: string - sub1?: { - sub2?: (null|_) - } - } - #Output: (null|〈0;#App〉) - out: (〈0;#Output〉 & { - name: "foo" - sub1: { - sub2: ({}|_) - } - sub1: { - sub2: { - sub3: { - let _let#1 = "bar" - foo: 〈0;let _let#1〉 - } - } - } - }) -} -- out/diff-v2-v3.txt -- Disjunctions with defaults: needs @test(final) for default field selection v3: sub2 is (#struct); v2: sub2 is (struct) diff --git a/cue/testdata/definitions/issue4000.txtar b/cue/testdata/definitions/issue4000.txtar index a25fcd6af..143a6b97c 100644 --- a/cue/testdata/definitions/issue4000.txtar +++ b/cue/testdata/definitions/issue4000.txtar @@ -67,64 +67,6 @@ _items: [#VMRuleList] spec: [...#RuleGroup] } #TypeMeta: kind: string | *"default" --- out/compile -- ---- in.cue -{ - items: 〈import;list〉.Sort(〈0;#List〉.items, { - x: {} - y: {} - less: (〈0;x〉.kind < 〈0;y〉.kind) - }) - #List: { - items: 〈import;list〉.Concat(〈1;_items〉) - } - _items: [ - 〈1;#VMRuleList〉, - ] - #VMRuleList: ([ - ...(null|〈1;#VMRule〉), - ] & [ - { - spec: [ - { - rules: [ - { - expr: "x" - }, - ] - }, - ] - }, - { - spec: [ - { - rules: [ - { - expr: "y" - }, - ] - }, - ] - }, - ]) - #RuleGroup: { - rules: [ - ...〈2;#Rule〉, - ] - } - #Rule: { - expr: string - } - #VMRule: { - 〈1;#TypeMeta〉 - spec: [ - ...〈2;#RuleGroup〉, - ] - } - #TypeMeta: { - kind: (string|*"default") - } -} -- out/eval/stats -- Leaks: 18 Freed: 36 diff --git a/cue/testdata/definitions/issue419.txtar b/cue/testdata/definitions/issue419.txtar index 2d7b09b72..94962766c 100644 --- a/cue/testdata/definitions/issue419.txtar +++ b/cue/testdata/definitions/issue419.txtar @@ -36,22 +36,3 @@ Conjuncts: 24 Disjuncts: 4 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - #A: { - a: string - } - #B: { - b: string - } - #X: (〈0;#A〉|〈0;#B〉) - l: [ - ...〈1;#X〉, - ] - l: [ - { - b: "bar" - }, - ] -} diff --git a/cue/testdata/definitions/issue471.txtar b/cue/testdata/definitions/issue471.txtar index f7909a224..c736c3759 100644 --- a/cue/testdata/definitions/issue471.txtar +++ b/cue/testdata/definitions/issue471.txtar @@ -45,24 +45,3 @@ Conjuncts: 30 Disjuncts: 2 NumCloseIDs: 4 --- out/compile -- ---- in.cue -{ - #a: ((〈0;#c〉|〈0;#d〉) & { - name: string - }) - #a1: (〈0;#c〉 & { - name: string - }) - #a2: (〈0;#d〉 & { - name: string - }) - #c: { - name: string - age: int - } - #d: { - name: string - address: string - } -} diff --git a/cue/testdata/definitions/issue483.txtar b/cue/testdata/definitions/issue483.txtar index ecc428ef4..9c7ac2821 100644 --- a/cue/testdata/definitions/issue483.txtar +++ b/cue/testdata/definitions/issue483.txtar @@ -14,30 +14,6 @@ instance: #Type & { alpha?: bravo?: charlie?: bool } #Root: {...} --- out/compile -- ---- in.cue -{ - out: { - 〈1;instance〉 - } - instance: (〈0;#Type〉 & { - alpha: { - bravo: { - charlie: true - } - } - }) - #Type: (〈0;#Root〉 & { - alpha?: { - bravo?: { - charlie?: bool - } - } - }) - #Root: { - ... - } -} -- out/eval/stats -- Leaks: 0 Freed: 14 diff --git a/cue/testdata/definitions/issue491.txtar b/cue/testdata/definitions/issue491.txtar index 34c16c901..27148ef5e 100644 --- a/cue/testdata/definitions/issue491.txtar +++ b/cue/testdata/definitions/issue491.txtar @@ -37,45 +37,6 @@ z: #PrestepNewUser & { }] } } @test(eq, {Args: {Repos: [{Var: "REPO1", Pattern: *"*" | string}]}}) --- out/compile -- ---- in.cue -{ - #Prestep: { - Args: (*null|_) - } - #PrestepNewUser: (〈0;#Prestep〉 & { - Args: 〈1;#NewUser〉 - }) - #NewUser: { - Repos: [ - ...〈2;#Repo〉, - ] - } - #Repo: { - Var: string - Pattern: (*"*"|string) - } - x: [ - ...〈1;#Repo〉, - ] - x: [ - { - Var: "REPO1" - }, - ] - y: (〈0;#Repo〉 & { - Var: "REPO1" - }) - z: (〈0;#PrestepNewUser〉 & { - Args: { - Repos: [ - { - Var: "REPO1" - }, - ] - } - }) -} -- out/eval/stats -- Leaks: 9 Freed: 33 diff --git a/cue/testdata/definitions/issue493.txtar b/cue/testdata/definitions/issue493.txtar index fedef558d..180e46dd6 100644 --- a/cue/testdata/definitions/issue493.txtar +++ b/cue/testdata/definitions/issue493.txtar @@ -13,22 +13,6 @@ #Both: #App | #Atom t1: #Both & {body: 3} @test(eq, {body: 3, other: {}}) --- out/compile -- ---- in.cue -{ - #Artifact: { - body: _ - other: { - [string]: int - } - } - #App: 〈0;#Artifact〉 - #Atom: 〈0;#Artifact〉 - #Both: (〈0;#App〉|〈0;#Atom〉) - t1: (〈0;#Both〉 & { - body: 3 - }) -} -- out/eval/stats -- Leaks: 6 Freed: 15 diff --git a/cue/testdata/definitions/issue496.txtar b/cue/testdata/definitions/issue496.txtar index ac6be69f1..ef0b8d64d 100644 --- a/cue/testdata/definitions/issue496.txtar +++ b/cue/testdata/definitions/issue496.txtar @@ -11,17 +11,6 @@ } @test(shareID=lN) l: #N @test(shareID=lN) --- out/compile -- ---- in.cue -{ - #A: _ - #N: (〈0;#A〉 & { - _E: { - name: "hello" - } - }) - l: 〈0;#N〉 -} -- out/eval/stats -- Leaks: 0 Freed: 6 diff --git a/cue/testdata/definitions/issue497.txtar b/cue/testdata/definitions/issue497.txtar index 5ed9986cf..6ca5f46f2 100644 --- a/cue/testdata/definitions/issue497.txtar +++ b/cue/testdata/definitions/issue497.txtar @@ -11,19 +11,6 @@ } @test(shareID=lN) @test(eq, {f: {j: {n: "hi"}}}) l: #N @test(shareID=lN) --- out/compile -- ---- in.cue -{ - #A: _ - #N: (〈0;#A〉 & { - f: { - j: { - n: "hi" - } - } - }) - l: 〈0;#N〉 -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/definitions/issue533.txtar b/cue/testdata/definitions/issue533.txtar index e9a7aec2e..7a2aa566f 100644 --- a/cue/testdata/definitions/issue533.txtar +++ b/cue/testdata/definitions/issue533.txtar @@ -38,24 +38,6 @@ Conjuncts: 17 Disjuncts: 0 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - #x: { - Name: string - } - _#x(:x): { - Name: string - } - x1: (〈0;#x〉 & { - Name: "hello" - Age: 50 - }) - x2: (〈0;_#x(:x)〉 & { - Name: "hello" - Age: 50 - }) -} -- out/diff-v2-v3.txt -- Positions: v3 reports fewer positions than v2 for the "field not allowed" errors. Verdict: worsening -- v3 reports fewer error positions than v2. diff --git a/cue/testdata/definitions/issue539.txtar b/cue/testdata/definitions/issue539.txtar index 24cb32c9f..5451df57b 100644 --- a/cue/testdata/definitions/issue539.txtar +++ b/cue/testdata/definitions/issue539.txtar @@ -30,17 +30,3 @@ Conjuncts: 17 Disjuncts: 4 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - #Schema: { - ... - } - Component: { - hostname: (string|*"localhost") - _#foo: { - hello: "world" - } - } - hello: (〈0;#Schema〉 & 〈0;Component〉) -} diff --git a/cue/testdata/definitions/list.txtar b/cue/testdata/definitions/list.txtar index 625db377a..3bc6a758a 100644 --- a/cue/testdata/definitions/list.txtar +++ b/cue/testdata/definitions/list.txtar @@ -5,24 +5,6 @@ c: #R & { #R: { w: [{}, ...] } --- out/compile -- ---- in.cue -{ - c: (〈0;#R〉 & { - w: [ - {}, - { - b: int - }, - ] - }) - #R: { - w: [ - {}, - ..., - ] - } -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/definitions/root1.txtar b/cue/testdata/definitions/root1.txtar index cada25804..8fda41603 100644 --- a/cue/testdata/definitions/root1.txtar +++ b/cue/testdata/definitions/root1.txtar @@ -22,12 +22,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - root1: 1 - #Root1: { - x: {} - } - (〈0;#Root1〉 & {}) -} diff --git a/cue/testdata/definitions/root2.txtar b/cue/testdata/definitions/root2.txtar index b85776b9f..56efbadc2 100644 --- a/cue/testdata/definitions/root2.txtar +++ b/cue/testdata/definitions/root2.txtar @@ -20,10 +20,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - root2: 1 - #Root2: {} - 〈0;#Root2〉 -} diff --git a/cue/testdata/definitions/root3.txtar b/cue/testdata/definitions/root3.txtar index c5c8493b7..4c8b3d5be 100644 --- a/cue/testdata/definitions/root3.txtar +++ b/cue/testdata/definitions/root3.txtar @@ -21,14 +21,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 4 --- out/compile -- ---- in.cue -{ - x: _ - #D: { - b: 〈1;x〉 - } - (〈0;#D〉 & { - b: _ - }) -} diff --git a/cue/testdata/definitions/root4.txtar b/cue/testdata/definitions/root4.txtar index 8326d2cb1..d18070ac5 100644 --- a/cue/testdata/definitions/root4.txtar +++ b/cue/testdata/definitions/root4.txtar @@ -34,19 +34,6 @@ Disjuncts: 0 Notifications: 2 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - #schema: { - a!: bool - } - (〈0;_hidden〉 & 〈0;#schema〉) - _hidden: { - a: true - notAllowed: true - } - allowed: true -} -- out/diff-v2-v3.txt -- Positions: v3 reports fewer positions than v2 for the "field not allowed" error. Reordering. diff --git a/cue/testdata/definitions/root5.txtar b/cue/testdata/definitions/root5.txtar index 8bc786b77..86ea8a7bd 100644 --- a/cue/testdata/definitions/root5.txtar +++ b/cue/testdata/definitions/root5.txtar @@ -72,34 +72,6 @@ Disjuncts: 0 Notifications: 4 NumCloseIDs: 7 --- out/compile -- ---- in.cue -{ - 〈0;_schema〉 - _schema: 〈0;#Schema〉 - #Schema: { - a?: { - b?: string - } - } - a: { - b: "foo" - } - c: "foo" - x: { - 〈0;_schema〉 - _schema: 〈0;#Schema〉 - #Schema: { - a?: { - b?: string - } - } - a: { - b: "foo" - } - c: "foo" - } -} -- out/diff-v2-v3.txt -- Reordering Verdict: cosmetic -- Field reordering only. No semantic change. diff --git a/cue/testdata/definitions/root6.txtar b/cue/testdata/definitions/root6.txtar index 388cf1e89..72934bedc 100644 --- a/cue/testdata/definitions/root6.txtar +++ b/cue/testdata/definitions/root6.txtar @@ -39,29 +39,3 @@ ConjunctInfos: 29 MaxConjunctInfos: 3 MaxReqSets: 7 MaxRedirect: 2 --- out/compile -- ---- in.cue -{ - c: "foo" - a: { - b: int - } - 〈0;#Schema〉 - #Schema: close({ - a: { - b: int - } - }) - x: { - c: "foo" - a: { - b: int - } - 〈0;#Schema〉 - #Schema: close({ - a: { - b: int - } - }) - } -} diff --git a/cue/testdata/definitions/root7.txtar b/cue/testdata/definitions/root7.txtar index 8e6217a64..09f7772dd 100644 --- a/cue/testdata/definitions/root7.txtar +++ b/cue/testdata/definitions/root7.txtar @@ -16,17 +16,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - root: { - input: { - #deps: { - root: {} - } - } - } - { - 〈1;root〉.input.#deps - } -} diff --git a/cue/testdata/definitions/root8.txtar b/cue/testdata/definitions/root8.txtar index 879307d85..ff0257d6b 100644 --- a/cue/testdata/definitions/root8.txtar +++ b/cue/testdata/definitions/root8.txtar @@ -29,31 +29,5 @@ Disjuncts: 2 Notifications: 1 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - root: { - input: { - foo: { - metadata: { - name: (*"foo"|string) - } - id: "id-\(〈0;metadata〉.name)" - #deps: { - [string]: _ - } - #deps: { - root: {} - } - spec: { - replicas: 1 - } - } - } - } - { - 〈1;root〉.input.foo.#deps - } -} -- out/diff-v2-v3.txt -- Disjunctions with defaults: needs @test(final) for default field selection diff --git a/cue/testdata/definitions/typocheck.txtar b/cue/testdata/definitions/typocheck.txtar index 6488ee72d..b4850c54a 100644 --- a/cue/testdata/definitions/typocheck.txtar +++ b/cue/testdata/definitions/typocheck.txtar @@ -1084,1107 +1084,3 @@ disjunction.withErr.t1.out.b1.b2.b3: undefined field: mayExistLater: Errors differ between v2 and v3 evaluators (v3 reports fewer positions). Structure sharing differences between v2 and v3. Verdict: mix -- improvement: v3 uses structure sharing. worsening: v3 reports fewer error positions. --- out/compile -- ---- chaineddef.cue -{ - issue3920: { - out: { - 〈1;#A〉 - a: { - b: "out" - } - } - #A: { - a?: 〈1;#B〉 - } - #B: { - c?: string - } - } - onlyCloseDirectStruct: { - #foo: {} - x: { - y: { - { - a: 〈3;#foo〉 - } - } - } - x: { - y: { - b: 1 - } - } - } - closeInEmbed: { - x: { - close({ - { - ["d"]: { - f: int - } - } - }) - } - x: { - d: { - e: 1 - } - } - } -} ---- cycle.cue -{ - issue4006: { - #A: { - 〈1;#B〉 - fieldA: string - } - #B: { - 〈1;#A〉 - } - #C: (〈0;#A〉 & {}) - out: (〈0;#C〉 & 〈0;#B〉) - } -} ---- disjunction.cue -{ - issue3947: { - full: { - #Schema: { - allowed?: string - } - _defaults: { - disallowed: (_|*"default value") - } - out: (〈0;#Schema〉 & 〈0;_defaults〉) - } - } - issue3957: { - reduced: { - c: { - a: "bar" - } - c: (〈0;#B〉 & { - a: (string|*"foo") - }) - #B: { - b?: string - } - } - } - issue3957: { - full: { - #oneof: ({ - a: string - }|{ - b?: [ - ...string, - ] - }) - c: (〈0;#oneof〉 & { - a: (string|*"foo") - }) - c: { - a: "bar" - } - } - } - issue3957: { - derived: { - t1: { - #Schema: { - in: (string|[ - ...string, - ]) - out: 〈import;list〉.FlattenN([ - 〈1;in〉, - ], 1) - } - x: (〈0;#Schema〉 & { - in: "foo" - }) - } - } - } - issue3957: { - derived: { - t2: { - #Schema: { - in: (string|[ - ...string, - ]) - let _flat#1 = 〈import;list〉.FlattenN([ - 〈1;in〉, - ], 1) - out: 〈0;let _flat#1〉 - } - out: (〈0;#Schema〉 & { - in: "foo" - }) - } - } - } -} ---- ellipsis.cue -{ - nestedEllipsis: { - minimal: { - out: (〈0;#Schema〉 & { - extra: "foo" - }) - #Schema: { - 〈1;#meta〉 - ... - } - #meta: {} - } - } - nestedEllipsis: { - nestedWithPatterns: { - out: (〈0;#Schema〉 & { - objs: { - obj1: { - extra: "foo" - } - } - }) - #Schema: { - [_]: { - [_]: { - 〈2;#meta〉 - ... - } - } - #meta: { - name?: int - } - objs?: _ - } - } - } - issue4015: { - reduced: { - #X: { - ... - } - out: { - 〈1;#X〉 - a: { - b: string - } - } - out: { - a: { - c: "h" - b: "x" - } - } - } - } - issue4015: { - nested: { - #X: { - foo: { - ... - } - } - out: { - 〈1;#X〉 - foo: { - a: { - b: string - } - } - } - out: { - foo: { - a: { - c: "h" - b: "x" - } - } - } - } - } - issue4015: { - full: { - #Schema: { - cfg: { - foo: { - enabled: (bool|*false) - fooField: string - } - bar: { - barField: string - } - } - capacity: (int|*3) - } - #MoreCapacity: { - capacity: 30 - ... - } - out: 〈0;#Schema〉 - out: { - 〈1;#MoreCapacity〉 - cfg: { - foo: { - enabled: true - } - } - } - out: { - cfg: { - foo: { - fooField: "h" - } - bar: { - barField: "x" - } - } - } - } - } -} ---- embedelim.cue -{ - issue3921: { - top: { - #A: 〈0;#B〉 - #A: { - b: string - } - #B: _ - a: { - (〈1;#A〉 & {}) - } - } - } - issue3921: { - hidden: { - #A: 〈0;#B〉 - #A: { - _hidden: { - b: string - } - } - #B: {} - a: { - (〈1;#A〉 & { - _hidden: {} - }) - } - } - } - issue3921: { - full: { - out: (〈0;#templateList〉 & 〈0;#defineMap〉) - #templateList: { - #stepMap: { - [string]: _ - } - stepList: [ - for _, c in 〈1;#stepMap〉 { - 〈1;c〉 - }, - ] - } - #defineMap: { - #stepMap: { - foo: (〈2;#Step〉 & { - image: "bar" - #config: {} - }) - } - stepList: _ - } - #Step: (〈0;#StepInner〉 & { - image: string - #config: { - version: string - } - }) - #StepInner: { - image: string - } - } - } -} ---- in.cue -{ - embed: { - simple: { - #A: { - b: 1 - } - a: { - 〈1;#A〉 - } - a: { - err: 1 - } - } - } - embed: { - andInStruct: { - #Foo: { - a: int - } - a: { - (〈1;#Foo〉 & { - err: 2 - }) - } - } - } - embed: { - embedDefWithEmbedding: { - #Foo: { - { - a: int - } - } - a: { - (〈1;#Foo〉 & { - err: 2 - }) - } - } - } - embed: { - embedComprehension: { - #Foo: { - if true { - a: int - } - } - a: { - (〈1;#Foo〉 & { - err: 2 - }) - } - } - } - embed: { - fieldWithAnd: { - #A: {} - { - a: (〈1;#A〉 & { - err: 3 - }) - } - } - } - embed: { - embedAndRecursive: { - #A: { - a: int - } - B: { - x: 〈1;#A〉 - } - (〈0;B〉 & { - x: { - err: 2 - } - }) - } - } - embed: { - andEmbed: { - #A: { - b: int - } - #B: { - b: int - } - #D: { - (〈1;#A〉 & 〈1;#B〉) - } - d: (〈0;#D〉 & { - err: 3 - }) - } - } - and: { - transitive: { - ok: { - Z: { - a: string - } - #Y: 〈0;Z〉 - #X: (〈0;#Y〉 & 〈0;Z〉) - out: (〈0;#X〉 & { - a: "foo" - }) - } - } - } - and: { - transitive: { - err: { - Z: { - a: string - } - #Y: 〈0;Z〉 - #X: (〈0;#Y〉 & 〈0;Z〉) - out: (〈0;#X〉 & { - err: "foo" - }) - } - } - } - and: { - transitiveWithEmbed: { - ok: { - Z: { - a: string - } - #X: (〈0;#Y〉 & 〈0;Z〉) - #Y: { - 〈1;Z〉 - } - out: (〈0;#X〉 & { - a: "foo" - }) - } - } - } - and: { - transitiveWithEmbed: { - err: { - Z: { - a: string - } - #X: (〈0;#Y〉 & 〈0;Z〉) - #Y: { - 〈1;Z〉 - } - out: (〈0;#X〉 & { - err: "foo" - }) - } - } - } - embed: { - nonDef: { - t1: { - X: { - a: string - } - #Y: (〈0;#Z〉 & 〈0;X〉) - #Z: { - 〈1;X〉 - b?: string - } - } - } - } - embed: { - defAndHidden: { - full: { - _stepCommon: { - Name: string - } - #Step: (〈0;#Command〉 & 〈0;_stepCommon〉) - #Command: { - 〈1;_stepCommon〉 - Path?: string - } - out: (〈0;#Step〉 & { - Name: "foo" - }) - } - } - } - embed: { - withIndirect: { - A: 〈0;#B〉 - #B: { - b: int - } - (〈0;A〉 & { - err: 2 - }) - } - } -} ---- inline.cue -{ - embedInline: { - #Schema: { - a: "hello" - b: { - { - x: { - c: "foo" - } - }.x - } - b: { - c: string - d: "never printed" - } - } - out: (〈0;#Schema〉 & _|_(no sharing)) - } - issue3853: { - #Schema: { - a: "hello" - b: { - { - x: { - c: "foo" - } - }.x - } - b: { - c: string - d: "never printed" - } - } - out: { - x: (〈1;#Schema〉 & {}).a - }.x - } -} ---- issue3832.cue -{ - issue3832: { - _person: { - self: { - firstName: "Sam" - } - } - #T: { - _subject: { - in: _ - out: { - let self#2 = 〈1;in〉.self - outFirstName: 〈0;let self#2〉.firstName - } - } - _assert: { - pass: _ - } - _assert: ({ - check!: _ - pass: "never" - }|{ - invoke!: _ - pass: (〈1;_subject〉 & { - in: 〈1;invoke〉 - }).out - }) - results: 〈0;_assert〉.pass - } - (〈0;#T〉 & { - _assert: { - invoke: 〈2;_person〉 - } - }) - } -} ---- issue3833.cue -{ - issue3833: { - ok: { - out: { - (〈1;#A〉 & { - a: 〈2;#B〉 - }) - } - #A: { - a: { - b: string - ... - } - ... - } - #C: { - c: string - } - #B: { - (〈1;#C〉 & { - c: "foo" - }) - b: "foo" - } - } - } - issue3833: { - evalv2Issue: { - out: { - (〈1;#A〉 & { - a: 〈2;#B〉 - }) - } - #A: { - a: { - b: string - } - ... - } - #C: { - c: string - } - #B: { - (〈1;#C〉 & { - c: "foo" - }) - b: "foo" - } - } - } -} ---- issue3837.cue -{ - issue3837: { - reduced: { - A: { - 〈1;#Embed〉 - extra: "foo" - } - out: { - { - x: (〈2;A〉 & _|_(no sharing)) - } - } - #Embed: {} - } - } - issue3837: { - full: { - #Embed: {} - #A: { - 〈1;#Embed〉 - extra: "foo" - } - #B: (〈0;#C〉|{}) - #C: { - bar: string - } - out: (〈0;#B〉 & { - bar: "baz" - { - #def: (〈2;#A〉 & _|_(no sharing)) - } - }) - } - } -} ---- issue3839.cue -{ - issue3839: { - reduced: { - x: { - (〈1;A〉 & _|_(no sharing)) - } - x: { - y: 1 - } - #B: {} - A: { - 〈1;#B〉 - ... - } - } - } - issue3839: { - full: { - _globals: { - glb: { - globalField: "" - } - } - #GlobalContext: { - globalField: string - } - #Context: { - glb: 〈1;#GlobalContext〉 - out: 〈0;glb〉 - } - out: { - ingress: { - (〈2;#Ingress〉 & { - #def: (〈3;#Context〉 & 〈3;_globals〉).out - }) - } - ingress?: { - foo: 1234 - bar: "http" - } - } - #Embed: { - #def: { - ... - } - } - #Ingress: { - 〈1;#Embed〉 - ... - } - } - } -} ---- issue3843.cue -{ - dedupPattern: { - t1: { - p1: { - A: { - #Z: { - [string]: _ - } - x: 〈0;#Z〉 - x: { - y: { - z: 1 - } - } - } - B: (〈0;A〉 & _|_(no sharing)) - out: (〈0;A〉.#Z & 〈0;B〉.x) - } - } - } - dedupPattern: { - t1: { - p2: { - A: { - #Z: { - [string]: _ - } - x: 〈0;#Z〉 - x: { - y: { - z: 1 - } - } - } - B: (〈0;A〉 & _|_(no sharing)) - out: (〈0;B〉.x & 〈0;A〉.#Z) - } - } - } -} ---- issue3858.cue -{ - orig: { - t1: { - #Image: { - embed: { - image: "foo:v1" - } - } - #JobConfig: { - image: 〈1;#Image〉 - job: (〈1;#Job〉 & { - 〈1;image〉.embed - }) - } - #Job: { - image: string - vcs: "git" - args: [ - ...string, - ] - env: { - [string]: string - } - } - #Output: { - _in: _ - out: (〈0;_in〉 & {}) - } - (〈0;#Output〉 & { - _in: (〈1;#JobConfig〉 & {}).job - }) - } - } - reduced: { - t1: { - Y: { - a: { - e: "foo" - } - b: (〈1;X〉 & { - 〈1;a〉 - }) - } - X: { - e: string - f: 1 - } - #Z: { - _in: _ - out: (〈0;_in〉 & _|_(no sharing)) - } - (〈0;#Z〉 & { - _in: 〈1;Y〉 - }) - } - } - orig: { - t2: { - #JobConfig: { - image: { - spec: { - image: "someimage" - } - } - job: (〈1;#Job〉 & { - 〈1;image〉.spec - }) - } - #Job: { - image: string - env: "FOO" - } - #Output: { - in: _ - out: (〈0;in〉 & {}).input - } - out: (〈0;#Output〉 & { - in: { - input: (〈2;#JobConfig〉 & {}).job - } - }) - } - } - reduced: { - t2: { - Y: { - a: { - e: "foo" - } - b: (〈1;X〉 & { - 〈1;a〉 - }) - } - X: { - e: string - f: 1 - } - #Z: { - _in: _ - out: 〈0;_in〉 - } - (〈0;#Z〉 & { - _in: 〈1;Y〉 - }) - } - } -} ---- issue3934.cue -{ - issue3934: { - out: (〈0;#Foo〉 & { - foo: { - if false { - extra: { - nested: 123 - } - } - } - }) - #Foo: { - foo?: (null|〈1;#Bar〉|*{ - bar: 3 - }) - } - #Bar: { - bar?: int - extra?: (null|{ - ... - }) - } - } -} ---- issue3964.cue -{ - issue3964: { - reduced: { - #Output: { - 〈1;#Embedded〉 - } - #Embedded: { - name: string - (〈1;#Unused〉|〈1;#Used〉) - } - #Unused: {} - #Used: {} - } - } - issue3964: { - full: { - out: (〈0;#Output〉 & { - name: "oauth2" - used: "bar" - }) - #Output: { - 〈1;#Embedded〉 - } - #Embedded: { - name: string - (〈1;#Unused〉|〈1;#Used〉) - } - #Unused: { - unused: string - } - #Used: { - used: string - } - } - } -} ---- large.cue -{ - full: { - #Resource: { - someMsg: string - obs: ({}|*{ - missing: true - }) - let pickMsg#3 = [ - if 〈1;obs〉.missing { - msg: "\(〈2;someMsg〉)" - }, - { - msg: "bar" - }, - ][0] - patches: [ - { - op: "add" - path: "/metadata" - value: 〈2;let pickMsg#3〉.msg - }, - ] - } - #Patches: { - [string]: _ - } - #JSONPatch: { - namespace?: string - patch: [ - ...〈2;#JSONOp〉, - ] - output: (〈1;#Patches〉 & { - 〈1;namespace〉: 〈1;patch〉 - }) - } - #JSONOp: ({ - op: "add" - path: string - value: _ - }|{ - op: "remove" - path: string - }) - #Main: { - namespace: string - output: 〈0;let jsonPatch#4〉.output - let jsonPatch#4 = (〈1;#JSONPatch〉 & { - let base#7 = (〈2;#Resource〉 & {}) - let withMsg#8 = (〈0;let base#7〉 & { - someMsg: "foo" - }) - namespace: 〈1;namespace〉 - patch: 〈0;let withMsg#8〉.patches - }) - } - out: (〈0;#Main〉 & { - namespace: "ns1" - }).output - } -} ---- validators.cue -{ - embed: { - normalValidator: { - #X: { - 〈import;struct〉.MaxFields(1) - a?: int - b?: int - } - x: 〈0;#X〉 - x: { - err: 1 - } - } - } - embed: { - openValidator: { - t1: { - #X: { - matchN(0, []) - a?: int - b?: int - } - x: 〈0;#X〉 - x: { - err: 1 - } - } - } - } - embed: { - openValidator: { - t2: { - Y: matchN(1, [ - 〈1;X〉, - ]) - X: { - b?: 〈1;Y〉 - } - a: 〈0;X〉 - a: { - b: 1 - } - } - } - } - disjunction: { - withErr: { - t1: { - params: {} - out: (〈0;#Schema1〉 & { - b1: { - b2: { - b3: 〈3;params〉.mayExistLater - } - } - }) - #Schema1: { - b1?: (null|〈1;#Schema2〉) - } - #Schema2: { - b2?: (null|{ - b3?: string - }) - } - } - } - } - embed: { - nestedValidator: { - #types: { - z?: 〈import;list〉.UniqueItems - } - x: { - y: { - z: [ - 1, - ] - } - } - x: { - 〈1;#def〉 - y?: 〈1;#types〉 - } - #def: {} - } - } -} diff --git a/cue/testdata/definitions/visibility.txtar b/cue/testdata/definitions/visibility.txtar index 314d8fb92..8a2fc870a 100644 --- a/cue/testdata/definitions/visibility.txtar +++ b/cue/testdata/definitions/visibility.txtar @@ -26,17 +26,5 @@ Conjuncts: 10 Disjuncts: 0 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - #foo: { - name: string - } - foo: (〈0;#foo〉 & { - _name: "foo" - _#name: "bar" - #name: "baz" - }) -} -- out/diff-v2-v3.txt -- Reordering: v3 outputs fields in different order than v2 (name appears after hidden fields in v3). diff --git a/cue/testdata/disjunctions/019_ips.txtar b/cue/testdata/disjunctions/019_ips.txtar index 964d373d4..b44b0fabc 100644 --- a/cue/testdata/disjunctions/019_ips.txtar +++ b/cue/testdata/disjunctions/019_ips.txtar @@ -31,40 +31,6 @@ MyIP: Inst & [_, _, 10, 10] @test(eq, [10, 10, 10, 10]) ] MyIP: [10, 10, 10, 10] }) --- out/compile -- ---- in.cue -{ - IP: 〈import;list〉.Repeat([ - &(int, >=0, <=255), - ], 4) - Private: (*[ - 192, - 168, - &(int, >=0, <=255), - &(int, >=0, <=255), - ]|[ - 10, - &(int, >=0, <=255), - &(int, >=0, <=255), - &(int, >=0, <=255), - ]|[ - 172, - (>=16 & <=32), - &(int, >=0, <=255), - &(int, >=0, <=255), - ]) - Inst: (〈0;Private〉 & [ - _, - 10, - ..., - ]) - MyIP: (〈0;Inst〉 & [ - _, - _, - 10, - 10, - ]) -} -- out/eval/stats -- Leaks: 10 Freed: 52 diff --git a/cue/testdata/disjunctions/confluence.txtar b/cue/testdata/disjunctions/confluence.txtar index 0efe67814..72578392f 100644 --- a/cue/testdata/disjunctions/confluence.txtar +++ b/cue/testdata/disjunctions/confluence.txtar @@ -24,30 +24,3 @@ issue3993: full: { addr: "10.10.10.10" @test(eq, {addr: "10.10.10.10"}) } --- out/compile -- ---- in.cue -{ - issue3993: { - reduced: { - x: (〈import;net〉.IPv4|=~"fail") - x: { - if 〈import;net〉.IPv4(〈1;x〉) { - =~"^10\\." - } - } - x: "10.10.10.10" - } - } - issue3993: { - full: { - addr!: (string & (〈import;net〉.IPv4|〈import;net〉.IPv6)) - if 〈import;net〉.IPv4(〈0;addr〉) { - addr: 〈import;strings〉.HasPrefix("10.") - } - if 〈import;net〉.IPv6(〈0;addr〉) { - addr: 〈import;strings〉.HasPrefix("2a02:") - } - addr: "10.10.10.10" - } - } -} diff --git a/cue/testdata/disjunctions/crossembed.txtar b/cue/testdata/disjunctions/crossembed.txtar index 704302953..1b58c0709 100644 --- a/cue/testdata/disjunctions/crossembed.txtar +++ b/cue/testdata/disjunctions/crossembed.txtar @@ -38,13 +38,3 @@ Conjuncts: 18 Disjuncts: 2 NumCloseIDs: 4 --- out/compile -- ---- in.cue -{ - out: 〈import;"foo.test/main/imported"〉 - out: { - either: { - foo: "world" - } - } -} diff --git a/cue/testdata/disjunctions/defaults.txtar b/cue/testdata/disjunctions/defaults.txtar index 80ac3f302..e1627aba8 100644 --- a/cue/testdata/disjunctions/defaults.txtar +++ b/cue/testdata/disjunctions/defaults.txtar @@ -30,34 +30,6 @@ issue3779: { #Bar: {fieldFoo: _, fieldBar: *_ | string} }) } --- out/compile -- ---- in.cue -{ - passToSingleValue: { - p1: (_|*((_|*"x") & "y")) - } - passToSingleValue: { - p2: (_|*((*"x"|_) & "y")) - } - passToSingleValue: { - p3: (*((_|*"x") & "y")|_) - } - passToSingleValue: { - p4: (*((*"x"|_) & "y")|_) - } - issue3779: { - out: (〈0;#Foo〉 & { - fieldFoo: "foo" - }) - #Foo: (〈0;#Bar〉 & { - fieldFoo: (string|*"foo-default") - }) - #Bar: { - fieldFoo: _ - fieldBar: (string|*〈0;fieldFoo〉) - } - } -} -- out/eval/stats -- Leaks: 7 Freed: 39 diff --git a/cue/testdata/disjunctions/defembed.txtar b/cue/testdata/disjunctions/defembed.txtar index 8fc691dfa..1e19854e6 100644 --- a/cue/testdata/disjunctions/defembed.txtar +++ b/cue/testdata/disjunctions/defembed.txtar @@ -57,45 +57,6 @@ z: { a: *"a" | "b" | "c" }) } --- out/compile -- ---- in.cue -{ - x: { - m1: ((1|(*2|3)) & (>=2 & <=3)) - m2: ((1|(*2|3)) & (2|3)) - m3: ((*1|*(*2|3)) & (2|3)) - } - y1: (〈0;x〉 & { - { - m4: ((〈2;x〉.m1 + 〈2;x〉.m2) + 〈2;x〉.m3) - } - }) - y2: { - 〈1;x〉 - { - m4: ((〈2;y2〉.m1 + 〈2;y2〉.m2) + 〈2;y2〉.m3) - } - } - y3: { - 〈1;x〉 - { - m4: ((〈2;y3〉.m1 + 〈2;y3〉.m2) + 〈2;y3〉.m3) - } - } - y4: (〈0;x〉 & { - { - m4: ((〈2;y4〉.m1 + 〈2;y4〉.m2) + 〈2;y4〉.m3) - } - }) - z: { - b: ((*"a"|"b")|"c") - ({ - a: 〈1;b〉 - }|{ - b: int - }) - } -} -- out/eval/stats -- Leaks: 40 Freed: 120 diff --git a/cue/testdata/disjunctions/discriminator.txtar b/cue/testdata/disjunctions/discriminator.txtar index a151ed109..cc88a8692 100644 --- a/cue/testdata/disjunctions/discriminator.txtar +++ b/cue/testdata/disjunctions/discriminator.txtar @@ -287,110 +287,3 @@ Conjuncts: 215 Disjuncts: 92 NumCloseIDs: 30 --- out/compile -- ---- in.cue -{ - noKind: { - manyWithStructEmbed: { - #Def: ({ - <10 - _hidden: "field" - }|>200|string) - out: (〈0;#Def〉 & 123) - } - manyStructsEmpty: { - #Def: ({ - f1!: int - }|{ - f2!: int - }|string) - out: (〈0;#Def〉 & {}) - } - manyScalars: { - #Def: (1|2|3) - out: (〈0;#Def〉 & 123) - } - zeroScalars: { - #Def: (int|string|null) - out: (〈0;#Def〉 & true) - } - } - byKind: { - nullableStructRegular: { - #Def1: { - f1: (null|〈1;#Def2〉) - } - #Def2: { - f2: (null|〈1;#Def3〉) - } - #Def3: { - f3: (null|int) - } - out: (〈0;#Def1〉 & { - f1: { - f2: { - f3: "not an int" - } - } - }) - } - nullableStructRequired: { - #Def1: { - f1!: (null|〈1;#Def2〉) - } - #Def2: { - f2!: (null|〈1;#Def3〉) - } - #Def3: { - f3!: (null|int) - } - out: (〈0;#Def1〉 & { - f1: { - f2: { - f3: "not an int" - } - } - }) - } - nullableStructOptional: { - #Def1: { - f1?: (null|〈1;#Def2〉) - } - #Def2: { - f2?: (null|〈1;#Def3〉) - } - #Def3: { - f3?: (null|int) - } - out: (〈0;#Def1〉 & { - f1: { - f2: { - f3: "not an int" - } - } - }) - } - nullableList: { - #Def1: [ - ...(null|〈1;#Def2〉), - ] - #Def2: [ - ...(null|〈1;#Def3〉), - ] - #Def3: [ - ...(null|int), - ] - out: (〈0;#Def1〉 & [ - [ - [ - "not an int", - ], - ], - ]) - } - scalarConstraints: { - #Def: (>10|""|null|false) - out: (〈0;#Def〉 & 5) - } - } -} diff --git a/cue/testdata/disjunctions/edge.txtar b/cue/testdata/disjunctions/edge.txtar index 0714ef81d..f6fbd9d3f 100644 --- a/cue/testdata/disjunctions/edge.txtar +++ b/cue/testdata/disjunctions/edge.txtar @@ -203,149 +203,3 @@ NumCloseIDs: 64 issue4251_notC, issue4251_notB, issue4251_notB_reversed: these are only evaluated correctly by v3. cyclicalInsertInDisjunction.err1: should be an error for both evaluators but both produce concrete values. preseveBottomSemantics: both evaluators are incorrect; result should be _ or _|{}. --- out/compile -- ---- in.cue -{ - cyclicalInsertInDisjunction: { - ok1: { - c: { - d: 〈0;e〉 - e: _ - } - c: ({ - d: 1 - e: 2 - }|{ - d: 2 - e: 2 - }) - } - maybe1: { - c: { - d: 〈1;c〉.e - } - c: ({ - d: 1 - e: 2 - }|{ - d: 2 - e: 2 - }) - } - err1: { - x: 〈0;c〉.e - c: { - d: 〈1;x〉 - } - c: ({ - d: 1 - e: 2 - }|{ - d: 2 - e: 2 - }) - } - err2: { - x: div(〈0;c〉.e, 2) - c: { - d: 〈1;x〉 - } - c: ({ - d: 1 - e: 2 - }|{ - d: 2 - e: 3 - }) - } - err3: { - x: 〈0;c〉.e - c: { - d: (1|2|〈1;x〉) - } - c: ({ - d: 1 - e: 2 - }|{ - d: 2 - e: 3 - }) - } - } - preseveBottomSemantics: { - ok: { - #x: { - (〈1;#x〉|{}) - } - } - } - eliminateOpenVariant: { - ok: { - c: ({ - a: 1 - }|〈0;#b〉) - #b: { - a: 1 - } - } - } - cyclicSelfElimination: { - ok: { - y: (1|{ - y: 1 - }) - 〈0;y〉 - } - } - issue4251_notC: { - #NotC: { - string - _must: (true & (〈1〉 != "c")) - } - a: 〈0;#NotC〉 - a: ("a"|"b") - a: "a" - } - issue4251_notB: { - #NotB: { - string - _must: (true & (〈1〉 != "b")) - } - a: 〈0;#NotB〉 - a: ("a"|"b") - a: "a" - } - issue4251_notB_reversed: { - #NotB: { - string - _must: (true & (〈1〉 != "b")) - } - a: 〈0;#NotB〉 - a: ("b"|"a") - a: "a" - } -} ---- panic.cue -{ - panic1: { - #TypeFoo: { - name: "foo" - foo_field: string - } - #TypeBar: { - 〈1;#TypeBar2〉 - bar_field?: string - } - #TypeBar2: { - name: "bar" - } - objs: { - obj1: { - type: (〈2;#TypeFoo〉|〈2;#TypeBar〉) - type: (*〈2;objs〉["missing"]|〈2;#TypeFoo〉|〈2;#TypeBar〉) - } - } - out: (〈0;#TypeFoo〉|〈0;#TypeBar〉) - out: 〈0;objs〉["obj1"].type - } -} diff --git a/cue/testdata/disjunctions/elimination.txtar b/cue/testdata/disjunctions/elimination.txtar index 00722db88..e8899f06d 100644 --- a/cue/testdata/disjunctions/elimination.txtar +++ b/cue/testdata/disjunctions/elimination.txtar @@ -1171,1325 +1171,3 @@ Notifications: 8 NumCloseIDs: 323 -- out/todo.txt -- issue2685: only evaluated by v3 evaluator. --- out/compile -- ---- in.cue -{ - disambiguateClosed: { - b: (〈0;#Def〉 & 〈0;a〉) - a: 〈0;#Def〉 - #Def: { - ({ - x: true - }|{ - y: true - }) - } - } - alwaysCheckMatchers1: { - b: ({ - [=~"^xxxx$"]: int - }|null) - b: ({ - c: string - }|null) - b: { - c: "yyyyy" - } - } - alwaysCheckPatterns2: { - a: 〈0;#X〉 - a: 〈0;b〉 - b: 〈0;#X〉 - b: { - c: "yyyyy" - } - #X: (string|{ - c: string - { - [=~"^xxxx$"]: int - } - }) - } - nestedNonMonotonic: { - resolved: { - n1: { - x: ({ - a: 〈import;struct〉.MinFields(2) - }|null) - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: { - d: 1 - } - }|null) - } - } - } - nestedNonMonotonic: { - resolved: { - n2: { - x: ({ - a: { - b: 〈import;struct〉.MinFields(2) - } - }|null) - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: { - d: 1 - } - } - }|null) - } - } - } - nestedNonMonotonic: { - eliminated: { - n1: { - p1: { - x: ({ - a: 〈import;struct〉.MaxFields(1) - }|null) - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: { - d: 1 - } - }|null) - } - } - } - } - nestedNonMonotonic: { - eliminated: { - n1: { - p2: { - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: 〈import;struct〉.MaxFields(1) - }|null) - x: ({ - a: { - d: 1 - } - }|null) - } - } - } - } - nestedNonMonotonic: { - eliminated: { - n1: { - p2: { - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: { - d: 1 - } - }|null) - x: ({ - a: 〈import;struct〉.MaxFields(1) - }|null) - } - } - } - } - nestedNonMonotonic: { - eliminated: { - n2: { - p1: { - x: ({ - a: { - b: 〈import;struct〉.MaxFields(1) - } - }|null) - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: { - d: 1 - } - } - }|null) - } - } - } - } - nestedNonMonotonic: { - eliminated: { - n2: { - p2: { - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: 〈import;struct〉.MaxFields(1) - } - }|null) - x: ({ - a: { - b: { - d: 1 - } - } - }|null) - } - } - } - } - nestedNonMonotonic: { - eliminated: { - n2: { - p2: { - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: { - d: 1 - } - } - }|null) - x: ({ - a: { - b: 〈import;struct〉.MaxFields(1) - } - }|null) - } - } - } - } - nestedNonMonotonic: { - incomplete: { - a: { - n1: { - p1: { - x: ({ - a: 〈import;struct〉.MinFields(2) - }|null) - x: ({ - a: { - c: 1 - } - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - a: { - n1: { - p2: { - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: 〈import;struct〉.MinFields(2) - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - a: { - n2: { - p1: { - x: ({ - a: { - b: 〈import;struct〉.MinFields(2) - } - }|null) - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - a: { - n2: { - p2: { - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: 〈import;struct〉.MinFields(2) - } - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - b: { - n1: { - p1: { - x: ({ - a: 〈import;struct〉.MinFields(3) - }|null) - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: { - d: 1 - } - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - b: { - n1: { - p2: { - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: 〈import;struct〉.MinFields(3) - }|null) - x: ({ - a: { - d: 1 - } - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - b: { - n1: { - p3: { - x: ({ - a: { - c: 1 - } - }|null) - x: ({ - a: { - d: 1 - } - }|null) - x: ({ - a: 〈import;struct〉.MinFields(3) - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - b: { - n2: { - p1: { - x: ({ - a: { - b: 〈import;struct〉.MinFields(3) - } - }|null) - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: { - d: 1 - } - } - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - b: { - n2: { - p1: { - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: 〈import;struct〉.MinFields(3) - } - }|null) - x: ({ - a: { - b: { - d: 1 - } - } - }|null) - } - } - } - } - } - nestedNonMonotonic: { - incomplete: { - b: { - n2: { - p1: { - x: ({ - a: { - b: { - c: 1 - } - } - }|null) - x: ({ - a: { - b: { - d: 1 - } - } - }|null) - x: ({ - a: { - b: 〈import;struct〉.MinFields(3) - } - }|null) - } - } - } - } - } - preserveClosedness: { - small: { - p1: { - #A: (〈0;#B〉 & { - a: string - }) - #B: { - (*{}|{ - a: string - }) - (*{}|{ - b: int - }) - } - } - } - } - preserveClosedness: { - small: { - p2: { - #A: (〈0;#B〉 & { - a: string - }) - #B: { - ({ - a: string - }|*{}) - (*{}|{ - b: int - }) - } - } - } - } - preserveClosedness: { - medium: { - p1: { - #A: (〈0;#B〉 & { - a: string - }) - #B: { - (*{}|{ - a: string - }|{ - b: string - }) - (*{}|{ - c: int - }|{ - d: string - }) - } - } - } - } - preserveClosedness: { - medium: { - p2: { - #A: (〈0;#B〉 & { - a: string - }) - #B: { - ({ - a: string - }|*{}|{ - b: string - }) - (*{}|{ - c: int - }|{ - d: string - }) - } - } - } - } - preserveClosedness: { - medium: { - p3: { - #A: (〈0;#B〉 & { - a: string - }) - #B: { - ({ - a: string - }|{ - b: string - }|*{}) - (*{}|{ - c: int - }|{ - d: string - }) - } - } - } - } - noChildError: _ - noChildError: { - issue1608: { - myValue: (〈0;#type〉 & { - fieldName: "some string" - }) - #type: { - fieldName: 〈1;#subtype〉 - } - #subtype: (string|{ - foo: string - }|{ - bar: 〈1;#subtype〉 - }) - } - } - noChildError: { - t1: { - #D: ({ - b: string - }|{ - c: 〈1;#D〉 - }) - o: (〈0;#D〉 & { - b: "test" - }) - } - } - noChildError: { - t2: { - o: (〈0;#D〉 & { - b: "test" - }) - #D: ({ - b: string - }|{ - c: 〈1;#D〉 - }) - } - } - noChildError: { - t3: { - #D: ({ - a: null - }|{ - b: string - }|{ - c: 〈1;#D〉 - }) - o: (〈0;#D〉 & { - b: "test" - }) - } - } - noChildError: { - t4: { - o: (〈0;#D〉 & { - b: "test" - }) - #D: ({ - a: null - }|{ - b: string - }|{ - c: 〈1;#D〉 - }) - } - } - issue1924: { - t1: { - m: { - a: 2 - } - x: (*[ - 〈1;m〉.b, - ]|2) - } - } - issue1924: { - t2: { - m: { - a: 2 - } - x: (*{ - v: 〈1;m〉.b - }|3) - } - } - issue1924: { - t3: { - m: { - a: 2 - } - x: (*〈0;m〉.b|1) - } - } - issue1838: { - t1: { - p?: [] - a: ([ - for _, k in 〈1;p〉 { - 〈1;k〉 - }, - ]|null) - } - } - issue1838: { - t2: { - p?: [] - a: (null|[ - for _, k in 〈1;p〉 { - 〈1;k〉 - }, - ]) - } - } - noHang: { - #T: ([ - "a", - 〈1;#T〉, - ]|[ - "d", - ...〈1;#T〉, - ]) - x: 〈0;#T〉 - #X: 〈0;x〉 - #X: 〈0;#T〉 - } - issue1940: { - #T: ([ - "a", - 〈1;#T〉, - ]|[ - "b", - 〈1;#T〉, - ]|[ - "c", - 〈1;#T〉, - ]|[ - "d", - [ - ...〈2;#T〉, - ], - ]) - #A: { - type: 〈1;#T〉 - } - #B: { - [string]: 〈1;#A〉 - } - #C: (〈0;#B〉 & { - x: 〈1;#A〉 - }) - } -} ---- issue1417.cue -{ - issue1417: { - #ID: (!~"^a"|=~"^ab$"|=~"^aB$") - #ID: (=~"^a"|!~"[A-Z]") - ids: ([ - ...〈1;#ID〉, - ] & [ - "xyz", - "ab", - "aB", - ]) - } -} ---- issue2209full.cue -{ - issue2209: { - simplified: { - t1: { - #SpecFoo: { - foo: { - min: 1 - } - } - #SpecBar: { - bar: { - min: 1 - } - } - spec: { - bar: {} - } - spec: (〈0;#SpecFoo〉|〈0;#SpecBar〉) - out: { - ({ - nullFoo: null - }|{ - nullBar: null - }) - ({ - minFoo: int - }|{ - minBar: int - }) - if (〈0;X〉.bar != _|_(explicit error (_|_ literal) in source)) { - minBar: 〈1;X〉.bar.min - } - X: 〈1;spec〉 - } - } - } - } - issue2209: { - simplified: { - t2: { - #SpecFoo: { - foo: {} - } - #SpecBar: { - bar: { - x: 1 - } - } - spec: { - bar: {} - } - spec: (*〈0;#SpecFoo〉|〈0;#SpecBar〉) - if (〈0;spec〉.bar != _|_(explicit error (_|_ literal) in source)) { - BAZ: 〈1;spec〉.bar.x - } - ({ - f1: int - }|{ - b2: int - }) - ({ - f2: int - }|{ - b2: int - }) - } - } - } - issue2209: { - simplified: { - t3: { - #A: { - v: 1 - } - ({ - f1: int - }|{ - b2: int - }) - ({ - f2: int - }|{ - b2: int - }) - BAZ: 〈0;S〉.y - S: (*〈0;#A〉|〈0;#B〉) - #B: { - x: 1 - y: 1 - } - S: { - x: 1 - } - } - } - } - issue2209: { - full: { - Foo: (〈0;#Abstract〉 & { - spec: { - foo: {} - } - }) - Bar: (〈0;#Abstract〉 & { - spec: { - bar: {} - } - }) - #Abstract: { - spec: 〈1;_#Spec〉 - resource: (〈1;_Thing〉 & { - _X: { - spec: 〈3〉.spec - } - }) - } - _#Spec: (*〈0;_#SpecFoo〉|〈0;_#SpecBar〉) - _#SpecFoo: { - foo: { - min: (int|*10) - max: (int|*20) - } - } - _#SpecBar: { - bar: { - min: (int|*30) - max: (int|*40) - } - } - _Thing: (〈0;#Constrained〉 & { - _X: _ - spec: { - if (〈1;_X〉.spec.foo != _|_(explicit error (_|_ literal) in source)) { - minFoo: 〈2;_X〉.spec.foo.min - maxFoo: 〈2;_X〉.spec.foo.max - } - if (〈1;_X〉.spec.bar != _|_(explicit error (_|_ literal) in source)) { - minBar: 〈2;_X〉.spec.bar.min - maxBar: 〈2;_X〉.spec.bar.max - } - } - }) - #Constrained: (〈0;#Base〉 & { - spec: ({ - minFoo: (int|*10) - maxFoo: (int|*20) - minBar?: null - maxBar?: null - }|{ - minBar: (int|*30) - maxBar: (int|*40) - minFoo?: null - maxFoo?: null - }) - spec: (*{ - fuga?: null - }|{ - hoge?: null - }) - }) - #Base: { - spec: { - minFoo?: (null|int) - maxFoo?: (null|int) - minBar?: (null|int) - maxBar?: (null|int) - hoge?: (null|bool) - fuga?: (null|bool) - } - } - } - } -} ---- issue2246.cue -{ - issue2246: { - simplified: { - #FormFoo: { - fooID: string - } - #FormBar: { - barID: string - } - #Form: { - (〈1;#FormFoo〉|〈1;#FormBar〉) - } - data: { - fooID: "123" - } - out1: (〈0;#Form〉 & 〈0;data〉) - out2: (〈0;#Form〉 & 〈0;out1〉) - } - } - issue2246: { - full: { - data: { - forms: [ - { - fooID: "00-0000001" - }, - ] - } - form1040: (〈0;#compute〉 & { - in: 〈1;data〉 - }).out - #K1: { - #_base: { - common: 3 - } - #FormFoo: { - 〈1;#_base〉 - fooID: string - } - #FormBar: { - 〈1;#_base〉 - barID: string - } - #Form: { - (〈1;#FormFoo〉|〈1;#FormBar〉) - } - } - #Input: { - forms: [ - ...〈2;#K1〉.#Form, - ] - } - #summarizeReturn: { - in: 〈1;#Input〉 - out: [ - for _, k in 〈1;in〉.forms { - 〈1;k〉.common - }, - ] - } - #compute: { - in: 〈1;#Input〉 - out: (〈1;#summarizeReturn〉 & { - in: 〈1;in〉 - }).out - } - } - } -} ---- issue2263.cue -{ - issue2263: { - simplified: { - metrics: 〈0;#Metric〉 - #Metric: { - (〈1;#IDSource〉|{}) - (〈1;#TargetAverage〉|{}) - } - metrics: { - id: "foo" - avg: 60 - } - #IDSource: { - id: string - } - #TargetAverage: { - avg: number - } - } - } - issue2263: { - full: { - metrics: [ - ...〈1;#Metric〉, - ] - metrics: [ - { - id: "foo" - avg: 60 - }, - { - id: "bar" - value: 80 - }, - { - uri: "baz" - avg: 70 - }, - { - uri: "qux" - value: 90 - }, - ] - #Metric: { - 〈1;#Source〉 - 〈1;#Target〉 - } - #Source: (〈0;#IDSource〉|〈0;#URISource〉) - #Target: (〈0;#TargetAverage〉|〈0;#TargetValue〉) - #IDSource: { - id: string - } - #URISource: { - uri: string - } - #TargetAverage: { - avg: number - } - #TargetValue: { - value: number - } - } - } -} ---- issue2685.cue -{ - issue2685: { - #Foo: ({ - bar: int - opt?: int - }|*{ - opt: int - }) - foo: 〈0;#Foo〉 - foo: { - bar: 0 - } - { - foo: 〈1;#Foo〉 - } - } -} ---- issue3149.cue -{ - issue3149: { - #valid: { - name!: ((=~"^Foo"|"an exception") & (=~"Foo$"|"an exception")) - } - list: [ - ...〈1;#valid〉, - ] - list: [ - { - name: "FooBarFoo" - }, - { - name: "FooBazFoo" - }, - { - name: "FooQuuxFoo" - }, - { - name: "an exception" - }, - ] - } -} ---- issue3528.cue -{ - issue3528: { - original: { - workflows: [ - ...〈1;#Workflow〉, - ] - workflows: [ - 〈1;test〉, - ] - test: (〈0;#Workflow〉 & {}) - #Workflow: { - container: { - [string]: (string|〈1;#container〉) - } - #container: (string|{ - volumes?: [ - ...string, - ] - }) - } - } - } - issue3528: { - reduced: { - a?: 〈0;#A〉 - a: (〈0;#A〉 & {}) - #A: { - A: { - [string]: (1|〈1;#a〉) - } - #a: (2|{ - v: 1 - }) - } - } - } - issue3528: { - counter: {} - } - issue3528: { - nested: { - t1: { - ({ - v: 1 - }|(2|3)) - ({ - v: 1 - }|(2|3)) - ({ - v: 1 - }|(2|3)) - ({ - v: 1 - }|(2|3)) - } - } - } - issue3528: { - nested: { - t2: { - ({ - v: 1 - }|2) - ({ - v: 1 - }|(2|3)) - ({ - v: 1 - }|2) - ({ - v: 1 - }|2) - } - } - } -} ---- issue3784.cue -{ - issue3784: { - reduced: { - #Schema: { - a: ({ - kind: "A" - b: { - c?: string - } - b: {} - }|{ - kind: "B" - }) - } - out: 〈0;#Schema〉 - out: { - a: { - kind: "A" - b: { - c: "x" - } - } - } - } - } - issue3784: { - full: { - #Schema: { - pages?: { - build_type?: ("legacy"|"workflow") - source?: { - branch?: string - path?: string - } - cname?: string - } - pages?: ({ - build_type!: "legacy" - source!: { - branch!: _ - } - }|close({ - build_type!: "workflow" - cname?: _ - })) - } - out: (〈0;#Schema〉 & { - pages: { - cname: "foo.com" - build_type: "legacy" - source: { - branch: "main" - path: "/" - } - } - }) - } - } - issue3784: { - variant1: { - #Schema: { - pages: { - build_type?: ("legacy"|"workflow") - source: { - branch?: string - path?: string - } - cname?: string - } - pages?: ({ - build_type!: "legacy" - source!: { - branch!: _ - } - }|close({ - build_type!: "workflow" - cname?: _ - })) - } - } - } - issue3784: { - variant2: { - #Schema: ({ - build_type!: "legacy" - source!: { - branch!: _ - } - }|close({ - build_type!: "workflow" - cname?: _ - })) - a: 〈0;#Schema〉 - a: { - build_type?: ("legacy"|"workflow") - source: { - branch?: string - path?: string - } - cname?: string - } - } - } -} ---- issue3958.cue -{ - issue3958: { - t1: { - #schema: (int|*1) - #schema: (int|*3) - test1: (〈0;#schema〉 & { - (int|*2) - }) - test2: (〈0;#schema〉 & { - (int|*4) - }) - } - } - issue3958: { - t2: { - a: ((((int|*4) & (int|*1)) & (int|*3)) & (int|*8)) - b: (((int|*4) & (int|*1)) & (int|*3)) - } - } -} ---- issue770.cue -{ - issue770: { - #A: { - v: ("a"|"b"|"c") - } - h: { - [string]: 〈1;#A〉 - } - h: { - a: { - v: (*"a"|string) - } - } - h: { - [=~"^b"]: { - v: (*〈2;h〉.a.v|string) - } - } - h: { - [=~"^c"]: { - v: (*〈2;h〉.b.v|string) - } - } - h: { - b: _ - } - h: { - boo: _ - } - h: { - c: _ - } - h: { - coo: _ - } - } -} diff --git a/cue/testdata/disjunctions/embed.txtar b/cue/testdata/disjunctions/embed.txtar index 819b2002d..4d93a2425 100644 --- a/cue/testdata/disjunctions/embed.txtar +++ b/cue/testdata/disjunctions/embed.txtar @@ -118,119 +118,3 @@ Disjuncts: 155 Notifications: 6 NumCloseIDs: 39 --- out/compile -- ---- in.cue -{ - default: { - y: (*1|{ - a: 2 - }) - 〈0;y〉 - } - unambiguous: { - y: (1|{ - a: 2 - }) - 〈0;y〉 - } - forDefault: { - y: (*1|{ - a: 2 - }) - for _, x in [ - 1, - ] { - 〈2;y〉 - } - } - openDefault: { - #y: (*1|{ - a: 2 - }) - 〈0;#y〉 - } - openAmbiguous: { - #y: (1|{ - a: 2 - }) - 〈0;#y〉 - } - forceStruct: { - #y: (1|{ - a: 2 - }) - 〈0;#y〉 - {} - } - defaultsMulti: { - a: { - #def: { - (*{}|{ - a: string - }|{ - b: string - }) - (*{}|{ - c: string - }|{ - d: string - }) - } - a: (〈0;#def〉 & { - a: "foo" - }) - } - b: { - #def: { - (*{}|{ - a: string - }|{ - b: string - }) - (*{}|{ - c: string - }|{ - d: string - }) - (*{}|{ - d: string - }|{ - e: string - }) - } - a: (〈0;#def〉 & { - a: "foo" - e: "bar" - }) - } - } - nested: { - a: (1|2|*((3|4|*(5|6|*7)) & (3|4|(*7|8)))) - } -} ---- issue3415.cue -{ - issue3415: { - full: { - A: (〈0;#A〉 & { - i: { - (〈0;_a〉 + 〈0;_b〉) - _a: 1 - _b: 10 - } - }) - #A: { - i: (*0|number) - } - } - } - issue3415: { - reduced: { - a: { - (1 + 〈0;#b〉) - #b: 10 - } - a: (*0|number) - } - } -} diff --git a/cue/testdata/disjunctions/errors.txtar b/cue/testdata/disjunctions/errors.txtar index f548ecce4..8dab93676 100644 --- a/cue/testdata/disjunctions/errors.txtar +++ b/cue/testdata/disjunctions/errors.txtar @@ -284,233 +284,3 @@ Notifications: 2 NumCloseIDs: 51 -- out/todo.txt -- issue4022: only evaluated by v3 evaluator. --- out/compile -- ---- in.cue -{ - issue570: { - results: 〈0;#DecodeOutput〉 - results: { - result: "hello" - } - #Output: ({ - result: _ - }|{ - error: string - }) - #DecodeOutput: (〈0;#Output〉 & { - result?: [ - ...string, - ] - ... - }) - } - issue516: { - #Def: ({ - match: { - metrics: { - string: {} - } - } - }|{}) - x: 〈0;#Def〉 - x: { - match: { - metrics: { - foo: {} - } - } - } - } - explicitDefaultError: { - a: (string|*_|_(explicit error (_|_ literal) in source)) - if (〈0;a〉 != "") {} - } - issue2916: { - b: _ - [_]: { - c: (&(int, >=0)|*1) - } - [string]: { - c: (>=3|*3) - } - } - issue3157: { - foo: (*42|_) - foo: (*43|bool) - } -} ---- issue3576.cue -{ - issue3576: { - reduced: { - #A: { - a!: string - } - #B: { - if false { - dummy: {} - } - } - foo: (〈0;#B〉|〈0;#A〉) - foo: { - a: "1" - } - } - } - issue3576: { - full: { - #Run: { - run!: string - options?: (〈1;#Option〉|[ - 〈2;#Option〉, - ..., - ]) - if (〈0;options〉 != _|_(explicit error (_|_ literal) in source)) { - optionsValue: 〈1;options〉 - } - } - #Copy: { - copy!: string - options?: (〈1;#Option〉|[ - 〈2;#Option〉, - ..., - ]) - if (〈0;options〉 != _|_(explicit error (_|_ literal) in source)) { - optionsValue: 〈1;options〉 - } - } - #Option: {} - foo: (〈0;#Run〉|〈0;#Copy〉) - foo: { - run: "make" - } - } - } -} ---- issue3581.cue -{ - issue3581: { - reduced: { - list: ([ - ..., - ]|*[]) - list: [ - "\(〈1;c〉)", - ] - c: _ - } - } -} ---- issue3599.cue -{ - issue3599: { - full: { - #Action: { - action: ({ - read!: string - write?: _|_(explicit error (_|_ literal) in source) - }|{ - write!: string - read?: _|_(explicit error (_|_ literal) in source) - }) - } - #Minio: { - container: (〈1;#Action〉 & { - action: ({ - read!: string - write?: _|_(explicit error (_|_ literal) in source) - }|{ - write!: string - read?: _|_(explicit error (_|_ literal) in source) - }) - }) - doWrite: (bool|*true) - container: { - action: 〈1;defaultAction〉 - } - defaultAction: { - if 〈1;doWrite〉 { - write: "somefile.txt" - } - if !〈1;doWrite〉 { - read: "somefile.txt" - } - } - } - } - } - issue3599: { - reduced: { - p1: { - ({ - a?: (1 & 2) - }|{ - a: string - b?: (1 & 2) - }) - ({}|{}) - } - } - } - issue3599: { - reduced: { - p2: { - ({}|{}) - ({ - a?: (1 & 2) - }|{ - a: string - b?: (1 & 2) - }) - } - } - } - issue3599: { - let: { - ({}|{ - a: (〈0;let B#1〉|1) - let B#1 = (1 & 2) - }) - ({}|{}) - } - } -} ---- optionalerror.cue -{ - issue4022: { - reduced: { - #NonNamespaced: { - metadata: { - namespace?: _|_(explicit error (_|_ literal) in source) - } - } - #NullOrNonNamespaced: (int|〈0;#NonNamespaced〉) - out: 〈0;#NullOrNonNamespaced〉 - out: 〈0;#NonNamespaced〉 - out: { - metadata: {} - } - } - } - issue4022: { - full: { - #NonNamespaced: { - metadata: { - name!: string - namespace?: _|_(explicit error (_|_ literal) in source) - ... - } - ... - } - #NullOrNonNamespaced: (null|〈0;#NonNamespaced〉) - out: 〈0;#NullOrNonNamespaced〉 - out: 〈0;#NonNamespaced〉 - out: { - metadata: { - name: "foo" - } - apiVersion: "v1" - } - } - } -} diff --git a/cue/testdata/disjunctions/incomplete.txtar b/cue/testdata/disjunctions/incomplete.txtar index 8ad3dfca8..4704aed14 100644 --- a/cue/testdata/disjunctions/incomplete.txtar +++ b/cue/testdata/disjunctions/incomplete.txtar @@ -132,75 +132,3 @@ Conjuncts: 104 Disjuncts: 42 NumCloseIDs: 9 --- out/compile -- ---- in.cue -{ - issue700: { - a: { - y: "y" - } - test1: (*〈0;a〉.x|1) - test2: (*〈0;a〉.y|1) - } - lookup: { - x: { - name: "Hello" - } - y: 〈0;x〉.a - ok1: (*〈0;x〉.a|〈0;x〉) - ok2: (〈0;x〉|*〈0;x〉.a) - ok3: (〈0;x〉.a|*〈0;x〉) - ok4: (*〈0;x〉|〈0;x〉.a) - ok5: (〈0;x〉|〈0;x〉.a) - ok5: (〈0;x〉.a|〈0;x〉) - allFail1: (〈0;x〉.a|〈0;x〉.b) - allFail2: (〈0;x〉.a|〈0;x〉.b) - } - func: { - s: string - ok1: (〈import;"encoding/yaml"〉.MarshalStream(〈0;s〉)|〈import;"encoding/yaml"〉.Marshal(〈0;s〉)) - } - issue782: { - a: { - inner: string - interpolation: (*"\(〈0;inner〉)"|string) - interpolation: "override" - } - b: { - inner: string - interpolation: (string|*"\(〈0;inner〉)") - interpolation: "override" - } - c: { - inner: string - interpolation: ("\(〈0;inner〉)"|string) - interpolation: "override" - } - d: { - inner: string - interpolation: (string|"\(〈0;inner〉)") - interpolation: "override" - } - } -} ---- issue3680.cue -{ - issue3680: { - t1: { - ({}|{ - a?: _|_(explicit error (_|_ literal) in source) - b?: _|_(explicit error (_|_ literal) in source) - }) - ({}|{}) - } - } - issue3680: { - t2: { - x: ({}|{ - a?: _|_(explicit error (_|_ literal) in source) - b?: _|_(explicit error (_|_ literal) in source) - }) - x: ({}|{}) - } - } -} diff --git a/cue/testdata/disjunctions/issue2209.txtar b/cue/testdata/disjunctions/issue2209.txtar index 8c0de7ba1..f974cee75 100644 --- a/cue/testdata/disjunctions/issue2209.txtar +++ b/cue/testdata/disjunctions/issue2209.txtar @@ -174,130 +174,6 @@ reduced: { -- out/todo.txt -- full: evalv2 produced errors ("empty disjunction") for full.Bar.resource.spec and reduced.Bar.out.minBar; evalv3 evaluates both correctly without errors. --- out/compile -- ---- input.cue -{ - full: { - Foo: (〈0;#Abstract〉 & { - spec: { - foo: {} - } - }) - Bar: (〈0;#Abstract〉 & { - spec: { - bar: {} - } - }) - #Abstract: { - spec: 〈1;_#Spec〉 - resource: (〈1;_Thing〉 & { - _X: { - spec: 〈3〉.spec - } - }) - } - _#Spec: (*〈0;_#SpecFoo〉|〈0;_#SpecBar〉) - _#SpecFoo: { - foo: { - min: (int|*10) - max: (int|*20) - } - } - _#SpecBar: { - bar: { - min: (int|*30) - max: (int|*40) - } - } - _Thing: (〈0;#Constrained〉 & { - _X: _ - spec: { - if (〈1;_X〉.spec.foo != _|_(explicit error (_|_ literal) in source)) { - minFoo: 〈2;_X〉.spec.foo.min - maxFoo: 〈2;_X〉.spec.foo.max - } - if (〈1;_X〉.spec.bar != _|_(explicit error (_|_ literal) in source)) { - minBar: 〈2;_X〉.spec.bar.min - maxBar: 〈2;_X〉.spec.bar.max - } - } - }) - #Constrained: (〈0;#Base〉 & { - spec: ({ - minFoo: (int|*10) - maxFoo: (int|*20) - minBar?: null - maxBar?: null - }|{ - minBar: (int|*30) - maxBar: (int|*40) - minFoo?: null - maxFoo?: null - }) - spec: (*{ - fuga?: null - }|{ - hoge?: null - }) - }) - #Base: { - spec: { - minFoo?: (null|int) - maxFoo?: (null|int) - minBar?: (null|int) - maxBar?: (null|int) - hoge?: (null|bool) - fuga?: (null|bool) - } - } - } - reduced: { - Foo: (〈0;#Obj〉 & { - spec: { - foo: {} - } - }) - Bar: (〈0;#Obj〉 & { - spec: { - bar: {} - } - }) - #Obj: { - spec: (*〈1;#SpecFoo〉|〈1;#SpecBar〉) - out: (〈1;#Out〉 & { - _Xspec: 〈2〉.spec - if (〈0;_Xspec〉.foo != _|_(explicit error (_|_ literal) in source)) { - minFoo: 〈1;_Xspec〉.foo.min - } - if (〈0;_Xspec〉.bar != _|_(explicit error (_|_ literal) in source)) { - minBar: 〈1;_Xspec〉.bar.min - } - }) - } - #SpecFoo: { - foo: { - min: (int|*10) - } - } - #SpecBar: { - bar: { - min: (int|*20) - } - } - #Out: { - ({ - minFoo: int - }|{ - minBar: int - }) - (*{ - nullFoo: null - }|{ - nullBar: null - }) - } - } -} -- out/eval/stats -- Leaks: 92 Freed: 910 diff --git a/cue/testdata/disjunctions/issue3850.txtar b/cue/testdata/disjunctions/issue3850.txtar index f764e495e..cc76f7904 100644 --- a/cue/testdata/disjunctions/issue3850.txtar +++ b/cue/testdata/disjunctions/issue3850.txtar @@ -110,98 +110,3 @@ Conjuncts: 125 Disjuncts: 22 NumCloseIDs: 18 --- out/compile -- ---- issue3850.cue -{ - issue3850: { - full: { - global: { - glb1: { - glb2: "123" - } - } - out: ({ - foo?: _ - }|{}) - out: ({ - foo?: _ - }|{}) - out: 〈0;#WithFoo〉 - #WithFoo: { - _global: 〈1;global〉 - foo: 〈0;_global〉.glb1.glb2 - } - } - } - issue3850: { - incomplete: { - global: { - glb1: { - glb2: "123" - } - } - out: ({ - foo?: _ - }|{}) - out: ({ - foo?: _ - }|{}) - out: 〈0;#WithFoo〉 - #WithFoo: { - _global: 〈1;global〉 - foo: 〈0;_global〉.glb1.glb2 - ... - } - } - } - issue3850: { - p2p: { - out: (*{}|_) - out: (*{}|_) - out: { - reg: 〈0;#def〉 - #def: { - foo: 〈2;_global〉 - } - } - _global: "global value" - } - } -} ---- issue3875.cue -{ - issue3875: { - full: { - _global: { - name: "foo" - } - out: { - desc: { - _hidden: 〈2;_global〉.name - name: 〈0;_hidden〉 - } - } - out: (〈0;#Schema〉|"never") - #Schema: { - desc: { - ... - } - } - } - } - issue3875: { - reduced: { - global: { - a: "foo" - } - out: { - desc: { - a: 〈0;b〉 - b: 〈2;global〉.a - } - } - out: (〈0;S〉|null) - S: {} - } - } -} diff --git a/cue/testdata/disjunctions/issue3857.txtar b/cue/testdata/disjunctions/issue3857.txtar index 883416451..02cb8e173 100644 --- a/cue/testdata/disjunctions/issue3857.txtar +++ b/cue/testdata/disjunctions/issue3857.txtar @@ -106,89 +106,3 @@ Conjuncts: 119 Disjuncts: 26 NumCloseIDs: 25 --- out/compile -- ---- in.cue -{ - reduced: { - t1: { - S: { - if true { - a: 〈2;U〉 - } - } - x: 〈0;S〉 - x: { - ["a"]: { - b: (1|〈2;T〉) - } - d: { - b: 〈2;x〉.a - } - } - T: 1 - U: { - b: (1|1) - } - } - } - issue3851: { - t1: { - #Top: _ - #Config: { - disj: (_|*"default") - shared: _ - } - #Schema: { - [string]: 〈1;#Config〉 - if true { - one: { - shared: "foo" - } - } - } - out: 〈0;#Schema〉 - out: { - ["one"]: { - disj: (_|〈2;#Top〉) - } - two: { - shared: 〈2;out〉.one.shared - } - } - } - } - issue3851: { - t2: { - #Top: _ - #Config: { - disj: (_|*{}) - shared: _ - } - #Env: { - conf: { - [string]: 〈2;#Config〉 - } - if true { - conf: { - one: { - shared: "foo" - } - } - } - } - env1: 〈0;#Env〉 - [string]: { - conf: { - ["one"]: { - disj: ({}|〈3;#Top〉) - } - } - conf: { - two: { - shared: 〈2;conf〉.one.shared - } - } - } - } - } -} diff --git a/cue/testdata/disjunctions/issue4339.txtar b/cue/testdata/disjunctions/issue4339.txtar index 2adf815eb..3ca0bde60 100644 --- a/cue/testdata/disjunctions/issue4339.txtar +++ b/cue/testdata/disjunctions/issue4339.txtar @@ -15,16 +15,3 @@ out: { // TODO: we should be able to use @test(final) here, avoiding the defaults. *{one: 1, enable: *true | false, extra: 1} | {one: 1, enable: *true | false}, ) --- out/compile -- ---- in.cue -{ - _withExtra: { - extra: 〈1;out〉.one - } - out: { - (*〈1;_withExtra〉|{}) - one: 1 - enable: (*true|false) - if 〈0;enable〉 {} - } -} diff --git a/cue/testdata/disjunctions/nested.txtar b/cue/testdata/disjunctions/nested.txtar index 5d7280276..132d6a42b 100644 --- a/cue/testdata/disjunctions/nested.txtar +++ b/cue/testdata/disjunctions/nested.txtar @@ -89,80 +89,3 @@ Conjuncts: 118 Disjuncts: 32 NumCloseIDs: 19 --- out/compile -- ---- issue3635.cue -{ - issue3635: { - case1: { - Run: { - env: (*{ - [string]: string - }|[ - ...string, - ]) - } - command: (〈0;Run〉 & { - env: 〈import;list〉.Concat([ - [ - "foo", - ], - [ - "bar", - ], - ]) - }) - } - } - issue3635: { - case2: { - out: [ - ...〈1;#Schema〉, - ] - out: [ - (〈1;#Schema〉 & { - name: "x" - }), - ] - #Schema: { - name?: string - container?: { - [string]: (string|〈1;#container〉) - } - #container: (string|{ - env?: 〈1;#env〉 - }) - #env: { - [string]: (bool|string) - } - } - } - } - issue3635: { - reduced: { - out: ({ - 〈1;X〉 - } & 〈0;X〉) - X: { - b: (int|〈0;c〉) - c: (int|{ - e: 〈2;d〉 - }) - } - d: 1 - } - } - issue3635: { - reduced_noshare: { - out: ({ - 〈1;X〉 - } & 〈0;X〉) - X: { - b: (int|〈0;c〉) - c: (int|{ - e: (〈2;d〉 & _|_(no sharing)) - }) - } - d: 1 - } - } -} diff --git a/cue/testdata/disjunctions/operands.txtar b/cue/testdata/disjunctions/operands.txtar index 5f644674e..0556a78c4 100644 --- a/cue/testdata/disjunctions/operands.txtar +++ b/cue/testdata/disjunctions/operands.txtar @@ -52,44 +52,3 @@ Conjuncts: 33 Disjuncts: 8 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - list: (*[ - 1, - ]|[ - 2, - ]) - condition: (*true|false) - num: (*1|2) - object: (*{ - a: 1 - }|{ - a: 2 - }) - forLoop: [ - for _, e in 〈1;list〉 { - "count: \(〈1;e〉)" - }, - ] - conditional: { - if 〈1;condition〉 { - a: 3 - } - if (〈1;num〉 < 5) { - b: 3 - } - } - selector: { - a: 〈1;object〉.a - } - index: { - a: 〈1;list〉[0] - } - binOp: { - a: (〈1;num〉 + 4) - } - unaryOp: { - a: -〈1;num〉 - } -} diff --git a/cue/testdata/disjunctions/propagate_err.txtar b/cue/testdata/disjunctions/propagate_err.txtar index c162ed1d5..671bb01e0 100644 --- a/cue/testdata/disjunctions/propagate_err.txtar +++ b/cue/testdata/disjunctions/propagate_err.txtar @@ -42,41 +42,3 @@ err: { ./pending.cue:4:5 ./pending.cue:3:5 ./pending.cue:4:9 --- out/compile -- ---- issue4056.cue -{ - issue4056: { - full: { - a: "foo-bar" - a: (_|error("error message 1")) - if 〈import;strings〉.HasPrefix(〈0;a〉, "foo") { - a: (_|error("error message 2")) - } - } - } - issue4056: { - reduced: { - a: "x" - a: (_|error("a")) - if (len(〈0;a〉) > 0) { - a: (_|error("b")) - } - } - } - variant: { - a: "x" - a: (string|int) - if (len(〈0;a〉) > 0) { - a: _ - } - } -} ---- pending.cue -{ - err: { - A: "forty two" - if (〈0;A〉 < 100) { - B: true - } - } -} diff --git a/cue/testdata/disjunctions/resolve.txtar b/cue/testdata/disjunctions/resolve.txtar index 92ce2adb2..06cfa2b24 100644 --- a/cue/testdata/disjunctions/resolve.txtar +++ b/cue/testdata/disjunctions/resolve.txtar @@ -24,37 +24,3 @@ Conjuncts: 33 Disjuncts: 12 NumCloseIDs: 6 --- out/compile -- ---- in.cue -{ - resolveAcrossDisjunct: { - t1: { - ({}|{ - #B: 1 - }) - ({ - d: 〈1;#B〉 - }|{}) - #B: int - } - } - resolveAcrossDisjunct: { - nested: { - ({}|{ - a: { - b: { - #B: 1 - } - } - }) - ({ - d: 〈1;a〉.b.#B - }|{}) - a: { - b: { - #B: int - } - } - } - } -} diff --git a/cue/testdata/disjunctions/specdeviation.txtar b/cue/testdata/disjunctions/specdeviation.txtar index da3bba933..24825f1d3 100644 --- a/cue/testdata/disjunctions/specdeviation.txtar +++ b/cue/testdata/disjunctions/specdeviation.txtar @@ -94,50 +94,3 @@ Conjuncts: 184 Disjuncts: 121 NumCloseIDs: 10 --- out/compile -- ---- in.cue -{ - Q: (*1|int) - q: (*〈0;Q〉|int) - P: (*1|int) - P: 2 - p: (*〈0;P〉|int) - r: ((*3|(*1|2)) & (1|2)) - s: ((3|(*1|2)) & (1|2)) - s1: (〈0;#Size〉 & { - min: 5 - }) - #Size: { - max: (>〈0;min〉|*〈0;min〉) - res: (&(int, >=0)|*0) - min: (>〈0;res〉|*(1 + 〈0;res〉)) - } - staged: { - c: (("a"|"b") & (*(*"a"|string)|string)) - d: ((*(*"a"|string)|string) & ("a"|"b")) - } - issue763a: { - #A: { - v: ("a"|"b"|"c") - } - h: { - [string]: 〈1;#A〉 - } - h: { - [=~"^b"]: (〈1;#A〉 & { - v: (*〈2;h〉.a.v|string) - }) - } - h: { - a: { - v: (*"a"|string) - } - } - h: { - baa: _ - } - h: { - boo: _ - } - } -} diff --git a/cue/testdata/eval/basictypes.txtar b/cue/testdata/eval/basictypes.txtar index c38388d40..7969b2901 100644 --- a/cue/testdata/eval/basictypes.txtar +++ b/cue/testdata/eval/basictypes.txtar @@ -24,60 +24,6 @@ comparison: { } -- out/todo.txt -- It doesn't seem like this should be a compile error. --- out/compile -- -comparison.typeComparison.err: invalid operand string ('==' requires concrete value): - ./in.cue:16:23 -comparison.typeComparison.err: invalid operand number ('==' requires concrete value): - ./in.cue:16:33 ---- in.cue -{ - top: { - a: { - _ - } - b: _ - } - scalar: { - a: { - string - } - b: string - c: { - { - { - number - } - } - } - d: number - } - comparison: { - basicEquality: { - t: (42 == 42) - } - typeComparison: { - err: (string == number) - } - structEquality: { - t: ({ - name: "test" - } == { - name: "test" - }) - } - nestedComparison: { - t: ({ - data: { - value: 1 - } - } == { - data: { - value: 1 - } - }) - } - } -} -- out/evalalpha -- comparison.typeComparison.err: invalid operand string ('==' requires concrete value): ./in.cue:16:23 diff --git a/cue/testdata/eval/bounds.txtar b/cue/testdata/eval/bounds.txtar index ba36b8107..80b520704 100644 --- a/cue/testdata/eval/bounds.txtar +++ b/cue/testdata/eval/bounds.txtar @@ -514,324 +514,3 @@ Conjuncts: 422 Disjuncts: 0 NumCloseIDs: 8 --- out/compile -- ---- binary.cue -{ - simplifyBinary: { - float: { - err1: { - p1: (<1 & >2) - p2: (>2 & <1) - } - err2: { - p1: (>2 & <=1) - p2: (<=1 & >2) - } - err3: { - p1: (>=2 & <2) - p2: (<2 & >=2) - p3: (>2 & <=2) - p4: (<=2 & >2) - } - ok1: { - p1: (>1 & <2) - p2: (<2 & >1) - } - ok2: { - p1: (>=2 & <=2) - p2: (<=2 & >=2) - } - } - } - simplifyBinary: { - integer: { - [_]: { - [_]: int - } - err1: { - p1: (<1 & >2) - p2: (>2 & <1) - } - err2: { - p1: (>2 & <=1) - p2: (<=1 & >2) - } - err3: { - p1: (>=2 & <2) - p2: (<2 & >=2) - p3: (>2 & <=2) - p4: (<=2 & >2) - } - err4: { - p1: (>1 & <2) - p2: (<2 & >1) - } - ok1: { - p1: (>=2 & <=3) - p2: (<=3 & >=2) - } - ok2: { - p1: (>=2 & <=2) - p2: (<=2 & >=2) - } - ok3: { - p1: (>=2 & <3) - p2: (>2 & <=3) - p3: (<3 & >=2) - p4: (<=3 & >2) - } - } - } -} ---- binarystring.cue -{ - simplifyBinary: { - strings: { - err1: { - p1: (<"a" & >"b") - p2: (>"b" & <"a") - } - err2: { - p1: (>"b" & <="a") - p2: (<="a" & >"b") - } - err3: { - p1: (>="b" & <"b") - p2: (<"b" & >="b") - p3: (>"b" & <="b") - p4: (<="b" & >"b") - } - ok1: { - p1: (>"a" & <"b") - p2: (<"b" & >"a") - } - ok2: { - p1: (>"a" & <="b") - p2: (<="b" & >"a") - p3: (>="a" & <"b") - p4: (<"b" & >="a") - } - ok3: { - p1: (>="b" & <="c") - p2: (<="c" & >="b") - } - ok4: { - p1: (>="b" & <="b") - } - } - } - simplifyBinary: { - byte: { - err1: { - p1: (<'a' & >'b') - p2: (>'b' & <'a') - } - err2: { - p1: (>'b' & <='a') - p2: (<='a' & >'b') - } - err3: { - p1: (>='b' & <'b') - p2: (<'b' & >='b') - p3: (>'b' & <='b') - p4: (<='b' & >'b') - } - ok1: { - p1: (>'a' & <'b') - p2: (<'b' & >'a') - } - ok2: { - p1: (>'a' & <='b') - p2: (<='b' & >'a') - p3: (>='a' & <'b') - p4: (<'b' & >='a') - } - ok3: { - p1: (>='b' & <='c') - p2: (<='c' & >='b') - } - ok4: { - p1: (>='b' & <='b') - } - } - } -} ---- equals.cue -{ - equalScalar: { - ok1: ==1 - ok1: 1 - ok2: [ - 1, - 2, - ] - ok2: ==[ - 1, - 2, - ] - err1: ==1 - err1: 2 - err2: [ - 1, - 2, - ] - err2: !=[ - 1, - 2, - ] - } - equalStruct: { - ok1: =={} - ok1: {} - ok2: { - a: 1 - b: 2 - } - ok2: =={ - a: 1 - b: 2 - } - err1: =={} - err1: { - a: 1 - b: 2 - } - err2: { - a: 1 - b: 2 - } - err2: !={ - a: 1 - b: 2 - } - } - nonConcrete: { - ok0: =="foo" - _int: int - iErr1: ==〈0;_int〉 - iErr2: !=〈0;_int〉 - iErr3: ==〈0;_int〉 - iErr3: ==1 - ok4: ==1 - ok4: 〈0;_int〉 - eErr5: =="foo" - eErr5: 〈0;_int〉 - eErr6: ==〈0;_int〉 - eErr6: "foo" - } -} ---- in.cue -{ - x0: 5 - x1: (〈0;b5〉 & 30) - b0: (<〈0;x0〉 & >0) - b1: (〈0;b0〉 & int) - b2: (int & <5.5) - b3: (<10 & <=5) - b4: (>=20 & >20) - b5: (>=21 & >20) - b6: ((int & >5) & <=6) - simplifyExpr: { - less1: <<3 - less2: <<=3 - less3: <=<3 - less4: <=<=3 - less5: >3 - gtr2: >>=3 - gtr3: >=>3 - gtr4: >=>=3 - gtr5: >!=3 - gtr6: >=!=3 - lg1: <>3 - lg2: <>=3 - lg3: <=>3 - lg4: <=>=3 - gl1: ><3 - gl2: ><=3 - gl3: >=<3 - gl4: >=<=3 - ne1: !=!=3 - ne2: !=<3 - ne3: !=<=3 - ne4: !=>3 - ne5: !=>=3 - s: string - n: number - i: int - f: float - b: bytes - basic1: <〈0;i〉 - basic2: >〈0;n〉 - basic3: >=〈0;s〉 - basic4: <=〈0;f〉 - basic5: <=〈0;b〉 - bne1: !=〈0;s〉 - bne2: !=〈0;n〉 - bne3: !=〈0;n〉 - bne4: !=〈0;i〉 - bne5: !=〈0;b〉 - e1: <=~"foo" - e2: >null - } -} ---- issue4142.cue -{ - inDefinitions: { - ok1: { - #X: =={ - name: "X" - } - x: (〈0;#X〉 & { - name: "X" - }) - } - } - inDefinitions: { - ok2: { - x: (〈0;#X〉 & { - name: "Y" - }) - #X: !={ - name: "X" - } - } - } - inDefinitions: { - err1: { - #X: =={ - name: "X" - } - x: (〈0;#X〉 & { - name: "Y" - }) - } - } - inDefinitions: { - err2: { - #X: !={ - name: "X" - } - x: (〈0;#X〉 & { - name: "X" - }) - } - } -} ---- issue4251-panic.cue -{ - issue4251: { - ok: { - a: ((!="c" & =="a") & "a") - b: ((=="b" & !="c") & "b") - c: ((=="x" & >="a") & "x") - d: ((<="z" & =="y") & "y") - } - } - issue4251: { - fail: { - b: ((=="b" & !="b") & "b") - } - } -} diff --git a/cue/testdata/eval/bulk.txtar b/cue/testdata/eval/bulk.txtar index c2cc2d59f..727f6683e 100644 --- a/cue/testdata/eval/bulk.txtar +++ b/cue/testdata/eval/bulk.txtar @@ -248,271 +248,6 @@ Disjuncts: 35 Notifications: 6 NumCloseIDs: 80 --- out/compile -- ---- in.cue -{ - a: { - foo: { - a: 1 - } - [=~"foo"]: { - b: 1 - name: 〈1;-〉 - } - } - d: (〈0;a〉 & { - foobar: { - c: 2 - } - }) - t1: { - #a: { - [(>"e" & <"z")]: int - } - b: (〈0;#a〉 & { - f: 4 - }) - c: (〈0;#a〉 & { - z: 4 - }) - } - t2: { - #a: { - [("x"|"y")]: int - } - b: (〈0;#a〉 & { - x: 4 - }) - c: (〈0;#a〉 & { - z: 4 - }) - } -} ---- intpattern.cue -{ - issue3670: { - #X: { - [int]: string - } - a: 〈0;#X〉 - a: { - not_int: "c" - } - } - dual: { - _ - [string]: _ - [int]: _ - } -} ---- issue2109.cue -{ - patternCycle: { - issue2109: { - p1: { - countries: [ - "US", - "GB", - "AU", - ] - FlagsURLs: { - [or(〈1;countries〉)]: string - } - 〈0;FlagsURLs〉 - } - } - } - patternCycle: { - issue2109: { - p2: { - FlagsURLs: { - [or(〈1;countries〉)]: string - } - 〈0;FlagsURLs〉 - countries: [ - "US", - "GB", - "AU", - ] - } - } - } - patternCycle: { - issue2109: { - p3: { - 〈0;FlagsURLs〉 - FlagsURLs: { - [or(〈1;countries〉)]: string - } - countries: [ - "US", - "GB", - "AU", - ] - } - } - } - patternCycle: { - t1: { - p1: { - countries: ("US"|"GB"|"AU") - FlagsURLs: { - [〈1;countries〉]: string - } - 〈0;FlagsURLs〉 - } - } - } - patternCycle: { - t1: { - p2: { - 〈0;FlagsURLs〉 - countries: ("US"|"GB"|"AU") - FlagsURLs: { - [〈1;countries〉]: string - } - } - } - } - patternCycle: { - t1: { - p3: { - 〈0;FlagsURLs〉 - FlagsURLs: { - [〈1;countries〉]: string - } - countries: ("US"|"GB"|"AU") - } - } - } -} ---- multi.cue -{ - issue3638: { - full: { - routes: { - default: {} - } - routes: { - [string]: { - spec: [ - { - refs: [ - { - "default" - }, - ] - }, - ] - } - } - #Fields: { - input: _ - output: [ - for _, x in 〈1;input〉 { - 〈1;x〉 - }, - ] - ... - } - #Kubernetes: { - (〈1;#Fields〉 & { - Routes: { - route: { - [_]: { - spec!: 〈5;let HTTPROUTESPEC#1〉.#x - } - } - } - }) - 〈1;#Fields〉 - Routes: _ - input: { - res1: 〈1;Routes〉 - } - } - let HTTPROUTESPEC#1 = { - #x: ([ - ...{ - refs: [ - ...{ - string - }, - ] - }, - ]|*[ - { - other: [] - }, - ]) - } - entrypoint: 〈0;used〉.output - used: (〈0;#Kubernetes〉 & { - Routes: { - route: 〈2;routes〉 - } - }) - } - } - issue3638: { - reduced: { - input: { - k1: { - [string]: { - a: 1 - } - } - } - input: { - k1: { - foo: 〈2;#x〉 - } - } - out: { - for _, x in 〈1;input〉 { - 〈1;x〉 - } - for _, x in 〈1;input〉 { - 〈1;x〉 - } - } - #x: ({ - a: int - }|*{ - b: 2 - }) - } - } - issue3638: { - compare: { - input: { - k1: { - foo: { - a: 1 - } - } - } - input: { - k1: { - foo: 〈2;#x〉 - } - } - out: { - for _, x in 〈1;input〉 { - 〈1;x〉 - } - for _, x in 〈1;input〉 { - 〈1;x〉 - } - } - #x: ({ - a: int - }|*{ - b: 2 - }) - } - } -} -- out/todo.txt -- patternCycle.t1.{p1,p2,p3}: v2 had cyclic pattern constraint errors; v3 resolves correctly. issue3638.full.entrypoint and issue3638.full.#Kubernetes.input.res1: v3 uses structure sharing (~), v2 expands. diff --git a/cue/testdata/eval/closed_disjunction.txtar b/cue/testdata/eval/closed_disjunction.txtar index 3ec16b9a3..5a8419895 100644 --- a/cue/testdata/eval/closed_disjunction.txtar +++ b/cue/testdata/eval/closed_disjunction.txtar @@ -34,27 +34,5 @@ Conjuncts: 39 Disjuncts: 12 NumCloseIDs: 8 --- out/compile -- ---- in.cue -{ - #A: { - b?: int - (*{}|{ - c?: int - }|{ - d?: int - }|{ - e?: int - }) - } - a: (〈0;#A〉 & { - b: 3 - c: 3 - }) - b: (〈0;#A〉 & { - c: 3 - d: 4 - }) -} -- out/todo.txt -- v3 drops e? from b's error result and only shows the two sub-errors without extra positions; v2 showed e? and more error positions including compile-time locations. diff --git a/cue/testdata/eval/closedness.txtar b/cue/testdata/eval/closedness.txtar index ce9ca13b5..198143a4f 100644 --- a/cue/testdata/eval/closedness.txtar +++ b/cue/testdata/eval/closedness.txtar @@ -1096,1320 +1096,3 @@ Disjuncts: 6 Notifications: 1 NumCloseIDs: 585 --- out/compile -- ---- ellipsis.cue -{ - issue3778: { - full: { - #x: { - a?: string - } - #y: (〈0;#x〉 & { - ... - }) - z: (〈0;#y〉 & { - a: "ok" - b: "something" - }) - } - } - issue3778: { - keepOpen: { - #x: { - a?: string - ... - } - #y: (〈0;#x〉 & { - ... - }) - z: (〈0;#y〉 & { - a: "ok" - b: "something" - }) - } - } - issue1867: { - one: { - #T: close({}) - #T: { - ... - } - x: 〈0;#T〉 - x: { - foo: "foo" - } - } - } - issue1867: { - two: { - #S: {} - #T: { - s: 〈1;#S〉 - } - #T: { - s: { - ... - } - } - x: 〈0;#T〉.s - x: { - foo: "foo" - } - } - } - issue1867: { - three: { - #T: { - s: close({}) - } - #T: { - s: { - ... - } - } - x: 〈0;#T〉.s - x: { - foo: "foo" - } - } - } - issue3924: { - one: { - #Schema: { - ... - { - [string]: 〈2;#SchemaInner〉 - } - } - #SchemaInner: { - allowed?: string - } - out: (〈0;#Schema〉 & { - foo: { - disallowed: "foo" - } - }) - } - } - issue3924: { - two: { - #Schema: { - { - [string]: 〈1;#job〉 - } - #job: (matchN(1, [ - { - other?: string - ... - }, - ]) & close({ - allowed?: string - })) - } - out: (〈0;#Schema〉 & { - foo: { - disallowed: "bar" - } - }) - } - } - issue3924: { - three: { - t1: { - { - foo: (〈1;#job〉 & { - disallowed: "bar" - }) - } - #job: { - other?: string - } - #job: 〈0;#def〉 - #def: { - allowed?: string - } - } - } - } - issue3924: { - three: { - t2: { - { - foo: (〈1;#job〉 & { - disallowed: "bar" - }) - } - #job: { - other?: string - ... - } - #job: 〈0;#def〉 - #def: { - allowed?: string - } - } - } - } - issue3924: { - three: { - t3: { - #job: { - ... - } - #job: 〈0;#def〉 - #def: {} - foo: (〈0;#job〉 & { - disallowed: "bar" - }) - } - } - } - issue3924: { - four: { - A: { - { - foo: 〈2;#B〉 - } - } - #B: { - allowed?: string - } - out: (〈0;A〉 & { - foo: { - disallowed: "foo" - } - }) - } - } -} ---- embed.cue -{ - issue3325: { - ok: { - #Items: { - [string]: { - name: 〈1;-〉 - } - } - #Base: { - name: "base" - type: string - items: 〈1;#Items〉 - } - #Extended: (〈0;#Base〉 & { - type: "extended" - items: { - "my-item": {} - } - }) - broken: { - 〈1;#Base〉 - 〈1;#Extended〉 - } - works: { - 〈1;#Extended〉 - 〈1;#Base〉 - } - } - } - patterns: { - shallow: { - #a: { - [>="k"]: int - } - #b: { - [<="m"]: int - } - #c: { - [>="w"]: int - } - #d: { - [<="y"]: int - } - single: { - X: 〈1;#a〉 - err: 〈0;X〉 - err: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - and: { - p1: { - X: (〈2;#a〉 & 〈2;#b〉) - err: 〈0;X〉 - err: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - } - and: { - p2: { - X: (〈2;#b〉 & 〈2;#a〉) - err: 〈0;X〉 - err: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - } - andEmbed: { - p1: { - X: { - (〈3;#a〉 & 〈3;#b〉) - } - err: 〈0;X〉 - err: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - } - andEmbed: { - p2: { - X: { - (〈3;#b〉 & 〈3;#a〉) - } - err: 〈0;X〉 - err: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - } - orEmbed: { - p1: { - X: { - 〈3;#a〉 - 〈3;#b〉 - } - ok1: 〈0;X〉 - ok1: { - j: 3 - } - ok2: 〈0;X〉 - ok2: { - k: 3 - } - } - } - orEmbed: { - p2: { - X: { - 〈3;#b〉 - 〈3;#a〉 - } - ok1: 〈0;X〉 - ok1: { - j: 3 - } - ok2: 〈0;X〉 - ok2: { - k: 3 - } - } - } - andOrEmbed: { - t1: { - p1: { - X: { - (〈4;#a〉 & 〈4;#b〉) - (〈4;#c〉 & 〈4;#d〉) - } - err1: 〈0;X〉 - err1: { - j: 3 - } - ok1: 〈0;X〉 - ok1: { - k: 3 - } - } - } - } - andOrEmbed: { - t1: { - p2: { - X: { - (〈4;#c〉 & 〈4;#d〉) - (〈4;#a〉 & 〈4;#b〉) - } - err1: 〈0;X〉 - err1: { - j: 3 - } - ok1: 〈0;X〉 - ok1: { - k: 3 - } - } - } - } - andOrEmbed: { - t2: { - X: { - (〈3;#a〉 & 〈3;#b〉) - (〈3;#c〉 & 〈3;#d〉) - ["p"]: int - } - err1: 〈0;X〉 - err1: { - j: 3 - } - ok1: 〈0;X〉 - ok1: { - k: 3 - } - ok2: 〈0;X〉 - ok2: { - p: 3 - } - } - } - indirect: { - a: { - [>="k"]: int - } - #a: 〈0;a〉 - p1: { - X: 〈1;#a〉 - err1: 〈0;X〉 - err1: { - j: 3 - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - p2: { - #a: (〈1;a〉 & _|_(no sharing)) - X: 〈0;#a〉 - err1: 〈0;X〉 - err1: { - j: 3 - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - p3: { - X: (〈1;#a〉 & _|_(no sharing)) - err1: 〈0;X〉 - err1: { - j: 3 - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - p4: { - #a: (〈1;a〉 & _|_(no sharing)) - X: 〈0;#a〉 - X: (〈0;#a〉 & _|_(no sharing)) - err1: 〈0;X〉 - err1: { - j: 3 - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - j: 3 - } - ok: 〈0;X〉 - ok: { - k: 3 - } - } - } - } - } - patterns: { - nested: { - #a: { - x: { - y: { - [>="k"]: int - } - } - } - #b: { - x: { - y: { - [<="m"]: int - } - } - } - #c: { - x: { - y: { - [>="w"]: int - } - } - } - #d: { - x: { - y: { - [<="y"]: int - } - } - } - single: { - X: 〈1;#a〉 - err: 〈0;X〉 - err: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - and: { - p1: { - X: (〈2;#a〉 & 〈2;#b〉) - err: 〈0;X〉 - err: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - } - and: { - p2: { - X: (〈2;#b〉 & 〈2;#a〉) - err: 〈0;X〉 - err: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - } - andEmbed: { - p1: { - X: { - (〈3;#a〉 & 〈3;#b〉) - } - err: 〈0;X〉 - err: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - } - andEmbed: { - p2: { - X: { - (〈3;#b〉 & 〈3;#a〉) - } - err: 〈0;X〉 - err: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - } - orEmbed: { - p1: { - X: { - 〈3;#a〉 - 〈3;#b〉 - } - ok1: 〈0;X〉 - ok1: { - x: { - y: { - j: 3 - } - } - } - ok2: 〈0;X〉 - ok2: { - x: { - y: { - k: 3 - } - } - } - } - } - orEmbed: { - p2: { - X: { - 〈3;#b〉 - 〈3;#a〉 - } - ok1: 〈0;X〉 - ok1: { - x: { - y: { - j: 3 - } - } - } - ok2: 〈0;X〉 - ok2: { - x: { - y: { - k: 3 - } - } - } - } - } - andOrEmbed: { - t1: { - p1: { - X: { - (〈4;#a〉 & 〈4;#b〉) - (〈4;#c〉 & 〈4;#d〉) - } - err1: 〈0;X〉 - err1: { - x: { - y: { - j: 3 - } - } - } - ok1: 〈0;X〉 - ok1: { - x: { - y: { - k: 3 - } - } - } - } - } - } - andOrEmbed: { - t1: { - p2: { - X: { - (〈4;#c〉 & 〈4;#d〉) - (〈4;#a〉 & 〈4;#b〉) - } - err1: 〈0;X〉 - err1: { - x: { - y: { - j: 3 - } - } - } - ok1: 〈0;X〉 - ok1: { - x: { - y: { - k: 3 - } - } - } - } - } - } - andOrEmbed: { - t2: { - X: { - (〈3;#a〉 & 〈3;#b〉) - (〈3;#c〉 & 〈3;#d〉) - ["p"]: int - } - err1: 〈0;X〉 - err1: { - x: { - y: { - j: 3 - } - } - } - ok1: 〈0;X〉 - ok1: { - x: { - y: { - k: 3 - } - } - } - ok2: 〈0;X〉 - ok2: { - x: { - y: { - p: 3 - } - } - } - } - } - indirect: { - a: { - x: { - y: { - [>="k"]: int - } - } - } - #a: 〈0;a〉 - p1: { - X: 〈1;#a〉 - err1: 〈0;X〉 - err1: { - x: { - y: { - j: 3 - } - } - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - p2: { - #a: (〈1;a〉 & _|_(no sharing)) - X: 〈0;#a〉 - err1: 〈0;X〉 - err1: { - x: { - y: { - j: 3 - } - } - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - p3: { - X: (〈1;#a〉 & _|_(no sharing)) - err1: 〈0;X〉 - err1: { - x: { - y: { - j: 3 - } - } - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - p4: { - #a: (〈1;a〉 & _|_(no sharing)) - X: 〈0;#a〉 - X: (〈0;#a〉 & _|_(no sharing)) - err1: 〈0;X〉 - err1: { - x: { - y: { - j: 3 - } - } - } - err2: (〈0;X〉 & _|_(no sharing)) - err2: { - x: { - y: { - j: 3 - } - } - } - ok: 〈0;X〉 - ok: { - x: { - y: { - k: 3 - } - } - } - } - } - } - } - issue2241: { - #close: {} - a: { - x: { - q: 2 - } - 〈1;#close〉 - } - b: 〈0;a〉 - b: { - x: { - r: 4 - } - } - } -} ---- in.cue -{ - #E: { - c: int - } - #A: { - b: int - q: { - 〈2;#E〉 - d: int - } - } - a: (〈0;#A〉 & { - b: 3 - q: { - c: 2 - e: 43 - } - }) - issue852: { - #A: { - [=~"^a-z$"]: string - } - a: 〈0;#A〉 - a: { - Foo: "foo" - } - for k, v in 〈0;a〉 { - b: { - "\(〈2;k〉)": 〈2;v〉 - } - } - } - dynamic: { - #D: { - key: "foo" - 〈0;key〉: int - } - d: (〈0;#D〉 & { - foo: 3 - }) - } - issue4180: { - out: { - if true { - iter: (〈2;#Schema〉 & { - FooOrBar: { - foo: "is foo" - } - }) - } - } - #Foo: { - foo: string - } - #Bar: { - bar: string - } - #Schema: { - FooOrBar: { - ... - } - FooOrBar: (〈1;#Foo〉|〈1;#Bar〉) - } - } -} ---- reroot.cue -{ - issue3330: { - let: { - ok: { - #struct: { - let empty#1 = {} - field: (null|{ - n: int - }) - field: (〈0;let empty#1〉 & { - n: 3 - }) - } - out: 〈import;list〉.Concat([ - [ - 〈2;#struct〉, - ], - ]) - } - } - matthew: { - ok1: { - #struct: { - field: ({ - n: 3 - } & 〈0;g〉) - g: {} - } - out: (〈0;#struct〉 & {}) - } - } - matthew: { - ok2: { - #struct: { - field: ({ - n: 3 - } & 〈0;g〉) - g: {} - } - out: 〈0;#struct〉 - out2: (〈0;out〉 & {}) - } - } - } - issue3331: { - original: { - ok: { - #A: { - let b#2 = {} - c: (〈0;let b#2〉 & { - d: 1 - }) - } - 〈import;list〉.Concat([ - [ - 〈2;#A〉, - ], - ]) - } - } - variant1: { - ok: { - #A: { - let b#3 = {} - c: (〈0;let b#3〉 & { - d: 1 - }) - } - [ - [ - 〈2;#A〉, - ], - ] - } - } - } - indirect: { - embed: { - err1: { - #A: { - x: { - 〈2;#x〉 - 〈2;#y〉 - } - zx: 〈0;x〉.a - } - #x: { - a: { - b: 1 - } - } - #y: { - a: { - c: 2 - } - } - b: 〈0;#A〉 - b1: 〈0;b〉.zx - b1: { - d: 1 - } - } - } - closed: { - err1: { - X: { - a: 〈0;b〉 - b: {} - a: { - e: 1 - } - } - Y: 〈0;X〉 - Y: { - b: 〈0;c〉 - c: 〈1;#X〉 - } - #X: {} - } - } - } - nested: { - ok1: { - #A: { - b: {} - #B: { - c: (〈1;b〉 & { - d: 1 - }) - } - } - x: 〈0;#A〉 - } - } - nested: { - embed: { - ok: { - x: 〈0;#A〉 - #A: { - 〈1;k〉 - } - k: { - d: (〈0;b〉 & { - e: int - }) - b: {} - } - } - } - } - nested: { - err1: { - x: 〈0;#A〉 - #A: { - b: { - f: 1 - } - v: 〈0;#V〉 - #V: { - c: (〈1;b〉 & { - d: 1 - }) - } - } - x: { - b: 〈1;#B〉 - } - #B: { - g: 1 - } - } - } - nested: { - err2: { - #A: { - b: {} - c: (〈0;b〉 & { - d: 1 - }) - } - x: 〈0;#A〉 - x: { - b: { - g: 1 - } - } - } - } - inline: { - #x: { - y: { - z?: { - name: string - } - } - } - err1: ((〈0;#x〉 & { - y: { - z: _ - } - }).y.z & { - name: "a" - age1: 5 - }) - err2: ((〈0;#x〉.y & { - z: _ - }).z & { - name: "a" - age2: 5 - }) - } - mixInDef: { - refInside: { - #x: { - b: { - c: { - d: {} - e: { - f: {} - } - } - } - } - a: 〈0;#x〉 - a: { - b: { - c: { - d: {} - } - } - } - a: { - b: { - c: { - e: 〈1;c〉.d - } - } - } - } - refEdge: { - #x: { - c: { - d: {} - e: { - f: {} - } - } - } - a: 〈0;#x〉 - a: { - c: { - d: {} - } - } - a: { - c: { - e: 〈1;c〉.d - } - } - } - refOutside: { - #x: { - c: { - d: {} - e: { - f: {} - } - } - } - a: 〈0;#x〉 - a: { - c: { - d: {} - } - } - a: { - c: { - e: 〈2;a〉.c.d - } - } - } - } - issue3601: { - original: { - out: { - 〈1;#Transform〉.output - } - #Transform: { - output: (〈1;#Patch〉 & {}).output - } - #Patch: { - target: {} - output: { - foo: { - final: 〈2;target〉 - final: { - version: "v1" - } - } - } - } - } - } - issue3601: { - originalNoShare: { - out: { - 〈1;#Transform〉.output - } - #Transform: { - output: (〈1;#Patch〉 & _|_(no sharing)).output - } - #Patch: { - target: {} - output: { - foo: { - final: 〈2;target〉 - final: { - version: "v1" - } - } - } - } - } - } - issue3601: { - reduced: { - #X: { - a: { - b: { - c: "v1" - } - } - a: { - b: 〈1;empty〉 - } - empty: {} - } - original: { - Y: (〈1;#X〉 & _|_(no sharing)).a - out: (〈0;Y〉 & _|_(no sharing)) - } - moreInlining: { - out: ((〈1;#X〉 & {}).a & {}) - } - noInline: { - Y: (〈1;#X〉 & _|_(no sharing)) - Z: (〈0;Y〉 & _|_(no sharing)) - out: (〈0;Z〉.a & _|_(no sharing)) - } - moreNesting: { - #X: { - a: { - b: { - c: { - d: "v1" - } - } - } - a: { - b: { - c: 〈2;empty〉 - } - } - empty: {} - } - Y: (〈0;#X〉.a & _|_(no sharing)).b - Z: (〈0;Y〉 & _|_(no sharing)) - } - } - } -} ---- validation.cue -{ - issue3332: { - #def: { - field: 〈import;list〉.MinItems(1) - } - use: (〈0;#def〉 & { - field: [ - "value", - ] - }) - } -} diff --git a/cue/testdata/eval/comprehensions.txtar b/cue/testdata/eval/comprehensions.txtar index fc89fb2d4..32f703a35 100644 --- a/cue/testdata/eval/comprehensions.txtar +++ b/cue/testdata/eval/comprehensions.txtar @@ -164,177 +164,6 @@ Conjuncts: 136 Disjuncts: 0 NumCloseIDs: 48 --- out/compile -- ---- in.cue -{ - a: { - x: 10 - y: 100 - z: 50 - } - b: { - for k, v in 〈1;a〉 if (〈0;v〉 <= 50) { - "\(〈1;k〉)": 〈1;v〉 - } - x: int - if (〈0;x〉 > 3) { - k: 20 - } - k: int - if (〈0;k〉 > 0) { - l: 40 - } - } - c: { - for k, v in 〈1;a〉 let y = (〈0;v〉 + 10) if (〈0;y〉 > 50) { - "\(〈2;k〉)": 〈1;y〉 - } - } - A: { - X: { - run: "dfoo" - } - } - if true { - A: { - X: { - run: string - files: "\(〈import;strings〉.Join([ - 〈1;run〉, - ], "\n"))" - } - } - } - matchOrder: { - a1: { - out: { - [string]: { - Val: 1 - } - } - out: 〈0;in〉.a - in: { - a: { - if true { - b: {} - } - } - } - } - a2: { - out: { - [string]: { - Val: 1 - } - } - in: { - a: { - if true { - b: {} - } - } - } - out: 〈0;in〉.a - } - a3: { - in: { - a: { - if true { - b: {} - } - } - } - out: { - [string]: { - Val: 1 - } - } - out: 〈0;in〉.a - } - a4: { - out: 〈0;in〉.a - out: { - [string]: { - Val: 1 - } - } - in: { - a: { - if true { - b: {} - } - } - } - } - a5: { - out: 〈0;in〉.a - in: { - a: { - if true { - b: {} - } - } - } - out: { - [string]: { - Val: 1 - } - } - } - a6: { - in: { - a: { - if true { - b: {} - } - } - } - out: 〈0;in〉.a - out: { - [string]: { - Val: 1 - } - } - } - } -} ---- issue3691.cue -{ - issue3691: { - original: { - X: { - [string]: string - } - a: { - [string]: 〈1;X〉 - } - a: { - if true { - b: { - c: 1 - } - } - } - } - } - issue3691: { - structuralCycle: { - X: { - [string]: string - } - a: { - [string]: 〈1;X〉 - } - a: { - if true { - b: { - c: 〈3;a〉 - } - } - } - } - } -} -- out/todo.txt -- A.X.files: v3 correctly resolves to "dfoo" (strings.Join(["dfoo"], "\n")); annotated at top level. issue3691.structuralCycle: v3 has different structural cycle representation in error output. diff --git a/cue/testdata/eval/conflicts.txtar b/cue/testdata/eval/conflicts.txtar index 59f0ff82c..abb1d573b 100644 --- a/cue/testdata/eval/conflicts.txtar +++ b/cue/testdata/eval/conflicts.txtar @@ -53,25 +53,3 @@ Conjuncts: 23 Disjuncts: 15 -- out/todo.txt -- v3 reports the argument order differently (string/int vs int/string in v2) and includes an additional error position (5:5) for the assignment in t0.v. --- out/compile -- ---- in.cue -{ - i: int - s: string - t0: { - v: (〈1;i〉 & 〈1;s〉) - } - t1: { - #d1: { - a: { - b: 3 - } - } - #d2: { - a: { - b: 4 - } - } - x: (〈0;#d1〉 & 〈0;#d2〉) - } -} diff --git a/cue/testdata/eval/conjuncts.txtar b/cue/testdata/eval/conjuncts.txtar index fa86bf776..85b7d6033 100644 --- a/cue/testdata/eval/conjuncts.txtar +++ b/cue/testdata/eval/conjuncts.txtar @@ -119,98 +119,6 @@ Disjuncts: 152 Notifications: 5 NumCloseIDs: 43 --- out/compile -- ---- in.cue -{ - conjunct: { - t1: ({ - #early: (*"X"|string) - 〈0;#early〉 - } & { - #early: (*"X"|string) - string - }) - } - conjunct: { - t2: { - #early: (*"X"|string) - 〈0;#early〉 - } - } - conjunct: { - t2: { - #early: (*"X"|string) - string - } - } - conjunct: { - t3: (〈1;conjunct〉.t1 & 〈1;conjunct〉.t2) - } - handleComprehensions: { - if false { - subs: (〈1;#sub2〉 & 2) - } - #sub2: 2 - } -} ---- issue2351.cue -{ - issue2351: { - let: { - let _param#1 = "foo" - { - param: (〈1;let _param#1〉 & [ - {}, - ]) - gen: [ - for _, p in 〈1;param〉 { - 〈1;p〉 - }, - ] - }.gen - } - } - issue2351: { - hidden: { - _in1: [ - "foo", - ] - { - in2: 〈1;_in1〉 - out: [ - for _, x in 〈1;in2〉 { - 〈1;x〉 - }, - ] - }.out - } - } -} ---- issue2355.cue -{ - issue2355: { - #GetF1: { - in: _ - out: 〈0;in〉.f1 - } - #PutOut1: { - in: _ - out: { - out1: "\(〈1;in〉)" - } - } - export: { - let data#2 = { - f1: "foo" - } - (〈1;#PutOut1〉 & { - in: (〈2;#GetF1〉 & { - in: 〈2;let data#2〉 - }).out - }).out - } - } -} -- out/todo.txt -- conjunct.t1/t2/t3: complex disjunctions with embedded hidden fields; only @test(eq) checked. issue2355.export: v3 correctly closes it (closing in new evaluator), v2 does not close. diff --git a/cue/testdata/eval/counters.txtar b/cue/testdata/eval/counters.txtar index d506c23ee..749d14e4b 100644 --- a/cue/testdata/eval/counters.txtar +++ b/cue/testdata/eval/counters.txtar @@ -180,155 +180,6 @@ Conjuncts: 267 Disjuncts: 36 NumCloseIDs: 60 --- out/compile -- ---- issue3750.cue -{ - issue3750: { - original: { - out: (〈0;#Foo〉 & { - sub: 〈1;#Foo〉 - }) - #Foo: { - sub: (〈1;#Foo〉|〈1;#Bar〉) - meta: { - strs: [ - ...string, - ] - for _, w in 〈import;list〉.FlattenN([ - 〈1;strs〉, - ], 1) {} - } - } - #Bar: { - kind: "bar" - meta: { - strs: [ - ...string, - ] - } - } - } - } - issue3750: { - reduced: { - out: (〈0;Foo〉 & { - sub: 〈1;Foo〉 - }) - Foo: { - sub: (〈1;Foo〉|{ - a: { - b: _ - } - }) - a: { - b: _ - for _, w in 〈import;list〉.FlattenN([ - 〈1;b〉, - ], 1) {} - } - } - } - } -} ---- issue3770.cue -{ - issue3770: { - task: { - m: { - let t#1 = [ - "x", - ] - for _, m in 〈0;let t#1〉 { - 〈1;m〉: { - a: 1 - } - } - x: { - b: 1 - } - } - m: (null|{}) - out: 〈0;m〉.x.a - } - } -} ---- issue3780.cue -{ - issue3780: { - panic1: { - objs: (〈0;#Objects〉 & {}) - param!: bool - if 〈0;param〉 { - objs: { - obj1: { - one: 1 - two: 2 - } - } - } - #Objects: { - [〈import;strings〉.HasPrefix("obj")]: { - kind: "object" - ... - } - } - } - } - issue3780: { - panic2: { - parent: { - objs: (〈0;#Objects〉 & {}) - param?: bool - if (〈0;param〉 != _|_(explicit error (_|_ literal) in source)) { - objs: { - obj1: { - one: 1 - two: 2 - } - } - } - #Objects: { - [〈import;strings〉.HasPrefix("obj")]: { - kind: "object" - ... - } - } - } - } - } -} ---- issue3824.cue -{ - issue3824: { - panic: { - thing: { - spec: { - name: string - } - outputField: string - } - val: string - things: { - [_]: 〈1;thing〉 - } - things: { - [_]: { - spec: (*{ - name: "self-signed" - }|{ - ... - }) - } - } - if true { - things: { - name: {} - } - val: 〈0;things〉["name"].outputField - } - } - } -} -- out/todo.txt -- issue3750.original: v3 has more complex nested disjunction structure in sub field; v2 resolves to concrete value. issue3750.reduced: v3 has different field ordering in disjunction sub-fields compared to v2. diff --git a/cue/testdata/eval/cycles_ref.txtar b/cue/testdata/eval/cycles_ref.txtar index 609e69537..9626380ee 100644 --- a/cue/testdata/eval/cycles_ref.txtar +++ b/cue/testdata/eval/cycles_ref.txtar @@ -17,18 +17,3 @@ Retain: 3 Unifications: 12 Conjuncts: 24 Disjuncts: 15 --- out/compile -- ---- in.cue -{ - a: (〈0;b〉 + 100) - b: (〈0;a〉 - 100) - a: 200 - c: (〈0;d〉 & { - b: 2 - }) - d: 〈0;e〉 - e: { - a: 1 - } - e: 〈0;c〉 -} diff --git a/cue/testdata/eval/deref.txtar b/cue/testdata/eval/deref.txtar index 7b589852f..5ad285bf3 100644 --- a/cue/testdata/eval/deref.txtar +++ b/cue/testdata/eval/deref.txtar @@ -51,53 +51,3 @@ Disjuncts: 37 MisalignedConjunct: 4 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - issue4011: { - full: { - let _hugoEnvironments#1 = { - default: "_default" - production: "production" - } - site: { - cls: _ - } - site: { - [_]: { - fs: { - Create: { - for envID, envName in 〈4;let _hugoEnvironments#1〉 let envConfig = 〈3;hugo〉[〈0;envID〉] if (〈0;envConfig〉 != _|_(explicit error (_|_ literal) in source)) { - config: { - Contents: 〈2;envConfig〉 - } - } - } - } - hugo: _ - } - } - site: { - [_]: { - hugo: { - production: {} - } - } - } - } - } - issue4011: { - reduced: { - result: { - for _, envName in [ - "foo", - ] let env = 〈2;envs〉[〈0;envName〉] if (〈0;env〉 != _|_(explicit error (_|_ literal) in source)) { - 〈2;envName〉: true - } - } - envs: { - foo: {} - } - } - } -} diff --git a/cue/testdata/eval/discontinuous.txtar b/cue/testdata/eval/discontinuous.txtar index c2027c9d9..537056c34 100644 --- a/cue/testdata/eval/discontinuous.txtar +++ b/cue/testdata/eval/discontinuous.txtar @@ -19,36 +19,6 @@ x: { DSpec: {} @test(eq, {D: bar: {}, DSpec: {}}) } --- out/compile -- ---- in.cue -{ - a: [ - for _, c in 〈1;foo〉.bar.baz { - 〈1;c〉 - }, - ] - a: [ - { - name: "http" - }, - ] - foo: { - 〈1;x〉.D - bar: { - baz: [ - { - port: 8080 - }, - ] - } - } - x: { - D: { - bar: 〈1;DSpec〉 - } - DSpec: {} - } -} -- out/eval/stats -- Leaks: 0 Freed: 14 diff --git a/cue/testdata/eval/disjselfcycle.txtar b/cue/testdata/eval/disjselfcycle.txtar index c3c748126..687d8795b 100644 --- a/cue/testdata/eval/disjselfcycle.txtar +++ b/cue/testdata/eval/disjselfcycle.txtar @@ -78,100 +78,3 @@ issue4119: full: { -- out/errors.txt -- [eval] issue4119.reducedNested.x.y.0.f: undefined field: f: ./comprehensions.cue:25:9 --- out/compile -- ---- comprehensions.cue -{ - issue4119: { - reduced: { - x: [ - ..., - ] - x: (_|*[ - { - f: 123 - }, - ]) - x: [ - for _, i in 〈1;x〉 { - f: 〈1;i〉.f - }, - ] - } - } - issue4119: { - reducedNested: { - x: { - y: [ - ..., - ] - } - x: ({ - y: _ - }|*{ - y: [ - { - f: 123 - }, - ] - }) - x: { - y: [ - for _, i in 〈2;x〉 { - f: 〈1;i〉.f - }, - ] - } - } - } - issue4119: { - full: { - _img: { - val: string - accounts: { - groups: (〈2〉.accounts.groups|*[ - { - gid: 65532 - }, - ]) - groups: [ - for _, g in 〈1;groups〉 let _gid = 〈0;g〉.gid { - gid: [ - if (〈2;_gid〉 != _|_(explicit error (_|_ literal) in source)) { - 〈3;_gid〉 - }, - 65532, - ][0] - }, - ] - } - } - art: { - images: { - [string]: 〈2;#Image〉 - } - for k, v in 〈0;images〉 { - images: { - 〈2;k〉: (〈4;_img〉 & 〈2;v〉) - } - } - } - #Image: { - val: string - accounts?: { - groups?: [ - ..., - ] - } - } - art: { - images: { - ko: { - val: "test" - } - } - } - } - } -} ---- in.cue -{} diff --git a/cue/testdata/eval/disjunctioncross.txtar b/cue/testdata/eval/disjunctioncross.txtar index f4d8930b0..95b26ebef 100644 --- a/cue/testdata/eval/disjunctioncross.txtar +++ b/cue/testdata/eval/disjunctioncross.txtar @@ -197,134 +197,5 @@ Conjuncts: 394 Disjuncts: 80 NumCloseIDs: 96 --- out/compile -- ---- in.cue -{ - #OneOrTwo: (〈0;#One〉|〈0;#Two〉) - #One: { - kind: "one" - one: { - oneField: "value" - } - } - #Two: { - kind: "two" - two: { - optional?: string - } - } - _appDefaults: { - two: { - two: { - optional: (*"optional set"|string) - } - } - } - valueDiscriminator: { - crossing: { - out: (〈0;#Application〉 & { - oneOrTwo: { - kind: "two" - } - }) - #Application: { - oneOrTwo: 〈3;#OneOrTwo〉 - oneOrTwo: (*〈3;_appDefaults〉[〈0;oneOrTwo〉.kind]|_) - } - } - } - valueDiscriminator: { - local: { - out: (〈0;#Application〉 & { - oneOrTwo: { - kind: "two" - } - }) - #Application: { - oneOrTwo: 〈3;#OneOrTwo〉 - oneOrTwo: { - (*〈4;_appDefaults〉[〈1〉.kind]|_) - } - } - } - } - fieldDiscriminator: { - crossing: { - out: (〈0;#Application〉 & { - oneOrTwo: { - two: {} - } - }) - #Application: { - oneOrTwo: 〈3;#OneOrTwo〉 - oneOrTwo: (*〈3;_appDefaults〉[〈0;oneOrTwo〉.kind]|_) - } - } - } - fieldDiscriminator: { - local: { - out: (〈0;#Application〉 & { - oneOrTwo: { - two: {} - } - }) - #Application: { - oneOrTwo: 〈3;#OneOrTwo〉 - oneOrTwo: { - (*〈4;_appDefaults〉[〈1〉.kind]|_) - } - } - } - } - issue3967: { - error: { - nested: { - out: (〈0;#Application〉 & { - oneOrTwo: { - two: {} - } - }) - #Application: { - oneOrTwo: (〈4;#OneOrTwo〉 & { - if (〈2〉.oneOrTwo.kind == "two") { - two: { - if (〈4〉.oneOrTwo.two.optional == _|_(explicit error (_|_ literal) in source)) { - optional: "optional set" - } - } - } - if (〈2〉.oneOrTwo.kind == "never") {} - }) - if (〈1〉.oneOrTwo.kind == "never") {} - } - } - } - } - issue3967: { - error: { - local: { - out: (〈0;#Application〉 & { - oneOrTwo: { - two: {} - } - }) - #Application: { - oneOrTwo: { - (〈5;#OneOrTwo〉 & { - if (〈2〉.kind == "two") { - two: { - if (〈4〉.two.optional == _|_(explicit error (_|_ literal) in source)) { - optional: "optional set" - } - } - } - if (〈2〉.kind == "never") {} - }) - } - } - } - } - } -} -- out/todo.txt -- v3 reports a cycle error for issue3967.error.nested.out (undefined field: kind) and issue3967.error.local.out.oneOrTwo (circular dependency), whereas v2 reported incomplete/cycle errors differently and resolved some fields that v3 does not. diff --git a/cue/testdata/eval/disjunctions.txtar b/cue/testdata/eval/disjunctions.txtar index 0cd79ec0d..87af9f262 100644 --- a/cue/testdata/eval/disjunctions.txtar +++ b/cue/testdata/eval/disjunctions.txtar @@ -567,572 +567,3 @@ ConjunctInfos: 415 MaxConjunctInfos: 6 MaxReqSets: 7 MaxRedirect: 2 --- out/compile -- ---- dependencies.cue -{ - issue3606: { - data: ({ - notAllowed: true - } & 〈0;#S〉) - #S: (string|{}) - } - issue3672: { - #A: (string|{ - y: true - }) - #B: (〈0;#A〉|{ - a: "append" - }|{ - b: "prepend" - }) - #fn: { - #C: 〈1;#B〉 - #out: { - x: [ - ...〈2;#C〉, - ] - } - } - #def: (〈0;#fn〉 & {}).#out - v: 〈0;#def〉 - v: { - x: [ - { - y: true - }, - ] - } - } - issue3681: { - out: { - one: 〈1;#strDefaultDef〉 - } - out: { - two: "\(〈1;strDefault〉)" - } - strDefault: (*"fallback"|string) - #strDefaultDef: 〈0;strDefault〉 - } - issue3699: { - reduced: { - p1: { - y: { - if 〈1;x〉.z { - 1 - } - } - x: (*{ - z: true - }|{}) - } - } - reduced: { - p2: { - y: { - if 〈1;x〉.z { - 1 - } - } - x: (*{ - z: true - }|{}) - } - } - reduced: { - full: { - _res: { - _fooTrue: ({}|*{ - foo: true - }) - _msgSwitch: [ - if 〈1;_fooTrue〉.foo { - msg: "foo" - }, - { - msg: "bar" - }, - ][0] - out: 〈0;_msgSwitch〉.msg - } - let res#1 = { - out: (〈1;_res〉 & {}).out - } - out: 〈0;let res#1〉.out - } - } - } -} ---- in.cue -{ - a: (*1|int) - aa: (*1|*2|int) - b: ({ - name: "int" - val: int - }|{ - name: "str" - val: string - }) - d: (〈0;b〉 & { - val: 3 - }) - c: (〈0;b〉 & { - name: "int" - val: 3 - }) - e: (〈0;b〉 & { - val: "foo" - }) - f: (〈0;b〉 & { - name: "str" - val: 3 - }) - e1: { - a: (null|{ - bar: 2 - }) - b: (〈0;a〉 & {}).bar - } - d1: { - a: ((null|{ - c: 1 - }) & {}) - b: ({} & (null|{ - c: 1 - })) - } - d2: { - a: (([ - ..., - ]|{ - c: 1 - }) & {}) - b: ({} & ([ - ..., - ]|{ - c: 1 - })) - } - d3: { - a: ((string|{ - c: 1 - }) & {}) - b: ({} & (string|{ - c: 1 - })) - } - d4: { - a: ((string|{ - c: 1 - }) & {}) - b: ({} & (string|{ - c: 1 - })) - } - d5: { - a: ((number|{ - c: 1 - }) & {}) - b: ({} & (number|{ - c: 1 - })) - } - d6: { - a: ((int|{ - c: 1 - }) & {}) - b: ({} & (int|{ - c: 1 - })) - } - t10: { - p1: { - schema: 〈0;test〉 - schema: (string|{ - name: string - }) - #A: { - (string|{ - name: string - }) - } - test: { - name: "Test" - } - test: 〈0;#A〉 - } - } - t10: { - p2: { - schema: (string|{ - name: string - }) - schema: 〈0;test〉 - #A: { - (string|{ - name: string - }) - } - test: { - name: "Test" - } - test: 〈0;#A〉 - } - } - t10: { - p3: { - #A: { - (string|{ - name: string - }) - } - test: { - name: "Test" - } - test: 〈0;#A〉 - schema: (string|{ - name: string - }) - schema: 〈0;test〉 - } - } - t11: { - p1: { - a: 〈0;#A〉 - a: 〈0;b〉 - b: (〈0;#A〉 & [ - "b", - ]) - #A: ([ - ("a"|"b"), - ]|{}) - } - } - t11: { - p2: { - b: (〈0;#A〉 & [ - "b", - ]) - #A: ([ - ("a"|"b"), - ]|{}) - a: 〈0;b〉 - a: 〈0;#A〉 - } - } - cross: { - a: (*"word"|string) - a: (string|*"word") - } - d100: { - i: (null|{ - bar: 2 - }) - j: 〈0;i〉.bar - } - issue641: { - #A: { - type: "a" - x: "" - } - #B: { - type: "b" - x: string - } - #C: { - b: (〈1;#A〉|〈1;#B〉) - } - e: { - [string]: (〈1;#C〉 & { - b: (〈2;#A〉|〈2;#B〉) - }) - } - e: { - foobar: (〈1;#C〉 & { - b: (〈2;#B〉 & { - x: "foobar" - }) - }) - } - } -} ---- indexelim.cue -{ - indexElimination: { - inStruct: { - x: { - a: (*〈1;x〉[0]|0) - }.a - } - inList1: { - x: [ - 〈1;x〉[0], - ][0] - } - inList2: { - x: [ - (*〈1;x〉[0]|0), - ][0] - } - issue3124: { - full: { - x: [ - ...bool, - ] - x: [ - true, - false, - true, - true, - ] - y: [ - for _, v in 〈1;x〉 { - [ - if 〈2;v〉 { - 1 - }, - 0, - ][0] - }, - ] - z: [ - for i, v in 〈1;y〉 { - 〈import;"math/bits"〉.Set((*〈3;z〉[(〈1;i〉 - 1)]|0), ((len(〈3;y〉) - 〈1;i〉) - 1), 〈1;v〉) - }, - ][3] - } - } - } -} ---- issue3406.cue -{ - issue3406: { - out: (〈0;d〉 & { - 〈1;d〉 - }) - d: { - kind: ("foo"|"bar") - } - d: ({ - kind: "foo" - }|{ - kind: "bar" - }) - } -} ---- issue3411.cue -{ - issue3411: { - x: { - y?: [ - ...string, - ] - } - x: ({ - y: [ - "foo", - ] - }|*{ - y: [ - "bar", - ] - }) - } -} ---- issue3434.cue -{ - issue3434: { - t1: { - ({}|{}) - { - ["x"]: 1 - } - { - ["y"]: 2 - } - } - } - issue3434: { - full: { - out: (〈0;#Schema〉 & { - steps: [ - { - run: "example" - }, - ] - }) - #Schema: { - steps: [ - ...{ - run: string - }, - ] - #matrixConfig: (string|[ - ...〈1;#matrixConfig〉, - ]) - matrix?: (({ - ... - }|string) & { - { - [=~"^foo"]: [ - ...{ - [string]: 〈4;#matrixConfig〉 - }, - ] - } - { - [=~"^bar"]: ([ - ...〈3;#matrixConfig〉, - ]|string) - } - }) - } - } - } -} ---- issue3490.cue -{ - issue3490: { - nested: { - p1: { - (("a"|"b")|"b") - ("a"|"b") - } - } - } - issue3490: { - nested: { - p2: { - ("a"|"b") - (("a"|"b")|"b") - } - } - } - issue3490: { - full: { - data: [ - ...〈1;#Schema〉, - ] - data: [ - (〈1;#Schema〉 & {}), - ] - #Schema: { - runs?: ("foo"|([ - 〈1;#D1〉, - ]|[ - 〈1;#D1〉, - 〈1;#D2〉, - ])) - #D1: "d1" - #D2: "d2" - } - } - } -} ---- issue3597.cue -{ - issue3597: { - t1: { - #Schema: { - _ok: bool - ({}|{ - _ok: true - let Ok#2 = 〈0;_ok〉 - ({}|{ - x: 〈1;let Ok#2〉 - }) - }) - } - [string]: 〈0;#Schema〉 - foo: 〈0;bar〉 - bar: {} - } - } - issue3597: { - t2: { - ok: true - X: (_|{ - let Ok#3 = 〈1;ok〉 - (_|{ - x: 〈1;let Ok#3〉 - }) - }) - foo: (〈0;X〉 & { - 〈1;X〉 - }) - } - } -} ---- issue3891.cue -{ - issue3891: { - reduced: { - ({ - x: _ - }|null) - ({ - x: _ - }|null) - x: (*〈0;a〉.y|_) - a: 〈0;b〉 - b: { - y: 1 - } - } - } - issue3891: { - full: { - out: (〈0;#Foo〉|"never") - out: (〈0;#Foo〉|"never") - out: (〈0;_fooTemplate〉 & { - _input: (〈1;_transform〉 & { - in: { - sub1: { - sub2: "bar" - } - } - }).out - }) - _transform: { - in: _ - out: 〈0;in〉 - } - #Foo: { - foo?: _ - } - _fooTemplate: { - _input: _ - foo: (*〈0;_input〉.sub1.sub2|_) - } - } - } -} ---- issue3899.cue -{ - issue3899: { - reduced: { - b: ((〈0;c〉 + "")|string) - c?: string - } - } - issue3899: { - full: { - out: (〈0;#Schema〉 & { - name: "foo" - }) - #Schema: { - _versions: { - foo: "123" - } - spec: { - limits: true - } - name!: string - spec: { - image: (string|*"\(〈1;name〉)") - } - deployImage: 〈0;_versions〉[〈0;spec〉.image] - } - } - } -} diff --git a/cue/testdata/eval/dynamic_field.txtar b/cue/testdata/eval/dynamic_field.txtar index 5cd829bec..7cbe70605 100644 --- a/cue/testdata/eval/dynamic_field.txtar +++ b/cue/testdata/eval/dynamic_field.txtar @@ -138,116 +138,6 @@ Conjuncts: 91 Disjuncts: 0 NumCloseIDs: 4 --- out/compile -- ---- constraints.cue -{ - constraints: { - t1: "foo" - t2: "bar" - 〈0;t1〉?: { - 〈1;t2〉!: 3 - } - } -} ---- in.cue -{ - a: "foo" - "\(〈0;a〉)": { - b: { - c: { - d: 〈3;e〉 - } - } - } - e: 2 - b: "bar" - "\(〈0;b〉)": { - a: 1 - } - c: 〈0;("\(〈0;b〉)")〉 - withError: { - issue799: ({ - key: &(int, >=-2147483648, <=2147483647) - } & { - "\((1 & 2))": 123 - }) - } - parenExprRefParent: { - a: { - 〈1;x〉: {} - } - x: "foo" - } - parenExprRefEqual: { - 〈0;x〉: {} - x: "foo" - } - chainedResolution: { - x: { - 〈1;x〉.baz: "bar" - 〈1;x〉.foo: "baz" - baz: "foo" - } - } - noCycleError: { - foo: { - [_]: { - #ID: "\(string)" - } - } - foo: { - bar: { - entries: { - 〈3;foo〉.baz.#ID: true - } - } - } - foo: { - baz: {} - } - } -} ---- issue3828.cue -{ - issue3828: { - reduced: { - a: { - b: {} - } - a: { - [_]: { - if true let x = 〈2;str〉 { - 〈1;x〉: true - } - } - } - str: "foobot1" - } - } - issue3828: { - full: { - orgs: { - org1: { - repos: { - repo1: {} - } - } - } - botUser: "bot1" - orgs: { - [_]: { - for repo_name, _ in 〈1〉.repos let orgBotUser = 〈3;botUser〉 { - collaborators: { - 〈3;repo_name〉: { - 〈3;orgBotUser〉: true - } - } - } - } - } - } - } -} -- out/todo.txt -- c: v3 uses structure sharing (~(bar)), v2 expands it. noCycleError: v3 adds extra error message about key value; v2 only reports invalid interpolation. diff --git a/cue/testdata/eval/embed.txtar b/cue/testdata/eval/embed.txtar index 8f7312703..15fe07186 100644 --- a/cue/testdata/eval/embed.txtar +++ b/cue/testdata/eval/embed.txtar @@ -204,195 +204,6 @@ Conjuncts: 189 Disjuncts: 6 NumCloseIDs: 43 --- out/compile -- ---- in.cue -{ - #A: { - 〈1;Common〉 - ... - } - Common: { - a: int - b: int - } - x: 〈0;#A〉 - x: { - c: int - } - #B: { - if true { - a: int - } - ... - } - y: 〈0;#B〉 - y: { - c: int - } -} ---- noclose.cue -{ - double: { - a: { - b?: { - c: { - d: "c" - } - } - } - a: { - { - b: { - { - c: { - e: "member" - } - } - } - } - } - } - doubleAsComprehension: { - a: { - b?: { - c: { - d: "c" - } - } - } - a: { - if true { - b: { - if true { - c: { - e: "member" - } - } - } - } - } - } - fieldNotAllowed: { - t1: { - #X: { - objs: { - extra: { - unused: "foo" - } - ... - } - ... - } - #Y: { - unused: {} - } - addTwo: (〈0;#X〉 & { - 〈1;#Y〉 - objs: { - name: "Two" - } - }) - } - t2: { - #AddObjsExtra: { - objs: { - [string]: { - extra: { - unused: "foo" - } - ... - } - } - ... - } - #EmbedUnused: { - unused: {} - } - #AddTwo: (〈0;#AddObjsExtra〉 & { - 〈1;#EmbedUnused〉 - objs: { - two: { - name: "Two" - labels: { - app: 〈3;objs〉.one.name - } - } - } - }) - out: (〈0;#AddTwo〉 & { - objs: { - one: { - name: "One" - } - } - }) - } - t3: { - x: 〈0;#X〉 - #X: { - y: { - z: { - a: { - [string]: string - } - b: { - E: "1" - } - } - ... - } - } - x1: { - y: 〈1;#Y〉 - } - #Y: { - port?: string - } - x: { - y: { - z: { - b: { - E: string - } - } - port: 〈0;z〉.b.E - z: { - a: { - c?: string - } - } - } - } - if true { - w: (〈1;x〉 & { - y: 〈2;x1〉.y - }) - } - } - } - closednessInversion: { - base: 〈0;#X〉 - base: { - x: 〈1;#Y〉 - } - #X: { - x: { - ... - } - } - #Y: { - y: (string|*"default") - } - out: { - 〈1;base〉.x - a: { - b: { - c: "d" - } - } - } - } -} -- out/todo.txt -- fieldNotAllowed: v3 correctly enforces closedness for cases that evalv2 missed. fieldNotAllowed.t1.addTwo.objs.extra: v3 reports error; evalv2 did not. diff --git a/cue/testdata/eval/errunifiy.txtar b/cue/testdata/eval/errunifiy.txtar index eaa57f0a9..9279be422 100644 --- a/cue/testdata/eval/errunifiy.txtar +++ b/cue/testdata/eval/errunifiy.txtar @@ -20,11 +20,3 @@ Retain: 0 Unifications: 4 Conjuncts: 6 Disjuncts: 0 --- out/compile -- ---- in.cue -{ - a: or([]) - a: "t" - b: _|_(explicit error (_|_ literal) in source) - b: "t" -} diff --git a/cue/testdata/eval/expressions.txtar b/cue/testdata/eval/expressions.txtar index 957fe691c..84b5a533b 100644 --- a/cue/testdata/eval/expressions.txtar +++ b/cue/testdata/eval/expressions.txtar @@ -29,38 +29,3 @@ Retain: 0 Unifications: 5 Conjuncts: 5 Disjuncts: 5 --- out/compile -- ---- in.cue -{ - a: 1 - b: (1 + 2) - c: (3 - 1) - d: rem(5, 3) - structComparison: { - equalStructs: ({ - a: 1 - b: 2 - } == { - a: 1 - b: 2 - }) - differentStructs: ({ - a: 1 - } == { - a: 2 - }) - emptyStructs: ({} == {}) - } - mixedComparison: { - structVsNumber: ({ - a: 1 - } == 1) - listVsStruct: ([ - 1, - 2, - ] == { - a: 1 - }) - stringVsNumber: ("hello" == 42) - } -} diff --git a/cue/testdata/eval/fields.txtar b/cue/testdata/eval/fields.txtar index c8aeac6c6..057ec4b3d 100644 --- a/cue/testdata/eval/fields.txtar +++ b/cue/testdata/eval/fields.txtar @@ -15,23 +15,6 @@ intField: { ./in.cue:4:18 [eval] intField: integer fields not supported: ./in.cue:9:3 --- out/compile -- ---- in.cue -{ - bulkToSelf: { - a: { - foo: { - [string]: int - } - foo: { - bar: "3" - } - } - } - intField: { - 2: string - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/eval/incomplete.txtar b/cue/testdata/eval/incomplete.txtar index 7a43d560d..a68d0a356 100644 --- a/cue/testdata/eval/incomplete.txtar +++ b/cue/testdata/eval/incomplete.txtar @@ -121,44 +121,3 @@ E.b: non-concrete value >=5 in operand to -: ./in.cue:48:14 [incomplete] issue1837.p3.x: undefined field: b: ./in.cue:61:14 --- out/compile -- ---- in.cue -{ - s: string - e1: (〈0;s〉 + 〈0;s〉) - e2: (>"bar" & 〈0;s〉) - e3: (>〈0;s〉 & "foo") - e3b: >〈0;s〉 - e4: (>〈0;e1〉 & 〈0;s〉) - e5: (<〈0;e5〉 & 〈0;s〉) - E: { - a: (〈0;c〉 - 〈0;b〉) - b: (〈0;c〉 - 〈0;a〉) - c: ((〈0;a〉 + 〈0;b〉) & >=5) - } - a: int - okay: ((>10 & <〈0;a〉) + 3) - issue1837: { - p1: { - context: {} - x: 〈0;context〉.b - if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { - message: "a" - } - } - p2: { - if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { - message: "a" - } - x: 〈0;context〉.b - context: {} - } - p3: { - if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { - message: "a" - } - context: {} - x: 〈0;context〉.b - } - } -} diff --git a/cue/testdata/eval/incompleteperm.txtar b/cue/testdata/eval/incompleteperm.txtar index 5232f8d2d..1bb9f4d0c 100644 --- a/cue/testdata/eval/incompleteperm.txtar +++ b/cue/testdata/eval/incompleteperm.txtar @@ -26,38 +26,6 @@ issue680: (>10 * 2) & 0 // applying <= to a bound (>=100) is not valid arithmetic. // https://cuelang.org/issue/405 issue405: >=100 <= 200 --- out/compile -- -permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): - ./in.cue:3:5 -permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): - ./in.cue:3:20 -permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): - ./in.cue:8:6 -permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): - ./in.cue:8:18 -permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): - ./in.cue:12:6 -permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): - ./in.cue:12:18 -issue680: invalid operand >10 ('*' requires concrete value): - ./in.cue:18:12 -issue405: invalid operand >=100 ('<=' requires concrete value): - ./in.cue:23:11 ---- in.cue -{ - permanentlyIncompleteOperands: { - a: ((string + ":") + string) - a: "golang/go:1.13.5" - } - permanentlyIncompleteOperandsNested: { - a: ((int + 1) + (int + 1)) - } - permanentlyIncompleteOperandsDisjunct: { - a: ((int + 1)|(int + 1)) - } - issue680: ((>10 * 2) & 0) - issue405: (>=100 <= 200) -} -- out/evalalpha -- permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): ./in.cue:3:5 diff --git a/cue/testdata/eval/insertion.txtar b/cue/testdata/eval/insertion.txtar index da5004ba8..a96674db0 100644 --- a/cue/testdata/eval/insertion.txtar +++ b/cue/testdata/eval/insertion.txtar @@ -132,133 +132,3 @@ Retain: 24 Unifications: 67 Conjuncts: 163 Disjuncts: 73 --- out/compile -- ---- a.cue -{ - embeddingDirect: { - t1: ({ - #a: _ - _ - } & { - #a: "s" - 〈0;#a〉 - }) - } - embeddingExpr: { - t1: ({ - #a: _ - _ - } & { - #a: "s" - [ - 〈1;#a〉, - ][0] - }) - } - unifiedDirect: { - t1: { - #a: _ - _ - } - t1: { - 〈0;#a〉 - #a: _ - } - t1: { - _ - #a: "s" - } - } - unifiedExpr: { - t1: { - #a: _ - _ - } - t1: { - [ - 〈1;#a〉, - ][0] - #a: _ - } - t1: { - #a: "s" - _ - } - } - cross: { - t1: { - a: { - b: { - v: 1 - a: { - w: 2 - } - } - } - b: { - a: { - x: 2 - b: { - y: 5 - } - } - } - 〈0;a〉 - 〈0;b〉 - } - } -} ---- complex.cue -{ - recursive: { - t1: { - e: {} - c: { - d: { - e: { - f: 1 - } - } - } - 〈0;c〉.d - c: { - d: { - c: { - d: { - e: { - g: 1 - } - } - } - } - } - } - t2: { - 〈0;c〉 - c: { - c: { - g: 1 - } - } - } - } -} ---- issue2169.cue -{ - embeddedFunctionalExpr: { - #fn: ({ - #in: _ - _ - } & { - #in: "str" - (({ - #t: _ - 〈0;#t〉 - } & { - #t: 〈1;#in〉 - _ - }) + "") - }) - 〈0;#fn〉 - } -} diff --git a/cue/testdata/eval/issue1640.txtar b/cue/testdata/eval/issue1640.txtar index 9cfcc298f..56349f6d2 100644 --- a/cue/testdata/eval/issue1640.txtar +++ b/cue/testdata/eval/issue1640.txtar @@ -27,31 +27,6 @@ fact2: #MCS & {lc: "foo"} @test(eq, {lc: "foo", uc: "foo"}) @test(closed) lc: string uc: lc } --- out/compile -- ---- a1.cue -{ - y: 〈0;fact2〉.uc - x: 〈0;fact1〉.uc -} ---- a2.cue -{ - x: 〈0;fact1〉.uc - y: 〈0;fact2〉.uc -} ---- x.cue -{ - fact1: (〈0;#MCS〉 & { - lc: 〈1;fact2〉.lc - }) - fact2: (〈0;#MCS〉 & { - lc: "foo" - }) - #MCS: 〈0;#MultiCaseString〉 - #MultiCaseString: { - lc: string - uc: 〈0;lc〉 - } -} -- out/eval/stats -- Leaks: 0 Freed: 15 diff --git a/cue/testdata/eval/issue1886.txtar b/cue/testdata/eval/issue1886.txtar index 1a526b153..4b2d3ae25 100644 --- a/cue/testdata/eval/issue1886.txtar +++ b/cue/testdata/eval/issue1886.txtar @@ -86,28 +86,3 @@ cycle.b: cycle with field: a: [incomplete] incompleteTwo._t: invalid interpolation: non-concrete value string (type string): ./in.cue:54:3 ./in.cue:53:7 --- out/compile -- ---- in.cue -{ - cycle: { - x: 200 - x: (〈0;y〉 + 100) - y: (〈0;x〉 - 100) - a: (〈0;b〉 + 100) - b: (〈0;a〉 - 100) - } - incompleteOne: { - _t: { - #p: string - "hello \(〈0;#p〉)" - } - r: "\(〈0;_t〉)" - } - incompleteTwo: { - r: "\(〈0;_t〉)" - _t: { - #p: string - "hello \(〈0;#p〉)" - } - } -} diff --git a/cue/testdata/eval/issue2146.txtar b/cue/testdata/eval/issue2146.txtar index 458fe1801..040870c75 100644 --- a/cue/testdata/eval/issue2146.txtar +++ b/cue/testdata/eval/issue2146.txtar @@ -73,56 +73,5 @@ Conjuncts: 157 Disjuncts: 12 NumCloseIDs: 38 --- out/compile -- ---- in.cue -{ - p1: { - #A: { - x?: int - y?: int - let list#1 = [ - 〈1;x〉, - 〈1;y〉, - ] - all: [ - for _, v in 〈1;let list#1〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) { - 〈1;v〉 - }, - ] - (*{ - x?: _|_(explicit error (_|_ literal) in source) - y: 1 - }|_) - } - a: (〈0;#A〉 & { - x: 3 - }) - b: (〈0;#A〉 & 〈0;a〉) - } - p2: { - #A: { - x?: int - y?: int - let list#2 = [ - 〈1;x〉, - 〈1;y〉, - ] - all: [ - for _, v in 〈1;let list#2〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) { - 〈1;v〉 - }, - ] - (_|*{ - x?: _|_(explicit error (_|_ literal) in source) - y: 1 - }) - } - a: (〈0;#A〉 & { - x: 3 - y: 2 - }) - b: (〈0;#A〉 & 〈0;a〉) - } -} -- out/todo.txt -- p1.b and p2.b: v2 uses structure-shared let (list#1multi/list#2multi), v3 evaluates it per arc. diff --git a/cue/testdata/eval/issue2235.txtar b/cue/testdata/eval/issue2235.txtar index 337536af6..06df39541 100644 --- a/cue/testdata/eval/issue2235.txtar +++ b/cue/testdata/eval/issue2235.txtar @@ -154,138 +154,6 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 28 --- out/compile -- ---- issue2235.cue -{ - shorewallParams: close({ - [=~"^[A-Z0-9_]+$"]: [ - ...〈import;net〉.IP, - ] - }) - #Cluster: { - clusterName: string - shorewallPrefix: "KUBERNETES_\(〈import;strings〉.ToUpper(〈0;clusterName〉))" - } - clusters: { - [string]: (〈1;#Cluster〉 & { - clusterName: 〈1;-〉 - }) - } - #Cluster: { - globalIngressControllers: { - [string]: 〈2;#GlobalIngressController〉 - } - globalIngressControllers: { - admin: (〈2;#GlobalIngressController〉 & { - class: "admin" - }) - } - for _, c in 〈0;globalIngressControllers〉 { - objects: 〈1;c〉.objects - } - } - for clusterName, cluster in 〈0;clusters〉 { - for class, controller in 〈1;cluster〉.globalIngressControllers { - let svc#1multi = 〈1;controller〉.objects.namespaced.ingress.Service["\(〈1;class〉)-nginx-ingress-controller"] - shorewallParams: { - "\(〈4;cluster〉.shorewallPrefix)_INGRESS_\(〈import;strings〉.ToUpper(〈2;class〉))": 〈1;let svc#1〉.spec.externalIPs - } - } - } - #GlobalIngressController: { - class: string - objects: { - namespaced: { - ingress: { - Service: { - "\(〈4;class〉)-nginx-ingress-controller": { - spec: { - externalIPs: [ - "127.0.0.1", - ] - } - } - } - } - } - } - for kind, objs in 〈0;objects〉.namespaced.ingress { - for name, obj in 〈1;objs〉 { - objects: { - namespaced: { - ingress: { - "\(〈6;kind〉)": { - "\(〈5;name〉)": { - metadata: { - labels: { - "ingress-class": 〈11;class〉 - stack: "ingress" - ... - } - } - } - } - } - } - } - } - } - } - clusters: { - foo: {} - } -} ---- reductions.cue -{ - t1: { - params: 〈0;x〉.y - x: { - y: {} - } - for _, _ in 〈0;x〉 { - if true { - x: { - y: { - a: {} - } - } - } - } - } - t2: { - out: 〈0;let X#2〉.y - let X#2 = 〈0;m〉.x - m: { - x: { - y: {} - } - } - for _, v in 〈0;m〉 { - if true { - m: { - x: { - y: { - z: {} - } - } - } - } - } - } - t3: { - out: 〈0;foo〉.bar - foo: { - bar: {} - } - for _, _ in 〈0;foo〉 { - for name, _ in 〈2;foo〉 { - foo: { - 〈2;name〉: _ - } - } - } - } -} -- out/todo.txt -- v3 uses structure sharing (~) for t1.params, t2.out, t2.let X; v2 expands them. #Cluster.objects and clusters.foo.objects: v3 uses ~(), v2 expands. diff --git a/cue/testdata/eval/issue2337.txtar b/cue/testdata/eval/issue2337.txtar index b0bd29e1b..4c7ce42a1 100644 --- a/cue/testdata/eval/issue2337.txtar +++ b/cue/testdata/eval/issue2337.txtar @@ -56,44 +56,6 @@ issue2473: two: { [eval] simple.x: conflicting values "foo" and "x": ./in.cue:4:7 ./in.cue:9:7 --- out/compile -- ---- in.cue -{ - simple: { - x: "x" - 〈0;x〉: "foo" - } - issue2473: { - one: { - c: { - env: "prod" - env: ("dev"|"prod") - env2: 〈0;env〉 - } - if (〈0;c〉.env2 == "prod") { - { - c: { - env2: string - } - example: 〈0;c〉.env2 - } - } - } - } - issue2473: { - two: { - env: "prod" - env: ("dev"|"prod") - env2: 〈0;env〉 - if (〈0;env2〉 == "prod") { - { - env2: string - example: 〈0;env2〉 - } - } - } - } -} -- out/eval/stats -- Leaks: 2 Freed: 19 diff --git a/cue/testdata/eval/issue2550.txtar b/cue/testdata/eval/issue2550.txtar index e19087d58..eca0bc54f 100644 --- a/cue/testdata/eval/issue2550.txtar +++ b/cue/testdata/eval/issue2550.txtar @@ -15,16 +15,6 @@ if bar.missing == "x" { -- out/errors.txt -- [eval] undefined field: missing: ./in.cue:4:8 --- out/compile -- ---- in.cue -{ - foo: string - bar: close({}) - if (〈0;bar〉.missing == "x") { - let _bar#1 = 〈1;bar〉 - foo: 〈0;let _bar#1〉 - } -} -- out/eval/stats -- Leaks: 1 Freed: 4 diff --git a/cue/testdata/eval/issue2649.txtar b/cue/testdata/eval/issue2649.txtar index daca8ba76..8b8ea818d 100644 --- a/cue/testdata/eval/issue2649.txtar +++ b/cue/testdata/eval/issue2649.txtar @@ -7,11 +7,6 @@ @test(eq:todo, 8) @test(kind=float) // TODO: should this be a float, or can it also be an int? (4 + 8 + 12) / 3 --- out/compile -- ---- in.cue -{ - (((4 + 8) + 12) / 3) -} -- out/eval/stats -- Leaks: 0 Freed: 1 diff --git a/cue/testdata/eval/issue285.txtar b/cue/testdata/eval/issue285.txtar index 5ecc10c44..a7483bbba 100644 --- a/cue/testdata/eval/issue285.txtar +++ b/cue/testdata/eval/issue285.txtar @@ -29,23 +29,3 @@ Retain: 0 Unifications: 10 Conjuncts: 23 Disjuncts: 10 --- out/compile -- ---- in.cue -{ - #TopLevel: { - [string]: { - path: string - content: string - } - } - #Mid: (〈0;#TopLevel〉 & { - myoutput: { - path: "/output" - } - }) - val: ((〈0;#Mid〉 & {}) & { - myoutput: { - content: "foo" - } - }) -} diff --git a/cue/testdata/eval/issue295.txtar b/cue/testdata/eval/issue295.txtar index be69820f4..ad94c78f0 100644 --- a/cue/testdata/eval/issue295.txtar +++ b/cue/testdata/eval/issue295.txtar @@ -9,16 +9,6 @@ p: close({ "\("f")": _ }) @test(eq, {f: 9}) @test(closed) p: f: 9 --- out/compile -- ---- in.cue -{ - p: close({ - "\("f")": _ - }) - p: { - f: 9 - } -} -- out/eval/stats -- Leaks: 1 Freed: 3 diff --git a/cue/testdata/eval/issue3301.txtar b/cue/testdata/eval/issue3301.txtar index f3dc5f9b8..b27bc5e65 100644 --- a/cue/testdata/eval/issue3301.txtar +++ b/cue/testdata/eval/issue3301.txtar @@ -42,28 +42,3 @@ Conjuncts: 25 Disjuncts: 18 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - object: (〈0;#Leaf〉 & {}) - #Base: { - extra?: { - ... - } - } - #Mid: { - 〈1;#Base〉 - } - #Leaf: { - 〈1;#Mid〉 - extra?: { - ... - } - more?: int - if (〈0;extra〉.foo != _|_(explicit error (_|_ literal) in source)) { - if (〈1;more〉 != _|_(explicit error (_|_ literal) in source)) { - foo: "bar" - } - } - } -} diff --git a/cue/testdata/eval/issue3330.txtar b/cue/testdata/eval/issue3330.txtar index 745e53218..0446b8d1f 100644 --- a/cue/testdata/eval/issue3330.txtar +++ b/cue/testdata/eval/issue3330.txtar @@ -63,42 +63,3 @@ Retain: 3 Unifications: 35 Conjuncts: 69 Disjuncts: 46 --- out/compile -- ---- in.cue -{ - issue3330: { - #A: { - let empty#1 = {} - field: (null|{ - n: int - }) - field: (〈0;let empty#1〉 & { - n: 3 - }) - } - out: 〈import;list〉.Concat([ - [ - 〈2;#A〉, - ], - ]) - } - eliminated: { - #empty: {} - x: (null|{ - n: 3 - }) - x: (〈0;#empty〉 & { - n: 3 - }) - out: len(〈0;x〉) - } - simplified: { - #struct: { - field: ({ - n: 3 - } & 〈0;g〉) - g: {} - } - out: (〈0;#struct〉 & {}) - } -} diff --git a/cue/testdata/eval/issue349.txtar b/cue/testdata/eval/issue349.txtar index 92ad91b28..fee6dca98 100644 --- a/cue/testdata/eval/issue349.txtar +++ b/cue/testdata/eval/issue349.txtar @@ -34,17 +34,3 @@ Retain: 0 Unifications: 10 Conjuncts: 10 Disjuncts: 10 --- out/compile -- ---- in.cue -{ - ex: { - aaa: "aaa" - list: "list" - zzz: "zzz" - AAA: "AAA" - html: "html" - HTML: "html" - ZZZ: "ZZZ" - Html: "html" - } -} diff --git a/cue/testdata/eval/issue353.txtar b/cue/testdata/eval/issue353.txtar index 61abf43de..8723dbd8a 100644 --- a/cue/testdata/eval/issue353.txtar +++ b/cue/testdata/eval/issue353.txtar @@ -30,19 +30,3 @@ Conjuncts: 18 Disjuncts: 4 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - e: 〈0;#Example〉 - e: { - a: "hello" - } - #Example: { - a: string - ({ - value?: string - }|{ - externalValue?: string - }) - } -} diff --git a/cue/testdata/eval/issue3672.txtar b/cue/testdata/eval/issue3672.txtar index e457415e7..c5525f288 100644 --- a/cue/testdata/eval/issue3672.txtar +++ b/cue/testdata/eval/issue3672.txtar @@ -147,182 +147,6 @@ value0: Only: [{UseSectionName: true}] [incomplete] #orgForConfigTextRules.orgSyntax.elems: invalid interpolation: unresolved disjunction string | {UseSectionName:true} | {Append:string | {UseSectionName:true}} | {Prepend:string | {UseSectionName:true}} | [string | {UseSectionName:true} | {Append:string | {UseSectionName:true}} | {Prepend:string | {UseSectionName:true}},string | {UseSectionName:true} | {Append:string | {UseSectionName:true}} | {Prepend:string | {UseSectionName:true}}] (type (string|list|struct)): ./x.cue:116:5 ./x.cue:114:18 --- out/compile -- ---- x.cue -{ - #FinDefSetElemType: { - #Type!: _ - } - #FinDefSetDefinition: { - #Elem!: 〈1;#FinDefSetElemType〉 - #Alternatives: { - allBut: { - AllBut: [ - ...〈3;#Elem〉.#Type, - ] - } - only: { - Only: [ - ...〈3;#Elem〉.#Type, - ] - } - } - } - #mkFinDefSet: { - #Definition!: 〈1;#FinDefSetDefinition〉 - #Type: or([ - for _, v in 〈1;#Definition〉.#Alternatives { - 〈1;v〉 - }, - ]) - } - #FinDefSetElemType: { - #Type: _ - toString!: { - _input: 〈1;#Type〉 - _output: string - } - } - #FinDefSetDefinition: { - #Elem!: 〈1;#FinDefSetElemType〉 - #Alternatives: { - allBut: { - AllBut: [ - ...〈3;#Elem〉.#Type, - ] - let xs#1 = [ - for _, x in 〈1;AllBut〉 { - (〈5;#Elem〉.toString & { - _input: 〈2;x〉 - })._output - }, - ] - let str#2 = 〈import;strings〉.Join(〈0;let xs#1〉, "\",\"") - orgSyntax: "AllBut [\(〈0;let str#2〉)]" - } - only: { - Only: [ - ...〈3;#Elem〉.#Type, - ] - let xs#3 = [ - for _, x in 〈1;Only〉 { - (〈5;#Elem〉.toString & { - _input: 〈2;x〉 - })._output - }, - ] - let str#4 = 〈import;strings〉.Join(〈0;let xs#3〉, "\",\"") - orgSyntax: "Only [\(〈0;let str#4〉)]" - } - } - } - #ConfigText: (string|{ - UseSectionName: true - }) - #ConfigTextRule: (〈0;#ConfigText〉|{ - Append: 〈1;#ConfigText〉 - }|{ - Prepend: 〈1;#ConfigText〉 - }) - #ConfigTextRules: (〈0;#ConfigTextRule〉|[ - 〈1;#ConfigTextRule〉, - 〈1;#ConfigTextRule〉, - ...〈1;#ConfigTextRule〉, - ]) - #FinDefSetConfigTextElem: 〈0;#FinDefSetElemType〉 - #FinDefSetConfigTextElem: { - #Type: 〈1;#ConfigTextRules〉 - } - #FinDefSetOfConfigText: (〈0;#mkFinDefSet〉 & { - #Definition: { - #Elem: 〈2;#FinDefSetConfigTextElem〉 - } - }).#Type - #FinDefSetConfigTextElem: { - toString: { - _input: 〈2;#ConfigTextRules〉 - _output: (〈2;#orgForConfigTextRules〉 & { - source: 〈1;_input〉 - }).orgSyntax - } - } - #orgForConfigText: { - source: 〈1;#ConfigText〉 - orgSyntax: { - let INS#5 = (〈1;source〉 & string) - let INO#6 = (〈1;source〉 & { - UseSectionName: _ - }) - [ - if (〈1;let INS#5〉 != _|_(explicit error (_|_ literal) in source)) { - 〈import;"encoding/json"〉.Marshal(〈2;let INS#5〉) - }, - if (〈1;let INO#6〉 != _|_(explicit error (_|_ literal) in source)) { - "UseSectionName" - }, - "Impossible", - ][0] - } - } - #orgForConfigTextRule: { - source: 〈1;#ConfigTextRule〉 - orgSyntax: { - let INA#7 = (〈1;source〉 & { - Append: _ - }) - let INP#8 = (〈1;source〉 & { - Prepend: _ - }) - [ - if (〈1;let INA#7〉 != _|_(explicit error (_|_ literal) in source)) { - ("Append " + (〈4;#orgForConfigText〉 & { - source: 〈3;let INA#7〉.Append - }).orgSyntax) - }, - if (〈1;let INP#8〉 != _|_(explicit error (_|_ literal) in source)) { - ("Prepend " + (〈4;#orgForConfigText〉 & { - source: 〈3;let INP#8〉.Prepend - }).orgSyntax) - }, - (〈3;#orgForConfigText〉 & { - source: 〈3;source〉 - }).orgSyntax, - ][0] - } - } - #orgForConfigTextRules: { - source: 〈1;#ConfigTextRules〉 - orgSyntax: { - let INL#9 = (〈1;source〉 & [ - ..., - ]) - [ - if (〈1;let INL#9〉 != _|_(explicit error (_|_ literal) in source)) { - let elems#A = [ - for _, x in 〈4;source〉 { - (〈7;#orgForConfigTextRule〉 & { - source: 〈2;x〉 - }).orgSyntax - }, - ] - let result#B = 〈import;strings〉.Join(〈0;let elems#A〉, "\",\"") - "[\(〈0;let result#B〉)]" - }, - (〈3;#orgForConfigTextRule〉 & { - source: 〈3;source〉 - }).orgSyntax, - ][0] - } - } - value0: 〈0;#FinDefSetOfConfigText〉 - value0: { - Only: [ - { - UseSectionName: true - }, - ] - } -} -- out/eval/stats -- Leaks: 345 Freed: 1738 diff --git a/cue/testdata/eval/issue3688.txtar b/cue/testdata/eval/issue3688.txtar index 4fecd2748..9df106d0c 100644 --- a/cue/testdata/eval/issue3688.txtar +++ b/cue/testdata/eval/issue3688.txtar @@ -60,51 +60,3 @@ Conjuncts: 139 Disjuncts: 22 NumCloseIDs: 43 --- out/compile -- ---- x.cue -{ - #TypeA: (string|{ - foo: int - }) - #fun1: { - _in(:x): 〈1;#TypeA〉 - out: [ - if ((〈1;_in(:x)〉 & string) != _|_(explicit error (_|_ literal) in source)) { - 〈2;_in(:x)〉 - }, - if (〈1;_in(:x)〉.foo != _|_(explicit error (_|_ literal) in source)) { - "foo" - }, - "impossible", - ][0] - } - examples: { - [string]: { - in: _ - res: (〈2;#fun1〉 & { - _in(:x): 〈1;in〉 - _ - }).out - } - } - examples: { - eg1: { - in: "test" - } - } - examples: { - eg2: { - in: { - foo: 5 - } - } - } - examples: { - eg3: { - in: { - foo: 5 - bar: "test" - } - } - } -} diff --git a/cue/testdata/eval/issue3709.txtar b/cue/testdata/eval/issue3709.txtar index 978d5dd97..8b9e9fa99 100644 --- a/cue/testdata/eval/issue3709.txtar +++ b/cue/testdata/eval/issue3709.txtar @@ -18,13 +18,6 @@ package imported #Foo: bar?: #Bar #Bar: foo?: #Foo --- out/compile -- ---- input.cue -{ - out: { - [string]: 〈import;"foo.test/bar/imported"〉.#Foo - } -} -- out/eval/stats -- Leaks: 0 Freed: 2 diff --git a/cue/testdata/eval/issue3801.txtar b/cue/testdata/eval/issue3801.txtar index 6b405dca4..3b64116d9 100644 --- a/cue/testdata/eval/issue3801.txtar +++ b/cue/testdata/eval/issue3801.txtar @@ -191,147 +191,5 @@ Conjuncts: 327 Disjuncts: 14 NumCloseIDs: 77 --- out/compile -- ---- nested.cue -{ - issue3801: { - let: { - reduced: { - let F#1 = { - base: { - in: string - let X#2 = { - a: "\(〈1;in〉)" - }.a - out: 〈0;let X#2〉 - } - filled: (〈0;base〉 & { - in: "foo" - }) - } - z: 〈0;let F#1〉.filled.out - } - } - } - issue3801: { - nonRooted: { - reduced: { - #Output: { - output: { - #base: { - val0: string - msgObj: { - a: 〈1;val0〉 - }.a - value: 〈0;msgObj〉 - } - out: (〈0;#base〉 & { - val0: "foo" - }) - } - } - out: (〈0;#Output〉 & {}).output - } - } - } - issue3801: { - let: { - full: { - #Resource: { - someMsg: string - obs: ({}|*{ - missing: true - }) - let pickMsg#4 = [ - if 〈1;obs〉.missing { - msg: "\(〈2;someMsg〉)" - }, - { - msg: "bar" - }, - ][0] - patches: [ - { - op: "add" - path: "/metadata" - value: 〈2;let pickMsg#4〉.msg - }, - ] - } - #Patches: { - [string]: _ - } - #JSONPatch: { - namespace?: string - patch: [ - ...〈2;#JSONOp〉, - ] - output: (〈1;#Patches〉 & { - 〈1;namespace〉: 〈1;patch〉 - }) - } - #JSONOp: ({ - op: "add" - path: string - value: _ - }|{ - op: "remove" - path: string - }) - #Main: { - namespace: string - output: 〈0;let jsonPatch#5〉.output - let jsonPatch#5 = (〈1;#JSONPatch〉 & { - let base#8 = (〈2;#Resource〉 & {}) - let withMsg#9 = (〈0;let base#8〉 & { - someMsg: "foo" - }) - namespace: 〈1;namespace〉 - patch: 〈0;let withMsg#9〉.patches - }) - } - out: (〈0;#Main〉 & { - namespace: "ns1" - }).output - } - } - } - issue3801: { - nonRooted: { - full: { - #Output: { - namespace: string - output: (〈1;#SubOutput〉 & { - namespace: 〈1;namespace〉 - let base2#A = { - let base#B = (〈3;#Base〉 & {}) - output: (〈0;let base#B〉 & { - val0: "foo" - }) - } - patch: 〈0;let base2#A〉.output.value - }).output - } - out: (〈0;#Output〉 & { - namespace: "ns1" - }).output - #SubOutput: { - namespace?: string - patch: _ - output: { - 〈1;namespace〉: 〈1;patch〉 - } - } - #Base: { - val0: string - let msgObj#D = [ - 〈1;val0〉, - ][0] - value: 〈0;let msgObj#D〉 - } - } - } - } -} -- out/todo.txt -- v3 differences in error messages and closedness for nonRooted.reduced.out (#struct vs struct). diff --git a/cue/testdata/eval/issue3805.txtar b/cue/testdata/eval/issue3805.txtar index 85204c9f8..c85123b3d 100644 --- a/cue/testdata/eval/issue3805.txtar +++ b/cue/testdata/eval/issue3805.txtar @@ -231,103 +231,6 @@ tabcatsExample: { }] }] }] }) } --- out/compile -- ---- x.cue -{ - #PatientViewSections: { - [string]: 〈1;#PatientViewSection〉 - } - #PatientViewSection: 〈0;#PvSection〉 - #PvSection: { - Section: { - display?: string - entries: 〈2;#PatientViewEntries〉 - } - _json: [ - for k, v in 〈1;Section〉.entries { - 〈1;k〉: 〈1;v〉._json - }, - ] - } - #PatientViewEntries: { - [string]: 〈1;#PatientViewEntry〉 - } - #PatientViewEntry: { - (〈1;#PvSingleForm〉|〈1;#PvLink〉) - } - #PvSingleForm: { - SingleForm: { - formId: string - showNumberOfInstances?: bool - } - _json: [ - { - iDoc: "singleFormIDoc" - "X-FormId": 〈2;SingleForm〉.formId - }, - ] - } - #PvLink: { - Link: { - icon?: string - sections: 〈2;#PatientViewSections〉 - } - _json: [ - for k, v in 〈1;Link〉.sections { - 〈1;k〉: 〈1;v〉._json - }, - ] - } - #TabcatsJson: { - config: { - tabcats: 〈2;#PatientViewSections〉 - ... - } - json: { - tabcats: [ - for k, v in 〈2;config〉.tabcats { - 〈1;k〉: 〈1;v〉._json - }, - ] - } - } - tabcatsExample: 〈0;#TabcatsJson〉 - tabcatsExample: { - _e1: 〈1;#PatientViewEntry〉 - _e1: { - Link: { - sections: { - Formulare: { - Section: { - entries: { - Fotodokumentation: 〈6;_e2〉 - } - } - } - } - } - } - _e2: 〈1;#PatientViewEntry〉 - _e2: { - SingleForm: { - formId: "fotodokumentation" - } - } - _s: 〈1;#PvSection〉 - _s: { - Section: { - entries: { - Dokumentation: 〈3;_e1〉 - } - } - } - config: { - tabcats: { - "02": 〈2;_s〉 - } - } - } -} -- out/eval/stats -- Leaks: 77 Freed: 162 diff --git a/cue/testdata/eval/issue3813.txtar b/cue/testdata/eval/issue3813.txtar index 333b19d87..ffa36ca26 100644 --- a/cue/testdata/eval/issue3813.txtar +++ b/cue/testdata/eval/issue3813.txtar @@ -18,23 +18,6 @@ y: { x } y: f: true --- out/compile -- ---- x.cue -{ - x: { - [string]: _ - } - x: 〈0;#d〉 - #d: { - f: _ - } - y: { - 〈1;x〉 - } - y: { - f: true - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/eval/issue3905.txtar b/cue/testdata/eval/issue3905.txtar index d93109d0f..aac181ec0 100644 --- a/cue/testdata/eval/issue3905.txtar +++ b/cue/testdata/eval/issue3905.txtar @@ -104,61 +104,5 @@ Disjuncts: 10 Notifications: 2 NumCloseIDs: 13 --- out/compile -- ---- in.cue -{ - issue3905: { - reduced: { - #Schema: { - params: { - name: (string|*"foo") - } - result: { - 〈1;params〉.name: "bar" - } - } - 〈0;#Schema〉.result - } - } - issue3905: { - full: { - #ReferenceGrantBuilder: { - parameters: { - namespace: string - gatewayNamespace: (string|*"foo") - } - referenceGrant: { - 〈1;parameters〉.gatewayNamespace: (〈2;#ReferenceGrant〉 & { - metadata: { - name: 〈3;parameters〉.gatewayNamespace - } - metadata: { - namespace: 〈3;parameters〉.namespace - } - }) - } - } - (〈0;#ReferenceGrantBuilder〉 & { - parameters: { - namespace: "foo" - } - }).referenceGrant - #ReferenceGrant: { - apiVersion: "gateway.networking.k8s.io/v1beta1" - kind: "ReferenceGrant" - metadata!: { - name!: string - namespace!: string - labels?: { - [string]: string - } - annotations?: { - [string]: string - } - } - } - } - } -} -- out/todo.txt -- issue3905.full: v2 evaluates as non-closed struct, v3 as closed (#struct). diff --git a/cue/testdata/eval/issue3919.txtar b/cue/testdata/eval/issue3919.txtar index 1c7cb2982..e12e026c8 100644 --- a/cue/testdata/eval/issue3919.txtar +++ b/cue/testdata/eval/issue3919.txtar @@ -127,122 +127,5 @@ Conjuncts: 100 Disjuncts: 4 NumCloseIDs: 27 --- out/compile -- ---- in.cue -{ - full: { - out: { - env: { - if true { - PORT: 〈import;math〉.Abs(〈3;out〉.port) - } - } - if true { - port: (int|*30080) - } - } - } - reduced: { - if true { - a: 〈import;math〉.Abs(〈1;port〉) - } - port: (int|*30080) - } -} ---- issue3946.cue -{ - issue3946: { - reduced: { - out: [ - for _, v in 〈1;_inputs〉 { - 〈1;v〉 - }, - ] - _inputs: { - [_]: { - doExtra?: bool - if (〈0;doExtra〉 != _|_(explicit error (_|_ literal) in source)) { - if true { - extra: "yes" - } - } - } - } - if true { - _inputs: { - input1: { - name: "input1" - } - } - } - } - } -} ---- let.cue -{ - issue3931: { - full: { - bar: { - [string]: { - spec?: 〈2;let Spec#1〉 - } - } - if true { - foo: { - label: "foo" - } - bar: { - bar1: { - spec: { - selector: 〈3;foo〉 - } - } - } - } - let Spec#1 = { - selector?: 〈1;let Selector#2〉 - } - let Selector#2 = { - label?: string - expr?: [ - ...string, - ] - } - } - } -} ---- secondary.cue -{ - related: { - [string]: { - if true { - shared: { - all_total: 〈3;foo〉.fooData.total - } - } - } - foo: { - fooData: { - total: { - tags: 〈1;_hidden〉 - } - _hidden: { - extra: {} - } - } - } - #Tags: { - [string]: {} - } - bar: { - shared: { - [string]: { - tags: 〈3;#Tags〉 - } - bar_total: 〈2;foo〉.fooData.total - } - } - } -} -- out/todo.txt -- related: v3 uses structure sharing (~) for related.foo.fooData.total.tags and related.foo.shared.all_total, v2 expands them. diff --git a/cue/testdata/eval/issue494.txtar b/cue/testdata/eval/issue494.txtar index ca990e451..2f8c2ac86 100644 --- a/cue/testdata/eval/issue494.txtar +++ b/cue/testdata/eval/issue494.txtar @@ -24,56 +24,3 @@ Retain: 0 Unifications: 26 Conjuncts: 56 Disjuncts: 28 --- out/compile -- ---- in.cue -{ - _Q: [ - { - pos: 0 - }, - { - pos: 1 - }, - ] - a: { - [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] - } - a: { - ben: [ - {}, - ] - } - b: { - [string]: 〈1;_Q〉[0:1] - } - b: { - ben: [ - {}, - ] - } - c: { - [string]: [ - ...{ - l: len(〈3;a〉[〈2;-〉]) - }, - ] - } - c: { - ben: [ - {}, - ] - } - #d: { - [string]: ([ - ...{ - pos: &(int, >=0) - }, - ] & 〈1;_Q〉[0:len(〈1;#d〉[〈0;-〉])]) - } - #d: { - ben: [ - {}, - ] - } - d: 〈0;#d〉 -} diff --git a/cue/testdata/eval/issue500.txtar b/cue/testdata/eval/issue500.txtar index 1d763b440..183c17d70 100644 --- a/cue/testdata/eval/issue500.txtar +++ b/cue/testdata/eval/issue500.txtar @@ -30,45 +30,3 @@ Retain: 6 Unifications: 38 Conjuncts: 45 Disjuncts: 42 --- out/compile -- ---- in.cue -{ - a: 〈import;strings〉.Join(〈import;strings〉.Split("test", "")[1:], "") - b: 〈import;strings〉.Join([ - "t", - "e", - "s", - "t", - ][1:], "") - c: [ - "t", - "e", - "s", - "t", - ][1:] - d: 〈import;strings〉.Join(〈0;c〉, "") - e: 〈import;strings〉.Join(〈import;list〉.Concat([ - [ - "a", - ], - [ - "b", - ], - ]), "") - f: 〈import;list〉.Concat([ - [ - "a", - ], - [ - "b", - ], - ]) - g: 〈import;strings〉.Join(〈0;f〉, "") - h: 〈import;strings〉.Join(〈import;list〉.Repeat([ - "a", - ], 3), "") - i: 〈import;list〉.Repeat([ - "b", - ], 3) - j: 〈import;strings〉.Join(〈0;i〉, "") -} diff --git a/cue/testdata/eval/issue545.txtar b/cue/testdata/eval/issue545.txtar index 0b2396044..32a6fc7b2 100644 --- a/cue/testdata/eval/issue545.txtar +++ b/cue/testdata/eval/issue545.txtar @@ -85,32 +85,5 @@ Disjuncts: 16 Notifications: 3 NumCloseIDs: 22 --- out/compile -- ---- in.cue -{ - t1: { - #Test: { - #HTTP: =~"^http://" - #SSH: !~"^ssh://" - #USER: 〈import;strings〉.MinRunes(3) - source: (〈0;#HTTP〉|〈0;#SSH〉|〈0;#USER〉|〈1;#Test〉) - } - foo: (〈0;#Test〉 & { - source: "http://blablabla" - }) - bar: (〈0;#Test〉 & { - source: 〈1;foo〉 - }) - } - t2: { - str: "foo" - a: =~〈0;str〉 - b: =~"foo" - c: (((〈0;a〉 & 〈0;b〉) & 〈0;a〉) & 〈0;b〉) - d: 〈import;time〉.Time - e: 〈import;time〉.Time() - f: (((〈0;d〉 & 〈0;e〉) & 〈0;d〉) & 〈0;e〉) - } -} -- out/todo.txt -- Reordering of fields in t1.foo and t1.bar between v2 and v3 (source field order differs). diff --git a/cue/testdata/eval/issue599.txtar b/cue/testdata/eval/issue599.txtar index eddbf92b5..ec2e6c000 100644 --- a/cue/testdata/eval/issue599.txtar +++ b/cue/testdata/eval/issue599.txtar @@ -119,83 +119,5 @@ ConjunctInfos: 87 MaxConjunctInfos: 6 MaxReqSets: 11 MaxRedirect: 2 --- out/compile -- ---- in.cue -{ - a: { - #A: { - n: string - depends_on: [ - ...〈2;#AnyA〉, - ] - } - #AnyA: { - n: string - depends_on: [ - ...〈2;#AnyA〉, - ] - ... - } - #A1: { - 〈1;#A〉 - x: int - y: { - z: string - } - } - #A2: { - 〈1;#A〉 - i: string - } - s: { - [string]: (〈1;#AnyA〉 & { - n: 〈1;-〉 - }) - } - s: { - foo: (〈1;#A1〉 & { - x: 10 - y: { - z: "z" - } - }) - } - s: { - bar: (〈1;#A2〉 & { - i: "hello bar" - depends_on: [ - 〈3;s〉.foo, - ] - }) - } - } - b: { - #A: { - f: { - ... - } - } - #A1: { - 〈1;#A〉 - } - #C: { - d: { - ... - } - } - s: { - [string]: 〈1;#A1〉 - } - s: { - foo: { - f: (〈2;#C〉 & { - d: { - foo: "bar" - } - }) - } - } - } -} -- out/todo.txt -- Reordering of fields between v2 and v3. diff --git a/cue/testdata/eval/issue962.txtar b/cue/testdata/eval/issue962.txtar index 44a41c794..fb4c74791 100644 --- a/cue/testdata/eval/issue962.txtar +++ b/cue/testdata/eval/issue962.txtar @@ -17,13 +17,3 @@ _obj: foo[_what] @test(err, code=incomplete, pos=[-1:8], contains="invalid non- ./in.cue:7:8 [incomplete] _obj: invalid non-ground value string (must be concrete string): ./in.cue:7:8 --- out/compile -- ---- in.cue -{ - foo: { - bar: "something" - } - text: 〈import;"encoding/yaml"〉.Marshal(〈0;_obj〉) - _what: string - _obj: 〈0;foo〉[〈0;_what〉] -} diff --git a/cue/testdata/eval/let.txtar b/cue/testdata/eval/let.txtar index 6df5635eb..0588d0e46 100644 --- a/cue/testdata/eval/let.txtar +++ b/cue/testdata/eval/let.txtar @@ -290,205 +290,5 @@ Disjuncts: 12 Notifications: 3 NumCloseIDs: 110 --- out/compile -- ---- in.cue -{ - let A#1 = (3 * 3) - let B#2 = (〈0;let A#1〉 + 〈0;let A#1〉) - let C#3 = (〈0;let B#2〉 + 〈0;let B#2〉) - let D#4 = (〈0;let C#3〉 + 〈0;let C#3〉) - let E#5 = (〈0;let D#4〉 + 〈0;let D#4〉) - let F#6 = (〈0;let E#5〉 + 〈0;let E#5〉) - b: { - let G#7 = (〈1;let F#6〉 + 〈1;let F#6〉) - let H#8 = (〈0;let G#7〉 + 〈0;let G#7〉) - let I#9 = (〈0;let H#8〉 + 〈0;let H#8〉) - let J#A = (〈0;let I#9〉 + 〈0;let I#9〉) - let K#B = (〈0;let J#A〉 + 〈0;let J#A〉) - let L#C = (〈0;let K#B〉 + 〈0;let K#B〉) - let M#D = (〈0;let L#C〉 + 〈0;let L#C〉) - let N#E = (〈0;let M#D〉 + 〈0;let M#D〉) - let O#F = (〈0;let N#E〉 + 〈0;let N#E〉) - let P#10 = (〈0;let O#F〉 + 〈0;let O#F〉) - let Q#11 = (〈0;let P#10〉 + 〈0;let P#10〉) - let R#12 = (〈0;let Q#11〉 + 〈0;let Q#11〉) - let S#13 = (〈0;let R#12〉 + 〈0;let R#12〉) - let T#14 = (〈0;let S#13〉 + 〈0;let S#13〉) - a: 〈0;let T#14〉 - b: 〈1;let F#6〉 - } - issue1828: { - volumes: 〈0;let L3#15〉 - let L3#15 = { - for _, v2 in [ - for _, v1 in 〈2;let L2#16〉 {}, - ] {} - } - let L2#16 = 〈0;let L1#17〉 - let L1#17 = [] - } - ignoreErrorInLet: { - let X#18 = (1 & 2) - disjunction: (*〈0;let X#18〉|3) - } -} ---- incomprehension.cue -{ - list: { - l: [ - 1, - 2, - 3, - ] - c: [ - for _, v in 〈1;l〉 { - let X#19 = (〈1;v〉 * 4) - 〈0;let X#19〉 - }, - ] - } - referencesForDirectly: { - l: [ - 1, - 2, - 3, - ] - for k, v in 〈0;l〉 { - let Y#1Amulti = (〈1;v〉 * 4) - "\(〈1;k〉)": 〈0;let Y#1A〉 - } - } - referencesForViaLet: { - l: [ - 1, - 2, - 3, - ] - for k, v in 〈0;l〉 let X = (〈0;v〉 * 4) { - let Y#1Bmulti = 〈1;X〉 - "\(〈2;k〉)": 〈0;let Y#1B〉 - } - } - letClauseReferencesInert: { - x: 2 - l: [ - 1, - 2, - 3, - ] - for k, v in 〈0;l〉 let X = 〈1;x〉 { - let Y#1C = 〈1;X〉 - "\(〈2;k〉)": 〈0;let Y#1C〉 - } - } - indirectReference: { - l: [ - 1, - 2, - 3, - ] - for k, v in 〈0;l〉 { - y: 〈1;v〉 - let X#1D = (〈0;y〉 * 4) - "\(〈1;k〉)": 〈0;let X#1D〉 - } - } - nestedFor: { - for k, y in [ - 4, - 5, - ] { - let X#1Emulti = { - for _, x in [ - 1, - 2, - ] { - let X#1Fmulti = 〈1;x〉 - "\(〈0;let X#1F〉)": 〈0;let X#1F〉 - } - } - "\(〈1;k〉)": 〈0;let X#1E〉 - } - } -} ---- interpolation.cue -{ - issue4022: { - full: { - envScript: [ - for _, v in 〈1;_env〉 let v = 〈2;_env〉["KEY"] { - "\(〈1;v〉)" - }, - ] - _env: { - KEY: (*""|_) - } - } - } -} ---- issue2063.cue -{ - keepDescending: { - t1: { - ec: {} - bs: { - let m#21 = 〈1;ec〉.b - if (〈0;let m#21〉 == _|_(explicit error (_|_ literal) in source)) {} - x: { - y: "" - } - } - } - } - keepDescending: { - t2: { - x: 〈import;"encoding/yaml"〉.Marshal(〈0;bs〉) - ec: {} - bs: { - let m#22 = 〈1;ec〉.b - if (〈0;let m#22〉.b == _|_(explicit error (_|_ literal) in source)) {} - X: { - Y: 〈import;strings〉.Join([], "") - } - } - } - } -} ---- issue2166.cue -{ - letWithDynamicInComprehension: { - _i: { - a: "d" - b: "e" - } - for k, v in 〈0;_i〉 { - let T#23multi = 〈1;v〉 - 〈0;let T#23〉: "1" - } - } -} ---- issue2218.cue -{ - _parent_configs: { - PARENT: true - } - _configs: { - CHILD1: { - property: true - } - CHILD2: { - property: true - parent: "PARENT" - } - } - disabled_parent_test: { - for k, v in 〈1;_configs〉 { - let parent_config#24multi = (*〈3;_parent_configs〉[〈1;v〉.parent]|false) - "\(〈1;k〉)": { - parent_config: 〈1;let parent_config#24〉 - } - } - } -} -- out/todo.txt -- v3 reports extra position info for indirectReference errors and shows letClauseReferencesInert with an unresolved let expression (let Y#1Cmulti = 〈1;X〉) rather than v2's concrete let Y#1C = 2. diff --git a/cue/testdata/eval/letjoin.txtar b/cue/testdata/eval/letjoin.txtar index 6e291dcf8..87f1ff31c 100644 --- a/cue/testdata/eval/letjoin.txtar +++ b/cue/testdata/eval/letjoin.txtar @@ -197,157 +197,5 @@ Conjuncts: 326 Disjuncts: 32 NumCloseIDs: 87 --- out/compile -- ---- in.cue -{ - t1: { - x: { - a: int - y: { - let X#1 = { - b: 〈2;a〉 - c: 1 - } - v: 〈0;let X#1〉.c - } - } - x1: 〈0;x〉 - x1: { - a: 1 - } - x2: 〈0;x〉 - x2: { - a: 2 - } - xy: (〈0;x1〉.y & 〈0;x2〉.y) - } - t2: { - x: { - a: {} - y: { - let X#2 = { - b: 〈2;a〉 - c: 1 - } - v: 〈0;let X#2〉.c - } - } - x1: 〈0;x〉 - x1: { - a: { - q: 1 - } - } - x2: 〈0;x〉 - x2: { - a: { - r: 2 - } - } - xy: (〈0;x1〉 & 〈0;x2〉) - } -} ---- issue3590.cue -{ - issue3590: { - reduced: { - result: { - [_]: { - [string]: string - } - } - _input: { - A: { - p: "A" - } - B: { - p: "B" - } - } - for _, v in 〈0;_input〉 { - let Var1#3multi = 〈1;v〉.p - let Var2#4multi = 〈0;let Var1#3〉 - let Items#5 = { - item: 〈1;let Var2#4〉 - } - result: { - "conflicting-\(〈2;v〉.p)": 〈1;let Items#5〉 - } - } - } - } - issue3590: { - full: { - #Result: { - [_]: { - [string]: string - } - } - result: 〈0;#Result〉 - #Input: { - p: ("A"|"B") - } - _input: { - [_]: (〈1;#Input〉 & { - p: 〈1;-〉 - }) - } - _input: { - A: {} - B: {} - } - for _, v in 〈0;_input〉 { - let Var1#6multi = 〈1;v〉.p - let Var2#7multi = 〈0;let Var1#6〉 - let Items#8 = { - item: 〈1;let Var2#7〉 - } - result: { - "conflicting-\(〈2;v〉.p)": 〈1;let Items#8〉 - } - } - } - } - issue3591: { - missing: { - #Result: { - [_]: { - [string]: string - } - } - result: 〈0;#Result〉 - #Input: { - p: ("A"|"B") - } - _input: { - [_]: (〈1;#Input〉 & { - p: 〈1;-〉 - }) - } - _input: { - A: {} - B: {} - } - for _, v in 〈0;_input〉 { - let Var1#9multi = 〈1;v〉.p - let Var2#Amulti = 〈0;let Var1#9〉 - let Items#B = { - item: { - key1: 〈2;let Var2#A〉 - } - } - result: { - "missing-items-\(〈2;v〉.p)": { - for s, attr in 〈2;let Items#B〉 { - if (〈1;attr〉.key1 != _|_(explicit error (_|_ literal) in source)) { - 〈2;s〉: 〈2;attr〉.key1 - } - } - } - } - } - } - } -} -- out/todo.txt -- v3 uses structure sharing (~) for let bindings in t2's x1/x2/xy. v2 incorrectly showed conflicting values errors for issue3590's let Items; v3 correctly handles chained let bindings in for comprehensions. diff --git a/cue/testdata/eval/lists.txtar b/cue/testdata/eval/lists.txtar index 97e265e8a..25ae3a835 100644 --- a/cue/testdata/eval/lists.txtar +++ b/cue/testdata/eval/lists.txtar @@ -17,34 +17,3 @@ Retain: 6 Unifications: 15 Conjuncts: 29 Disjuncts: 13 --- out/compile -- ---- in.cue -{ - a: [ - ...int, - ] - a: [ - 1, - 2, - 3, - 5, - ] - a: [ - 1, - 2, - 3, - 〈1;d〉, - ] - b: 〈0;a〉[3] - d: 5 - c: [ - for _, x in [ - [ - 1, - 2, - ], - ][0] { - (〈1;x〉 + 〈3;d〉) - }, - ] -} diff --git a/cue/testdata/eval/merge.txtar b/cue/testdata/eval/merge.txtar index bd15af04f..a80284f2b 100644 --- a/cue/testdata/eval/merge.txtar +++ b/cue/testdata/eval/merge.txtar @@ -34,41 +34,3 @@ Disjuncts: 22 MisalignedConjunct: 9 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - key: "app01" - manifests: [ - { - deployment: { - #map: { - [string]: { - name: string - image: string - desc: string - } - } - } - deployment: { - #map: { - "\(〈4;key〉)": { - name: "app01" - } - } - } - }, - { - deployment: { - #map: { - app01: { - image: "image01" - } - } - } - }, - ] - results: _ - for _, manifest in 〈0;manifests〉 { - results: 〈1;manifest〉 - } -} diff --git a/cue/testdata/eval/nonrooted.txtar b/cue/testdata/eval/nonrooted.txtar index 257b791ca..186cf2a8c 100644 --- a/cue/testdata/eval/nonrooted.txtar +++ b/cue/testdata/eval/nonrooted.txtar @@ -106,67 +106,3 @@ x: conflicting values 4 and 1: ./in.cue:31:23 x: 2 errors in empty disjunction:: ./in.cue:28:8 --- out/compile -- ---- in.cue -{ - issue3977: { - inlineExpr: { - #NetworkID: 1 - #fn: { - x: 〈1;#NetworkID〉 - out: (〈0;x〉 + 1) - } - err: (〈0;#fn〉 & { - x: 2 - }).out - } - } - issue3977: { - inlineDisj1: { - #NetworkID: ("2"|"3"|"4") - #fn: { - x: 〈1;#NetworkID〉 - out: "value=\(〈0;x〉)" - } - err: (〈0;#fn〉 & { - x: "invalid" - }).out - } - } - issue3977: { - inlineDisj2: { - #NetworkID: 1 - #fn: { - x: 〈1;#NetworkID〉 - out: (〈0;x〉 + 10) - } - err: (〈0;#fn〉 & { - x: (*2|4) - }).out - } - } - issue3977: { - inlineDisj3: { - #NetworkID: 1 - #fn: { - x: 〈1;#NetworkID〉 - out: (〈0;x〉 + 10) - } - ok: (〈0;#fn〉 & { - x: (*2|int) - }).out - } - } - issue3977: { - inlineLet: { - #NetworkID: 1 - let p#1 = ({ - x: 〈1;#NetworkID〉 - out: (〈0;x〉 + 10) - } & { - x: 2 - }) - err: 〈0;let p#1〉.out - } - } -} diff --git a/cue/testdata/eval/notify.txtar b/cue/testdata/eval/notify.txtar index 06fc43ad3..b11829e22 100644 --- a/cue/testdata/eval/notify.txtar +++ b/cue/testdata/eval/notify.txtar @@ -99,44 +99,5 @@ Disjuncts: 736 Notifications: 5 NumCloseIDs: 241 --- out/compile -- ---- in.cue -{ - t1: { - 〈0;a〉 - a: { - a: (2|1) - } - } - t2: { - d: 〈0;d〉.a - d: { - a: { - a: (2|1) - } - } - } - t3: { - b: 〈0;a〉 - b: ((1|2)|2) - a: (1|2) - } -} ---- issue3437.cue -{ - issue3437: { - r: 〈0〉.a - d: { - a: { - a: { - a: ({ - b: 4 - }|〈3;d〉) - } - } - } - out: (〈0;r〉 & 〈0;d〉) - } -} -- out/todo.txt -- v3 reports error messages with different operand ordering ("conflicting values {a,...} and 1" vs v2's "conflicting values 1 and {a:(2|1)}"). diff --git a/cue/testdata/eval/openinline.txtar b/cue/testdata/eval/openinline.txtar index 46ab8e384..66d601645 100644 --- a/cue/testdata/eval/openinline.txtar +++ b/cue/testdata/eval/openinline.txtar @@ -113,96 +113,3 @@ Conjuncts: 108 Disjuncts: 0 NumCloseIDs: 19 --- out/compile -- ---- in.cue -{ - inlineErr: { - #D: { - a: 1 - } - def: { - x: (〈1;#D〉 & { - b: 2 - }).b - } - } - outerErr: { - _inToOut: { - in: _ - out: 〈0;in〉.foo - } - issue3534: { - #Inner: { - foo: { - minor: 2 - } - } - #Outer: { - version: { - major: 1 - ... - } - } - t1: 〈0;#Outer〉 - t1: { - version: (〈2;_inToOut〉 & { - in: 〈2;#Inner〉 - }).out - } - } - usingClose: { - #Inner: { - foo: close({ - minor: 2 - }) - } - #Outer: { - version: { - major: 1 - ... - } - } - t1: 〈0;#Outer〉 - t1: { - version: (〈2;_inToOut〉 & { - in: 〈2;#Inner〉 - }).out - } - } - extraNesting: { - #Inner: { - foo: { - x: { - minor: 2 - } - } - } - #Outer: { - version: { - x: { - major: 1 - ... - } - } - } - t1: 〈0;#Outer〉 - t1: { - version: (〈2;_inToOut〉 & { - in: 〈2;#Inner〉 - }).out - } - } - } - refFromPkg: 〈import;"foo.com/example"〉.#E.b - refFromLet: { - let X#1 = { - #D: { - a: 2 - } - #E: (〈0;#D〉 & { - b: 1 - }) - } - x: 〈0;let X#1〉.#E.b - } -} diff --git a/cue/testdata/eval/required.txtar b/cue/testdata/eval/required.txtar index ca41ce985..bfb2a7f20 100644 --- a/cue/testdata/eval/required.txtar +++ b/cue/testdata/eval/required.txtar @@ -143,115 +143,6 @@ doNotEscalateError: { ./issue3918.cue:49:8 [incomplete] doNotEscalateError.b.pass: undefined field: self: ./issue3918.cue:49:11 --- out/compile -- ---- in.cue -{ - self: { - t1: { - a?: int - } - } - self: { - t2: { - a!: int - a!: int - } - } - unify: { - t1: { - a!: int - a: int - } - } - unify: { - t2: { - a!: int - a?: int - } - } - #Def: { - t1: { - a!: int - } - } - allowed: { - issue2306: { - #A: { - a!: int - } - #A: 〈0;#B〉 - #B: { - b!: int - } - } - } - reference: { - toWithinDefinition: { - #Foo: { - a!: int - } - b: 〈0;#Foo〉.a - } - toFieldFromDefinition: { - #Foo: { - a!: int - } - b: 〈0;#Foo〉 - c: 〈0;b〉.a - } - toNonDefinition: { - x: { - y!: _ - } - b: 〈0;x〉.y - } - toConcrete: { - a!: 1 - b: (〈0;a〉 + 1) - } - } -} ---- issue3918.cue -{ - issue3918: { - reduced: { - #disjuncts: { - in!: [ - ...string, - ] - out: 〈import;strings〉.Join(〈0;in〉, "|") - } - x: (〈0;#disjuncts〉 & { - in: [ - "foo", - "bar", - ] - }).out - } - noFunction: { - #disjuncts: { - in!: [ - ...string, - ] - out: 〈0;in〉 - } - _foo: (〈0;#disjuncts〉 & {}) - x: 〈0;_foo〉.out - } - } - doNotEscalateError: { - a: { - in: _ - out: 〈0;in〉.self - } - b: { - required!: _ - pass: (〈1;a〉 & { - in: 〈1;required〉 - }).out - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 93 diff --git a/cue/testdata/eval/resolve_basic.txtar b/cue/testdata/eval/resolve_basic.txtar index 65f52b343..c753a54ad 100644 --- a/cue/testdata/eval/resolve_basic.txtar +++ b/cue/testdata/eval/resolve_basic.txtar @@ -22,16 +22,3 @@ Retain: 0 Unifications: 9 Conjuncts: 16 Disjuncts: 9 --- out/compile -- ---- in.cue -{ - a: 1 - b: (〈0;a〉 + 1) - d: { - x: _ - y: (〈1;b〉 + 〈0;x〉) - } - e: (〈0;d〉 & { - x: 5 - }) -} diff --git a/cue/testdata/eval/resolve_env.txtar b/cue/testdata/eval/resolve_env.txtar index d4f564623..9eb1567d9 100644 --- a/cue/testdata/eval/resolve_env.txtar +++ b/cue/testdata/eval/resolve_env.txtar @@ -26,30 +26,3 @@ Retain: 0 Unifications: 15 Conjuncts: 22 Disjuncts: 15 --- out/compile -- ---- in.cue -{ - a: { - d: int - b: { - c: 〈1;d〉 - } - } - x: { - d: 2 - b: 〈1;a〉.b.c - } - a1: { - y: 5 - } - a1: { - a2: { - a3: { - a4: { - a5: 〈4;a1〉.y - } - } - } - } - b: 〈0;a1〉.a2.a3.a4.a5 -} diff --git a/cue/testdata/eval/selectors.txtar b/cue/testdata/eval/selectors.txtar index 68590a694..fc33a58a0 100644 --- a/cue/testdata/eval/selectors.txtar +++ b/cue/testdata/eval/selectors.txtar @@ -30,30 +30,3 @@ Retain: 0 Unifications: 18 Conjuncts: 27 Disjuncts: 18 --- out/compile -- ---- in.cue -{ - a: 1 - b: (〈0;a〉 + 1) - d: { - x: _ - y: (〈1;b〉 + 〈0;x〉) - } - e: (〈0;d〉 & { - x: 5 - }) - f: { - a: { - "foo-bar": 3 - } - b: 〈0;a〉."foo-bar" - } - g: { - a: { - "foo-bar": { - c: 3 - } - } - b: 〈0;a〉."foo-bar".c - } -} diff --git a/cue/testdata/eval/sharing.txtar b/cue/testdata/eval/sharing.txtar index 91a943595..5da29c401 100644 --- a/cue/testdata/eval/sharing.txtar +++ b/cue/testdata/eval/sharing.txtar @@ -397,340 +397,3 @@ Notifications: 1 NumCloseIDs: 105 -- out/todo.txt -- v3 uses structure sharing (~) extensively in issue3641, issue3546, debug, issue3849, issue3903, and pending sections where v2 expanded values inline. v3 also omits shareCycle.t2.Y.x.x structural cycle error and instead reports conflicting values for shareCycle.t2.Y.x with additional position info. --- out/compile -- ---- acrossdisjunction.cue -{ - issue3679: { - b: (null|[ - string, - ]) - b: 〈import;list〉.Repeat([ - for k, v in [ - 0, - ] { - "bar" - }, - ], 1) - } -} ---- dupshare.cue -{ - issue3641: { - simplified: { - t1: { - #Context1: { - ctx: {} - } - Context2: { - ctx: {} - } - #Config1: { - cfg: 〈1;#Context1〉 - } - #Config3: { - cfg: 〈1;#Context1〉 - } - Config2: { - cfg: 〈1;Context2〉 - } - Config: (〈0;#Config1〉 & 〈0;Config2〉) - out: 〈0;Config〉 - out: 〈0;#Config3〉 - } - } - } - issue3641: { - simplified: { - t2: { - #Context1: { - ctx: {} - } - Context2: { - ctx: {} - } - #Config1: { - cfg: 〈1;#Context1〉 - } - #Config3: { - cfg: 〈1;#Context1〉 - } - Config2: { - cfg: 〈1;Context2〉 - } - Config: (〈0;#Config1〉 & 〈0;Config2〉) - out: 〈0;Config〉 - out: 〈0;#Config3〉 - } - } - } - issue3641: { - simplified: { - t3: { - #Context1: { - ctx: {} - } - Context2: { - ctx: {} - } - #Config1: { - cfg: 〈1;#Context1〉 - } - #Config3: { - cfg: 〈1;#Context1〉 - } - Config2: { - cfg: 〈1;Context2〉 - } - Config: (〈0;#Config1〉 & 〈0;Config2〉) - out: _|_(no sharing) - out: 〈0;Config〉 - out: 〈0;#Config3〉 - } - } - } - issue3641: { - full: { - #Context1: { - ctx: {} - } - #Context2: { - ctx: {} - } - #Config1: { - cfg: 〈1;#Context1〉 - } - #Config2: { - cfg: 〈1;#Context2〉 - } - #Schema: { - sch: 〈1;#Config1〉 - } - #Config: (〈0;#Config1〉 & 〈0;#Config2〉) - let config#1 = 〈0;#Config〉 - out: (〈0;#Schema〉 & { - sch: 〈1;let config#1〉 - }) - } - } - issue3546: { - reduced: { - all: [ - "a", - ] - #all: 〈0;all〉 - #Network: { - list: 〈1;#List〉 - } - #List: [ - ...string, - ] - val: 〈0;#Network〉 - val: { - list: 〈1;#all〉 - } - out: 〈0;#Network〉 - out: 〈0;val〉 - } - } -} ---- in.cue -{ - issue3062: { - ok1: { - #S: "a" - #o: { - x: 〈1;#S〉 - } - o: 〈0;#o〉 - o: 〈0;X〉 - X: { - x: 〈1;A〉 - } - A: "a" - } - } - issue3601: { - ok1: { - Y: (〈0;X〉 & _|_(no sharing)).a - X: { - a: { - b: 〈1;a〉.b - } - } - out: (〈0;Y〉 & _|_(no sharing)) - } - } - debug: { - sharingOn: { - a: 〈0;b〉 - b: { - c: 1 - } - } - sharingOff: { - t1: { - a: (〈0;b〉 & _|_(no sharing)) - b: { - c: 1 - } - } - } - sharingOff: { - t2: { - a: 〈0;b〉 - a: _|_(no sharing) - b: { - c: 1 - } - } - } - sharingOff: { - t3: { - a: _|_(no sharing) - a: 〈0;b〉 - b: { - c: 1 - } - } - } - } -} ---- issue3835.cue -{ - issue3835: { - foo: {} - _global: "global value" - [string]: { - if true let orgBotUser = 〈1;_global〉 { - out: ("prefix: " + 〈1;orgBotUser〉) - } - } - } -} ---- let.cue -{ - issue3903: { - full: { - _input: (null|*{ - name: "foo" - }) - let _inputList#2 = 〈import;list〉.FlattenN([ - 〈1;_input〉, - ], 0) - _inputByName: { - for _, input in 〈1;let _inputList#2〉 { - 〈1;input〉.name: 〈1;input〉 - } - } - for name, _input in 〈0;_inputByName〉 { - 〈1;name〉: (〈2;_template〉 & { - input: 〈2;_input〉 - }) - } - _template: { - input: { - name: string - } - result: "result-\(〈0;input〉.name)" - } - } - } - issue3903: { - noshare: { - _input: (null|*{ - name: "foo" - }) - let _inputList#3 = 〈import;list〉.FlattenN([ - 〈1;_input〉, - ], 0) - _inputByName: { - for _, input in (〈1;let _inputList#3〉 & _|_(no sharing)) { - 〈1;input〉.name: 〈1;input〉 - } - } - for name, _input in 〈0;_inputByName〉 { - 〈1;name〉: (〈2;_template〉 & { - input: 〈2;_input〉 - }) - } - _template: { - input: { - name: string - } - result: "result-\(〈0;input〉.name)" - } - } - } -} ---- pendingarcs.cue -{ - pending: { - t1: { - a: 〈0;X〉 - if true { - a: { - b: { - c: { - e: 1 - } - } - } - } - X: { - b: 〈1;Y〉 - } - Y: { - c: { - d: int - } - } - } - } - issue3849: { - dep: (〈0;#Deployment〉 & {}) - if true { - dep: { - metadata: { - name: { - app: "mysql" - } - } - } - } - #Deployment: { - metadata?: 〈1;#ObjectMeta〉 - } - #ObjectMeta: { - name?: { - [string]: string - } - } - } -} ---- sharecycle.cue -{ - shareCycle: { - t1: { - #X: {} - Y: { - x: (〈1;#X〉 & 〈1;Y〉) - } - } - } - shareCycle: { - t2: { - #X: int - Y: { - x: (〈1;#X〉 & 〈1;Y〉) - } - } - } - shareCycle: { - t3: { - #X: {} - Y: { - x: (〈1;Y〉 & 〈1;#X〉) - } - } - } -} diff --git a/cue/testdata/eval/shortcircuit.txtar b/cue/testdata/eval/shortcircuit.txtar index f97ce58e2..ea41ebaef 100644 --- a/cue/testdata/eval/shortcircuit.txtar +++ b/cue/testdata/eval/shortcircuit.txtar @@ -30,19 +30,3 @@ orTrueTrue: true || true @test(eq, true) // No short-circuit: || falls through when left is false. orFalseFalse: false || false @test(eq, false) orFalseTrue: false || true @test(eq, true) --- out/compile -- ---- in.cue -{ - incompleteInt: int - incompleteBool: bool - andFalseBottom: (false && _|_(explicit error (_|_ literal) in source)) - andFalseIncomplete: (false && 〈0;incompleteInt〉) - andFalseTrue: (false && true) - andTrueTrue: (true && true) - andTrueFalse: (true && false) - orTrueBottom: (true || _|_(explicit error (_|_ literal) in source)) - orTrueIncomplete: (true || 〈0;incompleteBool〉) - orTrueTrue: (true || true) - orFalseFalse: (false || false) - orFalseTrue: (false || true) -} diff --git a/cue/testdata/eval/shortcircuit_noexp.txtar b/cue/testdata/eval/shortcircuit_noexp.txtar index 9f44dc5e9..344db5353 100644 --- a/cue/testdata/eval/shortcircuit_noexp.txtar +++ b/cue/testdata/eval/shortcircuit_noexp.txtar @@ -13,9 +13,3 @@ noExpOr: true || _|_ @test(err, code=user, contains="explicit error (_|_ lite ./in.cue:3:20 [user] explicit error (_|_ literal) in source: ./in.cue:4:20 --- out/compile -- ---- in.cue -{ - noExpAnd: (false && _|_(explicit error (_|_ literal) in source)) - noExpOr: (true || _|_(explicit error (_|_ literal) in source)) -} diff --git a/cue/testdata/eval/structs.txtar b/cue/testdata/eval/structs.txtar index d603292a5..e54e8d752 100644 --- a/cue/testdata/eval/structs.txtar +++ b/cue/testdata/eval/structs.txtar @@ -12,10 +12,3 @@ Retain: 2 Unifications: 4 Conjuncts: 7 Disjuncts: 4 --- out/compile -- ---- in.cue -{ - v: { - a: (〈import;struct〉.MaxFields(2) & {}) - }.a -} diff --git a/cue/testdata/eval/unify.txtar b/cue/testdata/eval/unify.txtar index 8c9997620..cca57f6e6 100644 --- a/cue/testdata/eval/unify.txtar +++ b/cue/testdata/eval/unify.txtar @@ -22,28 +22,3 @@ Retain: 1 Unifications: 8 Conjuncts: 19 Disjuncts: 9 --- out/compile -- ---- in.cue -{ - a: { - d: { - 〈2;#base〉 - #info: { - ... - } - Y: 〈0;#info〉.X - } - } - #base: { - #info: { - ... - } - } - a: { - [string]: { - #info: { - X: "foo" - } - } - } -} diff --git a/cue/testdata/eval/v0.7.txtar b/cue/testdata/eval/v0.7.txtar index d76fb18b8..168bdb0fe 100644 --- a/cue/testdata/eval/v0.7.txtar +++ b/cue/testdata/eval/v0.7.txtar @@ -354,510 +354,3 @@ Notifications: 10 NumCloseIDs: 86 -- out/todo.txt -- v3 uses structure sharing (~) for dynamic.t2.ok.foo/\#X and mutual.t4.ok's y.c fields. v3 reports fewer error positions for definition.t0.err and definition.t1.err (missing some context positions). --- out/compile -- ---- builtins.cue -{ - mutualBuiltin: { - t1: { - ok: { - s3: 〈import;strings〉.ContainsAny(〈0;s4〉) - s4: 〈import;strings〉.ContainsAny(〈0;s3〉) - s4: "dd" - } - } - } - mutualBuiltin: { - t2: { - ok: { - s3: 〈import;strings〉.ContainsAny(〈0;s5〉, "dd") - s5: 〈0;s6〉 - s6: "dd" - } - } - } -} ---- chained.cue -{ - issue3925: { - reduced: { - out: 〈import;"encoding/yaml"〉.Marshal(〈0;in〉.b.actual) - in: { - a: "actual" - a: ("actual"|"other") - b: { - 〈1;a〉: { - c: "str" - } - } - } - } - } - issue3925: { - full: { - for name, _ in 〈0;_inputs〉 { - out: { - 〈2;name〉: { - early: "early value" - } - } - } - _inputs: { - input1: { - name: "actual" - config: { - 〈1;name〉: { - one: "one value" - } - } - } - } - _inputs: { - [_]: { - name: ("actual"|"other") - } - } - for name, input in 〈0;_inputs〉 { - out: { - 〈2;name〉: { - lateYAML: 〈import;"encoding/yaml"〉.Marshal(〈3;input〉.config[〈3;input〉.name]) - } - } - } - } - } -} ---- comprehensions.cue -{ - comprehensions: { - t1: { - ok: { - src: [ - "foo", - ] - for _, v in 〈0;src〉 { - "\(〈1;v〉)": 〈1;v〉 - } - } - } - } -} ---- definition.cue -{ - definition: { - t0: { - err: { - #D1: { - env: {} - } - d1: { - env: { - c: "C" - } - } - d1: 〈0;#D1〉 - } - } - } - definition: { - t1: { - err: { - a: 〈0;#A〉 - a: { - c: 1 - } - #A: {} - } - } - } - definition: { - t2: { - ok: { - p1: { - #A: { - ... - { - a: int - } - } - x: (〈0;#A〉 & { - c: int - }) - } - } - } - } - definition: { - t2: { - ok: { - p2: { - #A: { - { - a: int - } - ... - } - x: (〈0;#A〉 & { - c: int - }) - } - } - } - } - definition: { - t2: { - ok: { - p3: { - x: (〈0;#A〉 & { - c: int - }) - #A: { - ... - { - a: int - } - } - } - } - } - } - definition: { - t2: { - ok: { - p4: { - x: (〈0;#A〉 & { - c: int - }) - #A: { - { - a: int - } - ... - } - } - } - } - } -} ---- dynamic.cue -{ - dynamic: { - t1: { - ok: { - [string]: { - name: 〈1;-〉 - } - 〈0;x〉.y: {} - x: { - y: "foo" - } - } - } - } - dynamic: { - t2: { - ok: { - foo: 〈0;#X〉 - #X: { - a: { - b: { - C: 1 - } - } - for _, _ in 〈0;a〉 { - a: { - "b": { - D: 2 - } - } - } - } - } - } - } -} ---- equality.cue -{ - issue3194: { - reduced: { - A: (*0|>10) - A: (*0|>10) - { - out: close({ - b: 〈2;A〉 - }) - out: { - b: 〈2;A〉 - } - }.out - } - } -} ---- expr.cue -{ - expr: { - t1: { - ok: { - a: 〈0;X〉 - X: 5.0 - X: (〈0;Y〉 / 2) - Y: (〈0;a〉 * 2) - } - } - } - expr: { - t2: { - ok: { - A: (〈0;X〉 + 2) - X: 5 - X: (〈0;A〉 - 2) - } - } - } - expr: { - t3: { - ok: { - p1: { - a0: 〈0;X〉 - X: 5.0 - X: (〈0;a0〉 * 1) - } - } - } - } - expr: { - t3: { - ok: { - p2: { - b: (〈0;Y〉 * 1) - Y: (〈0;b〉 * 1) - Y: 5.0 - } - } - } - } - expr: { - t4: { - ok: { - a0: 〈0;X〉 - b0: 〈0;a1〉 - a1: (〈0;a0〉 + 2) - b1: (〈0;b0〉 - 2) - a0: 〈0;X〉 - X: 〈0;b1〉 - X: 5.0 - } - } - } -} ---- in.cue -{ - mutual: { - t0: { - ok: { - c: (〈0;e〉 & { - b: 2 - }) - e: { - a: 1 - } - e: 〈0;c〉 - } - } - } - mutual: { - t1: { - ok: { - a: { - 〈0;b〉 - b: { - b: { - f: 1 - } - } - } - a: 〈0;a〉.b - a: { - b: { - b: { - f: 1 - } - } - } - } - } - } - mutual: { - t2: { - ok: { - x: { - a: { - a: { - f: 1 - } - } - } - x: 〈0;y〉.a - y: { - a: { - a: { - e: 1 - } - } - } - y: 〈0;x〉.a - } - } - } - mutual: { - t3: { - ok: { - d: { - e: { - f: 1 - } - } - 〈0;d〉 - d: { - d: { - e: { - g: 1 - } - } - } - } - } - } - mutual: { - t4: { - ok: { - p0: { - z: 〈0;x〉.b - x: { - b: 〈1;y〉.c - } - x: { - b: { - d: { - b: 2 - } - } - } - y: { - c: 〈1;z〉.d - } - z: { - d: { - a: 1 - } - } - } - p1: { - x: { - b: 〈1;y〉.c - } - z: 〈0;x〉.b - x: { - b: { - d: { - b: 2 - } - } - } - y: { - c: 〈1;z〉.d - } - z: { - d: { - a: 1 - } - } - } - p2: { - x: { - b: 〈1;y〉.c - } - x: { - b: { - d: { - b: 2 - } - } - } - y: { - c: 〈1;z〉.d - } - z: 〈0;x〉.b - z: { - d: { - a: 1 - } - } - } - p3: { - x: { - b: { - d: { - b: 2 - } - } - } - y: { - c: 〈1;z〉.d - } - z: 〈0;x〉.b - x: { - b: 〈1;y〉.c - } - z: { - d: { - a: 1 - } - } - } - p4: { - z: 〈0;x〉.b - x: { - b: { - d: { - b: 2 - } - } - } - y: { - c: 〈1;z〉.d - } - x: { - b: 〈1;y〉.c - } - z: { - d: { - a: 1 - } - } - } - p5: { - x: { - b: { - d: { - b: 2 - } - } - } - y: { - c: 〈1;z〉.d - } - x: { - b: 〈1;y〉.c - } - z: 〈0;x〉.b - z: { - d: { - a: 1 - } - } - } - check: ((((〈0;p1〉 & 〈0;p2〉) & 〈0;p3〉) & 〈0;p4〉) & 〈0;p5〉) - } - } - } -} diff --git a/cue/testdata/eval/v0.7errorprop.txtar b/cue/testdata/eval/v0.7errorprop.txtar index d0d99b67e..e9db6cd9a 100644 --- a/cue/testdata/eval/v0.7errorprop.txtar +++ b/cue/testdata/eval/v0.7errorprop.txtar @@ -19,15 +19,6 @@ Retain: 1 Unifications: 4 Conjuncts: 6 Disjuncts: 5 --- out/compile -- ---- in.cue -{ - a: 〈0;#A〉 - a: { - c: 1 - } - #A: {} -} -- out/todo.txt -- v2 reports additional error positions (in.cue:1:4 and in.cue:3:5) for the "field not allowed" error on a.c. v3 only reports the direct field definition position diff --git a/cue/testdata/export/000.txtar b/cue/testdata/export/000.txtar index afe083b0b..4502deddc 100644 --- a/cue/testdata/export/000.txtar +++ b/cue/testdata/export/000.txtar @@ -1,11 +1,6 @@ #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- "hello" --- out/compile -- ---- in.cue -{ - "hello" -} -- out/eval/stats -- Leaks: 0 Freed: 1 diff --git a/cue/testdata/export/001.txtar b/cue/testdata/export/001.txtar index 96af3cfa9..30f14f5d0 100644 --- a/cue/testdata/export/001.txtar +++ b/cue/testdata/export/001.txtar @@ -1,11 +1,6 @@ #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- 'hello' --- out/compile -- ---- in.cue -{ - 'hello' -} -- out/eval/stats -- Leaks: 0 Freed: 1 diff --git a/cue/testdata/export/002.txtar b/cue/testdata/export/002.txtar index 44a35536d..f58b62586 100644 --- a/cue/testdata/export/002.txtar +++ b/cue/testdata/export/002.txtar @@ -1,11 +1,6 @@ #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- 'hello\nworld' --- out/compile -- ---- in.cue -{ - 'hello\nworld' -} -- out/eval/stats -- Leaks: 0 Freed: 1 diff --git a/cue/testdata/export/003.txtar b/cue/testdata/export/003.txtar index 34116e0c0..f6ece4b88 100644 --- a/cue/testdata/export/003.txtar +++ b/cue/testdata/export/003.txtar @@ -1,11 +1,6 @@ #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- "hello\nworld" --- out/compile -- ---- in.cue -{ - "hello\nworld" -} -- out/eval/stats -- Leaks: 0 Freed: 1 diff --git a/cue/testdata/export/004.txtar b/cue/testdata/export/004.txtar index ca31385fd..0d348001b 100644 --- a/cue/testdata/export/004.txtar +++ b/cue/testdata/export/004.txtar @@ -6,16 +6,6 @@ "_foo": int _bar: int } --- out/compile -- ---- in.cue -{ - { - $type: 3 - "_": int - "_foo": int - _bar: int - } -} -- out/eval/stats -- Leaks: 0 Freed: 5 diff --git a/cue/testdata/export/005.txtar b/cue/testdata/export/005.txtar index fde98cfa1..26112620c 100644 --- a/cue/testdata/export/005.txtar +++ b/cue/testdata/export/005.txtar @@ -1,18 +1,6 @@ #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: 1, b: a + 2, c: null, d: true, e: _, f: string} --- out/compile -- ---- in.cue -{ - { - a: 1 - b: (〈0;a〉 + 2) - c: null - d: true - e: _ - f: string - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/export/006.txtar b/cue/testdata/export/006.txtar index 98d1d5f59..c7b73ac1f 100644 --- a/cue/testdata/export/006.txtar +++ b/cue/testdata/export/006.txtar @@ -1,20 +1,6 @@ #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: {b: 2.0, s: "abc"}, b: a.b, c: a.c, d: a["d"], e: a.t[2:3]} --- out/compile -- ---- in.cue -{ - { - a: { - b: 2.0 - s: "abc" - } - b: 〈0;a〉.b - c: 〈0;a〉.c - d: 〈0;a〉["d"] - e: 〈0;a〉.t[2:3] - } -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/export/007.txtar b/cue/testdata/export/007.txtar index 9e167d212..be0ccfd2c 100644 --- a/cue/testdata/export/007.txtar +++ b/cue/testdata/export/007.txtar @@ -7,20 +7,6 @@ d: #a["d"] e: #a.t[2:3] } --- out/compile -- ---- in.cue -{ - { - #a: { - b: 2.0 - s: "abc" - } - b: 〈0;#a〉.b - c: 〈0;#a〉.c - d: 〈0;#a〉["d"] - e: 〈0;#a〉.t[2:3] - } -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/export/008.txtar b/cue/testdata/export/008.txtar index 0dba03e7f..c74d16aae 100644 --- a/cue/testdata/export/008.txtar +++ b/cue/testdata/export/008.txtar @@ -1,15 +1,6 @@ #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: [ 3 & 4]} --- out/compile -- ---- in.cue -{ - { - a: [ - (3 & 4), - ] - } -} -- out/eval/stats -- Leaks: 0 Freed: 3 diff --git a/cue/testdata/export/009.txtar b/cue/testdata/export/009.txtar index b415aafb0..f571e9c58 100644 --- a/cue/testdata/export/009.txtar +++ b/cue/testdata/export/009.txtar @@ -9,33 +9,6 @@ import "list" e: [1, 2, ...] f: [1, 2, ...] } --- out/compile -- ---- in.cue -{ - { - a: 〈import;list〉.Repeat([ - int, - ], 5) - a: [ - 1, - 2, - ..., - ] - e: [ - ...int, - ] - e: [ - 1, - 2, - ..., - ] - f: [ - 1, - 2, - ..., - ] - } -} -- out/eval/stats -- Leaks: 0 Freed: 15 diff --git a/cue/testdata/export/010.txtar b/cue/testdata/export/010.txtar index a6a4020dd..6c66f3d5b 100644 --- a/cue/testdata/export/010.txtar +++ b/cue/testdata/export/010.txtar @@ -10,33 +10,6 @@ import "list" e: [1, 2, ...] f: [1, 2, ...] } --- out/compile -- ---- in.cue -{ - { - a: 〈import;list〉.Repeat([ - int, - ], 5) - a: [ - 1, - 2, - ..., - ] - e: [ - ...int, - ] - e: [ - 1, - 2, - ..., - ] - f: [ - 1, - 2, - ..., - ] - } -} -- out/eval/stats -- Leaks: 0 Freed: 15 diff --git a/cue/testdata/export/011.txtar b/cue/testdata/export/011.txtar index ef71cc051..409becc63 100644 --- a/cue/testdata/export/011.txtar +++ b/cue/testdata/export/011.txtar @@ -2,17 +2,6 @@ raw: true #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: {b: []}, c: a.b, d: a["b"]} --- out/compile -- ---- in.cue -{ - { - a: { - b: [] - } - c: 〈0;a〉.b - d: 〈0;a〉["b"] - } -} -- out/eval/stats -- Leaks: 0 Freed: 5 diff --git a/cue/testdata/export/012.txtar b/cue/testdata/export/012.txtar index 78c8cd5a3..b3aa5dbe1 100644 --- a/cue/testdata/export/012.txtar +++ b/cue/testdata/export/012.txtar @@ -2,14 +2,6 @@ raw: true #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: *"foo" | *"bar" | *string | int, b: a[2:3]} --- out/compile -- ---- in.cue -{ - { - a: (*"foo"|*"bar"|*string|int) - b: 〈0;a〉[2:3] - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/export/013.txtar b/cue/testdata/export/013.txtar index bb1bd25be..11169dde3 100644 --- a/cue/testdata/export/013.txtar +++ b/cue/testdata/export/013.txtar @@ -3,13 +3,6 @@ { a: >=0 & <=10 & !=1 } --- out/compile -- ---- in.cue -{ - { - a: ((>=0 & <=10) & !=1) - } -} -- out/eval/stats -- Leaks: 0 Freed: 2 diff --git a/cue/testdata/export/014.txtar b/cue/testdata/export/014.txtar index 9a892ea42..8245d8132 100644 --- a/cue/testdata/export/014.txtar +++ b/cue/testdata/export/014.txtar @@ -4,13 +4,6 @@ raw: true { a: >=0 & <=10 & !=1 } --- out/compile -- ---- in.cue -{ - { - a: ((>=0 & <=10) & !=1) - } -} -- out/eval/stats -- Leaks: 0 Freed: 2 diff --git a/cue/testdata/export/015.txtar b/cue/testdata/export/015.txtar index ca5a4e291..5c75e3f23 100644 --- a/cue/testdata/export/015.txtar +++ b/cue/testdata/export/015.txtar @@ -6,16 +6,6 @@ eval: true a: (*1 | 2) & (1 | *2) b: [(*1 | 2) & (1 | *2)] } --- out/compile -- ---- in.cue -{ - { - a: ((*1|2) & (1|*2)) - b: [ - ((*1|2) & (1|*2)), - ] - } -} -- out/eval/stats -- Leaks: 0 Freed: 16 diff --git a/cue/testdata/export/016.txtar b/cue/testdata/export/016.txtar index 28f87f846..a9a287668 100644 --- a/cue/testdata/export/016.txtar +++ b/cue/testdata/export/016.txtar @@ -17,25 +17,6 @@ eval: true f64: float64 fi: float64 & int } --- out/compile -- ---- in.cue -{ - { - u16: ((int & >=0) & <=65535) - u32: &(int, >=0, <=4294967295) - u64: &(int, >=0, <=18446744073709551615) - u128: &(int, >=0, <=340282366920938463463374607431768211455) - u8: &(int, >=0, <=255) - ua: (&(int, >=0, <=65535) & >0) - us: ((>=0 & <10000) & int) - i16: ((>=-32768 & int) & <=32767) - i32: (&(int, >=-2147483648, <=2147483647) & >0) - i64: &(int, >=-9223372036854775808, <=9223372036854775807) - i128: &(int, >=-170141183460469231731687303715884105728, <=170141183460469231731687303715884105727) - f64: &(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308) - fi: (&(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308) & int) - } -} -- out/eval/stats -- Leaks: 0 Freed: 14 diff --git a/cue/testdata/export/017.txtar b/cue/testdata/export/017.txtar index 606e96631..42ba28d0a 100644 --- a/cue/testdata/export/017.txtar +++ b/cue/testdata/export/017.txtar @@ -2,21 +2,6 @@ raw: true #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: [1, 2], b: {for k, v in a if v > 1 {"\(k)": v}}} --- out/compile -- ---- in.cue -{ - { - a: [ - 1, - 2, - ] - b: { - for k, v in 〈1;a〉 if (〈0;v〉 > 1) { - "\(〈1;k〉)": 〈1;v〉 - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 6 diff --git a/cue/testdata/export/018.txtar b/cue/testdata/export/018.txtar index c03e6b49c..5026f9b68 100644 --- a/cue/testdata/export/018.txtar +++ b/cue/testdata/export/018.txtar @@ -2,21 +2,6 @@ raw: true #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: [1, 2], b: [for k, v in a {v}]} --- out/compile -- ---- in.cue -{ - { - a: [ - 1, - 2, - ] - b: [ - for k, v in 〈1;a〉 { - 〈1;v〉 - }, - ] - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/export/019.txtar b/cue/testdata/export/019.txtar index e2cc7325e..c2a70c921 100644 --- a/cue/testdata/export/019.txtar +++ b/cue/testdata/export/019.txtar @@ -2,14 +2,6 @@ raw: true #inlinetest:exclude skip — tests export format, not evaluator semantics -- in.cue -- {a: >=0 & <=10, b: "Count: \(a) times"} --- out/compile -- ---- in.cue -{ - { - a: (>=0 & <=10) - b: "Count: \(〈0;a〉) times" - } -} -- out/eval/stats -- Leaks: 0 Freed: 3 diff --git a/cue/testdata/export/020.txtar b/cue/testdata/export/020.txtar index 8d10652bf..156cd4103 100644 --- a/cue/testdata/export/020.txtar +++ b/cue/testdata/export/020.txtar @@ -19,11 +19,3 @@ NumCloseIDs: 1 a: (string){ "" } b: (int){ 0 } } --- out/compile -- ---- in.cue -{ - { - a: "" - b: len(〈0;a〉) - } -} diff --git a/cue/testdata/export/021.txtar b/cue/testdata/export/021.txtar index 31adeaedc..aee0b8c69 100644 --- a/cue/testdata/export/021.txtar +++ b/cue/testdata/export/021.txtar @@ -10,24 +10,6 @@ eval: true b: a: b: 4 a: b: 3 } --- out/compile -- ---- in.cue -{ - { - b: { - idx: 〈1;a〉[〈0;str〉] - str: string - } - b: { - a: { - b: 4 - } - } - a: { - b: 3 - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/export/022.txtar b/cue/testdata/export/022.txtar index 8e9ded87c..e2327bfbd 100644 --- a/cue/testdata/export/022.txtar +++ b/cue/testdata/export/022.txtar @@ -17,30 +17,6 @@ noOpt: true replicas: 2 } } --- out/compile -- ---- in.cue -{ - { - job: { - [_]: { - name: 〈1;-〉 - replicas: (&(int, >=0)|*1) - command: string - } - } - job: { - list: { - command: "ls" - } - } - job: { - nginx: { - command: "nginx" - replicas: 2 - } - } - } -} -- out/eval/stats -- Leaks: 1 Freed: 13 diff --git a/cue/testdata/export/023.txtar b/cue/testdata/export/023.txtar index 6943a6bd5..99d90b51d 100644 --- a/cue/testdata/export/023.txtar +++ b/cue/testdata/export/023.txtar @@ -23,35 +23,6 @@ raw: true {[_]: <300} } } --- out/compile -- ---- in.cue -{ - { - #emb: { - a: 1 - sub: { - f: 3 - } - } - #def: { - 〈1;#emb〉 - b: 2 - } - #f: { - a: 10 - } - #e: { - 〈1;#f〉 - b: int - { - [_]: <100 - } - { - [_]: <300 - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 15 diff --git a/cue/testdata/export/024.txtar b/cue/testdata/export/024.txtar index 942901ba7..137cb31f0 100644 --- a/cue/testdata/export/024.txtar +++ b/cue/testdata/export/024.txtar @@ -16,29 +16,6 @@ noOpt: true } val2: #def2 } --- out/compile -- ---- in.cue -{ - { - reg: { - foo: 1 - bar: { - baz: 3 - } - } - #def: { - a: 1 - sub: 〈1;reg〉 - } - val: 〈0;#def〉 - #def2: { - a: { - b: int - } - } - val2: 〈0;#def2〉 - } -} -- out/eval/stats -- Leaks: 0 Freed: 16 diff --git a/cue/testdata/export/025.txtar b/cue/testdata/export/025.txtar index 5c09043ba..a53802552 100644 --- a/cue/testdata/export/025.txtar +++ b/cue/testdata/export/025.txtar @@ -12,24 +12,6 @@ eval: true a: int c: *1 | 2 } --- out/compile -- ---- in.cue -{ - { - b: [ - { - { - [_]: int - } - if (〈2;a〉 > 4) { - f: 4 - } - }, - ][〈0;a〉] - a: int - c: (*1|2) - } -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/export/026.txtar b/cue/testdata/export/026.txtar index f16e60b5b..8c1541645 100644 --- a/cue/testdata/export/026.txtar +++ b/cue/testdata/export/026.txtar @@ -6,19 +6,6 @@ raw: true {a: 1} | {b: 1} } } --- out/compile -- ---- in.cue -{ - { - if false { - ({ - a: 1 - }|{ - b: 1 - }) - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 1 diff --git a/cue/testdata/export/027.txtar b/cue/testdata/export/027.txtar index f076236e1..622c947a6 100644 --- a/cue/testdata/export/027.txtar +++ b/cue/testdata/export/027.txtar @@ -11,15 +11,6 @@ eval: true #Bar: #Foo | string } } --- out/compile -- ---- in.cue -{ - { - #Foo: { - #Bar: (〈1;#Foo〉|string) - } - } -} -- out/eval/stats -- Leaks: 1 Freed: 4 diff --git a/cue/testdata/export/028.txtar b/cue/testdata/export/028.txtar index 68cba31ee..e56edd405 100644 --- a/cue/testdata/export/028.txtar +++ b/cue/testdata/export/028.txtar @@ -8,22 +8,6 @@ eval: true } a: [...string] } --- out/compile -- ---- in.cue -{ - { - #FindInMap: { - #: { - "Fn::FindInMap": [ - (string|〈3;#FindInMap〉), - ] - } - } - a: [ - ...string, - ] - } -} -- out/eval/stats -- Leaks: 1 Freed: 7 diff --git a/cue/testdata/export/029.txtar b/cue/testdata/export/029.txtar index 87b527aba..155dfa2a8 100644 --- a/cue/testdata/export/029.txtar +++ b/cue/testdata/export/029.txtar @@ -11,26 +11,6 @@ noOpt: true #: "Fn::And": [_] } } --- out/compile -- ---- in.cue -{ - { - #And: { - #: { - "Fn::And": [ - ...(3|〈3;#And〉), - ] - } - } - #Ands: (〈0;#And〉 & { - #: { - "Fn::And": [ - _, - ] - } - }) - } -} -- out/eval/stats -- Leaks: 0 Freed: 12 diff --git a/cue/testdata/export/030.txtar b/cue/testdata/export/030.txtar index f9d341773..02075bd8f 100644 --- a/cue/testdata/export/030.txtar +++ b/cue/testdata/export/030.txtar @@ -17,25 +17,6 @@ eval: true } #Bar: string } --- out/compile -- ---- in.cue -{ - { - #Foo: { - sgl: 〈1;#Bar〉 - ref: (null|〈1;#Foo〉) - ext: (〈1;#Bar〉|null) - ref: (null|〈1;#Foo〉) - ref2: (null|〈1;#Foo〉.sgl) - ... - } - #Foo: { - "#Foo": 2 - ... - } - #Bar: string - } -} -- out/eval/stats -- Leaks: 1 Freed: 22 diff --git a/cue/testdata/export/031.txtar b/cue/testdata/export/031.txtar index 18294f244..4683ec37f 100644 --- a/cue/testdata/export/031.txtar +++ b/cue/testdata/export/031.txtar @@ -6,20 +6,6 @@ eval: true A: [uint] B: A & ([10] | [192]) } --- out/compile -- ---- in.cue -{ - { - A: [ - &(int, >=0), - ] - B: (〈0;A〉 & ([ - 10, - ]|[ - 192, - ])) - } -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/export/032.txtar b/cue/testdata/export/032.txtar index a6f01eacd..7f0d9c51a 100644 --- a/cue/testdata/export/032.txtar +++ b/cue/testdata/export/032.txtar @@ -4,14 +4,6 @@ [string]: _ foo: 3 } --- out/compile -- ---- in.cue -{ - { - [string]: _ - foo: 3 - } -} -- out/eval/stats -- Leaks: 0 Freed: 2 diff --git a/cue/testdata/export/issue2119.txtar b/cue/testdata/export/issue2119.txtar index 5783c9a2f..b2d038c75 100644 --- a/cue/testdata/export/issue2119.txtar +++ b/cue/testdata/export/issue2119.txtar @@ -71,39 +71,3 @@ Conjuncts: 36 Disjuncts: 0 NumCloseIDs: 14 --- out/compile -- ---- in.cue -{ - simplified: { - x: { - d: { - ".*" - [ - (〈2〉 + ""), - ][0] - } - } - out: 〈import;"encoding/yaml"〉.Marshal(〈0;x〉) - } - original: { - #testableRegexp: { - string - #test: close({ - in: string - out: 〈import;regexp〉.FindSubmatch((("^" + 〈2〉) + "$"), 〈0;in〉)[1] - }) - } - rule: { - #patterns: { - bar: (〈2;#testableRegexp〉 & { - "(.*)" - #test: { - in: "testcontent" - out: "testcontent" - } - }) - } - } - out: 〈import;"encoding/yaml"〉.Marshal(〈0;rule〉) - } -} diff --git a/cue/testdata/export/issue2244.txtar b/cue/testdata/export/issue2244.txtar index c4ec371e6..a0067a87d 100644 --- a/cue/testdata/export/issue2244.txtar +++ b/cue/testdata/export/issue2244.txtar @@ -65,27 +65,3 @@ and not allow #pattern in #step [incomplete] error in call to strings.HasSuffix: non-concrete value string: ./in.cue:11:6 ./in.cue:8:12 --- out/compile -- ---- in.cue -{ - _#matchPattern(:x): { - #pattern: string - [ - if 〈import;strings〉.HasSuffix(〈1;#pattern〉, "*") { - let prefix#1 = 〈import;strings〉.TrimSuffix(〈2;#pattern〉, "*") - 〈0;let prefix#1〉 - }, - "'\(〈1;#pattern〉)'", - ][0] - } - _#isReleaseTag(:x): (〈0;_#matchPattern(:x)〉 & { - #pattern: "refs/tags/v*" - _ - }) - #step: { - if: (number|string) - } - m: (〈0;#step〉 & { - if: 〈1;_#isReleaseTag(:x)〉 - }) -} diff --git a/cue/testdata/export/issue854.txtar b/cue/testdata/export/issue854.txtar index fbbe36cdc..8d8bcad8e 100644 --- a/cue/testdata/export/issue854.txtar +++ b/cue/testdata/export/issue854.txtar @@ -22,11 +22,6 @@ package c -- out/errors.txt -- [incomplete] b: undefined field: c: ./b/b.cue:5:6 --- out/compile -- ---- a.cue -{ - theb: 〈import;"mod.test/b"〉.name -} -- out/eval/stats -- Leaks: 5 Freed: 2 @@ -38,4 +33,4 @@ Unifications: 6 Conjuncts: 8 Disjuncts: 0 -NumCloseIDs: 1 \ No newline at end of file +NumCloseIDs: 1 diff --git a/cue/testdata/fulleval/000_detect_conflicting_value.txtar b/cue/testdata/fulleval/000_detect_conflicting_value.txtar index e7976c809..82a647437 100644 --- a/cue/testdata/fulleval/000_detect_conflicting_value.txtar +++ b/cue/testdata/fulleval/000_detect_conflicting_value.txtar @@ -23,9 +23,3 @@ Retain: 0 Unifications: 2 Conjuncts: 5 Disjuncts: 4 --- out/compile -- ---- in.cue -{ - a: 8000.9 - a: (7080|int) -} diff --git a/cue/testdata/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar b/cue/testdata/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar index edb132959..85c1d037c 100644 --- a/cue/testdata/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar +++ b/cue/testdata/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar @@ -10,19 +10,6 @@ c: d & {b?: 4} @test(eq, { } | { b?: 4, a: 2 }) --- out/compile -- ---- in.cue -{ - d: ({ - a: 1 - b?: 3 - }|{ - a: 2 - }) - c: (〈0;d〉 & { - b?: 4 - }) -} -- out/eval/stats -- Leaks: 0 Freed: 15 diff --git a/cue/testdata/fulleval/002_resolve_all_disjunctions.txtar b/cue/testdata/fulleval/002_resolve_all_disjunctions.txtar index 2a3c08e7f..b6ccb2fdb 100644 --- a/cue/testdata/fulleval/002_resolve_all_disjunctions.txtar +++ b/cue/testdata/fulleval/002_resolve_all_disjunctions.txtar @@ -15,29 +15,6 @@ service: baz: {name: "foobar"} @test(eq, { name: "foobar" port: *7080 | int }) --- out/compile -- ---- in.cue -{ - service: { - [string]: { - name: (string|*〈1;-〉) - port: (int|*7080) - } - } - service: { - foo: _ - } - service: { - bar: { - port: 8000 - } - } - service: { - baz: { - name: "foobar" - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 23 diff --git a/cue/testdata/fulleval/003_field_templates.txtar b/cue/testdata/fulleval/003_field_templates.txtar index d92585069..116761a86 100644 --- a/cue/testdata/fulleval/003_field_templates.txtar +++ b/cue/testdata/fulleval/003_field_templates.txtar @@ -15,41 +15,6 @@ c: { foo: {} @test(eq, {name: "foo", y: 1}) bar: _ @test(eq, {name: "bar", y: 1}) } --- out/compile -- ---- in.cue -{ - a: { - { - [_]: int - } - k: 1 - } - b: { - { - [_]: { - x: 0 - y: (*1|int) - } - } - v: {} - w: { - y: 0 - } - } - b: { - [_]: {} - } - c: { - { - [_]: { - name: 〈1;-〉 - y: 1 - } - } - foo: {} - bar: _ - } -} -- out/eval/stats -- Leaks: 0 Freed: 21 diff --git a/cue/testdata/fulleval/004_field_comprehension.txtar b/cue/testdata/fulleval/004_field_comprehension.txtar index e8613e3d5..02ac9bc4f 100644 --- a/cue/testdata/fulleval/004_field_comprehension.txtar +++ b/cue/testdata/fulleval/004_field_comprehension.txtar @@ -21,26 +21,6 @@ c: { } @test(eq, {b: 2, c: 3}) } --- out/compile -- ---- in.cue -{ - a: { - for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { - "\(〈1;k〉)": 〈1;v〉 - } - } - b: { - a: 1 - b: 2 - c: 3 - d: 4 - } - c: { - for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { - "\(〈1;k〉)": 〈1;v〉 - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 12 diff --git a/cue/testdata/fulleval/005_conditional_field.txtar b/cue/testdata/fulleval/005_conditional_field.txtar index f0e2ef865..762784e71 100644 --- a/cue/testdata/fulleval/005_conditional_field.txtar +++ b/cue/testdata/fulleval/005_conditional_field.txtar @@ -27,28 +27,6 @@ d: { [incomplete] d: non-concrete value int in operand to >: ./in.cue:20:5 ./in.cue:19:5 --- out/compile -- ---- in.cue -{ - a: { - if 〈0;b〉 { - a: "foo" - } - b: true - } - c: { - a: 3 - if (〈0;a〉 > 1) { - a: 3 - } - } - d: { - a: int - if (〈0;a〉 > 1) { - a: 3 - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/fulleval/006_referencing_field_in_field_comprehension.txtar b/cue/testdata/fulleval/006_referencing_field_in_field_comprehension.txtar index e651e95ed..763096cf3 100644 --- a/cue/testdata/fulleval/006_referencing_field_in_field_comprehension.txtar +++ b/cue/testdata/fulleval/006_referencing_field_in_field_comprehension.txtar @@ -7,23 +7,6 @@ a: { "\(k)": v } } --- out/compile -- ---- in.cue -{ - a: { - b: { - c: 4 - } - } - a: { - b: { - d: 5 - } - for k, v in 〈0;b〉 { - "\(〈1;k〉)": 〈1;v〉 - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/fulleval/007_different_labels_for_templates.txtar b/cue/testdata/fulleval/007_different_labels_for_templates.txtar index a666dc9c9..27fc5c675 100644 --- a/cue/testdata/fulleval/007_different_labels_for_templates.txtar +++ b/cue/testdata/fulleval/007_different_labels_for_templates.txtar @@ -2,23 +2,6 @@ a: [X=string]: {name: X} a: [Name=string]: {name: Name} a: foo: {} @test(eq, {name: "foo"}) --- out/compile -- ---- in.cue -{ - a: { - [string]: { - name: 〈1;-〉 - } - } - a: { - [string]: { - name: 〈1;-〉 - } - } - a: { - foo: {} - } -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/fulleval/008_nested_templates_in_one_field.txtar b/cue/testdata/fulleval/008_nested_templates_in_one_field.txtar index bc5049262..6173fa1fb 100644 --- a/cue/testdata/fulleval/008_nested_templates_in_one_field.txtar +++ b/cue/testdata/fulleval/008_nested_templates_in_one_field.txtar @@ -10,43 +10,6 @@ a: "EE": b: "FF": {c: "bar"} @test(eq, { name: "EE" kind: "FF" }) --- out/compile -- ---- in.cue -{ - a: { - [string]: { - b: { - [string]: { - name: 〈3;-〉 - kind: 〈1;-〉 - } - } - } - } - a: { - A: { - b: { - B: _ - } - } - } - a: { - C: { - b: { - D: _ - } - } - } - a: { - EE: { - b: { - FF: { - c: "bar" - } - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 18 diff --git a/cue/testdata/fulleval/009_template_unification_within_one_struct.txtar b/cue/testdata/fulleval/009_template_unification_within_one_struct.txtar index b88089004..b3c68dedc 100644 --- a/cue/testdata/fulleval/009_template_unification_within_one_struct.txtar +++ b/cue/testdata/fulleval/009_template_unification_within_one_struct.txtar @@ -12,33 +12,6 @@ a: "E": {c: "bar"} @test(eq, { name: "E" kind: "E" }) --- out/compile -- ---- in.cue -{ - a: { - { - [string]: { - name: 〈1;-〉 - } - } - { - [string]: { - kind: 〈1;-〉 - } - } - } - a: { - A: _ - } - a: { - C: _ - } - a: { - E: { - c: "bar" - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 12 diff --git a/cue/testdata/fulleval/010_field_comprehensions_with_multiple_keys.txtar b/cue/testdata/fulleval/010_field_comprehensions_with_multiple_keys.txtar index eb8e37cfd..8e68019f2 100644 --- a/cue/testdata/fulleval/010_field_comprehensions_with_multiple_keys.txtar +++ b/cue/testdata/fulleval/010_field_comprehensions_with_multiple_keys.txtar @@ -26,50 +26,6 @@ for x in [ C: D: {a: "C", b: "D"} E: F: {a: "E", b: "F"} }) --- out/compile -- ---- in.cue -{ - for _, x in [ - { - a: "A" - b: "B" - }, - { - a: "C" - b: "D" - }, - { - a: "E" - b: "F" - }, - ] { - a: { - "\(〈2;x〉.a)": { - b: { - "\(〈4;x〉.b)": 〈4;x〉 - } - } - } - } - for _, x in [ - { - a: "A" - b: "B" - }, - { - a: "C" - b: "D" - }, - { - a: "E" - b: "F" - }, - ] { - "\(〈1;x〉.a)": { - "\(〈2;x〉.b)": 〈2;x〉 - } - } -} -- out/eval/stats -- Leaks: 20 Freed: 29 diff --git a/cue/testdata/fulleval/011_field_comprehensions_with_templates.txtar b/cue/testdata/fulleval/011_field_comprehensions_with_templates.txtar index ec9ce7a1c..ee5a06705 100644 --- a/cue/testdata/fulleval/011_field_comprehensions_with_templates.txtar +++ b/cue/testdata/fulleval/011_field_comprehensions_with_templates.txtar @@ -15,28 +15,6 @@ a: { } }) a: b: c: d: "bar" --- out/compile -- ---- in.cue -{ - num: 1 - a: { - if (〈1;num〉 < 5) { - [string]: { - [string]: { - name: 〈2;-〉 - kind: 〈1;-〉 - } - } - } - } - a: { - b: { - c: { - d: "bar" - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/fulleval/012_disjunctions_of_lists.txtar b/cue/testdata/fulleval/012_disjunctions_of_lists.txtar index 789111b9a..cbd3d1d39 100644 --- a/cue/testdata/fulleval/012_disjunctions_of_lists.txtar +++ b/cue/testdata/fulleval/012_disjunctions_of_lists.txtar @@ -5,23 +5,6 @@ t1: { l & ["c", "d"] @test(eq, ["c", "d"]) } --- out/compile -- ---- in.cue -{ - l: (*[ - int, - int, - ]|[ - string, - string, - ]) - t1: { - (〈1;l〉 & [ - "c", - "d", - ]) - } -} -- out/eval/stats -- Leaks: 0 Freed: 18 diff --git a/cue/testdata/fulleval/013_normalization.txtar b/cue/testdata/fulleval/013_normalization.txtar index c711ec4dd..8bf1d82d3 100644 --- a/cue/testdata/fulleval/013_normalization.txtar +++ b/cue/testdata/fulleval/013_normalization.txtar @@ -6,13 +6,6 @@ The redundancy that remains from not normalizing can be useful. a: string | string @test(eq, string) b: *1 | *int @test(eq, *1 | *int) c: *1.0 | *float @test(eq, *1.0 | *float) --- out/compile -- ---- in.cue -{ - a: (string|string) - b: (*1|*int) - c: (*1.0|*float) -} -- out/eval/stats -- Leaks: 0 Freed: 10 diff --git a/cue/testdata/fulleval/014_default_disambiguation_and_elimination.txtar b/cue/testdata/fulleval/014_default_disambiguation_and_elimination.txtar index baa8c0301..62e93754f 100644 --- a/cue/testdata/fulleval/014_default_disambiguation_and_elimination.txtar +++ b/cue/testdata/fulleval/014_default_disambiguation_and_elimination.txtar @@ -10,17 +10,6 @@ d: { @test(eq, 1 | 3 | int) } --- out/compile -- ---- in.cue -{ - a: (*1|int) - b: (*3|int) - e: (*1|*1) - c: (〈0;a〉 & 〈0;b〉) - d: { - (〈1;b〉 & 〈1;a〉) - } -} -- out/eval/stats -- Leaks: 0 Freed: 24 diff --git a/cue/testdata/fulleval/016_struct_comprehension_with_template.txtar b/cue/testdata/fulleval/016_struct_comprehension_with_template.txtar index dcf6f030b..0b083b1ba 100644 --- a/cue/testdata/fulleval/016_struct_comprehension_with_template.txtar +++ b/cue/testdata/fulleval/016_struct_comprehension_with_template.txtar @@ -33,35 +33,6 @@ service: baz: {name: "foobar"} @test(eq, { type: "service" port: *7080 | int }) --- out/compile -- ---- in.cue -{ - result: [ - for _, v in 〈1;service〉 { - 〈1;v〉 - }, - ] - service: { - [string]: { - name: (*〈1;-〉|string) - type: "service" - port: (*7080|int) - } - } - service: { - foo: {} - } - service: { - bar: { - port: 8000 - } - } - service: { - baz: { - name: "foobar" - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 51 diff --git a/cue/testdata/fulleval/017_resolutions_in_struct_comprehension_keys.txtar b/cue/testdata/fulleval/017_resolutions_in_struct_comprehension_keys.txtar index acb26ba50..8260b0361 100644 --- a/cue/testdata/fulleval/017_resolutions_in_struct_comprehension_keys.txtar +++ b/cue/testdata/fulleval/017_resolutions_in_struct_comprehension_keys.txtar @@ -1,16 +1,5 @@ -- in.cue -- a: {for _, b in ["c"] {"\(b+".")": "a"}} @test(eq, {"c.": "a"}) --- out/compile -- ---- in.cue -{ - a: { - for _, b in [ - "c", - ] { - "\((〈1;b〉 + "."))": "a" - } - } -} -- out/eval/stats -- Leaks: 2 Freed: 3 diff --git a/cue/testdata/fulleval/018_recursive_evaluation_within_list.txtar b/cue/testdata/fulleval/018_recursive_evaluation_within_list.txtar index 11dc17446..89643718c 100644 --- a/cue/testdata/fulleval/018_recursive_evaluation_within_list.txtar +++ b/cue/testdata/fulleval/018_recursive_evaluation_within_list.txtar @@ -17,30 +17,6 @@ b1: { [incomplete] b1.d: non-concrete value string in operand to +: ./in.cue:10:5 ./in.cue:11:5 --- out/compile -- ---- in.cue -{ - l: [ - 〈1;a〉, - ] - a: (〈0;b〉 & { - c: "t" - }) - b: { - d: 〈0;c〉 - c: string - } - l1: [ - 〈1;a1〉, - ] - a1: (〈0;b1〉 & { - c: "t" - }) - b1: { - d: ("s" + 〈0;c〉) - c: string - } -} -- out/eval/stats -- Leaks: 0 Freed: 21 diff --git a/cue/testdata/fulleval/020_complex_interaction_of_groundness.txtar b/cue/testdata/fulleval/020_complex_interaction_of_groundness.txtar index 152cfff9b..13b4080d0 100644 --- a/cue/testdata/fulleval/020_complex_interaction_of_groundness.txtar +++ b/cue/testdata/fulleval/020_complex_interaction_of_groundness.txtar @@ -16,37 +16,6 @@ a: b: c: d: string ./in.cue:4:34 ./in.cue:4:23 ./in.cue:5:13 --- out/compile -- ---- in.cue -{ - res: [ - for _, x in 〈1;a〉 for _, y in 〈0;x〉 { - (〈1;y〉 & { - d: "b" - }) - }, - ] - res: [ - (〈1;a〉.b.c & { - d: "b" - }), - ] - a: { - b: { - [string]: { - d: string - s: ("a" + 〈0;d〉) - } - } - } - a: { - b: { - c: { - d: string - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 10 diff --git a/cue/testdata/fulleval/021_complex_groundness_2.txtar b/cue/testdata/fulleval/021_complex_groundness_2.txtar index a7fa84fd4..cd08cba2b 100644 --- a/cue/testdata/fulleval/021_complex_groundness_2.txtar +++ b/cue/testdata/fulleval/021_complex_groundness_2.txtar @@ -45,42 +45,6 @@ a.b.c.s: non-concrete value string in operand to +: ./in.cue:15:14 ./in.cue:20:23 ./in.cue:21:13 --- out/compile -- ---- in.cue -{ - r1: (〈0;f1〉 & { - y: "c" - }) - f1: { - y: string - res: (〈1;a〉.b.c & { - d: 〈1;y〉 - }) - } - a: { - b: { - c: { - d: string - s: ("a" + 〈0;d〉) - } - } - } - a: { - b: { - [string]: { - d: string - s: ("a" + 〈0;d〉) - } - } - } - a: { - b: { - c: { - d: string - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 16 diff --git a/cue/testdata/fulleval/022_references_from_template_to_concrete.txtar b/cue/testdata/fulleval/022_references_from_template_to_concrete.txtar index 1d4eb95d5..31e57ac33 100644 --- a/cue/testdata/fulleval/022_references_from_template_to_concrete.txtar +++ b/cue/testdata/fulleval/022_references_from_template_to_concrete.txtar @@ -19,24 +19,3 @@ Retain: 3 Unifications: 14 Conjuncts: 21 Disjuncts: 15 --- out/compile -- ---- in.cue -{ - res: [ - 〈1;t〉, - ] - t: { - [string]: { - a: (〈0;c〉 + 〈0;b〉.str) - b: { - str: string - } - c: "X" - } - x: { - b: { - str: "DDDD" - } - } - } -} diff --git a/cue/testdata/fulleval/024_Issue_#23.txtar b/cue/testdata/fulleval/024_Issue_#23.txtar index a0415fa65..2f1b36f09 100644 --- a/cue/testdata/fulleval/024_Issue_#23.txtar +++ b/cue/testdata/fulleval/024_Issue_#23.txtar @@ -25,15 +25,3 @@ Retain: 0 Unifications: 7 Conjuncts: 15 Disjuncts: 11 --- out/compile -- ---- in.cue -{ - x: ({ - a: 1 - }|{ - a: 2 - }) - y: (〈0;x〉 & { - a: 3 - }) -} diff --git a/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar b/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar index ab7bf9011..d903edba5 100644 --- a/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar +++ b/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar @@ -58,27 +58,6 @@ n1.max: cycle with field: min: ./in.cue:20:6 -- out/todo.txt -- n1.min and n1.max: v2 reports "cycle error" without position details; v3 reports the full cycle with positions. --- out/compile -- ---- in.cue -{ - n1: { - min: <〈0;max〉 - max: >〈0;min〉 - } - n2: -〈0;num〉 - n3: +〈0;num〉 - n4: (〈0;num〉 + 〈0;num〉) - n5: (〈0;num〉 - 〈0;num〉) - n6: (〈0;num〉 * 〈0;num〉) - n7: (〈0;num〉 / 〈0;num〉) - b1: !〈0;is〉 - s1: "\(〈0;str〉)" - s2: 〈import;strings〉.ContainsAny("dd") - s3: 〈import;strings〉.ContainsAny(〈0;str〉, "dd") - str: string - num: <4 - is: bool -} -- out/eval/stats -- Leaks: 0 Freed: 17 diff --git a/cue/testdata/fulleval/027_len_of_incomplete_types.txtar b/cue/testdata/fulleval/027_len_of_incomplete_types.txtar index 5c83fc235..78c8ecdaf 100644 --- a/cue/testdata/fulleval/027_len_of_incomplete_types.txtar +++ b/cue/testdata/fulleval/027_len_of_incomplete_types.txtar @@ -29,36 +29,3 @@ Retain: 0 Unifications: 27 Conjuncts: 37 Disjuncts: 10 --- out/compile -- ---- in.cue -{ - args: (*[]|[ - ...string, - ]) - v1: len(〈0;args〉) - v2: len([]) - v3: len({}) - v4: len({ - a: 3 - }) - v5: len(({ - a: 3 - }|{ - a: 4 - })) - v6: len(('sf'|'dd')) - v7: len(([ - 2, - ]|*[ - 1, - 2, - ])) - v8: len(([ - 2, - ]|[ - 1, - 2, - ])) - v9: len("😂") - v10: len("") -} diff --git a/cue/testdata/fulleval/028_slice_rewrite_bug.txtar b/cue/testdata/fulleval/028_slice_rewrite_bug.txtar index 2c42621a2..788376dd5 100644 --- a/cue/testdata/fulleval/028_slice_rewrite_bug.txtar +++ b/cue/testdata/fulleval/028_slice_rewrite_bug.txtar @@ -16,25 +16,6 @@ t1: { } }) } --- out/compile -- ---- in.cue -{ - t1: { - fn: { - arg: ([ - ...int, - ] & [ - 1, - ]) - out: 〈0;arg〉[1:] - } - fn1: (〈0;fn〉 & { - arg: [ - 1, - ] - }) - } -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/fulleval/029_Issue_#94.txtar b/cue/testdata/fulleval/029_Issue_#94.txtar index fe772b427..7ac51e292 100644 --- a/cue/testdata/fulleval/029_Issue_#94.txtar +++ b/cue/testdata/fulleval/029_Issue_#94.txtar @@ -48,33 +48,3 @@ Disjuncts: 22 MisalignedConjunct: 1 NumCloseIDs: 1 --- out/compile -- ---- in.cue -{ - foo: { - opt?: 1 - txt: 2 - #def: 3 - regular: 4 - _hidden: 5 - } - comp: { - for k, v in 〈1;foo〉 { - "\(〈1;k〉)": 〈1;v〉 - } - } - select: { - opt: 〈1;foo〉.opt - txt: 〈1;foo〉.txt - #def: 〈1;foo〉.#def - regular: 〈1;foo〉.regular - _hidden: 〈1;foo〉._hidden - } - index: { - opt: 〈1;foo〉["opt"] - txt: 〈1;foo〉["txt"] - #def: 〈1;foo〉["#def"] - regular: 〈1;foo〉["regular"] - _hidden: 〈1;foo〉["_hidden"] - } -} diff --git a/cue/testdata/fulleval/030_retain_references_with_interleaved_embedding.txtar b/cue/testdata/fulleval/030_retain_references_with_interleaved_embedding.txtar index bcfb05dd8..bd402f3d1 100644 --- a/cue/testdata/fulleval/030_retain_references_with_interleaved_embedding.txtar +++ b/cue/testdata/fulleval/030_retain_references_with_interleaved_embedding.txtar @@ -17,31 +17,6 @@ a: d: { a: [Name=string]: {#info: { X: "foo" }} --- out/compile -- ---- in.cue -{ - a: { - d: { - 〈2;#base〉 - #info: { - ... - } - Y: 〈0;#info〉.X - } - } - #base: { - #info: { - ... - } - } - a: { - [string]: { - #info: { - X: "foo" - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/fulleval/031_comparison_against_bottom.txtar b/cue/testdata/fulleval/031_comparison_against_bottom.txtar index 65cc8d92e..f16944ed3 100644 --- a/cue/testdata/fulleval/031_comparison_against_bottom.txtar +++ b/cue/testdata/fulleval/031_comparison_against_bottom.txtar @@ -34,33 +34,3 @@ Retain: 4 Unifications: 21 Conjuncts: 28 Disjuncts: 21 --- out/compile -- ---- in.cue -{ - a: (_|_(explicit error (_|_ literal) in source) == _|_(explicit error (_|_ literal) in source)) - b: ((〈0;err〉 == 1) & 2) - c: (〈0;err〉 == _|_(explicit error (_|_ literal) in source)) - d: (〈0;err〉 != _|_(explicit error (_|_ literal) in source)) - e: ((〈0;err〉 != 1) & 3) - f: (({ - a: 1 - } & { - a: 2 - }) == _|_(explicit error (_|_ literal) in source)) - g: (({ - a: 1 - } & { - b: 2 - }) == _|_(explicit error (_|_ literal) in source)) - h: (_|_(explicit error (_|_ literal) in source) == ({ - a: 1 - } & { - a: 2 - })) - i: (_|_(explicit error (_|_ literal) in source) == ({ - a: 1 - } & { - b: 2 - })) - err: (1 & 2) -} diff --git a/cue/testdata/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar b/cue/testdata/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar index a2373ee0d..7738416d0 100644 --- a/cue/testdata/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar +++ b/cue/testdata/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar @@ -21,25 +21,6 @@ foo: #Workflow & { -- out/errors.txt -- [incomplete] #Workflow.#JobID: error in call to or: empty list in call to or: ./in.cue:6:10 --- out/compile -- ---- in.cue -{ - #Workflow: { - jobs: { - [string]: {} - } - #JobID: or([ - for k, _ in 〈1;jobs〉 { - 〈1;k〉 - }, - ]) - } - foo: (〈0;#Workflow〉 & { - jobs: { - foo: {} - } - }) -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/fulleval/034_label_and_field_aliases.txtar b/cue/testdata/fulleval/034_label_and_field_aliases.txtar index accef3bdf..36c210511 100644 --- a/cue/testdata/fulleval/034_label_and_field_aliases.txtar +++ b/cue/testdata/fulleval/034_label_and_field_aliases.txtar @@ -27,25 +27,6 @@ c: C @test(eq, 5) str: (int){ 5 } } """) --- out/compile -- ---- in.cue -{ - p: { - [string]: { - name: 〈1;-〉 - } - } - p: { - q: _ - } - "foo=bar": "str" - a: 〈0;"foo=bar"〉 - bb: 4 - b1: 〈0;bb〉 - b1: 〈0;bb〉 - "\(〈0;a〉)": 5 - c: 〈0;("\(〈0;a〉)")〉 -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/fulleval/035_optionals_with_label_filters.txtar b/cue/testdata/fulleval/035_optionals_with_label_filters.txtar index c8dfff798..8aff76497 100644 --- a/cue/testdata/fulleval/035_optionals_with_label_filters.txtar +++ b/cue/testdata/fulleval/035_optionals_with_label_filters.txtar @@ -43,54 +43,6 @@ jobs3: fooTest1: name: "badName" // faulty ./in.cue:25:8 -- out/todo.txt -- v2 reports additional error positions for jobs1.foo1 and jobs3.fooTest1 (extra positions for pattern/optional constraints); v3 only reports the direct definition position. --- out/compile -- ---- in.cue -{ - #JobID: =~"^[a-zA-Z]*$" - #Job: { - name: string - cmd: string - } - #Jobs: { - { - [〈2;#JobID〉]: 〈2;#Job〉 - } - { - [=~"Test$"]: { - name: =~"^test" - } - } - } - jobs: { - foo: { - name: "allGood" - } - } - jobs: { - foo: { - name: "allGood" - } - } - jobs1: 〈0;#Jobs〉 - jobs1: { - foo1: {} - } - jobs2: 〈0;#Jobs〉 - jobs2: { - fooTest: { - name: "badName" - } - } - jobs3: 〈0;#Jobs〉 - jobs3: { - [string]: 〈1;#Job〉 - } - jobs3: { - fooTest1: { - name: "badName" - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 19 diff --git a/cue/testdata/fulleval/040.txtar b/cue/testdata/fulleval/040.txtar index 00fb3ed2c..7d3919f73 100644 --- a/cue/testdata/fulleval/040.txtar +++ b/cue/testdata/fulleval/040.txtar @@ -23,24 +23,6 @@ foo: #Task & {"op": "pull"} @test(eq, { tagExpr: "latestdd" tagInString: "latest" }) --- out/compile -- ---- in.cue -{ - #Task: { - ({ - op: "pull" - tag: (*"latest"|string) - refToTag: 〈0;tag〉 - tagExpr: (〈0;tag〉 + "dd") - tagInString: "\(〈0;tag〉)" - }|{ - op: "scratch" - }) - } - foo: (〈0;#Task〉 & { - op: "pull" - }) -} -- out/eval/stats -- Leaks: 8 Freed: 16 diff --git a/cue/testdata/fulleval/041.txtar b/cue/testdata/fulleval/041.txtar index a01a74b32..69f22dac2 100644 --- a/cue/testdata/fulleval/041.txtar +++ b/cue/testdata/fulleval/041.txtar @@ -24,16 +24,3 @@ Disjuncts: 11 MisalignedConjunct: 1 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - t: { - #ok: (*true|bool) - if 〈0;#ok〉 { - x: int - } - } - s: (〈0;t〉 & { - #ok: false - }) -} diff --git a/cue/testdata/fulleval/042_cross-dependent_comprehension.txtar b/cue/testdata/fulleval/042_cross-dependent_comprehension.txtar index b1b8f3b25..794ab46f7 100644 --- a/cue/testdata/fulleval/042_cross-dependent_comprehension.txtar +++ b/cue/testdata/fulleval/042_cross-dependent_comprehension.txtar @@ -26,19 +26,3 @@ Conjuncts: 18 Disjuncts: 12 NumCloseIDs: 3 --- out/compile -- ---- in.cue -{ - #a: { - if 〈0;b〉 { - c: 4 - } - b: bool - } - x: ((〈0;#a〉 & { - b: true - }) & { - c: 4 - }) - y: 〈0;x〉 -} diff --git a/cue/testdata/fulleval/043_optional_expanded_before_lookup.txtar b/cue/testdata/fulleval/043_optional_expanded_before_lookup.txtar index 97fc98ede..319bc8adf 100644 --- a/cue/testdata/fulleval/043_optional_expanded_before_lookup.txtar +++ b/cue/testdata/fulleval/043_optional_expanded_before_lookup.txtar @@ -15,22 +15,6 @@ B: test.A & {} @test(eq, { field2: "2" name: "A" }) --- out/compile -- ---- in.cue -{ - test: { - [_]: { - name: 〈1;-〉 - } - } - test: { - A: { - field1: "1" - field2: "2" - } - } - B: (〈0;test〉.A & {}) -} -- out/eval/stats -- Leaks: 0 Freed: 10 diff --git a/cue/testdata/fulleval/044_Issue_#178.txtar b/cue/testdata/fulleval/044_Issue_#178.txtar index 9d90b18f2..99b760107 100644 --- a/cue/testdata/fulleval/044_Issue_#178.txtar +++ b/cue/testdata/fulleval/044_Issue_#178.txtar @@ -32,11 +32,3 @@ Retain: 5 Unifications: 5 Conjuncts: 13 Disjuncts: 10 --- out/compile -- ---- in.cue -{ - foo: 〈import;"encoding/csv"〉.Decode(〈0;data〉) - data: bytes - len: int - bar: 〈import;"encoding/hex"〉.EncodedLen(〈0;len〉) -} diff --git a/cue/testdata/fulleval/046_non-structural_direct_cycles.txtar b/cue/testdata/fulleval/046_non-structural_direct_cycles.txtar index 7a9cf5538..8a26340ca 100644 --- a/cue/testdata/fulleval/046_non-structural_direct_cycles.txtar +++ b/cue/testdata/fulleval/046_non-structural_direct_cycles.txtar @@ -26,15 +26,3 @@ Retain: 2 Unifications: 7 Conjuncts: 10 Disjuncts: 8 --- out/compile -- ---- in.cue -{ - c1: ({ - bar: { - baz: 2 - } - } & 〈0;c1〉.bar) - c2: ({ - bar: 1 - } & 〈0;c2〉.bar) -} diff --git a/cue/testdata/fulleval/047_dont_bind_to_string_labels.txtar b/cue/testdata/fulleval/047_dont_bind_to_string_labels.txtar index 6e24b2d3d..7c0a88f6f 100644 --- a/cue/testdata/fulleval/047_dont_bind_to_string_labels.txtar +++ b/cue/testdata/fulleval/047_dont_bind_to_string_labels.txtar @@ -5,15 +5,6 @@ y: { "x": 2 z: x @test(eq, 1) } --- out/compile -- ---- in.cue -{ - x: 1 - y: { - x: 2 - z: 〈1;x〉 - } -} -- out/eval/stats -- Leaks: 0 Freed: 5 diff --git a/cue/testdata/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar b/cue/testdata/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar index ec9591999..7233463cc 100644 --- a/cue/testdata/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar +++ b/cue/testdata/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar @@ -18,9 +18,3 @@ Retain: 0 Unifications: 3 Conjuncts: 3 Disjuncts: 0 --- out/compile -- ---- in.cue -{ - input: string - foo: 〈import;"encoding/json"〉.Marshal(〈0;input〉) -} diff --git a/cue/testdata/fulleval/049_alias_reuse_in_nested_scope.txtar b/cue/testdata/fulleval/049_alias_reuse_in_nested_scope.txtar index b6ce9a4af..70332feaa 100644 --- a/cue/testdata/fulleval/049_alias_reuse_in_nested_scope.txtar +++ b/cue/testdata/fulleval/049_alias_reuse_in_nested_scope.txtar @@ -34,38 +34,3 @@ Retain: 10 Unifications: 29 Conjuncts: 40 Disjuncts: 29 --- out/compile -- ---- in.cue -{ - #Foo: { - let X#1 = or([ - for k, _ in {} { - 〈1;k〉 - }, - ]) - connection: { - [〈1;let X#1〉]: 〈1;let X#1〉 - } - } - #A: { - foo: "key" - let X#2 = 〈0;foo〉 - a: { - foo: { - [〈2;let X#2〉]: 〈2;let X#2〉 - } - } - } - #B: { - foo: string - let X#3 = 〈0;foo〉 - a: { - foo: { - [〈2;let X#3〉]: 〈2;let X#3〉 - } - } - } - b: (〈0;#B〉 & { - foo: "key" - }) -} diff --git a/cue/testdata/fulleval/050_json_Marshaling_detects_incomplete.txtar b/cue/testdata/fulleval/050_json_Marshaling_detects_incomplete.txtar index dafa3e91c..5b3d1df22 100644 --- a/cue/testdata/fulleval/050_json_Marshaling_detects_incomplete.txtar +++ b/cue/testdata/fulleval/050_json_Marshaling_detects_incomplete.txtar @@ -29,15 +29,3 @@ Retain: 5 Unifications: 16 Conjuncts: 24 Disjuncts: 21 --- out/compile -- ---- in.cue -{ - a: 〈import;"encoding/json"〉.Marshal({ - a: string - }) - foo: { - a: 3 - b: 〈1;foo〉.c - } - b: 〈import;"encoding/json"〉.Marshal(〈0;foo〉) -} diff --git a/cue/testdata/fulleval/051_detectIncompleteYAML.txtar b/cue/testdata/fulleval/051_detectIncompleteYAML.txtar index 8cc65d1b0..5028ef388 100644 --- a/cue/testdata/fulleval/051_detectIncompleteYAML.txtar +++ b/cue/testdata/fulleval/051_detectIncompleteYAML.txtar @@ -42,24 +42,3 @@ Retain: 0 Unifications: 17 Conjuncts: 32 Disjuncts: 17 --- out/compile -- ---- in.cue -{ - #Spec: { - _vars(:foobar): { - something: string - } - data: { - #foo: { - use: 〈2;_vars(:foobar)〉.something - } - baz: 〈import;"encoding/yaml"〉.Marshal(〈1;_vars(:foobar)〉.something) - foobar: 〈import;"encoding/yaml"〉.Marshal(〈0;#foo〉) - } - } - Val: (〈0;#Spec〉 & { - _vars(:foobar): { - something: "var-string" - } - }) -} diff --git a/cue/testdata/fulleval/052_detectIncompleteJSON.txtar b/cue/testdata/fulleval/052_detectIncompleteJSON.txtar index 18a264ec7..9c8cc5bfa 100644 --- a/cue/testdata/fulleval/052_detectIncompleteJSON.txtar +++ b/cue/testdata/fulleval/052_detectIncompleteJSON.txtar @@ -41,24 +41,3 @@ Retain: 0 Unifications: 17 Conjuncts: 32 Disjuncts: 17 --- out/compile -- ---- in.cue -{ - #Spec: { - _vars(:foobar): { - something: string - } - data: { - #foo: { - use: 〈2;_vars(:foobar)〉.something - } - baz: 〈import;"encoding/json"〉.Marshal(〈1;_vars(:foobar)〉.something) - foobar: 〈import;"encoding/json"〉.Marshal(〈0;#foo〉) - } - } - Val: (〈0;#Spec〉 & { - _vars(:foobar): { - something: "var-string" - } - }) -} diff --git a/cue/testdata/fulleval/053_issue312.txtar b/cue/testdata/fulleval/053_issue312.txtar index b27764320..68ec1e8d1 100644 --- a/cue/testdata/fulleval/053_issue312.txtar +++ b/cue/testdata/fulleval/053_issue312.txtar @@ -11,17 +11,6 @@ for x in [1] { } @test(eq, *{} | {}) --- out/compile -- ---- in.cue -{ - for _, x in [ - 1, - ] { - (*close({})|{ - [_]: null - }) - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/fulleval/054_issue312.txtar b/cue/testdata/fulleval/054_issue312.txtar index ee12e6147..8d8e9e4b4 100644 --- a/cue/testdata/fulleval/054_issue312.txtar +++ b/cue/testdata/fulleval/054_issue312.txtar @@ -6,20 +6,6 @@ x: { a: 2 y: *1 | { a: 2 } }) --- out/compile -- ---- in.cue -{ - x: { - y: (*1|{ - a: 2 - }) - for _, x in [ - 1, - ] { - 〈2;y〉 - } - } -} -- out/eval/stats -- Leaks: 1 Freed: 8 diff --git a/cue/testdata/fulleval/055_issue318.txtar b/cue/testdata/fulleval/055_issue318.txtar index 5ea96698e..5e7862278 100644 --- a/cue/testdata/fulleval/055_issue318.txtar +++ b/cue/testdata/fulleval/055_issue318.txtar @@ -23,19 +23,6 @@ ./in.cue:6:15 [eval] #T.vy: undefined field: y: ./in.cue:8:12 --- out/compile -- ---- in.cue -{ - #T: { - arg: { - x: string - } - out1: "\(〈0;arg〉.x) \(〈0;arg〉.y)" - out2: "\(〈0;arg〉.y)" - vx: 〈0;arg〉.x - vy: 〈0;arg〉.y - } -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/inlinetest/closedness.txtar b/cue/testdata/inlinetest/closedness.txtar index dc0d64c50..6eeb9507d 100644 --- a/cue/testdata/inlinetest/closedness.txtar +++ b/cue/testdata/inlinetest/closedness.txtar @@ -32,42 +32,3 @@ t4: close({"string": 1}) t4: _ @test(closed) t4: _ @test(allows, "string") // quoted: literal field named string t4: _ @test(allows=false, string) // unquoted: any-string pattern not present --- out/compile -- ---- in.cue -{ - t1: close({ - b: {} - }) - t1: _ - t1: { - b: _ - } - t1: _ - t1: _ - #X: { - [=~"^Q*$"]: int - } - #X: _ - #X: _ - #X: _ - #X: _ - t2: 〈0;#X〉 - t2: _ - t2: _ - t2: _ - t2: _ - #Y: { - ... - } - t3: 〈0;#Y〉 - t3: _ - t3: _ - t3: _ - t3: _ - t4: close({ - string: 1 - }) - t4: _ - t4: _ - t4: _ -} diff --git a/cue/testdata/inlinetest/debug.txtar b/cue/testdata/inlinetest/debug.txtar index 6e50d6e8b..4fc8c4c52 100644 --- a/cue/testdata/inlinetest/debug.txtar +++ b/cue/testdata/inlinetest/debug.txtar @@ -48,19 +48,3 @@ debugCheckVersioned: { """) z: 99 } --- out/compile -- ---- in.cue -{ - debugCheckScalar: 42 - debugCheckStruct: { - a: 1 - b: 2 - } - debugCheckComputed: { - x: 10 - y: (〈0;x〉 * 2) - } - debugCheckVersioned: { - z: 99 - } -} diff --git a/cue/testdata/inlinetest/decl_eq.txtar b/cue/testdata/inlinetest/decl_eq.txtar index d718143d2..b29ee6852 100644 --- a/cue/testdata/inlinetest/decl_eq.txtar +++ b/cue/testdata/inlinetest/decl_eq.txtar @@ -17,13 +17,3 @@ c: { y: 2 } }) --- out/compile -- ---- in.cue -{ - a: 1 - b: (〈0;a〉 + 1) - c: { - x: "hello" - y: 〈1;b〉 - } -} diff --git a/cue/testdata/inlinetest/decl_eq_mixed.txtar b/cue/testdata/inlinetest/decl_eq_mixed.txtar index dcad78a2a..fe2324ed3 100644 --- a/cue/testdata/inlinetest/decl_eq_mixed.txtar +++ b/cue/testdata/inlinetest/decl_eq_mixed.txtar @@ -6,9 +6,3 @@ x: 1 @test(eq, 1) y: x + 1 @test(eq, {x: 1, y: 2}) --- out/compile -- ---- in.cue -{ - x: 1 - y: (〈0;x〉 + 1) -} diff --git a/cue/testdata/inlinetest/decl_eq_pattern.txtar b/cue/testdata/inlinetest/decl_eq_pattern.txtar index 6c7d062b5..dc6a6d9a1 100644 --- a/cue/testdata/inlinetest/decl_eq_pattern.txtar +++ b/cue/testdata/inlinetest/decl_eq_pattern.txtar @@ -5,13 +5,3 @@ {[X=string]: baz: X} bar: {} @test(eq, {bar: baz: "bar"}) --- out/compile -- ---- in.cue -{ - { - [string]: { - baz: 〈1;-〉 - } - } - bar: {} -} diff --git a/cue/testdata/inlinetest/hidden_fields.txtar b/cue/testdata/inlinetest/hidden_fields.txtar index 5678bb5f2..1d7cc7cd8 100644 --- a/cue/testdata/inlinetest/hidden_fields.txtar +++ b/cue/testdata/inlinetest/hidden_fields.txtar @@ -31,25 +31,3 @@ hiddenDefInBoth: { // No hidden fields on either side: passes trivially. noHidden: {a: 1, b: 2} @test(eq, {a: 1, b: 2}) --- out/compile -- ---- in.cue -{ - hiddenInBoth: { - _secret(:foo): 42 - a: (〈0;_secret(:foo)〉 + 1) - } - hiddenDeclForm: { - _secret(:foo): "x" - b: (〈0;_secret(:foo)〉 + 〈0;_secret(:foo)〉) - } - hiddenDefInBoth: { - _#Meta(:foo): { - info: "internal" - } - a: 1 - } - noHidden: { - a: 1 - b: 2 - } -} diff --git a/cue/testdata/inlinetest/permute.txtar b/cue/testdata/inlinetest/permute.txtar index d12ba5254..9dfbfc7e9 100644 --- a/cue/testdata/inlinetest/permute.txtar +++ b/cue/testdata/inlinetest/permute.txtar @@ -69,33 +69,3 @@ concretePermute: { } }) } --- out/compile -- ---- in.cue -{ - threeFieldPermute: { - a: (〈0;b〉 + 〈0;c〉) - b: 1 - c: 2 - } - twoFieldPermute: { - x: (〈0;y〉 + 1) - y: 5 - } - inDeclPermute: { - p: (〈0;q〉 + 〈0;r〉) - q: 3 - r: 7 - } - concretePermute: { - x: { - alpha: 1 - beta: 2 - gamma: 3 - } - y: { - alpha: 1 - beta: 2 - gamma: 3 - } - } -} diff --git a/cue/testdata/inlinetest/struct_eq.txtar b/cue/testdata/inlinetest/struct_eq.txtar index fb222a013..69208c12a 100644 --- a/cue/testdata/inlinetest/struct_eq.txtar +++ b/cue/testdata/inlinetest/struct_eq.txtar @@ -4,11 +4,3 @@ myStruct: { a: 1 b: a + 1 } --- out/compile -- ---- in.cue -{ - myStruct: { - a: 1 - b: (〈0;a〉 + 1) - } -} diff --git a/cue/testdata/inlinetest/structural.txtar b/cue/testdata/inlinetest/structural.txtar index 5ef0ea9a1..02cf9c20c 100644 --- a/cue/testdata/inlinetest/structural.txtar +++ b/cue/testdata/inlinetest/structural.txtar @@ -50,31 +50,3 @@ mixedInline: 42 @test(eq, 42) [eval] errWithCode: conflicting values string and 1 (mismatched types string and int): ./in.cue:7:14 ./in.cue:7:23 --- out/compile -- ---- in.cue -{ - errOnly: (1 & 2) - errWithCode: (string & 1) - eqBasic: { - a: 1 - b: 2 - } - eqComputed: { - x: 10 - y: (〈0;x〉 * 2) - } - skippedTest: { - a: 1 - } - descTest: { - v: "ok" - } - versionOverride: { - x: 1 - } - plainFixture: { - x: 42 - } - refsFixture: 〈0;plainFixture〉.x - mixedInline: 42 -} diff --git a/cue/testdata/inlinetest/validators.txtar b/cue/testdata/inlinetest/validators.txtar index 195772024..db665912b 100644 --- a/cue/testdata/inlinetest/validators.txtar +++ b/cue/testdata/inlinetest/validators.txtar @@ -11,13 +11,3 @@ rawMin: struct.MinFields(3) @test(eq, struct.MinFields(3)) intMixDirect: int & <=1 @test(eq, <=1 & int) intMixEmbed: {int & <=1} @test(eq, {<=1 & int}) --- out/compile -- ---- in.cue -{ - rawMax: 〈import;struct〉.MaxFields(2) - rawMin: 〈import;struct〉.MinFields(3) - intMixDirect: (int & <=1) - intMixEmbed: { - (int & <=1) - } -} diff --git a/cue/testdata/interpolation/041_interpolation.txtar b/cue/testdata/interpolation/041_interpolation.txtar index 4261caf5e..3ab9bff6a 100644 --- a/cue/testdata/interpolation/041_interpolation.txtar +++ b/cue/testdata/interpolation/041_interpolation.txtar @@ -15,17 +15,6 @@ e: "\([])" @test(err, code=eval, contains="invalid interpolation: cannot use [ [eval] e: invalid interpolation: cannot use [] (type list) as type (bool|string|bytes|number): ./in.cue:7:4 ./in.cue:7:7 --- out/compile -- ---- in.cue -{ - a: "\(4)" - b: "one \(〈0;a〉) two \((〈0;a〉 + 〈0;c〉))" - c: "one" - d: "\(〈0;r〉)" - u: "\(_)" - r: _ - e: "\([])" -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/interpolation/042_multiline_interpolation.txtar b/cue/testdata/interpolation/042_multiline_interpolation.txtar index 8c4a2318d..1dc626e97 100644 --- a/cue/testdata/interpolation/042_multiline_interpolation.txtar +++ b/cue/testdata/interpolation/042_multiline_interpolation.txtar @@ -44,34 +44,6 @@ m4: """ 4) """ @test(eq, "\n4\n") --- out/compile -- ---- in.cue -{ - a1: "before - \(4) - after" - a2: "before - \(4) - " - a3: " - \(4) - after" - a4: " - \(4) - " - m1: "before - \(4) - after" - m2: "before - \(4) - " - m3: " - \(4) - after" - m4: " - \(4) - " -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/interpolation/incomplete.txtar b/cue/testdata/interpolation/incomplete.txtar index 092c6ecc2..007d69ab8 100644 --- a/cue/testdata/interpolation/incomplete.txtar +++ b/cue/testdata/interpolation/incomplete.txtar @@ -28,19 +28,3 @@ Retain: 0 Unifications: 7 Conjuncts: 11 Disjuncts: 7 --- out/compile -- ---- in.cue -{ - a: "foo" - b: "boo" - commands: { - #c: { - help: "help!" - } - } - out: "a is \(〈0;a〉) - b is \(〈0;b〉) - - c is \(〈0;commands〉.#c.help) - d is \(〈0;commands〉.#d.help)" -} diff --git a/cue/testdata/interpolation/issue487.txtar b/cue/testdata/interpolation/issue487.txtar index e832059df..c9d82ad7a 100644 --- a/cue/testdata/interpolation/issue487.txtar +++ b/cue/testdata/interpolation/issue487.txtar @@ -36,25 +36,3 @@ Retain: 0 Unifications: 15 Conjuncts: 29 Disjuncts: 15 --- out/compile -- ---- in.cue -{ - t1: { - #R: { - pos: &(int, >=0) - name: "hello_\(〈0;pos〉)" - } - a: (〈0;#R〉 & { - pos: 67 - }) - } - t2: { - #R: { - pos: string - name: "hello_\(〈0;pos〉)" - } - a: (〈0;#R〉 & { - pos: "a" - }) - } -} diff --git a/cue/testdata/interpolation/scalars.txtar b/cue/testdata/interpolation/scalars.txtar index 484dc35a8..de898d2fb 100644 --- a/cue/testdata/interpolation/scalars.txtar +++ b/cue/testdata/interpolation/scalars.txtar @@ -28,21 +28,6 @@ Retain: 0 Unifications: 11 Conjuncts: 12 Disjuncts: 0 --- out/compile -- ---- in.cue -{ - bool1: "1+1=2: \(true)" - bool1: "1+1=2: \(true)" - bool2: "1+1=1: \(false)" - b1: 'a\xed\x95a' - bytes1s: "\(〈0;b1〉)" - bytes1b: '\(〈0;b1〉)' - b2: 'a\x80\x95a' - bytes2s: "\(〈0;b2〉)" - bytes2b: '\(〈0;b2〉)' - n1: "\(1) \(2.00)" - n2: "\(1E+2)" -} -- out/diff-v2-v3.txt -- v2 produces two replacement characters for bytes2s ("a\uFFFD\uFFFDa"); v3 produces one ("a\uFFFDa"). Reason: V2 implements Go conversions standard, which diff --git a/cue/testdata/lists/019_list_types.txtar b/cue/testdata/lists/019_list_types.txtar index bb4df0efe..24aebd1d6 100644 --- a/cue/testdata/lists/019_list_types.txtar +++ b/cue/testdata/lists/019_list_types.txtar @@ -27,74 +27,6 @@ e1: [...int] e1: [...float] @test(eq, []) -- out/errors.txt -- [eval] e0: incompatible list lengths (1 and 2) --- out/compile -- ---- in.cue -{ - l0: 〈import;list〉.Repeat([ - int, - ], 3) - l0: [ - 1, - 2, - 3, - ] - l2: [ - ...{ - a: int - }, - ] - l2: [ - { - a: 1 - }, - { - a: 2 - b: 3 - }, - ] - s1: 〈import;list〉.Repeat([ - int, - ], 6)[2:3] - s2: [ - 0, - 2, - 3, - ][1:2] - i1: 〈import;list〉.Repeat([ - int, - ], 6)[2] - i2: [ - 0, - 2, - 3, - ][2] - t0: [ - ...{ - a: 8 - }, - ] - t0: [ - {}, - ] - t1: [ - ..., - ] - t1: [ - ...int, - ] - e0: 〈import;list〉.Repeat([ - {}, - ], 2) - e0: [ - {}, - ] - e1: [ - ...int, - ] - e1: [ - ...float, - ] -} -- out/eval/stats -- Leaks: 0 Freed: 41 diff --git a/cue/testdata/lists/020_list_compilefail.txtar b/cue/testdata/lists/020_list_compilefail.txtar index c24533ab9..9605d4f60 100644 --- a/cue/testdata/lists/020_list_compilefail.txtar +++ b/cue/testdata/lists/020_list_compilefail.txtar @@ -12,53 +12,6 @@ c: (>=3 & <=5) * [int] c: [1, 2, ...] d: >=2 * [int] d: [1, 2, ...] --- out/compile -- -l3: invalid operand <=2 ('*' requires concrete value): - ./in.cue:1:5 -l4: invalid operand <=2 ('*' requires concrete value): - ./in.cue:2:5 -l5: invalid operand <=2 ('*' requires concrete value): - ./in.cue:3:5 -l5: invalid operand int ('*' requires concrete value): - ./in.cue:3:12 -b: invalid operand <=5 ('*' requires concrete value): - ./in.cue:4:5 -d: invalid operand >=2 ('*' requires concrete value): - ./in.cue:8:4 ---- in.cue -{ - l3: (<=2 * []) - l4: (<=2 * [ - int, - ]) - l5: (<=2 * (int * [ - int, - ])) - b: (<=5 * [ - int, - ]) - b: [ - 1, - 2, - ..., - ] - c: ((>=3 & <=5) * [ - int, - ]) - c: [ - 1, - 2, - ..., - ] - d: (>=2 * [ - int, - ]) - d: [ - 1, - 2, - ..., - ] -} -- out/evalalpha -- l3: invalid operand <=2 ('*' requires concrete value): ./in.cue:1:5 diff --git a/cue/testdata/lists/021_list_equality.txtar b/cue/testdata/lists/021_list_equality.txtar index af2e5b035..d1398e2d7 100644 --- a/cue/testdata/lists/021_list_equality.txtar +++ b/cue/testdata/lists/021_list_equality.txtar @@ -67,285 +67,6 @@ neIncomplete1: [1] != [string] @test(err, code=incomplete, contains="invalid ri ./in.cue:61:16 [incomplete] neIncomplete1: invalid right-hand value to '!=' (type list): 0: incomplete value string: ./in.cue:63:16 --- out/compile -- ---- in.cue -{ - eq0: ([] == []) - eq1: ([ - ..., - ] == []) - eq2: ([] == [ - ..., - ]) - eq3: ([ - ..., - ] == [ - ..., - ]) - eq4: ([ - 1, - ] == [ - 1, - ]) - eq5: ([ - 1, - ..., - ] == [ - 1, - ]) - eq6: ([ - 1, - ] == [ - 1, - ..., - ]) - eq7: ([ - 1, - ..., - ] == [ - 1, - ..., - ]) - eq8: ([ - 1, - 2, - ] == [ - 1, - 2, - ]) - eq9: ([ - 1, - 2, - ..., - ] == [ - 1, - 2, - ]) - eq10: ([ - 1, - 2, - ] == [ - 1, - 2, - ..., - ]) - eq11: ([ - 1, - 2, - ..., - ] == [ - 1, - 2, - ..., - ]) - ne0: ([] != []) - ne1: ([ - ..., - ] != []) - ne2: ([] != [ - ..., - ]) - ne3: ([ - ..., - ] != [ - ..., - ]) - ne4: ([ - 1, - ] != [ - 1, - ]) - ne5: ([ - 1, - ..., - ] != [ - 1, - ]) - ne6: ([ - 1, - ] != [ - 1, - ..., - ]) - ne7: ([ - 1, - ..., - ] != [ - 1, - ..., - ]) - ne8: ([ - 1, - 2, - ] != [ - 1, - 2, - ]) - ne9: ([ - 1, - 2, - ..., - ] != [ - 1, - 2, - ]) - ne10: ([ - 1, - 2, - ] != [ - 1, - 2, - ..., - ]) - ne11: ([ - 1, - 2, - ..., - ] != [ - 1, - 2, - ..., - ]) - feq0: ([] == [ - 1, - ]) - feq1: ([ - ..., - ] == [ - 1, - ]) - feq2: ([] == [ - 1, - ..., - ]) - feq3: ([ - ..., - ] == [ - 1, - ..., - ]) - feq4: ([ - 1, - ] == []) - feq5: ([ - 1, - ..., - ] == []) - feq6: ([ - 1, - ] == [ - ..., - ]) - feq7: ([ - 1, - ..., - ] == [ - ..., - ]) - feq8: ([ - 1, - 2, - ] == [ - 1, - ]) - feq9: ([ - 1, - ..., - ] == [ - 1, - 2, - ]) - feq10: ([ - 1, - 2, - ] == [ - 1, - ..., - ]) - feq11: ([ - 1, - ..., - ] == [ - 1, - 2, - ..., - ]) - fne0: ([] != [ - 1, - ]) - fne1: ([ - ..., - ] != [ - 1, - ]) - fne2: ([] != [ - 1, - ..., - ]) - fne3: ([ - 1, - ..., - ] != [ - 1, - ..., - ]) - fne4: ([ - 1, - ] != []) - fne5: ([ - 1, - ..., - ] != []) - fne6: ([ - 1, - ] != [ - ..., - ]) - fne7: ([ - 1, - ..., - ] != [ - ..., - ]) - fne8: ([ - 1, - 2, - ] != [ - 1, - ]) - fne9: ([ - 1, - ..., - ] != [ - 1, - 2, - ]) - fne10: ([ - 1, - 2, - ] != [ - 1, - ..., - ]) - fne11: ([ - 1, - ..., - ] != [ - 1, - 2, - ..., - ]) - eqIncomplete1: ([ - 1, - ] == [ - string, - ]) - neIncomplete1: ([ - 1, - ] != [ - string, - ]) -} -- out/eval/stats -- Leaks: 0 Freed: 244 diff --git a/cue/testdata/packages/builtin.txtar b/cue/testdata/packages/builtin.txtar index 2afa6f03d..7e1f1c74f 100644 --- a/cue/testdata/packages/builtin.txtar +++ b/cue/testdata/packages/builtin.txtar @@ -9,10 +9,3 @@ foo: [ -- out/evalalpha -- builtin package "x/y" undefined: ./x.cue:1:8 --- out/compile -- ---- x.cue -{ - foo: [ - 〈import;"x/y"〉, - ] -} diff --git a/cue/testdata/packages/embed.txtar b/cue/testdata/packages/embed.txtar index 65b138872..e13d90295 100644 --- a/cue/testdata/packages/embed.txtar +++ b/cue/testdata/packages/embed.txtar @@ -38,9 +38,3 @@ Disjuncts: 0 Notifications: 1 NumCloseIDs: 9 --- out/compile -- ---- in.cue -{ - 〈import;"mod.test/pkg:bar"〉 - z: 3 -} diff --git a/cue/testdata/packages/issue398.txtar b/cue/testdata/packages/issue398.txtar index 7378fc518..e7129f59b 100644 --- a/cue/testdata/packages/issue398.txtar +++ b/cue/testdata/packages/issue398.txtar @@ -38,9 +38,3 @@ Disjuncts: 0 NumCloseIDs: 4 -- out/todo.txt -- Reordering --- out/compile -- ---- foo.cue -{ - 〈import;"mod.test/pkg:bar"〉 - zz: 3 -} diff --git a/cue/testdata/packages/sub.txtar b/cue/testdata/packages/sub.txtar index bcf7c9d1e..7f5663170 100644 --- a/cue/testdata/packages/sub.txtar +++ b/cue/testdata/packages/sub.txtar @@ -28,9 +28,3 @@ Conjuncts: 5 Disjuncts: 0 NumCloseIDs: 2 --- out/compile -- ---- in.cue -{ - #pkg1: 〈import;"mod.test/foo/pkg1"〉.Object - "Hello \(〈0;#pkg1〉)!" -} diff --git a/cue/testdata/references/alias.txtar b/cue/testdata/references/alias.txtar index 895f35738..8b240b4ff 100644 --- a/cue/testdata/references/alias.txtar +++ b/cue/testdata/references/alias.txtar @@ -216,154 +216,3 @@ usedef: X21.field @test(eq, 42) ./in.cue:120:8 [incomplete] opt.b: cannot reference optional field: opt: ./in.cue:131:5 --- out/compile -- ---- in.cue -{ - a1: { - foo: 1 - } - b1: (〈0;a1〉.foo + 2) - a1p: { - foo: 1 - } - b1p: (〈0;a1p〉.foo + 2) - a2: { - name: "a2" - val: 〈1;a2〉.foo - } - a2: { - foo: 42 - } - a3: { - foo: 1 - } - b3: "a3" - a4: { - foo: 1 - } - b4: (〈0;a4〉.foo + 2) - "dyn": { - foo: 1 - } - b5: (〈0;("dyn")〉.foo + 10) - "dyn2": { - name: 〈1;-〉 - val: 〈1;("dyn2")〉.foo - } - dyn2: { - foo: 100 - } - pattern: { - [string]: { - labelRef: 〈1;-〉 - } - foo: {} - } - pattern2: { - [string]: { - labelVal: 〈1;-〉 - fieldVal: 〈1;(〈0;-〉)〉.data - } - foo: { - data: 1 - } - bar: { - data: 2 - } - } - nested: { - inner: { - a: 1 - } - b: (〈0;inner〉.a + 〈1;nested〉.inner.a) - } - result1: 〈0;nested〉.b - multi: { - a: 1 - b: (〈0;a〉 + 2) - c: (〈0;b〉 + 3) - } - comp: { - items: [ - 1, - 2, - 3, - ] - for i, v in 〈0;items〉 { - "\(〈1;i〉)": { - index: 〈2;i〉 - value: 〈2;v〉 - double: (〈1;("\(〈1;i〉)")〉.value * 2) - } - } - } - constrained?: { - required: true - } - test1: 〈0;constrained〉.required - "\("inter")": { - foo: 1 - } - b6: (〈0;("\("inter")")〉.foo + 5) - opt?: { - a: 1 - b: 〈1;opt〉 - } - def: ({ - b: 2 - c: 〈1;def〉.b - }|{ - b: 3 - }) - pattern3: { - [string]: { - labelName: 〈1;-〉 - } - test: {} - } - pattern4: { - [string]: { - fieldRef: 〈1;(〈0;-〉)〉.x - } - test: { - x: 99 - } - } - same: { - a: 1 - b: 2 - c: (〈0;a〉 + 〈0;b〉) - } - chain: { - a: 1 - } - chain2: { - ref: 〈1;chain〉.a - } - result2: 〈0;chain2〉.ref - list: [ - 1, - 2, - 3, - ] - b7: (〈0;list〉[0] + 〈0;list〉[1]) - disj: (1|2|3) - b8: 〈0;disj〉 - deep: { - [string]: { - [string]: { - outer: 〈2;-〉 - inner: 〈1;-〉 - value: 〈1;(〈0;-〉)〉.x - } - foo: { - x: 1 - } - } - bar: {} - } - #Def: { - field: 42 - } - usedef: 〈0;#Def〉.field -} diff --git a/cue/testdata/references/alias_err.txtar b/cue/testdata/references/alias_err.txtar index c3301c367..1b52ffcc0 100644 --- a/cue/testdata/references/alias_err.txtar +++ b/cue/testdata/references/alias_err.txtar @@ -38,36 +38,3 @@ issue2094: unreferenced alias or let clause Y: ./old.cue:9:2 issue2094: cyclic reference in field alias: ./old.cue:9:5 --- out/compile -- -issue2527: cyclic reference in field alias: - ./new.cue:6:3 -issue2094: cyclic reference in field alias: - ./new.cue:11:3 -issue2094: unreferenced alias or let clause Y: - ./new.cue:11:5 -issue2527: cyclic reference in field alias: - ./old.cue:4:5 -issue2094: unreferenced alias or let clause Y: - ./old.cue:9:2 -issue2094: cyclic reference in field alias: - ./old.cue:9:5 ---- new.cue -{ - issue2527: { - 〈0;(_|_(cyclic reference in field alias))〉: 3 - } - issue2094: { - 〈0;("foo")〉: string - "foo": "bar" - } -} ---- old.cue -{ - issue2527: { - 〈0;(_|_(cyclic reference in field alias))〉: 3 - } - issue2094: { - 〈0;("foo")〉: string - "foo": "bar" - } -} diff --git a/cue/testdata/references/embed_self.txtar b/cue/testdata/references/embed_self.txtar index a6032ffac..d5a59f059 100644 --- a/cue/testdata/references/embed_self.txtar +++ b/cue/testdata/references/embed_self.txtar @@ -12,9 +12,3 @@ Retain: 1 Unifications: 2 Conjuncts: 4 Disjuncts: 3 --- out/compile -- ---- in.cue -{ - Foo: {} - 〈0;Foo〉 -} diff --git a/cue/testdata/references/errors.txtar b/cue/testdata/references/errors.txtar index ced9d4ba2..061fa1cb2 100644 --- a/cue/testdata/references/errors.txtar +++ b/cue/testdata/references/errors.txtar @@ -55,28 +55,3 @@ Retain: 0 Unifications: 17 Conjuncts: 17 Disjuncts: 0 --- out/compile -- ---- references.cue -{ - missingField: { - a: {} - r: 〈0;a〉.b - } - missingFieldClosed: { - #a: {} - r: 〈0;#a〉.b - } - missingFieldNested: { - a: {} - r: 〈0;a〉.b.c - } - missingFieldNestedClosed: { - #a: {} - r: 〈0;#a〉.d.c - } - missingFieldNestedInInterpolation: { - a: {} - r1: "\(〈0;a〉.b.c)" - r2: "\(〈0;a〉.d.c)" - } -} diff --git a/cue/testdata/references/incomplete.txtar b/cue/testdata/references/incomplete.txtar index 4980bdb34..be051914f 100644 --- a/cue/testdata/references/incomplete.txtar +++ b/cue/testdata/references/incomplete.txtar @@ -55,36 +55,3 @@ Conjuncts: 18 Disjuncts: 0 NumCloseIDs: 4 --- out/compile -- ---- in.cue -{ - comprehensions: { - a: {} - b: { - if 〈1;a〉.b {} - } - c: { - for _, x in 〈1;a〉.b { - 〈1;x〉 - } - } - } - openStruct: { - a: {} - b: 〈0;a〉.c - } - selectFromTop: { - top: _ - a: 〈0;top〉.foo - } - indexOnTop: { - top: _ - a: 〈0;top〉[2] - } - incompleteIndex: { - top: _ - a: [ - 1, - ][〈0;top〉] - } -} diff --git a/cue/testdata/references/index.txtar b/cue/testdata/references/index.txtar index 498d54af6..1686aae0e 100644 --- a/cue/testdata/references/index.txtar +++ b/cue/testdata/references/index.txtar @@ -72,60 +72,3 @@ Conjuncts: 50 Disjuncts: 8 NumCloseIDs: 5 --- out/compile -- ---- in.cue -{ - intIndex: [ - 2, - ][0] - stringIndex: { - foo: "bar" - }["foo"] - stringOfNumberIndex: { - "3": 3 - }["3"] - indexToDefault: (*[ - 0, - ]|{})[0] - outOfBoundsDisjunction: (*[]|{})[1] - indexDoesNotDistribute: (*[]|[ - 1, - ])[0] - doesNotDistributeType: { - l: [] - a: (*〈0;l〉|{ - "3": 3 - })["3"] - } - stringIndexToList: [ - 2, - ][""] - indexOutOfBounds2: 2[2] - booleanIndex: [][true] - indexOutOfBounds3: [ - 1, - 2, - 3, - ][4] - negativeIndex: [ - 1, - 2, - 3, - ][-1] - varIndexTooLarge: { - n: 3 - a: [ - 1, - 2, - 3, - ][〈0;n〉] - } - varNegativeIndex: { - n: -1 - a: [ - 1, - 2, - 3, - ][〈0;n〉] - } -} diff --git a/cue/testdata/references/labels.txtar b/cue/testdata/references/labels.txtar index dd8fd4a0f..e24862d23 100644 --- a/cue/testdata/references/labels.txtar +++ b/cue/testdata/references/labels.txtar @@ -134,155 +134,3 @@ Conjuncts: 101 Disjuncts: 2 NumCloseIDs: 9 --- out/compile -- ---- in.cue -{ - a: { - [string]: 〈0;-〉 - } - a: { - bar: _ - } - b: { - [string]: { - 〈1;-〉 - } - } - b: { - bar: _ - } - c: { - [string]: 〈0;-〉 - } - c: { - [string]: { - { - { - 〈3;-〉 - } - } - } - } - c: { - bar: _ - } - d: { - [string]: { - name: 〈1;-〉 - } - } - d: { - bar: {} - } - e: { - [string]: { - [string]: (〈1;-〉 + 〈0;-〉) - } - } - e: { - foo: { - bar: _ - } - } - patternField: { - t1: { - [string]: { - b: (〈1;(〈0;-〉)〉|null) - } - a: { - r: 0 - } - } - } - patternField: { - t2: { - a: { - r: 0 - } - [string]: { - z: 1 - b: 〈1;(〈0;-〉)〉.z - } - } - } - bar: 3 - f1: { - "foo\(〈1;bar〉)": { - name: "xx" - foo: 〈1;("foo\(〈1;bar〉)")〉.name - } - } - f1: { - "foo\(〈1;bar〉)": { - "foo\(〈2;bar〉)baz": { - name: "xx" - a: 〈2;("foo\(〈1;bar〉)")〉["foo\(〈3;bar〉)baz"].name - b: 〈1;("foo\(〈2;bar〉)baz")〉.name - } - } - } - c1: { - "foo\(〈1;bar〉)": { - [string]: { - name: 〈1;-〉 - foo: 〈2;("foo\(〈1;bar〉)")〉.x.name - } - } - } - c1: { - foo3: { - x: _ - } - } - emptyLabel: { - "": 1 - a: 〈1;emptyLabel〉[""] - } - underscore: { - a: { - foo: 〈0;#Foo〉 - foo: { - "_": "bar" - } - #Foo: { - [=~""]: string - } - } - } - underscore: { - c: { - foo: { - "_": "any" - } - foo: { - [=~""]: string - } - } - } - underscore: { - d: { - bar: { - "_": "any" - } - #bar: { - [string]: string - } - bar: 〈0;#bar〉 - } - } - underscore: { - e: { - baz: { - "_h": "any" - } - #baz: { - [=~"_"]: string - } - baz: 〈0;#baz〉 - } - } - invalidPattern: { - [(=~"BAD)" & =~"x")]: string - y: 123 - } -} diff --git a/cue/testdata/references/labelstop.txtar b/cue/testdata/references/labelstop.txtar index 70872decd..084908a21 100644 --- a/cue/testdata/references/labelstop.txtar +++ b/cue/testdata/references/labelstop.txtar @@ -14,13 +14,3 @@ Retain: 0 Unifications: 3 Conjuncts: 5 Disjuncts: 3 --- out/compile -- ---- in.cue -{ - { - [string]: { - baz: 〈1;-〉 - } - } - bar: {} -} diff --git a/cue/testdata/references/let.txtar b/cue/testdata/references/let.txtar index b42aa77d5..e9778f7c2 100644 --- a/cue/testdata/references/let.txtar +++ b/cue/testdata/references/let.txtar @@ -139,188 +139,3 @@ Disjuncts: 0 Notifications: 2 NumCloseIDs: 45 --- out/compile -- ---- in.cue -{ - a1list: [ - { - 1 - }, - ] - let A1#1 = 〈0;a1list〉 - a1: ((100 * 〈0;let A1#1〉[0]) + 〈0;let A1#1〉[0]) - a2list: [ - { - 2 - }, - ] - let A2#2 = 〈0;a2list〉 - a2: { - b: ((100 * 〈1;let A2#2〉[0]) + 〈1;let A2#2〉[0]) - } - a3list: [ - { - 3 - }, - ] - let A3#3 = 〈0;a3list〉 - a3: { - b: { - c: ((100 * 〈2;let A3#3〉[0]) + 〈2;let A3#3〉[0]) - } - } - a4list: [ - { - 4 - }, - ] - let A4#4 = 〈0;a4list〉 - a4: [ - for _, x in 〈1;let A4#4〉 { - v: 404 - }, - ] - a5list: [ - { - 5 - }, - ] - let A5#5 = 〈0;a5list〉 - a5: { - b: [ - for _, x in 〈2;let A5#5〉 { - v: 505 - }, - ] - } - a6list: [ - { - 6 - }, - ] - let A6#6 = 〈0;a6list〉 - a6: { - b: { - c: [ - for _, x in 〈3;let A6#6〉 { - v: 606 - }, - ] - } - } - a7list: [ - { - 7 - }, - ] - let A7#7 = 〈0;a7list〉 - a7: { - for _, x in 〈1;let A7#7〉 { - v: 707 - } - } - a8list: [ - { - 8 - }, - ] - let A8#8 = 〈0;a8list〉 - a8: { - b: { - for _, x in 〈2;let A8#8〉 { - v: 808 - } - } - } - a9list: [ - { - 9 - }, - ] - let A9#9 = 〈0;a9list〉 - a9: { - b: { - c: { - for _, x in 〈3;let A9#9〉 { - v: 909 - } - } - } - } - incompleteLet: { - input: [ - 1, - 2, - 3, - 4, - 5, - ] - last: { - min: 〈import;list〉.Min(〈1;input〉) - max: 〈import;list〉.Max(〈1;input〉) - } - bar: { - let mn#A = 〈1;last〉.min - let mx#B = 〈import;list〉.max - min: 〈0;let mn#A〉 - max: 〈0;let mx#B〉 - } - x: { - if (〈import;list〉.max < 0) {} - } - } - scalarReference: { - inScalar: { - p0: { - 5 - let x#C = 6 - #b: 〈0;let x#C〉 - } - } - inScalar: { - p1: { - #b: 〈0;let x#D〉 - let x#D = 6 - 5 - } - } - inList: { - p0: { - let x#E = { - a: 1 - } - [ - 〈1;let x#E〉, - ] - } - } - inList: { - p1: { - [ - 〈1;let x#F〉, - ] - let x#F = { - a: 1 - } - } - } - } - issue1116: { - a: { - #a: [ - "a", - "b", - ] - let List#10 = 〈0;#a〉 - 〈0;let List#10〉[(len(〈0;let List#10〉) - 1)] - } - b: { - let List#11 = 〈0;#a〉 - 〈0;let List#11〉[(len(〈0;let List#11〉) - 1)] - #a: [ - "a", - "b", - ] - } - } -} diff --git a/cue/testdata/references/letcycle.txtar b/cue/testdata/references/letcycle.txtar index e2ebef110..eb3622727 100644 --- a/cue/testdata/references/letcycle.txtar +++ b/cue/testdata/references/letcycle.txtar @@ -53,117 +53,6 @@ v2 error paths are more verbose than v3: v2: cycles.a.let[].c.c, v3: cycles.a.let[].c v2: cycles.b.let[].c.c, v3: cycles.b.let[].c v2: cycles.issue1042.#Add16.let[].for[].c.for[].for[].c, v3: cycles.issue1042.#Add16.let[].for[].c --- out/compile -- -cycles.a.let[].c: cyclic references in let clause or alias: - ./in.cue:5:15 -cycles.b.let[].c: cyclic references in let clause or alias: - ./in.cue:11:15 -cycles.issue1042.#Add16.let[].for[].c: cyclic references in let clause or alias: - ./in.cue:34:45 ---- in.cue -{ - cycles: { - a: { - let A#1 = { - c: 〈1;let B#2〉=>〈0;let A#1〉=>{ - c: 〈1;let B#2〉=>_|_(cyclic references in let clause or alias) - } - } - let B#2 = 〈0;let A#1〉=>{ - c: 〈1;let B#2〉=>_|_(cyclic references in let clause or alias) - } - out: 〈0;let A#1〉=>{ - c: 〈1;let B#2〉=>_|_(cyclic references in let clause or alias) - } - } - b: { - let A#3 = { - c: 〈1;let B#4〉=>{ - 〈1;let A#3〉=>{ - c: 〈1;let B#4〉=>_|_(cyclic references in let clause or alias) - }.c - } - } - let B#4 = { - 〈1;let A#3〉=>{ - c: 〈1;let B#4〉=>_|_(cyclic references in let clause or alias) - }.c - } - out: 〈0;let A#3〉=>{ - c: 〈1;let B#4〉=>_|_(cyclic references in let clause or alias) - } - } - issue1042: { - #FullAdder: { - a: bool - b: bool - c: bool - sum: bool - carry: bool - } - #Add16: { - a: ([ - bool, - ] * 16) - b: ([ - bool, - ] * 16) - out: ([ - bool, - ] * 16) - let fulladders#5 = [ - for _, i in 〈import;list〉.Range(0, 4, 1) { - (〈4;#FullAdder〉 & { - a: 〈4;a〉[〈2;i〉] - b: 〈4;b〉[〈2;i〉] - c: 〈4;let carries#6〉=>[ - false, - for _, i in 〈import;list〉.Range(0, 4, 1) { - 〈3;let fulladders#5〉=>[ - for _, i in 〈import;list〉.Range(0, 4, 1) { - (〈4;#FullAdder〉 & { - a: 〈4;a〉[〈2;i〉] - b: 〈4;b〉[〈2;i〉] - c: 〈4;let carries#6〉=>_|_(cyclic references in let clause or alias)[〈2;i〉] - }) - }, - ][〈1;i〉].carry - }, - ][〈2;i〉] - }) - }, - ] - let carries#6 = [ - false, - for _, i in 〈import;list〉.Range(0, 4, 1) { - 〈3;let fulladders#5〉=>[ - for _, i in 〈import;list〉.Range(0, 4, 1) { - (〈4;#FullAdder〉 & { - a: 〈4;a〉[〈2;i〉] - b: 〈4;b〉[〈2;i〉] - c: 〈4;let carries#6〉=>_|_(cyclic references in let clause or alias)[〈2;i〉] - }) - }, - ][〈1;i〉].carry - }, - ] - out: [ - for _, i in 〈import;list〉.Range(0, 4, 1) { - 〈3;let fulladders#5〉=>[ - for _, i in 〈import;list〉.Range(0, 4, 1) { - (〈4;#FullAdder〉 & { - a: 〈4;a〉[〈2;i〉] - b: 〈4;b〉[〈2;i〉] - c: 〈4;let carries#6〉=>_|_(cyclic references in let clause or alias)[〈2;i〉] - }) - }, - ][〈1;i〉].sum - }, - ] - } - } - } -} -- out/evalalpha -- cycles.a.let[].c: cyclic references in let clause or alias: ./in.cue:5:15 diff --git a/cue/testdata/references/optional.txtar b/cue/testdata/references/optional.txtar index 2c3a2d61c..68f821a5f 100644 --- a/cue/testdata/references/optional.txtar +++ b/cue/testdata/references/optional.txtar @@ -24,19 +24,3 @@ Retain: 1 Unifications: 9 Conjuncts: 9 Disjuncts: 10 --- out/compile -- ---- in.cue -{ - t1: { - a: { - foo?: int - b: 〈0;foo〉 - } - } - t2: { - a: { - b: 〈0;foo〉 - foo?: int - } - } -} diff --git a/cue/testdata/references/package.txtar b/cue/testdata/references/package.txtar index d38bf6ccc..af65566e7 100644 --- a/cue/testdata/references/package.txtar +++ b/cue/testdata/references/package.txtar @@ -34,9 +34,3 @@ Retain: 2 Unifications: 5 Conjuncts: 6 Disjuncts: 6 --- out/compile -- ---- in.cue -{ - a: 1 - incomplete: 〈import;"foo.com/example"〉.Settings -} diff --git a/cue/testdata/references/self.txtar b/cue/testdata/references/self.txtar index ddc03d8f0..bc754b68f 100644 --- a/cue/testdata/references/self.txtar +++ b/cue/testdata/references/self.txtar @@ -257,104 +257,3 @@ a: { ./validator.cue:19:12 ./validator.cue:18:12 ./validator.cue:19:19 --- out/compile -- ---- in.cue -{ - a: 〈1〉.b - b: "hello" - x: { - y: 〈1〉.z - z: "world" - } - foo: { - bar: 〈1〉.baz - } - foo: { - baz: "greeting" - } - nested: { - level1: { - field: 〈1〉.value - value: "level1 value" - } - } - listTest: { - items: [ - 1, - 2, - 〈1〉[0], - 〈1〉[1], - ] - first: 1 - second: 2 - } - computed: { - key: "test" - value: 〈1〉["key"] - } - cycle: 〈1〉.cycle -} ---- list.cue -{ - #IntStrings: { - 〈import;list〉.Repeat([ - int, - string, - ], div(len(〈1〉), 2)) - } - listCheck: { - ok1: 〈1;#IntStrings〉 - } - listCheck: { - ok1: [ - 1, - "foo", - 2, - "bar", - ] - } - listCheck: { - err: 〈1;#IntStrings〉 - } - listCheck: { - err: [ - 1, - "foo", - "bar", - 2, - ] - } -} ---- validator.cue -{ - validator: { - err1: { - { - { - { - ==(〈1〉 + 1) - } - } - } - } - err1: 2 - err2: { - ==(〈1〉 + 1) - } - err2: 2 - } - cyclicErr: { - err3: ==(〈1〉 + 1) - err3: 4 - } -} ---- withlet.cue -{ - withLet: { - let X#1 = 〈1〉 - foo: 1 - bar: { - baz: 〈1;let X#1〉.foo - } - } -} diff --git a/cue/testdata/references/value.txtar b/cue/testdata/references/value.txtar index aadbd9c5b..27f1be80c 100644 --- a/cue/testdata/references/value.txtar +++ b/cue/testdata/references/value.txtar @@ -65,32 +65,3 @@ NumCloseIDs: 2 2: (int){ 1 } } } --- out/compile -- ---- err.cue -{ - cycleErr: { - err3: ==(〈1〉 + 1) - err3: 4 - } -} ---- in.cue -{ - structShorthand: { - b: 3 - c: 〈1〉.b - } - fieldAndValue: { - foo: { - 3 - #sum: (〈1;foo〉 + 〈1〉) - } - } - valueCycle: { - b: (3 + 〈0〉) - } - listValueAlias: [ - 1, - 2, - 〈1〉[0], - ] -} diff --git a/cue/testdata/resolve/000_convert___to_top.txtar b/cue/testdata/resolve/000_convert___to_top.txtar index 0fe4a808c..aac2e0d49 100644 --- a/cue/testdata/resolve/000_convert___to_top.txtar +++ b/cue/testdata/resolve/000_convert___to_top.txtar @@ -2,13 +2,6 @@ # an open struct without any concrete fields. -- in.cue -- a: {[_]: _} @test(eq, {}) --- out/compile -- ---- in.cue -{ - a: { - [_]: _ - } -} -- out/eval/stats -- Leaks: 0 Freed: 2 diff --git a/cue/testdata/resolve/001.txtar b/cue/testdata/resolve/001.txtar index 659395580..a3693491e 100644 --- a/cue/testdata/resolve/001.txtar +++ b/cue/testdata/resolve/001.txtar @@ -3,22 +3,6 @@ a: b.c.d @test(eq, 3) b: {c: {d: 3}} c: {c: d.d} @test(eq, {c: 2}) d: {d: 2} --- out/compile -- ---- in.cue -{ - a: 〈0;b〉.c.d - b: { - c: { - d: 3 - } - } - c: { - c: 〈1;d〉.d - } - d: { - d: 2 - } -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/resolve/004.txtar b/cue/testdata/resolve/004.txtar index ba0956996..76b7080ce 100644 --- a/cue/testdata/resolve/004.txtar +++ b/cue/testdata/resolve/004.txtar @@ -3,17 +3,6 @@ a: _ b: a @test(eq, {d: 1}) @test(shareID=ba) a: {d: 1, d: _} @test(eq, {d: 1}) @test(shareID=ba) b: _ --- out/compile -- ---- in.cue -{ - a: _ - b: 〈0;a〉 - a: { - d: 1 - d: _ - } - b: _ -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/resolve/005_JSON.txtar b/cue/testdata/resolve/005_JSON.txtar index f636ab18b..fbe1ed7eb 100644 --- a/cue/testdata/resolve/005_JSON.txtar +++ b/cue/testdata/resolve/005_JSON.txtar @@ -4,16 +4,6 @@ a="a": 3 b: a @test(eq, 3) o: {"a\nb": 2} @test(eq, {"a\nb": 2}) c: o["a\nb"] @test(eq, 2) --- out/compile -- ---- in.cue -{ - a: 3 - b: 〈0;a〉 - o: { - "a\nb": 2 - } - c: 〈0;o〉["a\nb"] -} -- out/eval/stats -- Leaks: 0 Freed: 6 diff --git a/cue/testdata/resolve/006_arithmetic.txtar b/cue/testdata/resolve/006_arithmetic.txtar index 700eb3468..9de714875 100644 --- a/cue/testdata/resolve/006_arithmetic.txtar +++ b/cue/testdata/resolve/006_arithmetic.txtar @@ -11,16 +11,6 @@ e2: int & 4.0/2.0 @test(err, code=eval, contains="conflicting values int and 2 [eval] e2: conflicting values int and 2.0 (mismatched types int and float): ./in.cue:6:5 ./in.cue:6:11 --- out/compile -- ---- in.cue -{ - v1: (1000000000000 / 2.0) - v2: (2.0 == 2) - n1: 1 - v5: (2.0 / 〈0;n1〉) - v6: (1.0 / 1.0) - e2: (int & (4.0 / 2.0)) -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/cue/testdata/resolve/007_inequality.txtar b/cue/testdata/resolve/007_inequality.txtar index e3002f2ba..03d6dcdb1 100644 --- a/cue/testdata/resolve/007_inequality.txtar +++ b/cue/testdata/resolve/007_inequality.txtar @@ -5,16 +5,6 @@ c: true == null @test(eq, false) d: null != {} @test(eq, true) e: null == [] @test(eq, false) f: 0 == 0.0 @test(eq, true) // types are unified first TODO: make this consistent --- out/compile -- ---- in.cue -{ - a: (1 != 2) - b: (1 != null) - c: (true == null) - d: (null != {}) - e: (null == []) - f: (0 == 0.0) -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/resolve/008_attributes.txtar b/cue/testdata/resolve/008_attributes.txtar index 8e26de0ae..8597ea0ea 100644 --- a/cue/testdata/resolve/008_attributes.txtar +++ b/cue/testdata/resolve/008_attributes.txtar @@ -4,20 +4,6 @@ b: {foo: 1 @bar() @foo()} @test(eq, {foo: 1 @foo() @bar()}) c: a & b @test(eq, {foo: 1 @foo() @baz(1) @bar()}) e: a & {foo: 1 @foo(other)} @test(eq, {foo: 1 @foo(other) @foo() @baz(1)}) --- out/compile -- ---- in.cue -{ - a: { - foo: 1 - } - b: { - foo: 1 - } - c: (〈0;a〉 & 〈0;b〉) - e: (〈0;a〉 & { - foo: 1 - }) -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/resolve/009_optional_field_unification.txtar b/cue/testdata/resolve/009_optional_field_unification.txtar index b05909f19..9df4dc6df 100644 --- a/cue/testdata/resolve/009_optional_field_unification.txtar +++ b/cue/testdata/resolve/009_optional_field_unification.txtar @@ -10,25 +10,6 @@ e: { "g\(2)"?: 2 @test(eq, {g1: 1, g2?: 2}) } --- out/compile -- ---- in.cue -{ - a: { - foo?: string - } - b: { - foo: "foo" - } - c: (〈0;a〉 & 〈0;b〉) - d: (〈0;a〉 & { - foo?: "bar" - }) - e: { - g1: 1 - "g\(1)"?: 1 - "g\(2)"?: 2 - } -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/resolve/010_optional_field_resolves_to_incomplete.txtar b/cue/testdata/resolve/010_optional_field_resolves_to_incomplete.txtar index cf403c518..ec7f5bae6 100644 --- a/cue/testdata/resolve/010_optional_field_resolves_to_incomplete.txtar +++ b/cue/testdata/resolve/010_optional_field_resolves_to_incomplete.txtar @@ -9,15 +9,6 @@ r: { ./in.cue:3:6 [incomplete] r.c: cannot reference optional field: a: ./in.cue:4:8 --- out/compile -- ---- in.cue -{ - r: { - a?: 3 - b: 〈0;a〉 - c: 〈1;r〉["a"] - } -} -- out/eval/stats -- Leaks: 0 Freed: 5 diff --git a/cue/testdata/resolve/011_bounds.txtar b/cue/testdata/resolve/011_bounds.txtar index 1566b5a6a..010745cca 100644 --- a/cue/testdata/resolve/011_bounds.txtar +++ b/cue/testdata/resolve/011_bounds.txtar @@ -97,61 +97,6 @@ e9: >"a" & <1 @test(err, code=eval, contains="conflicting values", pos=[0:5, 0: [eval] e9: conflicting values >"a" and <1 (mismatched types string and number): ./in.cue:64:5 ./in.cue:64:12 --- out/compile -- ---- in.cue -{ - i1: (>1 & 5) - i2: ((>=0 & <=10) & 5) - i3: (!=null & []) - i4: (!=2 & !=4) - s1: ((>=0 & <=10) & !=1) - s2: ((>=0 & <=10) & !=11) - s3: (>5 & !=5) - s4: (<10 & !=10) - s5: (!=2 & !=2) - s6: (!=2 & >=2) - s7: (>=2 & !=2) - s8: (!=5 & >5) - s10: (((>=0 & <=10) & <12) & >1) - s11: (((>0 & >=0) & <=12) & <12) - s20: (>=10 & <=10) - s22: (>5 & <=6) - s22a: (>5 & (<=6 & int)) - s22b: ((int & >5) & <=6) - s22c: (>=5 & (<6 & int)) - s22d: ((int & >=5) & <6) - s22e: ((>=5 & <6) & int) - s22f: (int & (>=5 & <6)) - s23: (>0 & <2) - s23a: ((>0 & <2) & int) - s23b: (int & (>0 & <2)) - s23c: ((int & >0) & <2) - s23d: (>0 & (int & <2)) - s23e: (>0.0 & <2.0) - s30: (>0 & int) - floats: { - [string]: float - f1: (<10.0 & <=5.0) - f2: (<=10.0 & <5.0) - f3: (<1.1 & <=1.1) - f4: (<=1.1 & <=1.1) - f5: (>1.1 & >=1.1) - f6: (>=1.1 & >1.1) - f7: (>=1.1 & <=1.1) - issue1310: (>=2.1 & <=1.0) - fe2: (>2.1 & <=2.1) - fe3: ((float & >2) & <=3) - } - e1: (null & !=null) - e2: (!=null & null) - e3: (>1 & 1) - e4: (<0 & 0) - e5: (>1 & <0) - e6: (>11 & <11) - e7: (>=11 & <11) - e8: (>11 & <=11) - e9: (>"a" & <1) -} -- out/eval/stats -- Leaks: 0 Freed: 50 diff --git a/cue/testdata/resolve/012_bound_conversions.txtar b/cue/testdata/resolve/012_bound_conversions.txtar index 254ca9baa..ec45bf66b 100644 --- a/cue/testdata/resolve/012_bound_conversions.txtar +++ b/cue/testdata/resolve/012_bound_conversions.txtar @@ -23,21 +23,6 @@ c4: 1.2 & (>=1 & <2 & int) @test(err, code=eval, contains="conflicting values 1. [eval] c4: conflicting values 1.2 and int (mismatched types float and int): ./in.cue:14:5 ./in.cue:14:23 --- out/compile -- ---- in.cue -{ - r0: ((int & >0.1) & <=1.9) - r1: ((int & >0.1) & <1.9) - r2: ((int & >=0.1) & <1.9) - r3: ((int & >=-1.9) & <=-0.1) - r4: ((int & >-1.9) & <=-0.1) - r5: (>=1.1 & <=1.1) - r6: (〈0;r5〉 & 1.1) - c1: ((1.2 & >1.3) & <2) - c2: (1.2 & (>1.3 & <2)) - c3: (1.2 & (>=1 & <2)) - c4: (1.2 & ((>=1 & <2) & int)) -} -- out/eval/stats -- Leaks: 0 Freed: 12 diff --git a/cue/testdata/resolve/013_custom_validators.txtar b/cue/testdata/resolve/013_custom_validators.txtar index adeb212c7..5185e45a3 100644 --- a/cue/testdata/resolve/013_custom_validators.txtar +++ b/cue/testdata/resolve/013_custom_validators.txtar @@ -14,16 +14,6 @@ c: "dog" @test(eq, "dog") ./in.cue:6:4 ./in.cue:6:24 ./in.cue:7:4 --- out/compile -- ---- in.cue -{ - a: 〈import;strings〉.ContainsAny("ab") - a: "after" - b: 〈import;strings〉.ContainsAny("c") - b: "dog" - c: (〈import;strings〉.ContainsAny("d") & 〈import;strings〉.ContainsAny("g")) - c: "dog" -} -- out/eval/stats -- Leaks: 0 Freed: 4 diff --git a/cue/testdata/resolve/014_null_coalescing.txtar b/cue/testdata/resolve/014_null_coalescing.txtar index 0bbef8bdc..34981d255 100644 --- a/cue/testdata/resolve/014_null_coalescing.txtar +++ b/cue/testdata/resolve/014_null_coalescing.txtar @@ -2,13 +2,6 @@ a: null @test(eq, null) b: a.x | "b" @test(eq, "b") c: a["x"] | "c" @test(eq, "c") --- out/compile -- ---- in.cue -{ - a: null - b: (〈0;a〉.x|"b") - c: (〈0;a〉["x"]|"c") -} -- out/eval/stats -- Leaks: 0 Freed: 8 diff --git a/cue/testdata/resolve/016_index.txtar b/cue/testdata/resolve/016_index.txtar index 9778a57d3..203fb330c 100644 --- a/cue/testdata/resolve/016_index.txtar +++ b/cue/testdata/resolve/016_index.txtar @@ -48,55 +48,6 @@ e10: def["b"] @test(err, code=incomplete, contains="undefined field: b", pos=[0: ./in.cue:15:16 [incomplete] e10: undefined field: b: ./in.cue:21:10 --- out/compile -- ---- in.cue -{ - a: [ - 2, - ][0] - b: { - foo: "bar" - }["foo"] - c: (*〈0;l〉|{ - "3": 3 - })["3"] - d: (*[]|[ - 1, - ])[0] - l: [] - e1: [ - 2, - ][""] - e2: 2[2] - e3: [][true] - e4: [ - 1, - 2, - 3, - ][3] - e5: [ - 1, - 2, - 3, - ][-1] - e6: (*[]|{})[1] - e7: [ - 1, - 2, - 3, - ][3] - e8: [ - 1, - 2, - 3, - ][-1] - e9: (*[]|{})[1] - def: { - a: 1 - #b: 3 - } - e10: 〈0;def〉["b"] -} -- out/eval/stats -- Leaks: 0 Freed: 55 diff --git a/cue/testdata/resolve/017_disjunctions_of_lists.txtar b/cue/testdata/resolve/017_disjunctions_of_lists.txtar index 8896ea33b..bedd1fba2 100644 --- a/cue/testdata/resolve/017_disjunctions_of_lists.txtar +++ b/cue/testdata/resolve/017_disjunctions_of_lists.txtar @@ -3,25 +3,6 @@ l: [ int, int] | [ string, string] @test(eq, [int, int] | [string, string]) l1: ["a", "b"] @test(eq, ["a", "b"]) l2: l & ["c", "d"] @test(eq, ["c", "d"]) --- out/compile -- ---- in.cue -{ - l: ([ - int, - int, - ]|[ - string, - string, - ]) - l1: [ - "a", - "b", - ] - l2: (〈0;l〉 & [ - "c", - "d", - ]) -} -- out/eval/stats -- Leaks: 0 Freed: 18 diff --git a/cue/testdata/resolve/018_slice.txtar b/cue/testdata/resolve/018_slice.txtar index 5ae91cbae..8c82343af 100644 --- a/cue/testdata/resolve/018_slice.txtar +++ b/cue/testdata/resolve/018_slice.txtar @@ -25,33 +25,6 @@ e7: [2][:"9"] @test(err, code=eval, contains="cannot use \"9\"", pos=[0:5, 0:10 [eval] e7: cannot use "9" (type string) as type int in slice index: ./in.cue:9:5 ./in.cue:9:10 --- out/compile -- ---- in.cue -{ - a: [ - 2, - ][0:0] - b: [ - 0, - ][1:1] - e1: [][1:1] - e2: [ - 0, - ][-1:0] - e3: [ - 0, - ][1:0] - e4: [ - 0, - ][1:2] - e5: 4[1:2] - e6: [ - 2, - ]["":] - e7: [ - 2, - ][:"9"] -} -- out/eval/stats -- Leaks: 0 Freed: 25 diff --git a/cue/testdata/resolve/022_list_unification.txtar b/cue/testdata/resolve/022_list_unification.txtar index 347c17697..1bf3f1ab0 100644 --- a/cue/testdata/resolve/022_list_unification.txtar +++ b/cue/testdata/resolve/022_list_unification.txtar @@ -1,23 +1,6 @@ -- in.cue -- a: {l: ["foo", v], v: l[1]} @test(eq, {l: ["foo", _], v: _}) b: a & {l: [_, "bar"]} @test(eq, {l: ["foo", "bar"], v: "bar"}) --- out/compile -- ---- in.cue -{ - a: { - l: [ - "foo", - 〈1;v〉, - ] - v: 〈0;l〉[1] - } - b: (〈0;a〉 & { - l: [ - _, - "bar", - ] - }) -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/resolve/023_correct_error_messages.txtar b/cue/testdata/resolve/023_correct_error_messages.txtar index 489f3551f..0097faa58 100644 --- a/cue/testdata/resolve/023_correct_error_messages.txtar +++ b/cue/testdata/resolve/023_correct_error_messages.txtar @@ -5,11 +5,6 @@ a: "a" & 1 @test(err, code=eval, contains="conflicting values", [eval] a: conflicting values "a" and 1 (mismatched types string and int): ./in.cue:1:4 ./in.cue:1:10 --- out/compile -- ---- in.cue -{ - a: ("a" & 1) -} -- out/eval/stats -- Leaks: 0 Freed: 2 diff --git a/cue/testdata/resolve/024_structs.txtar b/cue/testdata/resolve/024_structs.txtar index 33ff0da18..67c02e42e 100644 --- a/cue/testdata/resolve/024_structs.txtar +++ b/cue/testdata/resolve/024_structs.txtar @@ -17,23 +17,6 @@ ti: t & {c: int} @test(eq, { ./in.cue:5:5 ./in.cue:4:5 ./in.cue:7:13 --- out/compile -- ---- in.cue -{ - a: (〈0;t〉 & { - c: 5 - }) - b: (〈0;ti〉 & { - c: 7 - }) - t: { - c: number - d: (〈0;c〉 * 3) - } - ti: (〈0;t〉 & { - c: int - }) -} -- out/eval/stats -- Leaks: 0 Freed: 13 diff --git a/cue/testdata/resolve/025_definitions.txtar b/cue/testdata/resolve/025_definitions.txtar index 5a94d786c..1e6a824ac 100644 --- a/cue/testdata/resolve/025_definitions.txtar +++ b/cue/testdata/resolve/025_definitions.txtar @@ -44,51 +44,6 @@ mixedRec: {Mixed: string} @test(eq, {#Mixed: string, Mixed: string}) ./in.cue:16:7 [eval] foo1.recursive.feild: field not allowed: ./in.cue:22:3 --- out/compile -- ---- in.cue -{ - #Foo: { - field: int - recursive: { - field: string - } - } - #Foo1: { - field: int - } - #Foo1: { - field2: string - } - foo: 〈0;#Foo〉 - foo: { - feild: 2 - } - foo1: 〈0;#Foo〉 - foo1: { - field: 2 - recursive: { - feild: 2 - } - } - #Bar: { - field: int - { - [_]: int - } - } - bar: 〈0;#Bar〉 - bar: { - feild: 2 - } - #Mixed: string - Mixed: string - mixedRec: { - #Mixed: string - } - mixedRec: { - Mixed: string - } -} -- out/eval/stats -- Leaks: 0 Freed: 28 diff --git a/cue/testdata/resolve/027_new-style_definitions.txtar b/cue/testdata/resolve/027_new-style_definitions.txtar index 4831193a8..46e1cdd6b 100644 --- a/cue/testdata/resolve/027_new-style_definitions.txtar +++ b/cue/testdata/resolve/027_new-style_definitions.txtar @@ -10,24 +10,6 @@ bulk: {[string]: string} & { _hid: 3 a: "foo" } @test(eq, {#def: 4, _hid: 3, a: "foo"}) --- out/compile -- ---- in.cue -{ - #Foo: { - a: 1 - b: int - } - "#Foo": (〈0;#Foo〉 & { - b: 1 - }) - bulk: ({ - [string]: string - } & { - #def: 4 - _hid: 3 - a: "foo" - }) -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar b/cue/testdata/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar index e7b5be70b..2b4349af3 100644 --- a/cue/testdata/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar +++ b/cue/testdata/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar @@ -29,50 +29,6 @@ c: #R & { ./in.cue:11:6 [eval] c.w.0.d: field not allowed: ./in.cue:22:7 --- out/compile -- ---- in.cue -{ - #S: { - [string]: { - a: int - } - } - a: (〈0;#S〉 & { - v: { - b: int - } - }) - #Q: { - [string]: ({ - a: int - }|{ - b: int - }) - } - b: (〈0;#Q〉 & { - w: { - c: int - } - }) - #R: { - [string]: [ - { - a: int - }, - { - b: int - }, - ] - } - c: (〈0;#R〉 & { - w: [ - { - d: int - }, - ..., - ] - }) -} -- out/eval/stats -- Leaks: 0 Freed: 24 diff --git a/cue/testdata/resolve/030_definitions_with_disjunctions.txtar b/cue/testdata/resolve/030_definitions_with_disjunctions.txtar index 53e303802..21f442b70 100644 --- a/cue/testdata/resolve/030_definitions_with_disjunctions.txtar +++ b/cue/testdata/resolve/030_definitions_with_disjunctions.txtar @@ -17,30 +17,6 @@ baz: {b: 2} @test(eq, {b: 2, field: int}) -- out/errors.txt -- [eval] bar.c: field not allowed: ./in.cue:12:7 --- out/compile -- ---- in.cue -{ - #Foo: { - field: int - ({ - a: 1 - }|{ - b: 2 - }) - } - foo: 〈0;#Foo〉 - foo: { - a: 1 - } - bar: 〈0;#Foo〉 - bar: { - c: 2 - } - baz: 〈0;#Foo〉 - baz: { - b: 2 - } -} -- out/eval/stats -- Leaks: 6 Freed: 34 diff --git a/cue/testdata/resolve/031_definitions_with_disjunctions_recurisive.txtar b/cue/testdata/resolve/031_definitions_with_disjunctions_recurisive.txtar index c7639bf15..008cc7880 100644 --- a/cue/testdata/resolve/031_definitions_with_disjunctions_recurisive.txtar +++ b/cue/testdata/resolve/031_definitions_with_disjunctions_recurisive.txtar @@ -10,23 +10,6 @@ } @test(eq, { x: {field: int, c: 3, a: 1} | {field: int, c: 3, b: 2} }) --- out/compile -- ---- in.cue -{ - #Foo: { - x: { - field: int - ({ - a: 1 - }|{ - b: 2 - }) - } - x: { - c: 3 - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 13 diff --git a/cue/testdata/resolve/033_top-level_definition_with_struct_and_disjunction.txtar b/cue/testdata/resolve/033_top-level_definition_with_struct_and_disjunction.txtar index 0ab82a942..5db7c6f86 100644 --- a/cue/testdata/resolve/033_top-level_definition_with_struct_and_disjunction.txtar +++ b/cue/testdata/resolve/033_top-level_definition_with_struct_and_disjunction.txtar @@ -12,22 +12,6 @@ Type: "A" Size: 1 } @test(eq, {Type: "B", Text: string, Size: 0} | {Type: "A", Text: string, Size: 1}) --- out/compile -- ---- in.cue -{ - #def: { - Type: string - Text: string - Size: int - } - #def: ({ - Type: "B" - Size: 0 - }|{ - Type: "A" - Size: 1 - }) -} -- out/eval/stats -- Leaks: 0 Freed: 13 diff --git a/cue/testdata/resolve/034_closing_structs.txtar b/cue/testdata/resolve/034_closing_structs.txtar index 5c7d7a71e..854ce335a 100644 --- a/cue/testdata/resolve/034_closing_structs.txtar +++ b/cue/testdata/resolve/034_closing_structs.txtar @@ -17,37 +17,6 @@ ctot: ct & ot @test(eq, {x: int}) @test(closed) @test(allows, string) cpct: cp & ct @test(eq, {x: int}) @test(closed) @test(allows, string) @test(allows:todo=false, string) ctcp: ct & cp @test(eq, {x: int}) @test(closed) @test(allows, string) @test(allows:todo=false, string) ctct: ct & ct @test(eq, {x: int}) @test(closed) @test(shareID=ctct) @test(allows, string) --- out/compile -- ---- in.cue -{ - op: { - x: int - } - ot: { - x: int - ... - } - cp: close({ - x: int - }) - ct: close({ - x: int - ... - }) - opot: (〈0;op〉 & 〈0;ot〉) - otop: (〈0;ot〉 & 〈0;op〉) - opcp: (〈0;op〉 & 〈0;cp〉) - cpop: (〈0;cp〉 & 〈0;op〉) - opct: (〈0;op〉 & 〈0;ct〉) - ctop: (〈0;ct〉 & 〈0;op〉) - otcp: (〈0;ot〉 & 〈0;cp〉) - cpot: (〈0;cp〉 & 〈0;ot〉) - otct: (〈0;ot〉 & 〈0;ct〉) - ctot: (〈0;ct〉 & 〈0;ot〉) - cpct: (〈0;cp〉 & 〈0;ct〉) - ctcp: (〈0;ct〉 & 〈0;cp〉) - ctct: (〈0;ct〉 & 〈0;ct〉) -} -- out/eval/stats -- Leaks: 0 Freed: 90 diff --git a/cue/testdata/resolve/035_excluded_embedding_from_closing.txtar b/cue/testdata/resolve/035_excluded_embedding_from_closing.txtar index d57053f28..29d62ef8c 100644 --- a/cue/testdata/resolve/035_excluded_embedding_from_closing.txtar +++ b/cue/testdata/resolve/035_excluded_embedding_from_closing.txtar @@ -22,32 +22,6 @@ V: #S & { ./in.cue:14:5 [eval] V.b.extra: field not allowed: ./in.cue:15:5 --- out/compile -- ---- in.cue -{ - #S: { - a: { - c: int - } - { - c: { - d: int - } - } - let B#1 = { - open: int - } - b: 〈0;let B#1〉 - } - V: (〈0;#S〉 & { - c: { - e: int - } - b: { - extra: int - } - }) -} -- out/eval/stats -- Leaks: 1 Freed: 21 diff --git a/cue/testdata/resolve/038_incomplete_comprehensions.txtar b/cue/testdata/resolve/038_incomplete_comprehensions.txtar index e3f66a13b..3401dac7f 100644 --- a/cue/testdata/resolve/038_incomplete_comprehensions.txtar +++ b/cue/testdata/resolve/038_incomplete_comprehensions.txtar @@ -20,25 +20,6 @@ B: A & { -- out/errors.txt -- [incomplete] A: cannot range over src (incomplete type _): ./in.cue:2:11 --- out/compile -- ---- in.cue -{ - A: { - for _, v in 〈0;src〉 { - "\(〈1;v〉)": 〈1;v〉 - } - src: _ - if true { - baz: "baz" - } - } - B: (〈0;A〉 & { - src: [ - "foo", - "bar", - ] - }) -} -- out/eval/stats -- Leaks: 0 Freed: 11 diff --git a/cue/testdata/resolve/039_reference_to_root.txtar b/cue/testdata/resolve/039_reference_to_root.txtar index 63a5f81db..3211ba461 100644 --- a/cue/testdata/resolve/039_reference_to_root.txtar +++ b/cue/testdata/resolve/039_reference_to_root.txtar @@ -34,34 +34,6 @@ wp: v & {b: 100} @test(eq, {b: 100, c: _|_}) [incomplete] wp.c: non-concrete value int in operand to +: ./in.cue:15:5 ./in.cue:14:5 --- out/compile -- ---- in.cue -{ - a: { - b: int - } - c: (〈0;a〉 & { - b: 100 - d: (〈1;a〉.b + 3) - }) - x: { - b: int - c: (〈0;b〉 + 5) - } - y: (〈0;x〉 & { - b: 100 - }) - v: { - b: int - c: (〈1;v〉.b + 5) - } - w: (〈0;v〉 & { - b: 100 - }) - wp: (〈0;v〉 & { - b: 100 - }) -} -- out/eval/stats -- Leaks: 0 Freed: 21 diff --git a/cue/testdata/resolve/040_references_from_template_to_concrete.txtar b/cue/testdata/resolve/040_references_from_template_to_concrete.txtar index 5069aa9d6..e9e773ef7 100644 --- a/cue/testdata/resolve/040_references_from_template_to_concrete.txtar +++ b/cue/testdata/resolve/040_references_from_template_to_concrete.txtar @@ -15,29 +15,6 @@ t: [X=string]: { } t: x: {b: str: "DDDD"} @test(eq, {b: {str: "DDDD"}, a: "XDDDD", c: "X"}) --- out/compile -- ---- in.cue -{ - res: [ - 〈1;t〉, - ] - t: { - [string]: { - a: (〈0;c〉 + 〈0;b〉.str) - b: { - str: string - } - c: "X" - } - } - t: { - x: { - b: { - str: "DDDD" - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 9 diff --git a/cue/testdata/resolve/043_diamond-shaped_constraints.txtar b/cue/testdata/resolve/043_diamond-shaped_constraints.txtar index 5469c79ce..a807fe379 100644 --- a/cue/testdata/resolve/043_diamond-shaped_constraints.txtar +++ b/cue/testdata/resolve/043_diamond-shaped_constraints.txtar @@ -18,26 +18,6 @@ T: S & {// S == { A: { a:1 }, B: { a:1, b:2 } } } @test(eq, {A: {c: 3, a: 1}, B: {d: 4, b: 2, c: 3, a: 1}}) -- out/todo.txt -- Reordering --- out/compile -- ---- in.cue -{ - S: { - A: { - a: 1 - } - B: (〈0;A〉 & { - b: 2 - }) - } - T: (〈0;S〉 & { - A: { - c: 3 - } - B: { - d: 4 - } - }) -} -- out/eval/stats -- Leaks: 0 Freed: 16 diff --git a/cue/testdata/resolve/044_field_templates.txtar b/cue/testdata/resolve/044_field_templates.txtar index 7959833f4..a238f7893 100644 --- a/cue/testdata/resolve/044_field_templates.txtar +++ b/cue/testdata/resolve/044_field_templates.txtar @@ -20,41 +20,6 @@ c: { foo: {name: "foo", y: 1} bar: {name: "bar", y: 1} }) --- out/compile -- ---- in.cue -{ - a: { - { - [_]: int - } - k: 1 - } - b: { - { - [_]: { - x: 0 - y: (*1|int) - } - } - v: {} - w: { - x: 0 - } - } - b: { - [_]: {} - } - c: { - { - [_]: { - name: 〈1;-〉 - y: 1 - } - } - foo: {} - bar: _ - } -} -- out/eval/stats -- Leaks: 0 Freed: 21 diff --git a/cue/testdata/resolve/045_range_unification.txtar b/cue/testdata/resolve/045_range_unification.txtar index a3e37ec2e..a169c8a33 100644 --- a/cue/testdata/resolve/045_range_unification.txtar +++ b/cue/testdata/resolve/045_range_unification.txtar @@ -72,45 +72,6 @@ n5: >=1 & <=5 & 2.5 @test(eq, 2.5) [eval] n2: incompatible integer bounds <=1.3 and >=1.1: ./in.cue:42:19 ./in.cue:42:11 --- out/compile -- ---- in.cue -{ - a1: ((>=1 & <=5) & 3) - a2: ((>=1 & <=5) & 1) - a3: ((>=1 & <=5) & 5) - a4: ((>=1 & <=5) & 6) - a5: ((>=1 & <=5) & 0) - a6: ((3 & >=1) & <=5) - a7: ((1 & >=1) & <=5) - a8: ((5 & >=1) & <=5) - a9: ((6 & >=1) & <=5) - a10: ((0 & >=1) & <=5) - b1: (((>=1 & <=5) & >=1) & <=5) - b2: (((>=1 & <=5) & >=1) & <=1) - b3: (((>=1 & <=5) & >=5) & <=5) - b4: (((>=1 & <=5) & >=2) & <=3) - b5: (((>=1 & <=5) & >=3) & <=9) - b6: (((>=1 & <=5) & >=5) & <=9) - b7: (((>=1 & <=5) & >=6) & <=9) - b8: (((>=1 & <=5) & >=1) & <=5) - b9: (((>=1 & <=1) & >=1) & <=5) - b10: (((>=5 & <=5) & >=1) & <=5) - b11: (((>=2 & <=3) & >=1) & <=5) - b12: (((>=3 & <=9) & >=1) & <=5) - b13: (((>=5 & <=9) & >=1) & <=5) - b14: (((>=6 & <=9) & >=1) & <=5) - c1: ((int & >=1) & <=5) - c2: ((>=1 & <=5) & int) - c3: ((string & >=1) & <=5) - c4: ((>=1 & <=5) & string) - s1: ((>="d" & <="z") & "e") - s2: ((>="d" & <="z") & "ee") - n1: ((number & >=1) & <=2) - n2: ((int & >=1.1) & <=1.3) - n3: ((>=1.0 & <=3.0) & 2) - n4: ((>=0.0 & <=0.1) & 0.09999) - n5: ((>=1 & <=5) & 2.5) -} -- out/eval/stats -- Leaks: 0 Freed: 36 diff --git a/cue/testdata/resolve/046_predefined_ranges.txtar b/cue/testdata/resolve/046_predefined_ranges.txtar index 2cb3b3309..0a6130774 100644 --- a/cue/testdata/resolve/046_predefined_ranges.txtar +++ b/cue/testdata/resolve/046_predefined_ranges.txtar @@ -19,15 +19,3 @@ s4: uint s3: (number){ &(>=-340282346638528859811704183484516925440, <=340282346638528859811704183484516925440) } s4: (int){ &(>=0, int) } } --- out/compile -- ---- in.cue -{ - k1: &(int, >=-128, <=127) - k1: 44 - k2: &(int, >=-9223372036854775808, <=9223372036854775807) - k2: -8000000000 - s1: &(int, >=-128, <=127) - s2: &(int, >=0, <=65535) - s3: &(>=-340282346638528859811704183484516925440, <=340282346638528859811704183484516925440) - s4: &(int, >=0) -} diff --git a/cue/testdata/resolve/046_predefined_ranges_error.txtar b/cue/testdata/resolve/046_predefined_ranges_error.txtar index 1aa69fca7..9016c25be 100644 --- a/cue/testdata/resolve/046_predefined_ranges_error.txtar +++ b/cue/testdata/resolve/046_predefined_ranges_error.txtar @@ -4,9 +4,3 @@ e1: 100_000 @test(err, code=eval, contains="invalid value 100000", pos=[0:5]) -- out/errors.txt -- [eval] e1: invalid value 100000 (out of bound <=32767): ./in.cue:2:5 --- out/compile -- ---- in.cue -{ - e1: &(int, >=-32768, <=32767) - e1: 100000 -} diff --git a/cue/testdata/resolve/047_struct_comprehensions.txtar b/cue/testdata/resolve/047_struct_comprehensions.txtar index 9efe1b087..19e5196fe 100644 --- a/cue/testdata/resolve/047_struct_comprehensions.txtar +++ b/cue/testdata/resolve/047_struct_comprehensions.txtar @@ -20,33 +20,6 @@ for k, v in {#def: 1, opt?: 2, _hid: 3, reg: 4} { reg: 4 }) --- out/compile -- ---- in.cue -{ - obj: { - foo: { - a: "bar" - } - } - obj: { - [string]: { - a: (*"dummy"|string) - if true { - sub: { - as: 〈2;a〉 - } - } - } - } - for k, v in { - #def: 1 - opt?: 2 - _hid: 3 - reg: 4 - } { - "\(〈1;k〉)": 〈1;v〉 - } -} -- out/eval/stats -- Leaks: 2 Freed: 12 diff --git a/cue/testdata/resolve/048_builtins.txtar b/cue/testdata/resolve/048_builtins.txtar index 8224c6553..aa2434de4 100644 --- a/cue/testdata/resolve/048_builtins.txtar +++ b/cue/testdata/resolve/048_builtins.txtar @@ -134,106 +134,6 @@ o3.a: conflicting values "baz" and "foo": [incomplete] decimalListErrors.b.result: error in call to list.Avg: non-concrete value int for element 0 of number list argument 0: ./in.cue:62:11 ./in.cue:61:7 --- out/compile -- ---- in.cue -{ - a1: { - a: and([ - 〈1;b〉, - 〈1;c〉, - ]) - b: =~"oo" - c: =~"fo" - } - a2: (〈0;a1〉 & { - a: "foo" - }) - a3: (〈0;a1〉 & { - a: "bar" - }) - o1: { - a: or([ - 〈1;b〉, - 〈1;c〉, - ]) - b: string - c: "bar" - } - o2: (〈0;o1〉 & { - a: "foo" - }) - o3: (〈0;o1〉 & { - a: "foo" - b: "baz" - }) - stringListErrors: { - a: { - x: [ - string, - ...string, - ] - result: 〈import;strings〉.Join(〈0;x〉, " ") - } - b: { - x: [ - int, - ...string, - ] - result: 〈import;strings〉.Join(〈0;x〉, " ") - } - c: { - x: [] - result: 〈import;strings〉.Join(〈0;x〉, int) - } - } - decimalListErrors: { - a: { - x: [ - string, - ] - result: 〈import;list〉.Avg(〈0;x〉) - } - b: { - x: [ - int, - ...string, - ] - result: 〈import;list〉.Avg(〈0;x〉) - } - } -} ---- issue3648.cue -{ - issue3648: { - reduced: { - [string]: { - a: 〈import;list〉.Concat([ - 〈1;b〉, - ]) - b: [ - {}, - ] - } - foo: {} - } - } - issue3648: { - full: { - #Redirect: { - path?: string - } - [string]: { - allRedirects: 〈import;list〉.Concat([ - 〈1;redirects〉, - ]) - redirects: [ - ...〈2;#Redirect〉, - ] - } - foo: {} - } - } -} -- out/eval/stats -- Leaks: 1 Freed: 86 diff --git a/cue/testdata/scalars/embed.txtar b/cue/testdata/scalars/embed.txtar index 8a460d2f0..dbdc2d64d 100644 --- a/cue/testdata/scalars/embed.txtar +++ b/cue/testdata/scalars/embed.txtar @@ -194,168 +194,6 @@ selfRefInEmbed: t1: { [incomplete] arithmetic.sum: non-concrete value int in operand to +: ./in.cue:79:3 ./in.cue:80:7 --- out/compile -- ---- in.cue -{ - intEmbed: { - a1: { - 2 - } - a2: { - v: { - 3 - #foo: (〈2;a2〉.v + 1) - } - w: 〈0;v〉 - x: 〈0;v〉.#foo - } - a3: (〈0;a1〉 + 〈0;a2〉.v) - } - listEmbed: { - a1: { - 2 - } - b3: { - [ - 1, - 2, - ] - #foo: 1 - } - b4: 〈import;list〉.Concat([ - 〈1;b3〉, - 〈1;b3〉, - ]) - b5: 〈0;b3〉[1] - b6: 〈0;b3〉[5] - b7: 〈0;b4〉[〈0;a1〉] - } - stringEmbed: { - s1: { - "foo" - #bar: "bar" - } - s2: [ - 〈1;s1〉, - { - 〈2;s1〉.#bar - #baz: 4 - }, - ] - s3: 〈import;strings〉.Join(〈0;s2〉, "--") - } - outPattern: { - sum: { - out: (〈0;#a〉 + 〈0;#b〉) - #a: int - #b: int - } - used: { - (〈1;sum〉 & { - #a: 1 - #b: 3 - }) - } - } - arithmetic: { - sum: { - (〈0;#a〉 + 〈0;#b〉) - #a: int - #b: int - } - a1: ((〈0;sum〉 & { - _ - #a: 1 - #b: 3 - }) + 2) - a2: (2 + (〈0;sum〉 & { - _ - #a: 1 - #b: 3 - })) - a3: (2 + (2 + (〈0;sum〉 & { - _ - #a: 1 - #b: 3 - }))) - } - defCheck: { - a: { - #def: 1 - } - b: 〈0;a〉.#def - } - optionalExists: { - (string|{ - value?: string - if (〈0;value〉 != _|_(explicit error (_|_ literal) in source)) { - other: int - } - }) - } - optionalCheck: { - thing: (string|{ - value?: string - if (〈0;value〉 != _|_(explicit error (_|_ literal) in source)) { - other: int - } - }) - thing: { - value: "some string" - other: 3 - } - } - hidden: { - issue794: { - _foo: "foo" - [ - 〈1;_foo〉, - ] - } - } -} ---- issue2113.cue -{ - merged: { - t1: { - #fn: { - #in2: _ - _ - } - #fn: { - #in2: { - c1: string - } - 〈0;#in2〉.c1 - } - x: (〈0;#fn〉 & { - #in2: { - c1: "V 1" - } - _ - }) - } - } -} ---- issue2163.cue -{ - selfRefInEmbed: { - t1: { - #Func: { - #in: _ - _ - } - #fn: 〈0;#Func〉 - #fn: { - #in: _ - ((〈1;#Func〉 & { - _foo: 〈1;#in〉 - "buzz" - }) + "fiz") - } - } - } -} -- out/eval/stats -- Leaks: 4 Freed: 132 diff --git a/cue/testdata/scalars/embed_bound.txtar b/cue/testdata/scalars/embed_bound.txtar index 09cac0c6b..0d872d3bc 100644 --- a/cue/testdata/scalars/embed_bound.txtar +++ b/cue/testdata/scalars/embed_bound.txtar @@ -14,15 +14,3 @@ c: { !=null x: 1 } @test(eq, {x: 1}) --- out/compile -- ---- in.cue -{ - a: { - !=null - } - b: !=null - c: { - !=null - x: 1 - } -} diff --git a/cue/testdata/scalars/emptystruct.txtar b/cue/testdata/scalars/emptystruct.txtar index 7d46934d3..e2dfa7ee5 100644 --- a/cue/testdata/scalars/emptystruct.txtar +++ b/cue/testdata/scalars/emptystruct.txtar @@ -139,69 +139,3 @@ Conjuncts: 102 Disjuncts: 6 NumCloseIDs: 56 --- out/compile -- ---- in.cue -{ - elipsis: { - test1: { - string - #foo: "bar" - } - #Def: { - ... - #foo: string - _ - } - check: (〈0;test1〉 & 〈0;#Def〉) - } - bulk: { - test1: { - string - #foo: "bar" - } - #Def: { - [string]: int - #foo: string - _ - } - check: (〈0;test1〉 & 〈0;#Def〉) - } - optional: { - test1: { - string - #foo: "bar" - } - #Def: { - bar?: int - #foo: string - _ - } - check: (〈0;test1〉 & 〈0;#Def〉) - } - issue783: { - test1: { - string - #foo: "bar" - } - test2: { - hello: "world" - #foo: "bar" - } - #Def1: ({ - ... - #foo: string - }|{ - string - #foo: string - }) - check1a: (〈0;test1〉 & 〈0;#Def1〉) - check1b: (〈0;test2〉 & 〈0;#Def1〉) - #Def2: { - ... - #foo: string - _ - } - check2a: (〈0;test1〉 & 〈0;#Def2〉) - check2b: (〈0;test2〉 & 〈0;#Def2〉) - } -} diff --git a/cue/testdata/scalars/yield.txtar b/cue/testdata/scalars/yield.txtar index 9abe6f40f..84bb9158b 100644 --- a/cue/testdata/scalars/yield.txtar +++ b/cue/testdata/scalars/yield.txtar @@ -32,33 +32,6 @@ ifScalarNested: { ./in.cue:14:2 ./in.cue:14:13 ./in.cue:16:2 --- out/compile -- ---- in.cue -{ - ifScalar: { - _#cond: true - if 〈0;_#cond〉 { - 5 - } - } - ifScalarConflict: { - _#cond: true - if 〈0;_#cond〉 { - 5 - } - "soo" - } - ifScalarNested: { - _#cond: true - if 〈0;_#cond〉 { - { - { - 5 - } - } - } - } -} -- out/eval/stats -- Leaks: 0 Freed: 7 diff --git a/internal/core/compile/compile_test.go b/internal/core/compile/compile_test.go index 2e1d43b8c..0e96e859b 100644 --- a/internal/core/compile/compile_test.go +++ b/internal/core/compile/compile_test.go @@ -15,8 +15,11 @@ package compile_test import ( + "bytes" "flag" "fmt" + "os" + "path/filepath" "strings" "testing" @@ -25,7 +28,9 @@ import ( "cuelang.org/go/internal/core/compile" "cuelang.org/go/internal/core/debug" "cuelang.org/go/internal/core/runtime" + "cuelang.org/go/internal/cuetest" "cuelang.org/go/internal/cuetxtar" + "golang.org/x/tools/txtar" ) var ( @@ -33,8 +38,12 @@ var ( ) func TestCompile(t *testing.T) { + if cuetest.UpdateGoldenFiles { + syncTestdataInputsCUE(t) + } + test := cuetxtar.TxTarTest{ - Root: "../../../cue/testdata/", + Root: "testdata", Name: "compile", } @@ -71,6 +80,49 @@ func TestCompile(t *testing.T) { }) } +func syncTestdataInputsCUE(t *testing.T) { + t.Helper() + + const srcRoot = "../../../cue/testdata" + const dstRoot = "testdata/sync" + + if err := os.RemoveAll(dstRoot); err != nil { + t.Fatal(err) + } + + err := filepath.WalkDir(srcRoot, func(srcPath string, entry os.DirEntry, err error) error { + if err != nil { + return err + } + if entry.IsDir() || filepath.Ext(srcPath) != ".txtar" { + return nil + } + srcArchive, err := txtar.ParseFile(srcPath) + if err != nil { + return err + } + rel, err := filepath.Rel(srcRoot, srcPath) + if err != nil { + return err + } + dstPath := filepath.Join(dstRoot, rel) + + archive := &txtar.Archive{Comment: bytes.Clone(srcArchive.Comment)} + for _, f := range srcArchive.Files { + if strings.HasSuffix(f.Name, ".cue") { + archive.Files = append(archive.Files, txtar.File{Name: f.Name, Data: bytes.Clone(f.Data)}) + } + } + if err := os.MkdirAll(filepath.Dir(dstPath), 0777); err != nil { + return err + } + return os.WriteFile(dstPath, txtar.Format(archive), 0666) + }) + if err != nil { + t.Fatal(err) + } +} + // TestX is for debugging. Do not delete. func TestX(t *testing.T) { in := ` diff --git a/internal/core/compile/testdata/README.md b/internal/core/compile/testdata/README.md new file mode 100644 index 000000000..6e76e5efd --- /dev/null +++ b/internal/core/compile/testdata/README.md @@ -0,0 +1,13 @@ +# Compile Testdata + +The `sync` directory is generated from `cue/testdata` when running: + +```sh +CUE_UPDATE=1 go test ./internal/core/compile +``` + +Do not edit files under `sync` directly. The update run deletes and recreates +that directory, then regenerates the compile output sections. + +Compile-specific test archives that should not be synced from `cue/testdata` +belong outside `sync`, for example under `local/`. diff --git a/internal/core/compile/testdata/sync/basicrewrite/000_errors.txtar b/internal/core/compile/testdata/sync/basicrewrite/000_errors.txtar new file mode 100644 index 000000000..918688f83 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/000_errors.txtar @@ -0,0 +1,19 @@ +-- in.cue -- +a: _|_ & _|_ @test(err, code=user) +b: null & _|_ @test(err, code=user) +c: b.a == _|_ @test(eq, true) +d: _|_ != b.a @test(eq, false) +e: _|_ == _|_ @test(eq, true) +f: ({} & false) == _|_ @test(eq, true) +g: _|_ != ({} & false) @test(eq, false) +-- out/compile -- +--- in.cue +{ + a: (_|_(explicit error (_|_ literal) in source) & _|_(explicit error (_|_ literal) in source)) + b: (null & _|_(explicit error (_|_ literal) in source)) + c: (〈0;b〉.a == _|_(explicit error (_|_ literal) in source)) + d: (_|_(explicit error (_|_ literal) in source) != 〈0;b〉.a) + e: (_|_(explicit error (_|_ literal) in source) == _|_(explicit error (_|_ literal) in source)) + f: (({} & false) == _|_(explicit error (_|_ literal) in source)) + g: (_|_(explicit error (_|_ literal) in source) != ({} & false)) +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/001_regexp.txtar b/internal/core/compile/testdata/sync/basicrewrite/001_regexp.txtar new file mode 100644 index 000000000..144ce8973 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/001_regexp.txtar @@ -0,0 +1,49 @@ +-- in.cue -- +c1: "a" =~ "a" @test(eq, true) +c2: "foo" =~ "[a-z]{3}" @test(eq, true) +c3: "foo" =~ "[a-z]{4}" @test(eq, false) +c4: "foo" !~ "[a-z]{4}" @test(eq, true) + +b1: =~"a" @test(eq, "a") +b1: "a" +b2: =~"[a-z]{3}" @test(eq, "foo") +b2: "foo" +b3: =~"[a-z]{4}" @test(err, code=eval, contains="out of bound", pos=[0:5, 1:5]) +b3: "foo" +b4: !~"[a-z]{4}" @test(eq, "foo") +b4: "foo" + +s1: !="b" & =~"c" @test(eq, =~"c") +s2: =~"c" & !="b" @test(eq, =~"c") +s3: !="b" & =~"[a-z]" @test(eq, !="b" & =~"[a-z]") +s4: =~"[a-z]" & !="b" @test(eq, =~"[a-z]" & !="b") // TODO: allow different order + +e1: "foo" =~ 1 @test(err, code=eval, + contains="cannot use 1", pos=[0:5, 0:14]) +e2: "foo" !~ true @test(err, code=eval, + contains="cannot use true", pos=[0:5, 0:14]) +e3: !="a" & <5 @test(err, code=eval, + contains="conflicting values", pos=[0:5, 0:13]) +-- out/compile -- +--- in.cue +{ + c1: ("a" =~ "a") + c2: ("foo" =~ "[a-z]{3}") + c3: ("foo" =~ "[a-z]{4}") + c4: ("foo" !~ "[a-z]{4}") + b1: =~"a" + b1: "a" + b2: =~"[a-z]{3}" + b2: "foo" + b3: =~"[a-z]{4}" + b3: "foo" + b4: !~"[a-z]{4}" + b4: "foo" + s1: (!="b" & =~"c") + s2: (=~"c" & !="b") + s3: (!="b" & =~"[a-z]") + s4: (=~"[a-z]" & !="b") + e1: ("foo" =~ 1) + e2: ("foo" !~ true) + e3: (!="a" & <5) +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/002_arithmetic.txtar b/internal/core/compile/testdata/sync/basicrewrite/002_arithmetic.txtar new file mode 100644 index 000000000..b214a1694 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/002_arithmetic.txtar @@ -0,0 +1,56 @@ +-- in.cue -- +i1: 1 & int @test(eq, 1) +i2: 2 & int @test(eq, 2) + +sum: -1 + +2 @test(eq, 1) +div1: 2.0 / 3 * 6 @test(eq, 4.0) @test(kind=float) +div2: 2 / 3 * 6 @test(eq, 4.0) @test(kind=float, + hint="we may consider this to be int in the future") +div3: 1.00 / 1.00 @test(eq, 1.0) @test(kind=float) +divZero: 1.0 / 0 @test(err, code=eval, contains="division by zero", pos=[0:10]) +div00: 0 / 0 @test(err, code=eval, contains="division undefined", pos=[0:10]) +b: 1 != 4 @test(eq, true) +add: div1 + 1.0 @test(eq, 5.0) + +idiv00: div(0, 0) @test(err, code=eval, contains="division by zero", pos=[0:9]) +imod00: mod(0, 0) @test(err, code=eval, contains="division by zero", pos=[0:9]) +iquo00: quo(0, 0) @test(err, code=eval, contains="division by zero", pos=[0:9]) +irem00: rem(0, 0) @test(err, code=eval, contains="division by zero", pos=[0:9]) + +v1: 1.0T / 2.0 @test(eq, 5.0E+11) +v2: 2.0 == 2 @test(eq, true) +v3: 2.0 / 3.0 @test(eq, 0.6666666666666666666666666666666667) +v5: div(i1, i2) @test(eq, 0) + +e0: 2 + "a" @test(err, code=eval, contains="invalid operands", pos=[0:5, 0:9]) +e5: div(1.0, 2) @test(err, code=eval, contains="cannot use", pos=[0:9]) +e6: rem(2, 2.0) @test(err, code=eval, contains="cannot use", pos=[0:12]) +e7: quo(2, 2.0) @test(err, code=eval, contains="cannot use", pos=[0:12]) +e8: mod(1.0, 1) @test(err, code=eval, contains="cannot use", pos=[0:9]) +-- out/compile -- +--- in.cue +{ + i1: (1 & int) + i2: (2 & int) + sum: (-1 + +2) + div1: ((2.0 / 3) * 6) + div2: ((2 / 3) * 6) + div3: (1.00 / 1.00) + divZero: (1.0 / 0) + div00: (0 / 0) + b: (1 != 4) + add: (〈0;div1〉 + 1.0) + idiv00: div(0, 0) + imod00: mod(0, 0) + iquo00: quo(0, 0) + irem00: rem(0, 0) + v1: (1000000000000 / 2.0) + v2: (2.0 == 2) + v3: (2.0 / 3.0) + v5: div(〈0;i1〉, 〈0;i2〉) + e0: (2 + "a") + e5: div(1.0, 2) + e6: rem(2, 2.0) + e7: quo(2, 2.0) + e8: mod(1.0, 1) +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/003_integer-specific_arithmetic.txtar b/internal/core/compile/testdata/sync/basicrewrite/003_integer-specific_arithmetic.txtar new file mode 100644 index 000000000..b7f9c4b9c --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/003_integer-specific_arithmetic.txtar @@ -0,0 +1,56 @@ +-- in.cue -- +q1: quo(5, 2) @test(eq, 2) +q2: quo(5, -2) @test(eq, -2) +q3: quo(-5, 2) @test(eq, -2) +q4: quo(-5, -2) @test(eq, 2) +qe1: quo(2.0, 1) @test(err, code=eval, pos=[0:10], contains="cannot use") +qe2: quo(2, 1.0) @test(err, code=eval, pos=[0:13], contains="cannot use") + +r1: rem(5, 2) @test(eq, 1) +r2: rem(5, -2) @test(eq, 1) +r3: rem(-5, 2) @test(eq, -1) +r4: rem(-5, -2) @test(eq, -1) +re1: rem(2.0, 1) @test(err, code=eval, pos=[0:10], contains="cannot use") +re2: rem(2, 1.0) @test(err, code=eval, pos=[0:13], contains="cannot use") + +d1: div(5, 2) @test(eq, 2) +d2: div(5, -2) @test(eq, -2) +d3: div(-5, 2) @test(eq, -3) +d4: div(-5, -2) @test(eq, 3) +de1: div(2.0, 1) @test(err, code=eval, pos=[0:10], contains="cannot use") +de2: div(2, 1.0) @test(err, code=eval, pos=[0:13], contains="cannot use") + +m1: mod(5, 2) @test(eq, 1) +m2: mod(5, -2) @test(eq, 1) +m3: mod(-5, 2) @test(eq, 1) +m4: mod(-5, -2) @test(eq, 1) +me1: mod(2.0, 1) @test(err, code=eval, pos=[0:10], contains="cannot use") +me2: mod(2, 1.0) @test(err, code=eval, pos=[0:13], contains="cannot use") +-- out/compile -- +--- in.cue +{ + q1: quo(5, 2) + q2: quo(5, -2) + q3: quo(-5, 2) + q4: quo(-5, -2) + qe1: quo(2.0, 1) + qe2: quo(2, 1.0) + r1: rem(5, 2) + r2: rem(5, -2) + r3: rem(-5, 2) + r4: rem(-5, -2) + re1: rem(2.0, 1) + re2: rem(2, 1.0) + d1: div(5, 2) + d2: div(5, -2) + d3: div(-5, 2) + d4: div(-5, -2) + de1: div(2.0, 1) + de2: div(2, 1.0) + m1: mod(5, 2) + m2: mod(5, -2) + m3: mod(-5, 2) + m4: mod(-5, -2) + me1: mod(2.0, 1) + me2: mod(2, 1.0) +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/004_booleans.txtar b/internal/core/compile/testdata/sync/basicrewrite/004_booleans.txtar new file mode 100644 index 000000000..2511640bf --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/004_booleans.txtar @@ -0,0 +1,17 @@ +-- in.cue -- +t: true @test(eq, true) +t: !false +f: false @test(eq, false) +f: !t +e: true @test(err, code=eval, pos=[0:4, 1:4], contains="conflicting values") +e: !true +-- out/compile -- +--- in.cue +{ + t: true + t: !false + f: false + f: !〈0;t〉 + e: true + e: !true +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/005_boolean_arithmetic.txtar b/internal/core/compile/testdata/sync/basicrewrite/005_boolean_arithmetic.txtar new file mode 100644 index 000000000..5e9eb0a35 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/005_boolean_arithmetic.txtar @@ -0,0 +1,17 @@ +-- in.cue -- +a: true && true @test(eq, true) +b: true || false @test(eq, true) +c: false == true @test(eq, false) +d: false != true @test(eq, true) +e: true & true @test(eq, true) +f: true & false @test(err, code=eval, pos=[0:4, 0:11]) +-- out/compile -- +--- in.cue +{ + a: (true && true) + b: (true || false) + c: (false == true) + d: (false != true) + e: (true & true) + f: (true & false) +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/006_basic_type.txtar b/internal/core/compile/testdata/sync/basicrewrite/006_basic_type.txtar new file mode 100644 index 000000000..f816a1920 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/006_basic_type.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +a: 1 & int @test(eq, 1) +b: number & 1 @test(eq, 1) +c: 1.0 @test(eq, 1.0) +c: float +d: int & float @test(err, code=eval, pos=[0:4, 0:10]) +e: "4" & string @test(eq, "4") +f: true @test(eq, true) +f: bool +-- out/compile -- +--- in.cue +{ + a: (1 & int) + b: (number & 1) + c: 1.0 + c: float + d: (int & float) + e: ("4" & string) + f: true + f: bool +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/007_strings_and_bytes.txtar b/internal/core/compile/testdata/sync/basicrewrite/007_strings_and_bytes.txtar new file mode 100644 index 000000000..618e8de90 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/007_strings_and_bytes.txtar @@ -0,0 +1,24 @@ +-- in.cue -- +s0: "foo" + "bar" @test(eq, "foobar") +s1: 3 * "abc" @test(eq, "abcabcabc") +s2: "abc" * 2 @test(eq, "abcabc") + +b0: 'foo' + 'bar' @test(eq, 'foobar') +b1: 3 * 'abc' @test(eq, 'abcabcabc') +b2: 'abc' * 2 @test(eq, 'abcabc') + +// TODO: consider the semantics of this and perhaps allow this. +e0: "a" + '' @test(err, code=eval) +e1: 'b' + "c" @test(err, code=eval) +-- out/compile -- +--- in.cue +{ + s0: ("foo" + "bar") + s1: (3 * "abc") + s2: ("abc" * 2) + b0: ('foo' + 'bar') + b1: (3 * 'abc') + b2: ('abc' * 2) + e0: ("a" + '') + e1: ('b' + "c") +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/008_escaping.txtar b/internal/core/compile/testdata/sync/basicrewrite/008_escaping.txtar new file mode 100644 index 000000000..6aa065af3 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/008_escaping.txtar @@ -0,0 +1,11 @@ +-- in.cue -- +a: "foo\nbar" @test(eq, "foo\nbar") +b: a @test(eq, "foo\nbar") + +// TODO: mimic http://exploringjs.com/es6/ch_template-literals.html#sec_introduction-template-literals +-- out/compile -- +--- in.cue +{ + a: "foo\nbar" + b: 〈0;a〉 +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/009_reference.txtar b/internal/core/compile/testdata/sync/basicrewrite/009_reference.txtar new file mode 100644 index 000000000..ddbe243df --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/009_reference.txtar @@ -0,0 +1,37 @@ +-- in.cue -- +a: b @test(eq, 2) +b: 2 +d: { + d: 3 + e: d @test(eq, 3) +} @test(eq, {d: 3, e: 3}) +e: { + @test(eq, { + e: {v: 1} + f: {v: 1} + }) + e: { + v: 1 + } + f: { + v: e.v + } +} +-- out/compile -- +--- in.cue +{ + a: 〈0;b〉 + b: 2 + d: { + d: 3 + e: 〈0;d〉 + } + e: { + e: { + v: 1 + } + f: { + v: 〈1;e〉.v + } + } +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/010_lists.txtar b/internal/core/compile/testdata/sync/basicrewrite/010_lists.txtar new file mode 100644 index 000000000..17e3fa2d6 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/010_lists.txtar @@ -0,0 +1,61 @@ +-- in.cue -- +list: [1, 2, 3] @test(eq, [1, 2, 3]) +index: [1, 2, 3][1] @test(eq, 2) +unify: [1, 2, 3] & [_, 2, 3] @test(eq, [1, 2, 3]) +e: [] & 4 @test(err, code=eval, pos=[0:8, 0:13], contains="conflicting values", args=[list, int]) + +// No "contains" as message may vary by implementation. +e2: [3]["d"] @test(err, code=eval, pos=[0:12]) +e3: [3][-1] @test(err, code=eval, pos=[0:8, 0:12], contains="invalid index", args=[-1]) +e4: [1, 2, ...>=4 & <=5] & [1, 2, 4, 8] @test(err, code=eval, pos=[0:24, 0:41], contains="invalid value", args=[8, <=5]) +e5: [1, 2, 4, 8] & [1, 2, ...>=4 & <=5] @test(err, code=eval, pos=[0:39, 0:18], contains="invalid value", args=[8, <=5]) +-- out/compile -- +--- in.cue +{ + list: [ + 1, + 2, + 3, + ] + index: [ + 1, + 2, + 3, + ][1] + unify: ([ + 1, + 2, + 3, + ] & [ + _, + 2, + 3, + ]) + e: ([] & 4) + e2: [ + 3, + ]["d"] + e3: [ + 3, + ][-1] + e4: ([ + 1, + 2, + ...(>=4 & <=5), + ] & [ + 1, + 2, + 4, + 8, + ]) + e5: ([ + 1, + 2, + 4, + 8, + ] & [ + 1, + 2, + ...(>=4 & <=5), + ]) +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/012_selecting.txtar b/internal/core/compile/testdata/sync/basicrewrite/012_selecting.txtar new file mode 100644 index 000000000..6df67bce8 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/012_selecting.txtar @@ -0,0 +1,39 @@ +-- in.cue -- +obj: {a: 1, b: 2} @test(eq, {a: 1, b: 2}) +index: {a: 1, b: 2}["b"] @test(eq, 2) +mulidx: {a: 1, b: {a: 1, b: 3}}["b"]["b"] @test(eq, 3) +e: {a: 1}[4] @test(err, code=eval, pos=[0:16]) +f: {a: 1}.b @test(err, code=incomplete, pos=[0:16]) +g: {a: 1}["b"] @test(err, code=incomplete, pos=[0:16]) +h: [3].b @test(err, code=eval, pos=[0:13]) +-- out/compile -- +--- in.cue +{ + obj: { + a: 1 + b: 2 + } + index: { + a: 1 + b: 2 + }["b"] + mulidx: { + a: 1 + b: { + a: 1 + b: 3 + } + }["b"]["b"] + e: { + a: 1 + }[4] + f: { + a: 1 + }.b + g: { + a: 1 + }["b"] + h: [ + 3, + ].b +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/013_obj_unify.txtar b/internal/core/compile/testdata/sync/basicrewrite/013_obj_unify.txtar new file mode 100644 index 000000000..2714a5a48 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/013_obj_unify.txtar @@ -0,0 +1,52 @@ +-- in.cue -- +o1: {a: 1} & {b: 2} @test(eq, {a: 1, b: 2}) +o2: {a: 1, b: 2} & {b: 2} @test(eq, {a: 1, b: 2}) +o3: {a: 1} & {a: 1, b: 2} @test(eq, {a: 1, b: 2}) +o4: {a: 1} & {b: 2} +o4: {a: 1, b: 2} & {b: 2} +o4: {a: 1} & {a: 1, b: 2} @test(eq, {a: 1, b: 2}) + +e: 1 @test(err, code=eval, pos=[0:4, 1:4], contains="conflicting values") +e: {a: 3} +-- out/compile -- +--- in.cue +{ + o1: ({ + a: 1 + } & { + b: 2 + }) + o2: ({ + a: 1 + b: 2 + } & { + b: 2 + }) + o3: ({ + a: 1 + } & { + a: 1 + b: 2 + }) + o4: ({ + a: 1 + } & { + b: 2 + }) + o4: ({ + a: 1 + b: 2 + } & { + b: 2 + }) + o4: ({ + a: 1 + } & { + a: 1 + b: 2 + }) + e: 1 + e: { + a: 3 + } +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/014_disjunctions.txtar b/internal/core/compile/testdata/sync/basicrewrite/014_disjunctions.txtar new file mode 100644 index 000000000..bf2beef3c --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/014_disjunctions.txtar @@ -0,0 +1,54 @@ +-- in.cue -- +o1: 1 | 2 | 3 @test(eq, 1 | 2 | 3) +o2: (1 | 2 | 3) & 1 @test(eq, 1) +o3: 2 & (1 | *2 | 3) @test(eq, 2) +o4: (1 | *2 | 3) & (1 | 2 | *3) @test(eq, 1 | 2 | 3) +o5: (1 | *2 | 3) & (3 | *2 | 1) @test(eq, *2 | 1 | 3) +o6: (1 | 2 | 3) & (3 | 1 | 2) @test(eq, 1 | 2 | 3) +o7: (1 | 2 | 3) & (2 | 3) @test(eq, 2 | 3) +o8: (1 | 2 | 3) & (3 | 2) @test(eq, 2 | 3) +o9: (2 | 3) & (1 | 2 | 3) @test(eq, 2 | 3) +o10: (3 | 2) & (1 | *2 | 3) @test(eq, *2 | 3) + +m1: (1 | (*2 | 3)) & (>=2 & <=3) @test(eq, *2 | 3) +m2: (1 | (*2 | 3)) & (2 | 3) @test(eq, *2 | 3) +m3: (*1 | *(*2 | 3)) & (2 | 3) @test(eq, *2 | 3) +m4: (2 | 3) & (*2 | 3) @test(eq, *2 | 3) +m5: (*2 | 3) & (2 | 3) @test(eq, *2 | 3) + +// 2&(*2 | 3) | 3&(*2 | 3) +// (*1 | (*2 | 3)) & (2 | 3) +// *1& (2 | 3) | (*2 | 3)&(2 | 3) +// *2&(2 | 3) | 3&(2 | 3) + +// (2 | 3)&(*1 | (*2 | 3)) +// 2&(*1 | (*2 | 3)) | 3&(*1 | (*2 | 3)) +// *1&2 | (*2 | 3)&2 | *1&3 | (*2 | 3)&3 +// (*2 | 3)&2 | (*2 | 3)&3 +// *2 | 3 + +// All errors are treated the same as per the unification model. +i1: [1, 2][3] | "c" @test(eq, "c") +-- out/compile -- +--- in.cue +{ + o1: (1|2|3) + o2: ((1|2|3) & 1) + o3: (2 & (1|*2|3)) + o4: ((1|*2|3) & (1|2|*3)) + o5: ((1|*2|3) & (3|*2|1)) + o6: ((1|2|3) & (3|1|2)) + o7: ((1|2|3) & (2|3)) + o8: ((1|2|3) & (3|2)) + o9: ((2|3) & (1|2|3)) + o10: ((3|2) & (1|*2|3)) + m1: ((1|(*2|3)) & (>=2 & <=3)) + m2: ((1|(*2|3)) & (2|3)) + m3: ((*1|*(*2|3)) & (2|3)) + m4: ((2|3) & (*2|3)) + m5: ((*2|3) & (2|3)) + i1: ([ + 1, + 2, + ][3]|"c") +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/015_types.txtar b/internal/core/compile/testdata/sync/basicrewrite/015_types.txtar new file mode 100644 index 000000000..061e745aa --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/015_types.txtar @@ -0,0 +1,23 @@ +-- in.cue -- +i: int @test(eq, int) +j: int & 3 @test(eq, 3) +s: string @test(eq, string) +t: "s" & string @test(eq, "s") +e: int & string @test(err, code=eval, contains="conflicting values") +e2: 1 & string @test(err, code=eval, contains="conflicting values") +b: !int @test(err, code=eval, pos=[0:6], contains="invalid operand") +p: +true @test(err, code=eval, pos=[0:5], contains="invalid operation") +m: -false @test(err, code=eval, pos=[0:5], contains="invalid operation") +-- out/compile -- +--- in.cue +{ + i: int + j: (int & 3) + s: string + t: ("s" & string) + e: (int & string) + e2: (1 & string) + b: !int + p: +true + m: -false +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/016_comparison.txtar b/internal/core/compile/testdata/sync/basicrewrite/016_comparison.txtar new file mode 100644 index 000000000..95d97492d --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/016_comparison.txtar @@ -0,0 +1,792 @@ +#name: comparison +#evalPartial +-- cue.mod/module.cue -- +module: "x.test" +language: version: "v0.14.0" +-- in.cue -- +// Explanation of error markers: +// t: true +// f: false +// e: permanent error +// i: incomplete error +numbers: { + tLss: 1 < 2 @test(eq, true) + tLeq: 1 <= 1.0 @test(eq, true) + tLeq: 2.0 <= 3 @test(eq, true) + tEql: 1 == 1.0 @test(eq, true) + tNeq: 1.0 == 1 @test(eq, true) + tGeq: 2.0 >= 2 @test(eq, true) + tGtr: !(2 > 3) @test(eq, true) + tExpr: "a"+"b" == "ab" @test(eq, true) +} +-- lists.cue -- +lists: { + // Equal lists + t1: [] == [] @test(eq, true) + t2: [1, 2, 3] == [1, 2, 3] @test(eq, true) + t3: [1, "foo", true] == [1, "foo", true] @test(eq, true) + t4: [[1, 2], [3, 4]] == [[1, 2], [3, 4]] @test(eq, true) + t5: ([1, ...int] & [1, 2, 3]) == [1, 2, 3] @test(eq, true) + t6: [1] == ([...1] & [_]) @test(eq, true) + t7: [{a: 1}] == ([...{a: 1}] & [_]) @test(eq, true) + t8: [{a: 1}] != [...{a: 1}] @test(eq, true) // true as it is not equal + t9: [...int] == [...string] @test(eq, true) // additional types are irrelevant. + + // Non-equal lists + f1: [1, 2, 3] == [1, 2, 4] @test(eq, false) + f2: [1, 2, 3] == [1, 2] @test(eq, false) + f3: [1, 2, 3] == [1, 3, 2] @test(eq, false) // different order + f4: [] == [1] @test(eq, false) + f5: [1, 2] == [1, "2"] @test(eq, false) // different types + f6: [*1 | 2 | 3] == [*2 | 3 | 4] @test(eq, false) + + + // TODO: types can never match. This could be a permanent error. + // This was V2 behavior. + eIncompat: [int] == [string] @test(err, code=incomplete|eval, pos=[0:13]) @test(err:todo, code=eval, pos=[0:13]) + + // Error cases + eErrPassthrough: [1/0] == [1] @test(err, code=eval, contains="invalid", pos=[0:19]) + + // incomplete passtrhough + _e3l: {} + eErrPassthrough: [_e3l.b] == [1] @test(err, code=eval, + suberr=(code=eval, contains="division by zero", pos=[-4:19]), + suberr=(code=eval, contains="conflicting values", pos=[6:19]), + ) + + // error reported as part of combined eErrPassthrough error + eErrPassthrough: [1, 2] == [1, int & string] + + // Inequality tests + tNeq1: [1, 2] != [1, 3] @test(eq, true) + fNeq2: [1, 2] != [1, 2] @test(eq, false) +} +-- structs.cue -- +@experiment(structcmp) + +structs: eq: { + // Equal structs + t1: {} == {} @test(eq, true) + t2: {a: 1, b: "foo"} == {a: 1, b: "foo"} @test(eq, true) + t3: {a: 1, b: 2} == {b: 2, a: 1} @test(eq, true) // different order + t4: {a: {x: 1, y: 2}} == {a: {x: 1, y: 2}} @test(eq, true) // nested structs + t5: ({a: 1, b: 2, c: 3} & {d: 4}) == {a: 1, b: 2, c: 3, d: 4} @test(eq, true) // unification + t6: {{{{a: 1}}}} == {{a: 1}} @test(eq, true) // embedding + t7: {[string]: int} == {[string]: string} @test(eq, true) + _t8l: *1 | 2 | 3 + t8: {a: _t8l} == {a: 3| *1} @test(eq, true) + + // Non-equal structs + f1: {a: 1, b: "foo"} == {a: 2, b: "foo"} @test(eq, false) + f2: {a: 1, b: "foo"} == {a: 1, c: "foo"} @test(eq, false) + f3: {a: {x: 1}} == {a: {x: 2}} @test(eq, false) + f4: {a: 1, b: 2} == {a: 1} @test(eq, false) + f5: {} == {a: 1} @test(eq, false) + f6: {a: 1} == 1 @test(eq, false) + f7: {a: 1, b?: 2} == {a: 1, b: 2} @test(eq, false) // optional field does not exist + f8: {{{{a: 1}}}} == {{a: 1, b: 2}} @test(eq, false) // embedding + _f9r: *2 | 3 | 4 + f9: {a: *1 | 2 | 3} == {a: _f9r} @test(eq, false) + + // Only test some versions of != recognizing the same code paths are + // followed for ==. + tNe1: {a: 1} != {a: 2} @test(eq, true) + fNe1: {a: 2} != {a: 2} @test(eq, false) +} +ignore: { + t0: {_hidden: 1} == {_hidden: 2} @test(eq, true) + t1: {_hidden: 1} == {} @test(eq, true) + t1: {} == {_hidden: 1} @test(eq, true) + t2: {#def: 1} == {#def: 2} @test(eq, true) + t3: {#def: 1} == {} @test(eq, true) + t4: {} == {#def: 1} @test(eq, true) + t5: {_#hiddenDef: 1} == {_#hiddenDef: 2} @test(eq, true) + t6: {_#hiddenDef: 1} == {} @test(eq, true) + t7: {} == {_#hiddenDef: 1} @test(eq, true) + + f0: {_hidden: 1} != {_hidden: 2} @test(eq, false) + f1: {_hidden: 1} != {} @test(eq, false) + f1: {} != {_hidden: 1} @test(eq, false) + f2: {#def: 1} != {#def: 2} @test(eq, false) + f3: {#def: 1} != {} @test(eq, false) + f4: {} != {#def: 1} @test(eq, false) + f5: {_#hiddenDef: 1} != {_#hiddenDef: 2} @test(eq, false) + f6: {_#hiddenDef: 1} != {} @test(eq, false) + f7: {} != {_#hiddenDef: 1} @test(eq, false) +} +embeddedScalars: { + _one: 1 + _two: 2 + + t1: 1 == {1} @test(eq, true) + t2: [1] == [{1}] @test(eq, true) + t3: {a: 1} == {a: {1}} @test(eq, true) + t4: [_one] == [{_one}] @test(eq, true) + + f1: _one == [{_two}] @test(eq, false) + f2: {a: _two} == {a: {_one}} @test(eq, false) + f3: _one == {_two} @test(eq, false) + f4: [_two] == [{_one}] @test(eq, false) +} + +// Error cases +incomplete: { + _int: int + _string: string + + iErr1: {a!: _int} == {a!: _int} @test(err, code=incomplete, contains="field is required but not present", pos=[0:9]) + iErr2: {a!: _int} == {a!: 1} @test(err, code=incomplete, contains="field is required but not present", pos=[0:9]) + eErr3: {a: _int} == {a: _string} @test(err, code=incomplete|eval, contains="incomplete value int", pos=[0:9]) @test(err:todo, code=eval) + eErr4: {a: 1/0} == {a: 1} @test(err, code=eval, contains="failed arithmetic", pos=[0:9]) // Error passthrough + + eErr5: {a: 1} == {a: _int & _string} @test(err, code=eval, contains="conflicting values", pos=[0:9]) // Error passthrough + iErr6: {a!: 1} == {a: 1} @test(err, code=incomplete, contains="field is required but not present", pos=[0:9]) + eErr7: {a: 1} == {a!: 2} @test(err, code=incomplete, contains="field is required but not present", pos=[0:9]) @test(err:todo, code=eval) // Required cannot match even when concrete. + + // Only test some versions of != recognizing the same code paths are + // followed for ==. + tNe1: {a: 1} != {a: 2} @test(eq, true) + fNe1: {a: 2} != {a: 2} @test(eq, false) +} +-- typediff.cue -- +@experiment(structcmp) + +diffTypes: { + // Right now, all these tests are expected to report a type error. The + // result indicators are assuming, however, that we define equality to be + // total for all concrete values. This means that those marked as false (or + // true for !=) are permanent errors. + + // Tests with different types. + fScalar1: 2 == "s" @test(eq, false) + fScalar2: "s" == 2 @test(eq, false) + fScalar3: true == 2 @test(eq, false) + + fStruct1: {a: 1} == "s" @test(eq, false) + + fList1: 5 == [5] @test(eq, false) + fList2: "ab" == ["a", "b"] @test(eq, false) + fList3: true == [true] @test(eq, false) + fList4: {a: 1} == [{a: 1}] @test(eq, false) + fList5: [1, 2] == 3 @test(eq, false) + fList6: [1, 2] == "ab" @test(eq, false) + fList7: [true] == false @test(eq, false) + fList8: [1, 2] == {a: 1} @test(eq, false) + fList9: [1, 2] == null @test(eq, false) + + // Negated comparisons + tNeList1: [1, 2] != 3 @test(eq, true) + tNeList2: [1, 2] != "ab" @test(eq, true) + + _int: int + _string: string + + // Lists with incompatible element types + iRecursive1: [_int] == [_int] @test(err, code=incomplete, contains="incomplete value int", pos=[0:15]) // can still match, but not concrete + eRecursive2: [_int] == [_string] @test(err, code=incomplete, contains="incomplete value int", pos=[0:15]) @test(err:todo, code=eval) // can never match + fRecursive3: [1, 2] == [1, "2"] @test(eq, false) + tRecursive4: [...int] == [...string] @test(eq, true) + fRecursive5: [1, "a"] == [1, 2] @test(eq, false) + + eNe1: [1, 2] != [_int] @test(err, code=incomplete, contains="incomplete value int", pos=[0:8]) @test(err:todo, code=eval) // length can never match + iNe2: [_int] != [1] @test(err, code=incomplete, contains="incomplete value int", pos=[0:8]) + iNe3: {a: 1} != {a: _int} @test(err, code=incomplete, contains="incomplete value int", pos=[0:8]) + iNe4: {a: _int} != {a: 1} @test(err, code=incomplete, contains="incomplete value int", pos=[0:8]) +} +-- out/compile -- +--- in.cue +{ + numbers: { + tLss: (1 < 2) + tLeq: (1 <= 1.0) + tLeq: (2.0 <= 3) + tEql: (1 == 1.0) + tNeq: (1.0 == 1) + tGeq: (2.0 >= 2) + tGtr: !(2 > 3) + tExpr: (("a" + "b") == "ab") + } +} +--- lists.cue +{ + lists: { + t1: ([] == []) + t2: ([ + 1, + 2, + 3, + ] == [ + 1, + 2, + 3, + ]) + t3: ([ + 1, + "foo", + true, + ] == [ + 1, + "foo", + true, + ]) + t4: ([ + [ + 1, + 2, + ], + [ + 3, + 4, + ], + ] == [ + [ + 1, + 2, + ], + [ + 3, + 4, + ], + ]) + t5: (([ + 1, + ...int, + ] & [ + 1, + 2, + 3, + ]) == [ + 1, + 2, + 3, + ]) + t6: ([ + 1, + ] == ([ + ...1, + ] & [ + _, + ])) + t7: ([ + { + a: 1 + }, + ] == ([ + ...{ + a: 1 + }, + ] & [ + _, + ])) + t8: ([ + { + a: 1 + }, + ] != [ + ...{ + a: 1 + }, + ]) + t9: ([ + ...int, + ] == [ + ...string, + ]) + f1: ([ + 1, + 2, + 3, + ] == [ + 1, + 2, + 4, + ]) + f2: ([ + 1, + 2, + 3, + ] == [ + 1, + 2, + ]) + f3: ([ + 1, + 2, + 3, + ] == [ + 1, + 3, + 2, + ]) + f4: ([] == [ + 1, + ]) + f5: ([ + 1, + 2, + ] == [ + 1, + "2", + ]) + f6: ([ + (*1|2|3), + ] == [ + (*2|3|4), + ]) + eIncompat: ([ + int, + ] == [ + string, + ]) + eErrPassthrough: ([ + (1 / 0), + ] == [ + 1, + ]) + _e3l: {} + eErrPassthrough: ([ + 〈1;_e3l〉.b, + ] == [ + 1, + ]) + eErrPassthrough: ([ + 1, + 2, + ] == [ + 1, + (int & string), + ]) + tNeq1: ([ + 1, + 2, + ] != [ + 1, + 3, + ]) + fNeq2: ([ + 1, + 2, + ] != [ + 1, + 2, + ]) + } +} +--- structs.cue +{ + structs: { + eq: { + t1: ({} == {}) + t2: ({ + a: 1 + b: "foo" + } == { + a: 1 + b: "foo" + }) + t3: ({ + a: 1 + b: 2 + } == { + b: 2 + a: 1 + }) + t4: ({ + a: { + x: 1 + y: 2 + } + } == { + a: { + x: 1 + y: 2 + } + }) + t5: (({ + a: 1 + b: 2 + c: 3 + } & { + d: 4 + }) == { + a: 1 + b: 2 + c: 3 + d: 4 + }) + t6: ({ + { + { + { + a: 1 + } + } + } + } == { + { + a: 1 + } + }) + t7: ({ + [string]: int + } == { + [string]: string + }) + _t8l: (*1|2|3) + t8: ({ + a: 〈1;_t8l〉 + } == { + a: (3|*1) + }) + f1: ({ + a: 1 + b: "foo" + } == { + a: 2 + b: "foo" + }) + f2: ({ + a: 1 + b: "foo" + } == { + a: 1 + c: "foo" + }) + f3: ({ + a: { + x: 1 + } + } == { + a: { + x: 2 + } + }) + f4: ({ + a: 1 + b: 2 + } == { + a: 1 + }) + f5: ({} == { + a: 1 + }) + f6: ({ + a: 1 + } == 1) + f7: ({ + a: 1 + b?: 2 + } == { + a: 1 + b: 2 + }) + f8: ({ + { + { + { + a: 1 + } + } + } + } == { + { + a: 1 + b: 2 + } + }) + _f9r: (*2|3|4) + f9: ({ + a: (*1|2|3) + } == { + a: 〈1;_f9r〉 + }) + tNe1: ({ + a: 1 + } != { + a: 2 + }) + fNe1: ({ + a: 2 + } != { + a: 2 + }) + } + } + ignore: { + t0: ({ + _hidden: 1 + } == { + _hidden: 2 + }) + t1: ({ + _hidden: 1 + } == {}) + t1: ({} == { + _hidden: 1 + }) + t2: ({ + #def: 1 + } == { + #def: 2 + }) + t3: ({ + #def: 1 + } == {}) + t4: ({} == { + #def: 1 + }) + t5: ({ + _#hiddenDef: 1 + } == { + _#hiddenDef: 2 + }) + t6: ({ + _#hiddenDef: 1 + } == {}) + t7: ({} == { + _#hiddenDef: 1 + }) + f0: ({ + _hidden: 1 + } != { + _hidden: 2 + }) + f1: ({ + _hidden: 1 + } != {}) + f1: ({} != { + _hidden: 1 + }) + f2: ({ + #def: 1 + } != { + #def: 2 + }) + f3: ({ + #def: 1 + } != {}) + f4: ({} != { + #def: 1 + }) + f5: ({ + _#hiddenDef: 1 + } != { + _#hiddenDef: 2 + }) + f6: ({ + _#hiddenDef: 1 + } != {}) + f7: ({} != { + _#hiddenDef: 1 + }) + } + embeddedScalars: { + _one: 1 + _two: 2 + t1: (1 == { + 1 + }) + t2: ([ + 1, + ] == [ + { + 1 + }, + ]) + t3: ({ + a: 1 + } == { + a: { + 1 + } + }) + t4: ([ + 〈1;_one〉, + ] == [ + { + 〈2;_one〉 + }, + ]) + f1: (〈0;_one〉 == [ + { + 〈2;_two〉 + }, + ]) + f2: ({ + a: 〈1;_two〉 + } == { + a: { + 〈2;_one〉 + } + }) + f3: (〈0;_one〉 == { + 〈1;_two〉 + }) + f4: ([ + 〈1;_two〉, + ] == [ + { + 〈2;_one〉 + }, + ]) + } + incomplete: { + _int: int + _string: string + iErr1: ({ + a!: 〈1;_int〉 + } == { + a!: 〈1;_int〉 + }) + iErr2: ({ + a!: 〈1;_int〉 + } == { + a!: 1 + }) + eErr3: ({ + a: 〈1;_int〉 + } == { + a: 〈1;_string〉 + }) + eErr4: ({ + a: (1 / 0) + } == { + a: 1 + }) + eErr5: ({ + a: 1 + } == { + a: (〈1;_int〉 & 〈1;_string〉) + }) + iErr6: ({ + a!: 1 + } == { + a: 1 + }) + eErr7: ({ + a: 1 + } == { + a!: 2 + }) + tNe1: ({ + a: 1 + } != { + a: 2 + }) + fNe1: ({ + a: 2 + } != { + a: 2 + }) + } +} +--- typediff.cue +{ + diffTypes: { + fScalar1: (2 == "s") + fScalar2: ("s" == 2) + fScalar3: (true == 2) + fStruct1: ({ + a: 1 + } == "s") + fList1: (5 == [ + 5, + ]) + fList2: ("ab" == [ + "a", + "b", + ]) + fList3: (true == [ + true, + ]) + fList4: ({ + a: 1 + } == [ + { + a: 1 + }, + ]) + fList5: ([ + 1, + 2, + ] == 3) + fList6: ([ + 1, + 2, + ] == "ab") + fList7: ([ + true, + ] == false) + fList8: ([ + 1, + 2, + ] == { + a: 1 + }) + fList9: ([ + 1, + 2, + ] == null) + tNeList1: ([ + 1, + 2, + ] != 3) + tNeList2: ([ + 1, + 2, + ] != "ab") + _int: int + _string: string + iRecursive1: ([ + 〈1;_int〉, + ] == [ + 〈1;_int〉, + ]) + eRecursive2: ([ + 〈1;_int〉, + ] == [ + 〈1;_string〉, + ]) + fRecursive3: ([ + 1, + 2, + ] == [ + 1, + "2", + ]) + tRecursive4: ([ + ...int, + ] == [ + ...string, + ]) + fRecursive5: ([ + 1, + "a", + ] == [ + 1, + 2, + ]) + eNe1: ([ + 1, + 2, + ] != [ + 〈1;_int〉, + ]) + iNe2: ([ + 〈1;_int〉, + ] != [ + 1, + ]) + iNe3: ({ + a: 1 + } != { + a: 〈1;_int〉 + }) + iNe4: ({ + a: 〈1;_int〉 + } != { + a: 1 + }) + } +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/017_null.txtar b/internal/core/compile/testdata/sync/basicrewrite/017_null.txtar new file mode 100644 index 000000000..2dc5a87fd --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/017_null.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +eql: null == null @test(eq, true) +neq: null != null @test(eq, false) +unf: null & null @test(eq, null) + +// errors +eq1: null == 1 @test(eq, false) +eq2: 1 == null @test(eq, false) +ne1: "s" != null @test(eq, true) +call: null() @test(err, code=eval, pos=[0:7], contains="cannot call non-function") +-- out/compile -- +--- in.cue +{ + eql: (null == null) + neq: (null != null) + unf: (null & null) + eq1: (null == 1) + eq2: (1 == null) + ne1: ("s" != null) + call: null() +} diff --git a/internal/core/compile/testdata/sync/basicrewrite/018_self-reference_cycles.txtar b/internal/core/compile/testdata/sync/basicrewrite/018_self-reference_cycles.txtar new file mode 100644 index 000000000..45368c691 --- /dev/null +++ b/internal/core/compile/testdata/sync/basicrewrite/018_self-reference_cycles.txtar @@ -0,0 +1,184 @@ +-- in.cue -- +a: b - 100 @test(err, code=cycle) +b: a + 100 @test(err, code=cycle) + +c: [c[1], c[0]] @test(eq, [_, _]) + +d: e - 1 @test(eq, 1) +e: 1 + d +e: *2 | 0 @test(eq, *2 | 0) +-- disjunction.cue -- +oneway: { + t1: { + a: *1 | int + a: b + 1 + b: "b" and (>"b" & string) get equated when at least the task has + // completed. + #a + #a: <"a" | >"b" | string + #a: <"a" | >"b" | string // conjuncts 127 disjuncts 120 + #a: <"a" | >"b" | string // conjuncts 219 disjuncts 210 (+92; +90) + #a: <"a" | >"b" | string // conjuncts 311 disjuncts 300 (+92; +90) + #a: <"a" | >"b" | string // conjuncts 403 disjuncts 390 (+92; +90) + #a: <"a" | >"b" | string // conjuncts 495 disjuncts 480 (+92; +90) +} +@test(eq, at=issue3610, { + <"a" + #a: <"a" | >"b" | string +} | { + >"b" + #a: <"a" | >"b" | string +} | { + string + #a: <"a" | >"b" | string +}) + +-- out/compile -- +--- in.cue +{ + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + pat: ({ + [string]: 1 + }|{ + a: 2 + }) + list: ([ + 1, + ]|[ + 2, + ]|[ + 3, + ]|[ + 4, + ]) + list: ([ + 1, + ]|[ + 2, + ]|[ + 3, + ]|[ + 4, + ]) + list: ([ + 1, + ]|[ + 2, + ]|[ + 3, + ]|[ + 4, + ]) + list: ([ + 1, + ]|[ + 2, + ]|[ + 3, + ]|[ + 4, + ]) + list: ([ + 1, + ]|[ + 2, + ]|[ + 3, + ]|[ + 4, + ]) + list: ([ + 1, + ]|[ + 2, + ]|[ + 3, + ]|[ + 4, + ]) + list: ([ + 1, + ]|[ + 2, + ]|[ + 3, + ]|[ + 4, + ]) + issue3610: { + 〈0;#a〉 + #a: (<"a"|>"b"|string) + #a: (<"a"|>"b"|string) + #a: (<"a"|>"b"|string) + #a: (<"a"|>"b"|string) + #a: (<"a"|>"b"|string) + #a: (<"a"|>"b"|string) + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/disjunction.txtar b/internal/core/compile/testdata/sync/benchmarks/disjunction.txtar new file mode 100644 index 000000000..23af50b09 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/disjunction.txtar @@ -0,0 +1,139 @@ +// Triggering recomputation of disjunctions on each branch results +// in exponential run time. Ensure this does not happen. +-- in.cue -- +x: a0: {} +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int +x: [_]: f: *1 | int + +x: { + a0: {} + @test(eq, {a0: {f: *1 | int}}) +} +-- out/compile -- +--- in.cue +{ + x: { + a0: {} + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + [_]: { + f: (*1|int) + } + } + x: { + a0: {} + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/inlinedisjunction.txtar b/internal/core/compile/testdata/sync/benchmarks/inlinedisjunction.txtar new file mode 100644 index 000000000..f16be32fe --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/inlinedisjunction.txtar @@ -0,0 +1,60 @@ +-- in.cue -- +#def: { + {} | {c: string} + {} | {c: string} + {} | {c: string} + {} | {c: string} + {} | {c: string} + {} | {c: string} + {} | {c: string} + {} | {c: string} + {} | {c: string} + {} | {a: string} +} +x: #def +x: c: "foo" + +@test(eq, { + #def: {} | {a: string} | {c: string} | {c: string, a: string} + x: {c: "foo"} | {c: "foo", a: string} +}) +-- out/compile -- +--- in.cue +{ + #def: { + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + c: string + }) + ({}|{ + a: string + }) + } + x: 〈0;#def〉 + x: { + c: "foo" + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue1684.txtar b/internal/core/compile/testdata/sync/benchmarks/issue1684.txtar new file mode 100644 index 000000000..f6da1deed --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue1684.txtar @@ -0,0 +1,165 @@ +# Tests that recursive secret/nested-map structures (#secrets) unify correctly +# without exponential conjunct expansion. Performance regression originally +# caused quadratic growth when #secrets disjunctions were repeatedly applied. +# https://cuelang.org/issue/1684 + +// TODO: significantly reduce the number of counts in this evaluation. +-- in.cue -- +#Secret: { + $secret: id: string +} +#secrets: #Secret | {[string]: #secrets} + +out: #secrets & { + FOO: $secret: id: "100" + ONE: TWO: THREE: $secret: id: "123" +} + +#Secret: { + $secret: _id: string +} +#secrets: #Secret | {[string]: #secrets} + +out: #secrets & { + FOO: $secret: _id: "100" + ONE: TWO: THREE: $secret: _id: "123" +} @test(eq, { + FOO: $secret: {id: "100", _id: "100"} + ONE: TWO: THREE: $secret: {id: "123", _id: "123"} +}) + +-- perf.cue -- +nestedCross: closed: { + #D: {id: string} | {[string]: #D} + #D: {id: string} | {[string]: #D} + #D: {id: string} | {[string]: #D} +} @test(eq, {#D: {id: string} | {}}) + +nestedCross: open: { + D: {id: string} | {[string]: D} + D: {id: string} | {[string]: D} + D: {id: string} | {[string]: D} +} @test(eq, {D: {id: string} | {}}) + +// TODO(perf): support this case. This is currently exponential, although the +// tight bound on the detection of structural cycles mitigates the situation. +// +// An additional improvement would be to stop processing disjunctions if we see +// there are more than two solutions. +nestedClosed: passing: { + D: {id: {}} | {[string]: D} + D: {id: {}} | {[string]: D} + D: {id: {}} | {[string]: D} +} @test(eq, {D: {id: {}} | {}}) +-- out/compile -- +--- in.cue +{ + #Secret: { + $secret: { + id: string + } + } + #secrets: (〈0;#Secret〉|{ + [string]: 〈1;#secrets〉 + }) + out: (〈0;#secrets〉 & { + FOO: { + $secret: { + id: "100" + } + } + ONE: { + TWO: { + THREE: { + $secret: { + id: "123" + } + } + } + } + }) + #Secret: { + $secret: { + _id: string + } + } + #secrets: (〈0;#Secret〉|{ + [string]: 〈1;#secrets〉 + }) + out: (〈0;#secrets〉 & { + FOO: { + $secret: { + _id: "100" + } + } + ONE: { + TWO: { + THREE: { + $secret: { + _id: "123" + } + } + } + } + }) +} +--- perf.cue +{ + nestedCross: { + closed: { + #D: ({ + id: string + }|{ + [string]: 〈1;#D〉 + }) + #D: ({ + id: string + }|{ + [string]: 〈1;#D〉 + }) + #D: ({ + id: string + }|{ + [string]: 〈1;#D〉 + }) + } + } + nestedCross: { + open: { + D: ({ + id: string + }|{ + [string]: 〈1;D〉 + }) + D: ({ + id: string + }|{ + [string]: 〈1;D〉 + }) + D: ({ + id: string + }|{ + [string]: 〈1;D〉 + }) + } + } + nestedClosed: { + passing: { + D: ({ + id: {} + }|{ + [string]: 〈1;D〉 + }) + D: ({ + id: {} + }|{ + [string]: 〈1;D〉 + }) + D: ({ + id: {} + }|{ + [string]: 〈1;D〉 + }) + } + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue2176.txtar b/internal/core/compile/testdata/sync/benchmarks/issue2176.txtar new file mode 100644 index 000000000..a570a55b7 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue2176.txtar @@ -0,0 +1,108 @@ +# Tests that a sliding-window computation over string characters (finding unique +# character combinations of a given length) evaluates efficiently. The nested +# let-bindings and list comprehensions triggered performance regressions between +# CUE versions. +# https://cuelang.org/issue/2176 +-- in.cue -- +import ( + "strings" + "list" +) + +#Datastream: { + message: string + message: strings.MinRunes(4) + + marker: { + length: int + position: { + let characters = strings.Split(message, "") + let unique_combinations = { + // begin computation once we have more than x number of characters. + for i, _ in characters if i >= length-1 { + // this line is causing an increased evaluation time between cue versions. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + let combination = list.Slice(characters, i-length+1, i+1) + + // last x number of characters are not unique. + if list.UniqueItems(list.Slice(characters, i-length+1, i+1)) { + "\(i+1)": combination + } + } + } + [for i, _ in unique_combinations {i}][0] + } + } +} + +input_short: """ + mjqjpqmgbljsphdztnvjfqwrcgsmlb + """ +input_long: """ + qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw + """ + +input: *input_short | input_long + +datastream: #Datastream & {message: input} + +output: [string]: string +output: { + "1": (datastream & {marker: length: 4}).marker.position + "2": (datastream & {marker: length: 14}).marker.position +} @test(eq, {"1": {"7"}, "2": {"19"}}) +// NOTE: output contains lots of expanded lets. Use @test(debug) to view. + +@test(eq,at=datastream, { + message: *"mjqjpqmgbljsphdztnvjfqwrcgsmlb" | "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" + marker: {length: int, position: {_|_}} +}) + +-- out/compile -- +--- in.cue +{ + #Datastream: { + message: string + message: 〈import;strings〉.MinRunes(4) + marker: { + length: int + position: { + let characters#1 = 〈import;strings〉.Split(〈2;message〉, "") + let unique_combinations#2multi = { + for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { + let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) + if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { + "\((〈2;i〉 + 1))": 〈1;let combination#3〉 + } + } + } + [ + for i, _ in 〈1;let unique_combinations#2〉 { + 〈1;i〉 + }, + ][0] + } + } + } + input_short: "mjqjpqmgbljsphdztnvjfqwrcgsmlb" + input_long: "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" + input: (*〈0;input_short〉|〈0;input_long〉) + datastream: (〈0;#Datastream〉 & { + message: 〈1;input〉 + }) + output: { + [string]: string + } + output: { + "1": (〈1;datastream〉 & { + marker: { + length: 4 + } + }).marker.position + "2": (〈1;datastream〉 & { + marker: { + length: 14 + } + }).marker.position + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue3307.txtar b/internal/core/compile/testdata/sync/benchmarks/issue3307.txtar new file mode 100644 index 000000000..039656da2 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue3307.txtar @@ -0,0 +1,57 @@ +# Tests that a large `if` guard on an incomplete bool does not trigger +# O(n) work per field inside the conditional block. Each field in the +# guarded struct should not independently re-evaluate the condition. +# https://cuelang.org/issue/3307 +-- in.cue -- +@test(err, code=incomplete, contains="incomplete bool") +if _request.enabled { + r1: { + k1: 0 + k2: 0 + k3: 0 + k4: 0 + k5: 0 + k6: 0 + k7: 0 + k8: 0 + k9: 0 + k10: 0 + k11: 0 + k12: 0 + k13: 0 + k14: 0 + k15: 0 + k16: 0 + k17: 0 + } +} + +_request: enabled: _ +-- out/compile -- +--- in.cue +{ + if 〈0;_request〉.enabled { + r1: { + k1: 0 + k2: 0 + k3: 0 + k4: 0 + k5: 0 + k6: 0 + k7: 0 + k8: 0 + k9: 0 + k10: 0 + k11: 0 + k12: 0 + k13: 0 + k14: 0 + k15: 0 + k16: 0 + k17: 0 + } + } + _request: { + enabled: _ + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue3334.txtar b/internal/core/compile/testdata/sync/benchmarks/issue3334.txtar new file mode 100644 index 000000000..a8f855f77 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue3334.txtar @@ -0,0 +1,319 @@ +# Tests that a single top-level disjunction (null | Schema) applied to a deeply +# nested struct does not cause exponential evaluation. Schema is a recursive +# JSON-Schema-like definition with many optional disjunctive fields. +# https://cuelang.org/issue/3334 +-- in.cue -- +// Single disjunction at the top. +x?: null | Schema +x: properties: { + disableSelfServiceScrape: {} + dnsConfig: { + properties: { + nameservers: {} + } + } + podDisruptionBudget: { + properties: { + maxUnavailable: {} + minAvailable: { + anyOf: [{}, {}] + } + labels: {} + } + } +} + +Schema: { + title?: string + $ref?: null | string + enum?: [...] + required?: [...string] + items?: null | _ + anyOf?: [...Schema] + allOf?: [...Schema] + oneOf?: [...Schema] + not?: null | Schema + properties?: [string]: Schema + additionalProperties?: null | _ + patternProperties?: [string]: Schema + dependencies?: [string]: _ + additionalItems?: null | _ + definitions?: [string]: _ + externalDocs?: null | { + description?: string + url?: string + } + example?: null | _ + nullable?: bool +} + +@test(eq, at=x, { + properties: { + disableSelfServiceScrape: { + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + properties?: {} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + } + dnsConfig: { + properties: { + nameservers: { + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + properties?: {} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + } + } + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + } + podDisruptionBudget: { + properties: { + maxUnavailable: { + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + properties?: {} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + } + minAvailable: { + anyOf: [{ + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + properties?: {} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + }, + { + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + properties?: {} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + }] + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + properties?: {} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + } + labels: { + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + properties?: {} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + } + } + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool + } + } + title?: string + $ref?: null | string + enum?: [] + required?: [] + items?: null | _ + anyOf?: [] + allOf?: [] + oneOf?: [] + not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null | {title?: string, $ref?: null | string, enum?: [], required?: [], items?: null | _, anyOf?: [], allOf?: [], oneOf?: [], not?: null, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool}, properties?: {}, additionalProperties?: null | _, patternProperties?: {}, dependencies?: {}, additionalItems?: null | _, definitions?: {}, externalDocs?: null | {description?: string, url?: string}, example?: null | _, nullable?: bool} + additionalProperties?: null | _ + patternProperties?: {} + dependencies?: {} + additionalItems?: null | _ + definitions?: {} + externalDocs?: null | {description?: string, url?: string} + example?: null | _ + nullable?: bool +}) +-- out/compile -- +--- in.cue +{ + x?: (null|〈0;Schema〉) + x: { + properties: { + disableSelfServiceScrape: {} + dnsConfig: { + properties: { + nameservers: {} + } + } + podDisruptionBudget: { + properties: { + maxUnavailable: {} + minAvailable: { + anyOf: [ + {}, + {}, + ] + } + labels: {} + } + } + } + } + Schema: { + title?: string + $ref?: (null|string) + enum?: [ + ..., + ] + required?: [ + ...string, + ] + items?: (null|_) + anyOf?: [ + ...〈2;Schema〉, + ] + allOf?: [ + ...〈2;Schema〉, + ] + oneOf?: [ + ...〈2;Schema〉, + ] + not?: (null|〈1;Schema〉) + properties?: { + [string]: 〈2;Schema〉 + } + additionalProperties?: (null|_) + patternProperties?: { + [string]: 〈2;Schema〉 + } + dependencies?: { + [string]: _ + } + additionalItems?: (null|_) + definitions?: { + [string]: _ + } + externalDocs?: (null|{ + description?: string + url?: string + }) + example?: (null|_) + nullable?: bool + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue3514.txtar b/internal/core/compile/testdata/sync/benchmarks/issue3514.txtar new file mode 100644 index 000000000..d2af282e7 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue3514.txtar @@ -0,0 +1,93 @@ +# Tests that matching a data value against a large matchIf schema (with many +# nested disjunctions and required fields) completes in bounded time. The +# schema models a Dependabot config; the original issue caused a hang. +# https://cuelang.org/issue/3514 +-- in.cue -- +import "list" + +_schema & _data +_data: { + "updates": [ + { + "schedule": { + "interval": "daily" + } + } + ], +} + +_schema: { + matchIf( + null | bool | number | string | [...] | {"enable-beta-ecosystems"!: true}, + _, + null | bool | number | string | [...] | { + "updates"?: null | bool | number | string | [...null | bool | number | string | [...] | {...}] | {...} + ... + } + ) & { + "updates"!: [...#update] + } + + #update: { + "schedule"!: { + "timezone"?: #timezone + ... + } + ... + } + + // This was originally a list of 571 explicit time zones. + #timezone: or([for i in list.Range(0, 571, 1) {"\(i)"}]) +} + +@test(eq, at=_data, { updates: [{schedule: {interval: "daily"}}] }) +-- out/compile -- +--- in.cue +{ + (〈0;_schema〉 & 〈0;_data〉) + _data: { + updates: [ + { + schedule: { + interval: "daily" + } + }, + ] + } + _schema: { + (matchIf((null|bool|number|string|[ + ..., + ]|{ + "enable-beta-ecosystems"!: true + }), _, (null|bool|number|string|[ + ..., + ]|{ + updates?: (null|bool|number|string|[ + ...(null|bool|number|string|[ + ..., + ]|{ + ... + }), + ]|{ + ... + }) + ... + })) & { + updates!: [ + ...〈2;#update〉, + ] + }) + #update: { + schedule!: { + timezone?: 〈2;#timezone〉 + ... + } + ... + } + #timezone: or([ + for _, i in 〈import;list〉.Range(0, 571, 1) { + "\(〈1;i〉)" + }, + ]) + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue3517.txtar b/internal/core/compile/testdata/sync/benchmarks/issue3517.txtar new file mode 100644 index 000000000..6f8a9022f --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue3517.txtar @@ -0,0 +1,132 @@ +# Tests that cyclic arithmetic constraints (#TimeSpan: start = end - duration +# etc.) within a task set unify and report errors correctly. The original +# issue involved a hang or very slow evaluation with interdependent tasks. +# https://cuelang.org/issue/3517 +-- main.cue -- +package p + +#TimeSpan: { + start: float + duration: float + end: float + + start: end - duration + duration: end - start + end: start + duration + + start: <=end +} + +#Task: { + action: string + timeSpan: #TimeSpan +} + +#TaskSet: { + action: string + #tasks: [string]: #Task + tasks: [for _, v in #tasks {v}] + tasks: [...#Task] + timeSpan?: #TimeSpan +} + +#T1: #Task & { + action: "Task 1" + timeSpan: #TimeSpan & { + duration: 4.2 + } +} + +#T2: #Task & { + action: "Task 2" + timeSpan: #TimeSpan & { + duration: 120.0 + } +} + +ts: #TaskSet +ts: this={ + action: "Task 1 and Task 2" + #tasks: { + t1: #T1 & { + timeSpan: end: this.#tasks.t2.timeSpan.start + } + t2: #T2 & { + timeSpan: end: 119 // this.timeSpan.end + } + } + timeSpan: start: this.#tasks.t1.timeSpan.start +} +@test(err, at=ts.#tasks.t1, code=eval, path=ts.#tasks.t2.timeSpan.end, + contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[119, float, int, float], + pos=[-49:12, -18:12, -6:7, -5:19], +) +@test(err, at=ts.#tasks.t2, code=eval, path=ts.#tasks.t2.timeSpan.end, + contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[119, float, int, float], + pos=[-54:12, -23:12, -11:7, -10:19], +) +-- out/compile -- +--- main.cue +{ + #TimeSpan: { + start: float + duration: float + end: float + start: (〈0;end〉 - 〈0;duration〉) + duration: (〈0;end〉 - 〈0;start〉) + end: (〈0;start〉 + 〈0;duration〉) + start: <=〈0;end〉 + } + #Task: { + action: string + timeSpan: 〈1;#TimeSpan〉 + } + #TaskSet: { + action: string + #tasks: { + [string]: 〈2;#Task〉 + } + tasks: [ + for _, v in 〈1;#tasks〉 { + 〈1;v〉 + }, + ] + tasks: [ + ...〈2;#Task〉, + ] + timeSpan?: 〈1;#TimeSpan〉 + } + #T1: (〈0;#Task〉 & { + action: "Task 1" + timeSpan: (〈1;#TimeSpan〉 & { + duration: 4.2 + }) + }) + #T2: (〈0;#Task〉 & { + action: "Task 2" + timeSpan: (〈1;#TimeSpan〉 & { + duration: 120.0 + }) + }) + ts: 〈0;#TaskSet〉 + ts: { + action: "Task 1 and Task 2" + #tasks: { + t1: (〈2;#T1〉 & { + timeSpan: { + end: 〈4〉.#tasks.t2.timeSpan.start + } + }) + t2: (〈2;#T2〉 & { + timeSpan: { + end: 119 + } + }) + } + timeSpan: { + start: 〈2〉.#tasks.t1.timeSpan.start + } + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue3633.txtar b/internal/core/compile/testdata/sync/benchmarks/issue3633.txtar new file mode 100644 index 000000000..b13555cfe --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue3633.txtar @@ -0,0 +1,257 @@ +# Tests that recursive schema definitions with many optional fields (e.g. a +# JSON-Schema-like #Schema with properties/required) do not cause exponential +# conjunct blowup when embedded or unified. The `reduced` case validates basic +# self-embedding; `full` validates a realistic JSON-Schema-style structure. +# https://cuelang.org/issue/3633 +-- in.cue -- +reduced: { + #Schema: { + a?: null | bool | string | int | #Schema + b?: null | bool | string | int | #Schema + c?: null | bool | string | int | #Schema + d?: null | bool | string | int | #Schema + e?: null | bool | string | int | #Schema + f?: null | bool | string | int | #Schema + } + + out: #Schema & { #Schema } +} +full: { + #Schema: { + required?: [...string] + properties?: [string]: null | bool | string | [...int] | #Schema + + foo00?: null | bool | string | [...int] | {string: int32} + foo01?: null | bool | string | [...int] | {string: int32} + foo02?: null | bool | string | [...int] | {string: int32} + foo03?: null | bool | string | [...int] | {string: int32} + foo04?: null | bool | string | [...int] | {string: int32} + foo05?: null | bool | string | [...int] | {string: int32} + foo06?: null | bool | string | [...int] | {string: int32} + foo07?: null | bool | string | [...int] | {string: int32} + foo08?: null | bool | string | [...int] | {string: int32} + foo09?: null | bool | string | [...int] | {string: int32} + foo10?: null | bool | string | [...int] | {string: int32} + foo11?: null | bool | string | [...int] | {string: int32} + foo12?: null | bool | string | [...int] | {string: int32} + foo13?: null | bool | string | [...int] | {string: int32} + foo14?: null | bool | string | [...int] | {string: int32} + foo15?: null | bool | string | [...int] | {string: int32} + foo16?: null | bool | string | [...int] | {string: int32} + foo17?: null | bool | string | [...int] | {string: int32} + foo18?: null | bool | string | [...int] | {string: int32} + foo19?: null | bool | string | [...int] | {string: int32} + } + + out: [...#Schema] & [{ + #Schema + properties: foo: required: ["bar", "baz"] + }] +} + +// TODO(inline): +// 1) format better +// 2) identify repeated elements +// 3) leave at= flag at begginning when generating. +@test(eq, at=full.out, [{ + properties: { + foo: { + required: ["bar", "baz"] + properties?: {} + foo00?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo01?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo02?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo03?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo04?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo05?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo06?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo07?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo08?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo09?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo10?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo11?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo12?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo13?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo14?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo15?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo16?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo17?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo18?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo19?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + } + } + required?: [] + foo00?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo01?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo02?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo03?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo04?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo05?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo06?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo07?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo08?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo09?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo10?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo11?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo12?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo13?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo14?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo15?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo16?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo17?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo18?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} + foo19?: null | bool | string | [] | {string: >=-2147483648 & <=2147483647 & int} +}]) +@test(eq, { + a?: null | bool | string | int | {a?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, b?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, c?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, d?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, e?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, f?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}} + b?: null | bool | string | int | {a?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, b?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, c?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, d?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, e?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, f?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}} + c?: null | bool | string | int | {a?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, b?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, c?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, d?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, e?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, f?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}} + d?: null | bool | string | int | {a?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, b?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, c?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, d?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, e?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, f?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}} + e?: null | bool | string | int | {a?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, b?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, c?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, d?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, e?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, f?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}} + f?: null | bool | string | int | {a?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, b?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, c?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, d?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, e?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}, f?: null | bool | string | int | {a?: null | bool | string | int, b?: null | bool | string | int, c?: null | bool | string | int, d?: null | bool | string | int, e?: null | bool | string | int, f?: null | bool | string | int}} +}, at=reduced.out) + +-- out/compile -- +--- in.cue +{ + reduced: { + #Schema: { + a?: (null|bool|string|int|〈1;#Schema〉) + b?: (null|bool|string|int|〈1;#Schema〉) + c?: (null|bool|string|int|〈1;#Schema〉) + d?: (null|bool|string|int|〈1;#Schema〉) + e?: (null|bool|string|int|〈1;#Schema〉) + f?: (null|bool|string|int|〈1;#Schema〉) + } + out: (〈0;#Schema〉 & { + 〈1;#Schema〉 + }) + } + full: { + #Schema: { + required?: [ + ...string, + ] + properties?: { + [string]: (null|bool|string|[ + ...int, + ]|〈2;#Schema〉) + } + foo00?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo01?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo02?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo03?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo04?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo05?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo06?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo07?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo08?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo09?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo10?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo11?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo12?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo13?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo14?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo15?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo16?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo17?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo18?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + foo19?: (null|bool|string|[ + ...int, + ]|{ + string: &(int, >=-2147483648, <=2147483647) + }) + } + out: ([ + ...〈1;#Schema〉, + ] & [ + { + 〈2;#Schema〉 + properties: { + foo: { + required: [ + "bar", + "baz", + ] + } + } + }, + ]) + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/issue572.txtar b/internal/core/compile/testdata/sync/benchmarks/issue572.txtar new file mode 100644 index 000000000..9c0849abd --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/issue572.txtar @@ -0,0 +1,36 @@ +# Tests that a large comprehension-generated struct (1500 entries) evaluates +# in linear time rather than exhibiting quadratic or worse blowup from +# repeated unification of the accumulating result. +# https://cuelang.org/issue/572 +-- in.cue -- +package p + +import "list" + +_entries: [for i in list.Range(1, 1500, 1) {i}] +unified: { + for entry in _entries { + "\(entry)": true + } +} + +// TODO(inline): _entries$p and [0] don't work here. +// @test(eq, at=_entries$p[0], 1) +// @test(eq, at=_entries$[1498], 1499) +@test(eq, at=unified."1", true) +@test(eq, at=unified."1499", true) + +-- out/compile -- +--- in.cue +{ + _entries(:p): [ + for _, i in 〈import;list〉.Range(1, 1500, 1) { + 〈1;i〉 + }, + ] + unified: { + for _, entry in 〈1;_entries(:p)〉 { + "\(〈1;entry〉)": true + } + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/listdedup.txtar b/internal/core/compile/testdata/sync/benchmarks/listdedup.txtar new file mode 100644 index 000000000..cc0b1919b --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/listdedup.txtar @@ -0,0 +1,161 @@ +# Tests that repeated references to the same type in a struct (e.g. #ref twice, +# _ | {} twice) do not cause exponential blowup in conjuncts/disjuncts. +# https://cuelang.org/issue/758 +# https://cuelang.org/issue/1044 + +// TODO(perf): reduce number of conjunctions and disjunctions. +-- in.cue -- +A: #Task +B: #steps: #Script & {mount: [A]} +C: #steps: #Script & {mount: [B]} + +#Script: {mount: [...#Task]} @test(eq, {mount: []}) + +#Task: { + // Without the proper constructs, repeating the below results + // in exponential runtime. + #ref + #ref + _ | {} + _ | {} + #steps: #Script + ... +} + +#ref: {a: 1} | {b: 2} @test(eq, {a: 1} | {b: 2}) + +@test(eq, { + A: {#steps: {mount: []}, a: 1} | {#steps: {mount: []}, b: 2} + B: { + #steps: { + mount: [{#steps: {mount: []}, a: 1} | {#steps: {mount: []}, b: 2}] + } + } + C: { + #steps: { + mount: [{#steps: { + mount: [{#steps: {mount: []}, a: 1} | {#steps: {mount: []}, b: 2}] +}, a: 1} | {#steps: { + mount: [{#steps: {mount: []}, a: 1} | {#steps: {mount: []}, b: 2}] +}, b: 2}] + } + } + #Script: {mount: []} + #Task: {#steps: {mount: []}, a: 1} | {#steps: {mount: []}, b: 2} + #ref: {a: 1} | {b: 2} +}) +// TODO(inline): replace @test(debug) with @test(shareID=...) once the +// framework supports asserting sharing inside disjunction members. All +// ~(#Script) occurrences here are inside disjunct arms (A, #Task, +// B.#steps.mount[0]) — the CUE API creates a fresh vertex when projecting +// a field through a disjunction boundary, so pointer-identity checks fail. +@test(debug, """ + (struct){ + A: (#struct){ |((#struct){ + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + b: (int){ 2 } + }) } + B: (struct){ + #steps: (#struct){ + mount: (#list){ + 0: (#struct){ |((#struct){ + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + b: (int){ 2 } + }) } + } + } + } + C: (struct){ + #steps: (#struct){ + mount: (#list){ + 0: (#struct){ |((#struct){ + #steps: (#struct){ + mount: (#list){ + 0: (#struct){ |((#struct){ + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + b: (int){ 2 } + }) } + } + } + a: (int){ 1 } + }, (#struct){ + #steps: (#struct){ + mount: (#list){ + 0: (#struct){ |((#struct){ + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + b: (int){ 2 } + }) } + } + } + b: (int){ 2 } + }) } + } + } + } + #Script: (#struct){ + mount: (list){ + } + } + #Task: (#struct){ |((#struct){ + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + b: (int){ 2 } + }) } + #ref: (#struct){ |((#struct){ + a: (int){ 1 } + }, (#struct){ + b: (int){ 2 } + }) } + } + """) +-- out/compile -- +--- in.cue +{ + A: 〈0;#Task〉 + B: { + #steps: (〈1;#Script〉 & { + mount: [ + 〈3;A〉, + ] + }) + } + C: { + #steps: (〈1;#Script〉 & { + mount: [ + 〈3;B〉, + ] + }) + } + #Script: { + mount: [ + ...〈2;#Task〉, + ] + } + #Task: { + 〈1;#ref〉 + 〈1;#ref〉 + (_|{}) + (_|{}) + #steps: 〈1;#Script〉 + ... + } + #ref: ({ + a: 1 + }|{ + b: 2 + }) +} diff --git a/internal/core/compile/testdata/sync/benchmarks/listdisj.txtar b/internal/core/compile/testdata/sync/benchmarks/listdisj.txtar new file mode 100644 index 000000000..54077f40f --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/listdisj.txtar @@ -0,0 +1,47 @@ +# Tests that a recursive list-typed disjunction (#T) shared across multiple +# fields does not cause exponential blowup. x and y both reference #T and +# should share the same vertex rather than being independently expanded. +# https://cuelang.org/issue/1940 +-- in.cue -- +#T: + ["a", #T] | + ["b", #T] | + ["c", #T] | + ["d", ...#T] @test(shareID=T) + +x: #T @test(shareID=T) +y: #T @test(shareID=T) +z: #T @test(shareID=T) +v: #T @test(shareID=T) + +#X: x @test(shareID=T) +#X: y +#X: z +#X: v +#X: #T +-- out/compile -- +--- in.cue +{ + #T: ([ + "a", + 〈1;#T〉, + ]|[ + "b", + 〈1;#T〉, + ]|[ + "c", + 〈1;#T〉, + ]|[ + "d", + ...〈1;#T〉, + ]) + x: 〈0;#T〉 + y: 〈0;#T〉 + z: 〈0;#T〉 + v: 〈0;#T〉 + #X: 〈0;x〉 + #X: 〈0;y〉 + #X: 〈0;z〉 + #X: 〈0;v〉 + #X: 〈0;#T〉 +} diff --git a/internal/core/compile/testdata/sync/benchmarks/mergeddisjunction.txtar b/internal/core/compile/testdata/sync/benchmarks/mergeddisjunction.txtar new file mode 100644 index 000000000..ea5b1a2d1 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/mergeddisjunction.txtar @@ -0,0 +1,87 @@ +// Here one comprehension creates a number of distinct values, each of which +// with a disjunction, then another comprehension maps them back to the +// same value, creating a large number of disjunctions. +// +// The disjunctions cannot be identified as equal in the general case. If no +// care is taken, disjunction elimination will be exponential, causing over +// a billion disjuncts to process in the below example. With the proper +// optimizations, there is a small, constant number of disjunction ops per +// disjunct. +// +// Issue #651 +-- in.cue -- +list: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, +] + +a: [X=string]: text: *"default" | string +a: { + for i in list { + "\(i)": text: string + } +} + +b: { + for x in a { + "\(x.text)": {text: x.text} + } +} @test(eq, {default: {text: *"default" | string}}) +-- out/compile -- +--- in.cue +{ + list: [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + ] + a: { + [string]: { + text: (*"default"|string) + } + } + a: { + for _, i in 〈1;list〉 { + "\(〈1;i〉)": { + text: string + } + } + } + b: { + for _, x in 〈1;a〉 { + "\(〈1;x〉.text)": { + text: 〈2;x〉.text + } + } + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/share.txtar b/internal/core/compile/testdata/sync/benchmarks/share.txtar new file mode 100644 index 000000000..400be1fac --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/share.txtar @@ -0,0 +1,48 @@ +See https://en.wikipedia.org/wiki/Billion_lauHs_attack. +-- in.cue -- +f: [g, g, g, g, g, g, g] @test(shareID=G, at=0) @test(shareID=G, at=3) @test(shareID=G, at=6) +g: [h, h, h, h, h, h, h] @test(shareID=G) @test(shareID=H, at=0) @test(shareID=H, at=3) @test(shareID=H, at=6) +h: [i, i, i, i, i, i, i] @test(shareID=H) @test(shareID=I, at=0) @test(shareID=I, at=3) @test(shareID=I, at=6) +i: [j, j, j, j, j, j, j] @test(shareID=I) +j: 1 +-- out/compile -- +--- in.cue +{ + f: [ + 〈1;g〉, + 〈1;g〉, + 〈1;g〉, + 〈1;g〉, + 〈1;g〉, + 〈1;g〉, + 〈1;g〉, + ] + g: [ + 〈1;h〉, + 〈1;h〉, + 〈1;h〉, + 〈1;h〉, + 〈1;h〉, + 〈1;h〉, + 〈1;h〉, + ] + h: [ + 〈1;i〉, + 〈1;i〉, + 〈1;i〉, + 〈1;i〉, + 〈1;i〉, + 〈1;i〉, + 〈1;i〉, + ] + i: [ + 〈1;j〉, + 〈1;j〉, + 〈1;j〉, + 〈1;j〉, + 〈1;j〉, + 〈1;j〉, + 〈1;j〉, + ] + j: 1 +} diff --git a/internal/core/compile/testdata/sync/benchmarks/sharefg.txtar b/internal/core/compile/testdata/sync/benchmarks/sharefg.txtar new file mode 100644 index 000000000..602611fb2 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/sharefg.txtar @@ -0,0 +1,434 @@ +# This file has fine-grained sharing tests. +-- in.cue -- +// In each case, the number of output nodes should be linear in the input size. +// +// This means that in each case, the next line should not retrigger the +// computation of the previous field. + +// 26 Nodes computed: +// f1: 5 +// f2+: +3 each +binexpr: { + f1: { out: x: 2 } + f2: { out: x: f1.out.x + 1 } + f3: { out: x: f2.out.x + 1 } + f4: { out: x: f3.out.x + 1 } + f5: { out: x: f4.out.x + 1 } + f6: { out: x: f5.out.x + 1 } + f7: { out: x: f6.out.x + 1 } + f8: { out: x: f7.out.x + 1 } @test(eq, {out: {x: 9}}) +} + +// 26 Nodes computed: +// f1: 5 +// f2+: +3 each +parenthesized: { + f1: { out: x: 2 } + f2: { out: x: (f1.out).x + 1 } + f3: { out: x: (f2.out).x + 1 } + f4: { out: x: (f3.out).x + 1 } + f5: { out: x: (f4.out).x + 1 } + f6: { out: x: (f5.out).x + 1 } + f7: { out: x: (f6.out).x + 1 } + f8: { out: x: (f7.out).x + 1 } @test(eq, {out: {x: 9}}) +} + +// TODO(perf): fix +// 82 Nodes computed [O(n^2)]: +// f1: 5 +// fn: +(n*2 + 1) +// SHOULD BE: +// 26 Nodes computed: +// f1: 5 +// f2+: +3 each +embedded: { + f1: { out: x: 2 } + f2: { out: x: {f1.out}.x + 1 } + f3: { out: x: {f2.out}.x + 1 } + f4: { out: x: {f3.out}.x + 1 } + f5: { out: x: {f4.out}.x + 1 } + f6: { out: x: {f5.out}.x + 1 } + f7: { out: x: {f6.out}.x + 1 } + f8: { out: x: {f7.out}.x + 1 } @test(eq, {out: {x: 9}}) +} + +// TODO(perf): fix +// 82 Nodes computed [O(n^2)]: +// f1: 5 +// fn: +(n*2 + 1) each +// SHOULD BE: +// 26 Nodes computed: +// f1: 5 +// f2+: +3 each +embeddedWithEmpty: { + f1: { out: x: 2 } + f2: { out: x: {f1.out & {}}.x + 1 } + f3: { out: x: {f2.out & {}}.x + 1 } + f4: { out: x: {f3.out & {}}.x + 1 } + f5: { out: x: {f4.out & {}}.x + 1 } + f6: { out: x: {f5.out & {}}.x + 1 } + f7: { out: x: {f6.out & {}}.x + 1 } + f8: { out: x: {f7.out & {}}.x + 1 } @test(eq, {out: {x: 9}}) +} + +// TODO(perf): fix +// This will visualize O(n^2) output size unless CUE allows for a bit more +// sophisticated sharing. +weave: { + f: X={ + out: in + 1 + in: X.ref.out + 1 + ref: _ & {} + } + f8: f&{ ref: f7 } + f7: f&{ ref: f6 } + f6: f&{ ref: f5 } + f5: f&{ ref: f4 } + f4: f&{ ref: f3 } + f3: f&{ ref: f2 } @test(eq, {ref: {ref: {out: 2}, out: 4, in: 3}, out: 6, in: 5 }) + f2: f&{ ref: f1 } @test(eq, {ref: {out: 2}, out: 4, in: 3}) + f1: { out: 2 } @test(eq, {out: 2}) +} +@test(eq, at=weave.f8, { + ref: { + ref: { + ref: { + ref: { + ref: { + ref: {ref: {out: 2}, out: 4, in: 3} + out: 6 + in: 5 + } + out: 8 + in: 7 + } + out: 10 + in: 9 + } + out: 12 + in: 11 + } + out: 14 + in: 13 + } + out: 16 + in: 15 +}) + +// TODO(perf): fix +// This will visualize O(n^2) output size unless CUE supports fine-grained +// sharing. +weaveExtraField: { + f: X={ + out: in + 1 + in: X.ref.out + 1 + ref: {y: 4} // Cannot share because of this, but sub arcs still can be. + } + f8: f&{ ref: f7 } @test(eq, 16, at=out) + f7: f&{ ref: f6 } + f6: f&{ ref: f5 } + f5: f&{ ref: f4 } + f4: f&{ ref: f3 } + f3: f&{ ref: f2 } + f2: f&{ ref: f1 } @test(eq, {ref: {y: 4, out: 2}, out: 4, in: 3}) + f1: { out: 2 } @test(eq, {out: 2}) +} + @test(eq, at=weaveExtraField.f8, { + ref: { + y: 4 + ref: { + y: 4 + ref: { + y: 4 + ref: { + y: 4 + ref: { + y: 4 + ref: { + y: 4 + ref: {y: 4, out: 2} + out: 4 + in: 3 + } + out: 6 + in: 5 + } + out: 8 + in: 7 + } + out: 10 + in: 9 + } + out: 12 + in: 11 + } + out: 14 + in: 13 + } + out: 16 + in: 15 +}) +-- out/compile -- +--- in.cue +{ + binexpr: { + f1: { + out: { + x: 2 + } + } + f2: { + out: { + x: (〈2;f1〉.out.x + 1) + } + } + f3: { + out: { + x: (〈2;f2〉.out.x + 1) + } + } + f4: { + out: { + x: (〈2;f3〉.out.x + 1) + } + } + f5: { + out: { + x: (〈2;f4〉.out.x + 1) + } + } + f6: { + out: { + x: (〈2;f5〉.out.x + 1) + } + } + f7: { + out: { + x: (〈2;f6〉.out.x + 1) + } + } + f8: { + out: { + x: (〈2;f7〉.out.x + 1) + } + } + } + parenthesized: { + f1: { + out: { + x: 2 + } + } + f2: { + out: { + x: (〈2;f1〉.out.x + 1) + } + } + f3: { + out: { + x: (〈2;f2〉.out.x + 1) + } + } + f4: { + out: { + x: (〈2;f3〉.out.x + 1) + } + } + f5: { + out: { + x: (〈2;f4〉.out.x + 1) + } + } + f6: { + out: { + x: (〈2;f5〉.out.x + 1) + } + } + f7: { + out: { + x: (〈2;f6〉.out.x + 1) + } + } + f8: { + out: { + x: (〈2;f7〉.out.x + 1) + } + } + } + embedded: { + f1: { + out: { + x: 2 + } + } + f2: { + out: { + x: ({ + 〈3;f1〉.out + }.x + 1) + } + } + f3: { + out: { + x: ({ + 〈3;f2〉.out + }.x + 1) + } + } + f4: { + out: { + x: ({ + 〈3;f3〉.out + }.x + 1) + } + } + f5: { + out: { + x: ({ + 〈3;f4〉.out + }.x + 1) + } + } + f6: { + out: { + x: ({ + 〈3;f5〉.out + }.x + 1) + } + } + f7: { + out: { + x: ({ + 〈3;f6〉.out + }.x + 1) + } + } + f8: { + out: { + x: ({ + 〈3;f7〉.out + }.x + 1) + } + } + } + embeddedWithEmpty: { + f1: { + out: { + x: 2 + } + } + f2: { + out: { + x: ({ + (〈3;f1〉.out & {}) + }.x + 1) + } + } + f3: { + out: { + x: ({ + (〈3;f2〉.out & {}) + }.x + 1) + } + } + f4: { + out: { + x: ({ + (〈3;f3〉.out & {}) + }.x + 1) + } + } + f5: { + out: { + x: ({ + (〈3;f4〉.out & {}) + }.x + 1) + } + } + f6: { + out: { + x: ({ + (〈3;f5〉.out & {}) + }.x + 1) + } + } + f7: { + out: { + x: ({ + (〈3;f6〉.out & {}) + }.x + 1) + } + } + f8: { + out: { + x: ({ + (〈3;f7〉.out & {}) + }.x + 1) + } + } + } + weave: { + f: { + out: (〈0;in〉 + 1) + in: (〈1〉.ref.out + 1) + ref: (_ & {}) + } + f8: (〈0;f〉 & { + ref: 〈1;f7〉 + }) + f7: (〈0;f〉 & { + ref: 〈1;f6〉 + }) + f6: (〈0;f〉 & { + ref: 〈1;f5〉 + }) + f5: (〈0;f〉 & { + ref: 〈1;f4〉 + }) + f4: (〈0;f〉 & { + ref: 〈1;f3〉 + }) + f3: (〈0;f〉 & { + ref: 〈1;f2〉 + }) + f2: (〈0;f〉 & { + ref: 〈1;f1〉 + }) + f1: { + out: 2 + } + } + weaveExtraField: { + f: { + out: (〈0;in〉 + 1) + in: (〈1〉.ref.out + 1) + ref: { + y: 4 + } + } + f8: (〈0;f〉 & { + ref: 〈1;f7〉 + }) + f7: (〈0;f〉 & { + ref: 〈1;f6〉 + }) + f6: (〈0;f〉 & { + ref: 〈1;f5〉 + }) + f5: (〈0;f〉 & { + ref: 〈1;f4〉 + }) + f4: (〈0;f〉 & { + ref: 〈1;f3〉 + }) + f3: (〈0;f〉 & { + ref: 〈1;f2〉 + }) + f2: (〈0;f〉 & { + ref: 〈1;f1〉 + }) + f1: { + out: 2 + } + } +} diff --git a/internal/core/compile/testdata/sync/benchmarks/sort.txtar b/internal/core/compile/testdata/sync/benchmarks/sort.txtar new file mode 100644 index 000000000..1cdcde44e --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/sort.txtar @@ -0,0 +1,76 @@ +// NOTE: the performance of Sort is not measured by counters. The issues +// of https://cuelang.org/issues/745 were mostly related to poor memory +// management. +-- in.cue -- +import "list" + +_a: [{name: 1}, {name: 3}, {name: 4}, {name: 5}, {name: 6}, {name: 7}, {name: 8}, {name: 9}, {name: 0}] +_b: [_a, _a, _a, _a, _a, _a, _a, _a, _a, _a] +_c: [_b, _b, _b, _b, _b, _b, _b, _b, _b, _b] + +out: list.Sort(list.FlattenN(_c, 4), {x: _, y: _, less: x.name < y.name}) + +@test(eq, at=out.0, {name: 0}) +@test(eq, at=out.899, {name: 9}) +-- out/compile -- +--- in.cue +{ + _a: [ + { + name: 1 + }, + { + name: 3 + }, + { + name: 4 + }, + { + name: 5 + }, + { + name: 6 + }, + { + name: 7 + }, + { + name: 8 + }, + { + name: 9 + }, + { + name: 0 + }, + ] + _b: [ + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + 〈1;_a〉, + ] + _c: [ + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + 〈1;_b〉, + ] + out: 〈import;list〉.Sort(〈import;list〉.FlattenN(〈0;_c〉, 4), { + x: _ + y: _ + less: (〈0;x〉.name < 〈0;y〉.name) + }) +} diff --git a/internal/core/compile/testdata/sync/benchmarks/typocheck.txtar b/internal/core/compile/testdata/sync/benchmarks/typocheck.txtar new file mode 100644 index 000000000..cb82ead90 --- /dev/null +++ b/internal/core/compile/testdata/sync/benchmarks/typocheck.txtar @@ -0,0 +1,57 @@ +// Issue #3881 +-- in.cue -- +import "list" + +out: #Output & {#input: _input} + +_input: { + for n in list.Range(1, 100, 1) { + "A\(n)": "B\(n)": name: "name\(n)" + } +} +#Embed: [string]: string +#Output: { + #Embed + #input: _ + + for _, lvlA in #input { + for nameB, lvlB in lvlA { + (nameB): lvlB.name + } + } +} + +_checkB1: out.B1 @test(eq, "name1") +_checkB50: out.B50 @test(eq, "name50") +_checkB99: out.B99 @test(eq, "name99") +-- out/compile -- +--- in.cue +{ + out: (〈0;#Output〉 & { + #input: 〈1;_input〉 + }) + _input: { + for _, n in 〈import;list〉.Range(1, 100, 1) { + "A\(〈1;n〉)": { + "B\(〈2;n〉)": { + name: "name\(〈3;n〉)" + } + } + } + } + #Embed: { + [string]: string + } + #Output: { + 〈1;#Embed〉 + #input: _ + for _, lvlA in 〈0;#input〉 { + for nameB, lvlB in 〈1;lvlA〉 { + 〈1;nameB〉: 〈1;lvlB〉.name + } + } + } + _checkB1: 〈0;out〉.B1 + _checkB50: 〈0;out〉.B50 + _checkB99: 〈0;out〉.B99 +} diff --git a/internal/core/compile/testdata/sync/builtins/056_issue314.txtar b/internal/core/compile/testdata/sync/builtins/056_issue314.txtar new file mode 100644 index 000000000..e64ad6da2 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/056_issue314.txtar @@ -0,0 +1,62 @@ +# Tests that builtin encoding/template functions (text/template.Execute, +# encoding/json.Marshal, encoding/yaml.Marshal) correctly produce [incomplete] +# errors rather than panicking when called with abstract (non-concrete) values. +# https://cuelang.org/issue/314 +-- in.cue -- +import ( + "text/template" + "encoding/yaml" + "encoding/json" +) + +x: { + s: "myname" + #T + @test(eq, {s: "myname", out: "myname"}) +} + +#T: { + s: string + out: template.Execute("{{.s}}", { + "s": s + }) @test(err, code=incomplete, + contains="error in call to text/template.Execute: cannot convert non-concrete value string", pos=[0:7, -1:2]) +} + +#V: { + s: string + out: json.Marshal({"s": s}) @test(err, code=incomplete, + contains="cannot convert incomplete value", pos=[0:7, -1:7]) +} + +#U: { + s: string + out: yaml.Marshal({"s": s}) @test(err, code=incomplete, + contains="incomplete value string", pos=[0:7, -1:7, 0:26]) +} +-- out/compile -- +--- in.cue +{ + x: { + s: "myname" + 〈1;#T〉 + } + #T: { + s: string + out: 〈import;"text/template"〉.Execute("{{.s}}", { + s: 〈1;s〉 + }) + } + #V: { + s: string + out: 〈import;"encoding/json"〉.Marshal({ + s: 〈1;s〉 + }) + } + #U: { + s: string + out: 〈import;"encoding/yaml"〉.Marshal({ + s: 〈1;s〉 + }) + } +} diff --git a/internal/core/compile/testdata/sync/builtins/all.txtar b/internal/core/compile/testdata/sync/builtins/all.txtar new file mode 100644 index 000000000..ba8922ddb --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/all.txtar @@ -0,0 +1,77 @@ +-- in.cue -- +fatalArg: { + x: len("eee" + 'eee') @test(err, code=eval, + contains="invalid operands", + args= ["eee", 'eee', string, bytes], pos=[0:9, 0:17]) +} + +// don't call builtin for a permanent error of a child node +fatalChild: { + #b: {} + x: and([{a: #b.c}]) @test(err, at=a, code=eval, contains="undefined field: c", pos=[0:17]) +} + +// allow incomplete child values. The error will persist after `and` is +// evaluated down the line. This allows the and-ing of templates that may +// complete later. +okIncompleteChild: { + b: {} + x: and([{a: b.c}, {b: 1}]) @test(eq, { + a: _|_ @test(err, code=incomplete, contains="undefined field: c") + b: 1 + }) +} +-- issue3412.cue -- +// Tests that using and() in a pattern constraint with a definition +// reference defined after its use does not crash (nil pointer +// dereference in matchPatternValue). Issue: evalv3 panicked when +// #constraints appeared after its usage in the pattern key. +// https://cuelang.org/issue/3412 +andInPattern: { + out: { + [and(#constraints)]: _ + someKey: {} + } @test(eq, { + [=~"^.*$"]: _ + someKey: {} + }) + #constraints: [=~"^.*$"] @test(eq, [=~"^.*$"]) +} +-- out/compile -- +--- in.cue +{ + fatalArg: { + x: len(("eee" + 'eee')) + } + fatalChild: { + #b: {} + x: and([ + { + a: 〈2;#b〉.c + }, + ]) + } + okIncompleteChild: { + b: {} + x: and([ + { + a: 〈2;b〉.c + }, + { + b: 1 + }, + ]) + } +} +--- issue3412.cue +{ + andInPattern: { + out: { + [and(〈1;#constraints〉)]: _ + someKey: {} + } + #constraints: [ + =~"^.*$", + ] + } +} diff --git a/internal/core/compile/testdata/sync/builtins/and.txtar b/internal/core/compile/testdata/sync/builtins/and.txtar new file mode 100644 index 000000000..fc3d2cf8d --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/and.txtar @@ -0,0 +1,60 @@ +-- in.cue -- +merge: and([1, 1]) @test(eq, 1) + +// ensure definitions along embedded scalars are preserved. +embed: and([{2, #x: 1}, {2, #x: 2}]) @test(err, code=eval, contains="conflicting values", args=[2, 1], pos=[0:13, 0:21, 0:25, 0:33]) + +// issue3719: and() with a comprehension over an incomplete field failed in +// evalv3 while the equivalent expression without and() worked correctly. +// https://cuelang.org/issue/3719 +issue3719: { + #openStruct: {...} + _filledLater: #openStruct.foo @test(err, code=incomplete, contains="undefined field: foo", pos=[0:28]) + + // The comprehension below should work regardless of whether it's wrapped in "and". + + withoutAnd: { + for k, v in _filledLater.bar { + (k): v + } + } @test(err, code=incomplete, contains="undefined field: foo", pos=[in.cue:11:28]) + withAnd: and([ + for k, v in _filledLater.bar { + (k): v + } + ]) @test(err, code=incomplete, contains="undefined field: foo", pos=[in.cue:11:28]) +} +-- out/compile -- +--- in.cue +{ + merge: and([ + 1, + 1, + ]) + embed: and([ + { + 2 + #x: 1 + }, + { + 2 + #x: 2 + }, + ]) + issue3719: { + #openStruct: { + ... + } + _filledLater: 〈0;#openStruct〉.foo + withoutAnd: { + for k, v in 〈1;_filledLater〉.bar { + 〈1;k〉: 〈1;v〉 + } + } + withAnd: and([ + for k, v in 〈1;_filledLater〉.bar { + 〈1;k〉: 〈1;v〉 + }, + ]) + } +} diff --git a/internal/core/compile/testdata/sync/builtins/args.txtar b/internal/core/compile/testdata/sync/builtins/args.txtar new file mode 100644 index 000000000..f25fe30fa --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/args.txtar @@ -0,0 +1,46 @@ +-- in.cue -- +import ( + "math" + "strings" +) + +// issue3584: builtin functions with default-valued disjunction arguments +// (e.g. *1 | 2) caused an "error in call" panic in evalv3. +// https://cuelang.org/issue/3584 +issue3584: reduced: t1: { + ref: out + trigger: *1 | 2 + out: strings.SliceRunes("ABC", 0, trigger) + @test(eq, { + ref: "A" + trigger: *1 | 2 + out: "A" + }) +} + +issue3584: reduced: t2: { + x: math.Abs(y) + y: *6 | 5 + @test(eq, {x: 6, y: *6 | 5}) +} +-- out/compile -- +--- in.cue +{ + issue3584: { + reduced: { + t1: { + ref: 〈0;out〉 + trigger: (*1|2) + out: 〈import;strings〉.SliceRunes("ABC", 0, 〈0;trigger〉) + } + } + } + issue3584: { + reduced: { + t2: { + x: 〈import;math〉.Abs(〈0;y〉) + y: (*6|5) + } + } + } +} diff --git a/internal/core/compile/testdata/sync/builtins/closeall.txtar b/internal/core/compile/testdata/sync/builtins/closeall.txtar new file mode 100644 index 000000000..82bf9d9b7 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/closeall.txtar @@ -0,0 +1,97 @@ +-- in.cue -- +@experiment(explicitopen) + +// Basic usage of __closeAll - makes structs recursively closed +a: __closeAll({ + field1: 1 + nested: { + field2: "hello" + } +}) @test(eq, {field1: 1, nested: {field2: "hello"}}) + +// Test that extra fields are not allowed (should error) +b: { + err: a & {extra: "not allowed"} + @test(err, at=err.extra, code=eval, contains="field not allowed", pos=[1:12]) +} + +// Test that nested extra fields are not allowed (should error) +c: { + err: a & { + field1: 1 + nested: { + field2: "hello" + extra: "not allowed" + } + } + @test(err, at=err.nested.extra, code=eval, contains="field not allowed", pos=[5:4]) +} + +// Test with non-struct should error +d: { + err: __closeAll("not a struct") @test(err, code=eval, contains="argument must be a struct or list literal", pos=[0:7]) +} + +// Test with empty struct +e: __closeAll({}) @test(eq, {}) +f: { + err: e & {extra: "not allowed"} // should error + @test(err, at=err.extra, code=eval, contains="field not allowed", pos=[1:12]) +} + + +#A: a: int +g: { + err: __closeAll(#A) @test(err, code=eval, contains="argument must be a struct or list literal", pos=[0:7]) +} +-- old.cue -- +// May not be used if explicitopen is not set. +h: { + err: __closeAll({}) @test(err, code=eval, contains="__closeAll may only be used when explicitopen is enabled", pos=[0:7]) +} + +-- out/compile -- +--- in.cue +{ + a: __closeAll({ + field1: 1 + nested: { + field2: "hello" + } + }) + b: { + err: (〈1;a〉 & { + extra: "not allowed" + }) + } + c: { + err: (〈1;a〉 & { + field1: 1 + nested: { + field2: "hello" + extra: "not allowed" + } + }) + } + d: { + err: __closeAll("not a struct") + } + e: __closeAll({}) + f: { + err: (〈1;e〉 & { + extra: "not allowed" + }) + } + #A: { + a: int + } + g: { + err: __closeAll(〈1;#A〉) + } +} +--- old.cue +{ + h: { + err: __closeAll({}) + } +} diff --git a/internal/core/compile/testdata/sync/builtins/closed.txtar b/internal/core/compile/testdata/sync/builtins/closed.txtar new file mode 100644 index 000000000..9dcbd7689 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/closed.txtar @@ -0,0 +1,415 @@ +-- in.cue -- +a: close({ + a: b: int +}) + +b: a & {x: int} @test(err, code=eval, at=x, contains="field not allowed", pos=[0:9]) // err +c: a & {a: c: int} @test(eq, {a: {c: int, b: int}}) // okay (non-recursive close) + +inDisjunctions: { + x: [string]: #Def + #Def: [string]: { + a: b: true + let X = a + close({uint: a: b: X.b}) | close({string: a: b: true}) + } + x: socket: string: {} + x: syslog: x.socket + x: syslog: xxx: {} + + @test(eq, { + x: { + socket: string: { + a: b: true + uint: a: b: true + } | { + a: b: true + string: a: b: true + } + syslog: { + string: { + a: b: true + uint: a: b: true + } | { + a: b: true + string: a: b: true + } + xxx: { + a: b: true + uint: a: b: true + } | { + a: b: true + string: a: b: true + } + } + } + #Def: {} + }) +} + +// issue642: Tests that close() with merged struct patterns (concrete fields and +// bulk optional) correctly allows subfields. https://cuelang.org/issue/642 +issue642: { + test: close({ + a: _ + b: x: _ + } & { + [string]: y: _ + }) @test(closed) + + test: a: x: _ + test: b: x: _ + + @test(eq, { + test: { + [string]: y: _ + a: { + y: _ + x: _ + } + b: { + x: _ + y: _ + } + } + }) +} + +// Issue 642 +withSubfields: { + test: close({ + a: _ + b: x: _ + [string]: y: _ + }) + + test: a: x: _ + test: b: x: _ + + @test(eq, { + test: { + [string]: y: _ + a: { + y: _ + x: _ + } + b: { + x: _ + y: _ + } + } + }) +} + +// issue3572: Tests that close({...}) allows additional fields when unified +// with an open struct. https://cuelang.org/issue/3572 +issue3572: { + t1: close({...}) & {a: 5} @test(eq, {a: 5}) @test(closed) + + e: close({...}) @test(closed) // TODO: @test(allows=expr) + + t2: e & {a: 5} @test(eq, {a: 5}) @test(closed) +} + +// issue3580: Tests that close() does not panic when a field inside the closed +// struct references another field of the same struct. https://cuelang.org/issue/3580 +issue3580: { + x: close({ + a: _ + b: x.a + }) @test(closed) +} +-- embed.cue -- +nestedEmbedded: base: { + close({ foo?: close({ foo?: _ }) }) + foo: allowed: 5 + + @test(eq, { foo: { allowed: 5, foo?: _ } }) +} +nestedEmbedded: t1: { + { close({ foo?: close({ foo?: _ }) }) } + foo: allowed: 5 + + @test(eq, { foo: { allowed: 5, foo?: _ } }) +} +nestedEmbedded: t2: { + {{ close({ foo?: close({ foo?: _ }) }) }} + foo: allowed: 5 + + @test(eq, { foo: { allowed: 5, foo?: _ } }) +} +unified: base: { + x: close({ foo?: close({ foo?: _ }) }) + x: foo: disallowed: 5 @test(err, code=eval, contains="field not allowed", pos=[0:10]) +} +unified: t1: { + x: { close({ foo?: close({ foo?: _ }) }) } + x: foo: disallowed: 5 @test(err, code=eval, contains="field not allowed", pos=[0:10]) +} +unified: t2: { + x: {{ close({ foo?: close({ foo?: _ }) }) }} + x: foo: disallowed: 5 @test(err, code=eval, contains="field not allowed", pos=[0:10]) +} +nestedWithSelfReference: t1: { + _schema: close({ + foo?: _schema + }) @test(shareID=S) + // TODO(inline): make work for hidden fields. + // @test(err, at=_schema.foo, code=structural_cycle) + // @test(shareID=S, at=x.foo.foo) + + x: {_schema} + x: foo: disallowed: 5 @test(err, code=eval, contains="field not allowed", pos=[0:10]) +} +nestedWithSelfReference: t2: { + _schema: close({ + foo?: _schema + }) + // TODO(inline): make work for hidden fields. + // @test(err, at=foo, code=structural_cycle) + x: {{_schema}} + x: foo: disallowed: 5 @test(err, code=eval, contains="field not allowed", pos=[0:10]) +} +-- out/compile -- +--- embed.cue +{ + nestedEmbedded: { + base: { + close({ + foo?: close({ + foo?: _ + }) + }) + foo: { + allowed: 5 + } + } + } + nestedEmbedded: { + t1: { + { + close({ + foo?: close({ + foo?: _ + }) + }) + } + foo: { + allowed: 5 + } + } + } + nestedEmbedded: { + t2: { + { + { + close({ + foo?: close({ + foo?: _ + }) + }) + } + } + foo: { + allowed: 5 + } + } + } + unified: { + base: { + x: close({ + foo?: close({ + foo?: _ + }) + }) + x: { + foo: { + disallowed: 5 + } + } + } + } + unified: { + t1: { + x: { + close({ + foo?: close({ + foo?: _ + }) + }) + } + x: { + foo: { + disallowed: 5 + } + } + } + } + unified: { + t2: { + x: { + { + close({ + foo?: close({ + foo?: _ + }) + }) + } + } + x: { + foo: { + disallowed: 5 + } + } + } + } + nestedWithSelfReference: { + t1: { + _schema: close({ + foo?: 〈1;_schema〉 + }) + x: { + 〈1;_schema〉 + } + x: { + foo: { + disallowed: 5 + } + } + } + } + nestedWithSelfReference: { + t2: { + _schema: close({ + foo?: 〈1;_schema〉 + }) + x: { + { + 〈2;_schema〉 + } + } + x: { + foo: { + disallowed: 5 + } + } + } + } +} +--- in.cue +{ + a: close({ + a: { + b: int + } + }) + b: (〈0;a〉 & { + x: int + }) + c: (〈0;a〉 & { + a: { + c: int + } + }) + inDisjunctions: { + x: { + [string]: 〈1;#Def〉 + } + #Def: { + [string]: { + a: { + b: true + } + let X#1 = 〈0;a〉 + (close({ + uint: { + a: { + b: 〈3;let X#1〉.b + } + } + })|close({ + string: { + a: { + b: true + } + } + })) + } + } + x: { + socket: { + string: {} + } + } + x: { + syslog: 〈1;x〉.socket + } + x: { + syslog: { + xxx: {} + } + } + } + issue642: { + test: close(({ + a: _ + b: { + x: _ + } + } & { + [string]: { + y: _ + } + })) + test: { + a: { + x: _ + } + } + test: { + b: { + x: _ + } + } + } + withSubfields: { + test: close({ + a: _ + b: { + x: _ + } + [string]: { + y: _ + } + }) + test: { + a: { + x: _ + } + } + test: { + b: { + x: _ + } + } + } + issue3572: { + t1: (close({ + ... + }) & { + a: 5 + }) + e: close({ + ... + }) + t2: (〈0;e〉 & { + a: 5 + }) + } + issue3580: { + x: close({ + a: _ + b: 〈1;x〉.a + }) + } +} diff --git a/internal/core/compile/testdata/sync/builtins/default.txtar b/internal/core/compile/testdata/sync/builtins/default.txtar new file mode 100644 index 000000000..e016aeb7b --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/default.txtar @@ -0,0 +1,31 @@ +-- in.cue -- +Len: len(*[1, 2, 3] | 0) @test(eq, 3) +Close: close(*{} | 0) @test(eq, {}) @test(closed) +And: and(*[1, 1] | int) @test(eq, 1) +Or: or(*[1, 1] | int) @test(eq, 1) +Div: div(*5 | string, 2) @test(eq, 2) +Mod: mod(*5 | string, 2) @test(eq, 1) +Quo: quo(*5 | string, 2) @test(eq, 2) +Rem: rem(*5 | string, 2) @test(eq, 1) +-- out/compile -- +--- in.cue +{ + Len: len((*[ + 1, + 2, + 3, + ]|0)) + Close: close((*{}|0)) + And: and((*[ + 1, + 1, + ]|int)) + Or: or((*[ + 1, + 1, + ]|int)) + Div: div((*5|string), 2) + Mod: mod((*5|string), 2) + Quo: quo((*5|string), 2) + Rem: rem((*5|string), 2) +} diff --git a/internal/core/compile/testdata/sync/builtins/error.txtar b/internal/core/compile/testdata/sync/builtins/error.txtar new file mode 100644 index 000000000..897ce3f62 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/error.txtar @@ -0,0 +1,163 @@ +-- cue.mod/module.cue -- +module: "cuelang.org/error" +language: version: "v0.15.0" +-- in.cue -- +selection: { + dropError: 1 | error("drop me") @test(eq, 1) + + useCustomError: 1&2 | error("use me") @test(err, code=eval, contains="use me", pos=[0:24, 0:18, 0:20]) + + twoCustomErrors: 1&2 | error("error one") | error("error two") @test(err, code=eval, contains="empty disjunction", + suberr=(code=eval, contains="error one", pos=[0:25]), + suberr=(code=eval, contains="error two", pos=[0:46]), + ) + + x: int + dropIncomplete: x + 1 | error("user msg: x + 1 failed") @test(err, code=incomplete, contains="user msg: x + 1 failed", pos=[0:26, -1:5]) +} + +interpolation: { + a: {b: int} + world: "world" @test(eq, "world") + + substituteAll: a.notExist | error("hello \(world)") @test(err, code=incomplete, contains="hello world", pos=[0:30]) + + substituteFail: a.b + 1 | a.notExist | error("reference failed: \(a.b) | \(a.notExist)") @test(err, code=incomplete, contains="reference failed:", pos=[0:41, -5:9, 0:77]) + + // When the error() message itself contains an error, + // the custom error should not be thrown away. + // For comparison, without interpolation: + errorNoInterpolation: "a" | "b" | error("custom") + errorNoInterpolation: "c" @test(err, code=eval, contains="custom", pos=[-1:36, -1:24, 0:24]) + + // When the struct interpolation fails, the custom error should + // still be shown rather than being replaced by the interpolation error. + errorStructInterpolation: "a" | "b" | error("custom: \({x: 1})") + errorStructInterpolation: "c" @test(err, code=eval, contains="custom: {x:1}", pos=[-1:40, -1:28, -1:57, 0:28]) + + // When the interpolation always results in an error, the custom + // error should still be shown. + errorBottomInterpolation: "a" | "b" | error("custom: \(1 & 2)") + errorBottomInterpolation: "c" @test(err, code=eval, contains="custom: (1 & 2)", pos=[-1:40, -1:28, -1:57, 0:28]) +} +indirect: { + x: error @test(eq, error) + y: x("msg") @test(err, code=user, contains="msg", pos=[0:5]) +} +-- incomplete.cue -- +import "struct" + +// The custom error should not alter the type of error. +minFields: struct.MinFields(2) | error("should remain incomplete") @test(eq, struct.MinFields(2)) +maxFields: a: 1 @test(eq, 1) + +multi: struct.MinFields(2) | error("should remain incomplete") | error("second") @test(err, code=incomplete, + pos=[0:8, 0:25, 4:8], + suberr=(code=eval, contains="should remain incomplete", pos=[0:30]), + suberr=(code=eval, contains="second", pos=[0:66])) +multi: a: 1 + +-- self.cue -- +@experiment(aliasv2) + +// When error() interpolates "self" which is the enclosing struct +// containing the error value itself (a cycle), the custom error +// should still be shown. +errorSelf: { + v: "x" | "y" | error("bad: \(self)") + v: "z" + @test(err, code=eval, contains="bad:", pos=[1:17, 0:12, 1:5, 2:5]) +} +-- issues.cue -- +// issue4001: Tests that error() text is shown correctly when the message uses +// string concatenation with interpolation. https://cuelang.org/issue/4001 +issue4001: { + a: "b" + a: int | error("error: "+"a='\(a)'") @test(err, code=eval, contains="error: a='b'", pos=[0:11, -1:5, 0:5]) +} +// issue3983: Tests that multiple error() disjunctions aggregate all user-defined +// error messages correctly. https://cuelang.org/issue/3983 +issue3983: { + x: int | error("I wanted an integer") + x: >10 | error("I wanted more than 10") + x: <20 | error("I wanted less than 20") + + x: 3 + @test(err, code=eval, contains="2 errors in empty disjunction", pos=[2:5, 5:5], + suberr=(code=eval, contains="I wanted an integer", hint="this could be dropped"), + suberr=(code=eval, contains="I wanted more than 10"), + hint="we could also include the third condition, if we want to be consistent.", + ) +} +// issue3984: Tests that error() shows all relevant source locations when the +// error builtin is used in a disjunction. https://cuelang.org/issue/3984 +issue3984: { + v: "a" | error("must be a") + v: "b" @test(err, code=eval, contains="must be a", pos=[-1:11, -1:5, 0:5]) +} +-- out/compile -- +--- in.cue +{ + selection: { + dropError: (1|error("drop me")) + useCustomError: ((1 & 2)|error("use me")) + twoCustomErrors: ((1 & 2)|error("error one")|error("error two")) + x: int + dropIncomplete: ((〈0;x〉 + 1)|error("user msg: x + 1 failed")) + } + interpolation: { + a: { + b: int + } + world: "world" + substituteAll: (〈0;a〉.notExist|error("hello \(〈0;world〉)")) + substituteFail: ((〈0;a〉.b + 1)|〈0;a〉.notExist|error("reference failed: \(〈0;a〉.b) | \(〈0;a〉.notExist)")) + errorNoInterpolation: ("a"|"b"|error("custom")) + errorNoInterpolation: "c" + errorStructInterpolation: ("a"|"b"|error("custom: \({ + x: 1 + })")) + errorStructInterpolation: "c" + errorBottomInterpolation: ("a"|"b"|error("custom: \((1 & 2))")) + errorBottomInterpolation: "c" + } + indirect: { + x: error + y: 〈0;x〉("msg") + } +} +--- incomplete.cue +{ + minFields: (〈import;struct〉.MinFields(2)|error("should remain incomplete")) + maxFields: { + a: 1 + } + multi: (〈import;struct〉.MinFields(2)|error("should remain incomplete")|error("second")) + multi: { + a: 1 + } +} +--- issues.cue +{ + issue4001: { + a: "b" + a: (int|error(("error: " + "a='\(〈0;a〉)'"))) + } + issue3983: { + x: (int|error("I wanted an integer")) + x: (>10|error("I wanted more than 10")) + x: (<20|error("I wanted less than 20")) + x: 3 + } + issue3984: { + v: ("a"|error("must be a")) + v: "b" + } +} +--- self.cue +{ + errorSelf: { + v: ("x"|"y"|error("bad: \(〈1〉)")) + v: "z" + } +} diff --git a/internal/core/compile/testdata/sync/builtins/export.txtar b/internal/core/compile/testdata/sync/builtins/export.txtar new file mode 100644 index 000000000..47ed783ef --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/export.txtar @@ -0,0 +1,60 @@ +-- in.cue -- +import "encoding/yaml" + +// issue3972: Tests that yaml.Marshal with list comprehensions over conditionally +// defined fields works correctly in evalv3. https://cuelang.org/issue/3972 +issue3972: { + // yaml uses Syntax to convert CUE to YAML. Ensure that unresolved values + // are properly handled. + // TODO(inline): the inline testing framework indicated that this field + // was not used in the computation of the test result. That seems correct. + // But maybe this test is then not testing what it is supposed to do. + // Investigate against the original issue. + output: out0: "static" @test(eq, "static") // has to go first + + input: inputStatic: "static" + if false { + input: inputNever: "never" + } + + derived: derivedStatic: "static" + if false { + derived: derivedNever: input.inputNever + } + + _out1: [for svc, _ in derived {svc}] + output: out1: yaml.Marshal(_out1) @test(eq, "- derivedStatic\n") +} +-- out/compile -- +--- in.cue +{ + issue3972: { + output: { + out0: "static" + } + input: { + inputStatic: "static" + } + if false { + input: { + inputNever: "never" + } + } + derived: { + derivedStatic: "static" + } + if false { + derived: { + derivedNever: 〈2;input〉.inputNever + } + } + _out1: [ + for svc, _ in 〈1;derived〉 { + 〈1;svc〉 + }, + ] + output: { + out1: 〈import;"encoding/yaml"〉.Marshal(〈1;_out1〉) + } + } +} diff --git a/internal/core/compile/testdata/sync/builtins/incomplete.txtar b/internal/core/compile/testdata/sync/builtins/incomplete.txtar new file mode 100644 index 000000000..018c7bb97 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/incomplete.txtar @@ -0,0 +1,208 @@ +-- in.cue -- +import ( + "list" + "strings" + "text/template" +) + +list1: { + // Note that Top is not incomplete, only its first element is. + // We allow FlattenN to proceed and pass on the incomplete values. + Out1: list.FlattenN(Top, 1) @test(err, at=0, code=incomplete, contains="undefined field: b", pos=[in.cue:19:10]) + Out2: [...] & list.FlattenN(Top, 1) @test(err, at=0, code=incomplete, contains="undefined field: b", pos=[in.cue:19:10]) + Out3: list.FlattenN(Top, 1) & [...] @test(err, at=0, code=incomplete, contains="undefined field: b", pos=[in.cue:19:10]) + + // This evaluates to a list with an incomplete element. + Top: [ + [for _, F in _Sub {F}], + ] @test(err, at=0, code=incomplete, contains="undefined field: b", pos=[in.cue:19:10]) + + _Sub: a.b @test(err, code=incomplete, contains="undefined field: b", pos=[in.cue:19:10]) + a: {} // b does not +} + +list2: { + Out1: list.FlattenN(_Top, 1) @test(err, code=incomplete, contains="undefined field: b", pos=[9:10]) + Out2: [...] & list.FlattenN(_Top, 1) @test(err, code=incomplete, contains="undefined field: b", pos=[8:10]) + Out3: list.FlattenN(_Top, 1) & [...] @test(err, code=incomplete, contains="undefined field: b", pos=[7:10]) + + // This evaluates to a list with an incomplete element. + _Top: [ + for _, F in #Sub {F}, + ] @test(err, code=incomplete, contains="undefined field: b", pos=[4:10]) + + #Sub: a.b @test(err, code=incomplete, contains="undefined field: b", pos=[0:10]) + + a: {} // b does not +} + +value1: { + a: len('sf' | 'dd') @test(err, code=incomplete|eval, + hint="this can never be resolve so could be a permanent error" + contains="unresolved disjunction", pos=[0:5]) @test(err:todo, code=eval) +} + +value2: { + len('sf' | 'dd') + + @test(err, code=incomplete|eval, + hint="this can never be resolve so could be a permanent error" + contains="unresolved disjunction") + @test(err:todo, code=eval) +} + +incompleteArgDecimalList: { + a: #a & {param: 123} @test(eq, {param: 123, transformed: 123, max: 123}) + #a: { + param: int + transformed: +param @test(err, code=incomplete, contains="operand param of '+' not concrete", pos=[0:17]) + max: list.Max([transformed]) @test(err, code=incomplete, contains="operand param of '+' not concrete", pos=[0:16, -1:17]) + } +} + +incompleteArgStringList: { + a: #a & {param: "123"} @test(eq, {param: "123", transformed: "123", joined: "123"}) + #a: { + param: string + transformed: param + "" @test(err, code=incomplete, contains="non-concrete value string in operand to +", pos=[0:16, -1:16]) + joined: strings.Join([transformed], "-") @test(err, code=incomplete, contains="non-concrete value string in operand to +", pos=[0:16, -2:16, -1:16]) + } +} + +incompleteList: { + x: _ + decimal: list.Max(x) @test(err, code=incomplete, contains="non-concrete list for argument 0", pos=[0:11]) + str: strings.Join(x, "") @test(err, code=incomplete, contains="non-concrete list for argument 0", pos=[0:11]) +} + +// TODO: add better error positions. +incompleteListError: { + x: y + [] @test(err, code=incomplete, contains="non-concrete value _ in operand to +", pos=[0:11, 1:11]) + y: _ + decimal: list.Max(x) @test(err, code=incomplete, contains="non-concrete value _ in operand to +", pos=[-2:11, -1:11]) + str: strings.Join(x, "") @test(err, code=incomplete, contains="non-concrete value _ in operand to +", pos=[-3:11, -2:11]) +} + +badListType: { + x: 2 + decimal: list.Max(x) @test(err, code=eval, contains="cannot use 2 (type int) as list", pos=[-1:11]) + str: strings.Join(x, "") @test(err, code=eval, contains="cannot use 2 (type int) as list", pos=[-2:11]) +} + +badListError: { + x: 2 + y @test(err, code=eval, contains="invalid operands 2 and \"foo\" to '+'", pos=[0:11, 1:11]) + y: "foo" + decimal: list.Max(x) @test(err, code=eval, contains="invalid operands 2 and \"foo\" to '+'", pos=[-2:11, -1:11]) + str: strings.Join(x, "") @test(err, code=eval, contains="invalid operands 2 and \"foo\" to '+'", pos=[-3:11, -2:11]) +} + +// Issue #1095 +// Preserve combined error severity for multiple errors. +multipleErrors: { + #T: { + params: { + x: string + y: string + } + out: template.Execute("{{.x}} {{.y}}", params) @test(err, code=incomplete, contains="cannot convert non-concrete value string", pos=[0:8, -3:4]) + } +} +-- out/compile -- +--- in.cue +{ + list1: { + Out1: 〈import;list〉.FlattenN(〈0;Top〉, 1) + Out2: ([ + ..., + ] & 〈import;list〉.FlattenN(〈0;Top〉, 1)) + Out3: (〈import;list〉.FlattenN(〈0;Top〉, 1) & [ + ..., + ]) + Top: [ + [ + for _, F in 〈2;_Sub〉 { + 〈1;F〉 + }, + ], + ] + _Sub: 〈0;a〉.b + a: {} + } + list2: { + Out1: 〈import;list〉.FlattenN(〈0;_Top〉, 1) + Out2: ([ + ..., + ] & 〈import;list〉.FlattenN(〈0;_Top〉, 1)) + Out3: (〈import;list〉.FlattenN(〈0;_Top〉, 1) & [ + ..., + ]) + _Top: [ + for _, F in 〈1;#Sub〉 { + 〈1;F〉 + }, + ] + #Sub: 〈0;a〉.b + a: {} + } + value1: { + a: len(('sf'|'dd')) + } + value2: { + len(('sf'|'dd')) + } + incompleteArgDecimalList: { + a: (〈0;#a〉 & { + param: 123 + }) + #a: { + param: int + transformed: +〈0;param〉 + max: 〈import;list〉.Max([ + 〈1;transformed〉, + ]) + } + } + incompleteArgStringList: { + a: (〈0;#a〉 & { + param: "123" + }) + #a: { + param: string + transformed: (〈0;param〉 + "") + joined: 〈import;strings〉.Join([ + 〈1;transformed〉, + ], "-") + } + } + incompleteList: { + x: _ + decimal: 〈import;list〉.Max(〈0;x〉) + str: 〈import;strings〉.Join(〈0;x〉, "") + } + incompleteListError: { + x: (〈0;y〉 + []) + y: _ + decimal: 〈import;list〉.Max(〈0;x〉) + str: 〈import;strings〉.Join(〈0;x〉, "") + } + badListType: { + x: 2 + decimal: 〈import;list〉.Max(〈0;x〉) + str: 〈import;strings〉.Join(〈0;x〉, "") + } + badListError: { + x: (2 + 〈0;y〉) + y: "foo" + decimal: 〈import;list〉.Max(〈0;x〉) + str: 〈import;strings〉.Join(〈0;x〉, "") + } + multipleErrors: { + #T: { + params: { + x: string + y: string + } + out: 〈import;"text/template"〉.Execute("{{.x}} {{.y}}", 〈0;params〉) + } + } +} diff --git a/internal/core/compile/testdata/sync/builtins/intdiv.txtar b/internal/core/compile/testdata/sync/builtins/intdiv.txtar new file mode 100644 index 000000000..473fd5d7f --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/intdiv.txtar @@ -0,0 +1,72 @@ +-- in.cue -- +quo1: quo(5, 2) @test(eq, 2) +quo2: quo(5, -2) @test(eq, -2) +quo3: quo(-5, 2) @test(eq, -2) +quo4: quo(-5, -2) @test(eq, 2) + +quoDivByZero: quo(2, 0) @test(err, code=eval, contains="division by zero", pos=[0:15]) + +quoTypeError1: quo(2.0, 1) @test(err, code=eval, contains="cannot use 2.0 (type float) as int in argument 1 to quo", pos=[0:20]) +quoTypeError2: quo(2, 1.0) @test(err, code=eval, contains="cannot use 1.0 (type float) as int in argument 2 to quo", pos=[0:23]) + +rem1: rem(5, 2) @test(eq, 1) +rem2: rem(5, -2) @test(eq, 1) +rem3: rem(-5, 2) @test(eq, -1) +rem4: rem(-5, -2) @test(eq, -1) + +remDivByZero: rem(2, 0) @test(err, code=eval, contains="division by zero", pos=[0:15]) + +remTypeError1: rem(2.0, 1) @test(err, code=eval, contains="cannot use 2.0 (type float) as int in argument 1 to rem", pos=[0:20]) +remTypeError2: rem(2, 1.0) @test(err, code=eval, contains="cannot use 1.0 (type float) as int in argument 2 to rem", pos=[0:23]) + +div1: div(5, 2) @test(eq, 2) +div2: div(5, -2) @test(eq, -2) +div3: div(-5, 2) @test(eq, -3) +div4: div(-5, -2) @test(eq, 3) + +divDivByZero: div(2, 0) @test(err, code=eval, contains="division by zero", pos=[0:15]) + +divTypeError1: div(2.0, 1) @test(err, code=eval, contains="cannot use 2.0 (type float) as int in argument 1 to div", pos=[0:20]) +divTypeError2: div(2, 1.0) @test(err, code=eval, contains="cannot use 1.0 (type float) as int in argument 2 to div", pos=[0:23]) + +mod1: mod(5, 2) @test(eq, 1) +mod2: mod(5, -2) @test(eq, 1) +mod3: mod(-5, 2) @test(eq, 1) +mod4: mod(-5, -2) @test(eq, 1) + +modDivByZero: mod(2, 0) @test(err, code=eval, contains="division by zero", pos=[0:15]) + +modTypeError1: mod(2.0, 1) @test(err, code=eval, contains="cannot use 2.0 (type float) as int in argument 1 to mod", pos=[0:20]) +modTypeError2: mod(2, 1.0) @test(err, code=eval, contains="cannot use 1.0 (type float) as int in argument 2 to mod", pos=[0:23]) +-- out/compile -- +--- in.cue +{ + quo1: quo(5, 2) + quo2: quo(5, -2) + quo3: quo(-5, 2) + quo4: quo(-5, -2) + quoDivByZero: quo(2, 0) + quoTypeError1: quo(2.0, 1) + quoTypeError2: quo(2, 1.0) + rem1: rem(5, 2) + rem2: rem(5, -2) + rem3: rem(-5, 2) + rem4: rem(-5, -2) + remDivByZero: rem(2, 0) + remTypeError1: rem(2.0, 1) + remTypeError2: rem(2, 1.0) + div1: div(5, 2) + div2: div(5, -2) + div3: div(-5, 2) + div4: div(-5, -2) + divDivByZero: div(2, 0) + divTypeError1: div(2.0, 1) + divTypeError2: div(2, 1.0) + mod1: mod(5, 2) + mod2: mod(5, -2) + mod3: mod(-5, 2) + mod4: mod(-5, -2) + modDivByZero: mod(2, 0) + modTypeError1: mod(2.0, 1) + modTypeError2: mod(2, 1.0) +} diff --git a/internal/core/compile/testdata/sync/builtins/issue299.txtar b/internal/core/compile/testdata/sync/builtins/issue299.txtar new file mode 100644 index 000000000..3cfaefd80 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/issue299.txtar @@ -0,0 +1,22 @@ +# Tests that list.UniqueItems correctly rejects lists with duplicate +# values, which were silently passed through instead of producing an error. +# https://cuelang.org/issue/299 +-- in.cue -- +import "list" + +x: list.UniqueItems +x: [string, ...string] +x: ["x", "x"] @test(err, code=eval, contains="does not satisfy list.UniqueItems", pos=[-2:4, -1:4, 0:4]) +-- out/compile -- +--- in.cue +{ + x: 〈import;list〉.UniqueItems + x: [ + string, + ...string, + ] + x: [ + "x", + "x", + ] +} diff --git a/internal/core/compile/testdata/sync/builtins/issue4208.txtar b/internal/core/compile/testdata/sync/builtins/issue4208.txtar new file mode 100644 index 000000000..5358cf42c --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/issue4208.txtar @@ -0,0 +1,53 @@ +# Test that error() in a disjunction used as a pattern constraint key +# surfaces the custom error message instead of the generic "field not allowed". +# +# Issue: https://cuelang.org/issue/4208 +-- in.cue -- +#Environment: "sbx" | "stg" | "pro" | error("Must specify a valid environment") +#Envs: [Env=#Environment]: {} + +// Valid key should work fine. +valid: #Envs @test(eq, {["sbx"|"stg"|"pro"]: {}, sbx: {}}, hint="user error should be preserved in pattern") +valid: sbx: {} + +// Invalid key should show the custom error message. +invalid: #Envs +invalid: foo: {} @test(err, code=eval, contains="field not allowed", incorrect) @test(err:todo, code=eval, contains="Must specify a valid environment") + + +@test(debug, """ + (_|_){ + // [eval] + #Environment: (string){ |((string){ "sbx" }, (string){ "stg" }, (string){ "pro" }) } + #Envs: (#struct){ + } + valid: (#struct){ + sbx: (#struct){ + } + } + invalid: (_|_){ + // [eval] + foo: (_|_){ + // [eval] invalid.foo: field not allowed: + // in.cue:10:10 + } + } + } + """) + +-- out/compile -- +--- in.cue +{ + #Environment: ("sbx"|"stg"|"pro"|error("Must specify a valid environment")) + #Envs: { + [〈1;#Environment〉]: {} + } + valid: 〈0;#Envs〉 + valid: { + sbx: {} + } + invalid: 〈0;#Envs〉 + invalid: { + foo: {} + } +} diff --git a/internal/core/compile/testdata/sync/builtins/issue490.txtar b/internal/core/compile/testdata/sync/builtins/issue490.txtar new file mode 100644 index 000000000..be60e78e6 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/issue490.txtar @@ -0,0 +1,42 @@ +# Tests that close() correctly rejects fields not present in the closed struct +# when the closed value is later unified with an open struct adding new fields. +# https://cuelang.org/issue/490 +-- test.cue -- +A: close({ + a: 1 + b: 2 +}) @test(eq, {a: 1, b: 2}) + +B: A & { + c: 3 +} @test(err, code=eval, at=c, contains="field not allowed", pos=[1:2]) + +@test(debugCheck, """ + (_|_){ + // [eval] + A: (#struct){ + a: (int){ 1 } + b: (int){ 2 } + } + B: (_|_){ + // [eval] + c: (_|_){ + // [eval] B.c: field not allowed: + // test.cue:7:2 + } + a: (int){ 1 } + b: (int){ 2 } + } + } + """) +-- out/compile -- +--- test.cue +{ + A: close({ + a: 1 + b: 2 + }) + B: (〈0;A〉 & { + c: 3 + }) +} diff --git a/internal/core/compile/testdata/sync/builtins/issue_3567.txtar b/internal/core/compile/testdata/sync/builtins/issue_3567.txtar new file mode 100644 index 000000000..0323b0abb --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/issue_3567.txtar @@ -0,0 +1,14 @@ +-- in.cue -- +import "strings" +a: strings.Join( [ strings.Join(["1"]), "2" ], "\n") @test(err, code=eval, contains="not enough arguments in call to strings.Join", pos=[0:4, 0:20]) + +-- out/compile -- +--- in.cue +{ + a: 〈import;strings〉.Join([ + 〈import;strings〉.Join([ + "1", + ]), + "2", + ], "\n") +} diff --git a/internal/core/compile/testdata/sync/builtins/list/issue332.txtar b/internal/core/compile/testdata/sync/builtins/list/issue332.txtar new file mode 100644 index 000000000..ae1f07cfe --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/list/issue332.txtar @@ -0,0 +1,37 @@ +# Tests that list.FlattenN does not spuriously report an "incomplete value" +# error when its input list is derived from a definition field passed through +# a conjunction. Previously FlattenN failed when the list element was abstract. +# https://cuelang.org/issue/332 +-- in.cue -- +import "list" + +#d: { + #x: string + result: [#x] +} +#foo: { + X=#x: _ + y: list.FlattenN((#d & {#x: X}).result, 1) +} +r: #foo & { + #x: "hello" +} @test(eq, {#x: "hello", y: ["hello"]}) +-- out/compile -- +--- in.cue +{ + #d: { + #x: string + result: [ + 〈1;#x〉, + ] + } + #foo: { + #x: _ + y: 〈import;list〉.FlattenN((〈1;#d〉 & { + #x: 〈1;#x〉 + }).result, 1) + } + r: (〈0;#foo〉 & { + #x: "hello" + }) +} diff --git a/internal/core/compile/testdata/sync/builtins/list/sort.txtar b/internal/core/compile/testdata/sync/builtins/list/sort.txtar new file mode 100644 index 000000000..9d5fcbd8e --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/list/sort.txtar @@ -0,0 +1,18 @@ +-- in.cue -- +import "list" + +a: list.Sort([2, 3, 1, 4], {x: _, y: _, less: x < y}) @test(eq, [1, 2, 3, 4]) +-- out/compile -- +--- in.cue +{ + a: 〈import;list〉.Sort([ + 2, + 3, + 1, + 4, + ], { + x: _ + y: _ + less: (〈0;x〉 < 〈0;y〉) + }) +} diff --git a/internal/core/compile/testdata/sync/builtins/matchif.txtar b/internal/core/compile/testdata/sync/builtins/matchif.txtar new file mode 100644 index 000000000..306ebf0f1 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/matchif.txtar @@ -0,0 +1,60 @@ +-- in.cue -- +regularFields: { + [_]: matchIf({x!: >2}, {y!: 5}, {y!: 1}) + ok1: {x: 10, y: 5} @test(eq, {x: 10, y: 5}) + ok2: {x: 11, y: 5} @test(eq, {x: 11, y: 5}) + ok3: {x: 2, y: 1} @test(eq, {x: 2, y: 1}) + ok4: {x: 1, y: 1} @test(eq, {x: 1, y: 1}) + + // TODO: allow unwrapping errors so that we can test args in wrapped errors, + // without having to match the other arguments. + err1: {x: 10, y: 6} @test(err, code=eval, contains="conflicting values 5 and 6", pos=[in.cue:2:7, in.cue:2:30, 0:8, 0:19]) + err2: {x: 11, y: 6} @test(err, code=eval, contains="conflicting values 5 and 6", pos=[in.cue:2:7, in.cue:2:30, 0:8, 0:19]) + err3: {x: 2, y: 5} @test(err, code=eval, contains="conflicting values 1 and 5", pos=[in.cue:2:7, in.cue:2:39, 0:8, 0:18]) + err4: {x: 1, y: 2} @test(err, code=eval, contains="conflicting values 1 and 2", pos=[in.cue:2:7, in.cue:2:39, 0:8, 0:18]) +} +-- out/compile -- +--- in.cue +{ + regularFields: { + [_]: matchIf({ + x!: >2 + }, { + y!: 5 + }, { + y!: 1 + }) + ok1: { + x: 10 + y: 5 + } + ok2: { + x: 11 + y: 5 + } + ok3: { + x: 2 + y: 1 + } + ok4: { + x: 1 + y: 1 + } + err1: { + x: 10 + y: 6 + } + err2: { + x: 11 + y: 6 + } + err3: { + x: 2 + y: 5 + } + err4: { + x: 1 + y: 2 + } + } +} diff --git a/internal/core/compile/testdata/sync/builtins/matchn.txtar b/internal/core/compile/testdata/sync/builtins/matchn.txtar new file mode 100644 index 000000000..fe2b4fdef --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/matchn.txtar @@ -0,0 +1,1170 @@ +-- in.cue -- +import "math" + +#Foo: { + a: int +} + +match: { + [=~"^single"]: matchN(1, [#Foo]) + singleOK: {a: 2} @test(eq, {a: 2}) + singleErr: { + a: "foo" + @test(err, code=eval, contains="does not satisfy matchN", pos=[-2:17, -2:24, 0:13]) + } + + [=~"^incomplete"]: matchN(1, [#Foo]) + incompleteOK: {a: int} @test(eq, {a: int}) + incompleteErr: { + a: string + @test(err, code=eval, contains="does not satisfy matchN", pos=[-2:21, -2:28, 0:17]) + } + + #A: { + a: int + b: _ + ... + } + + defaults: { + // Because validators distribute over disjunctions, this validator may erase + // a default value. Nonethenless, it will be guaranteed that the value + // resulting from evaluation does not violate the validator. + // TODO(defaults): take this use case into consideration for the defaults + // rethink, as it seems less than ideal. Note that this typically not an + // issue if the schema matched against is not concrete. + [=~"^pickTop"]: matchN(1, [2]) + // TODO(inline): this matches the debug output, but it nonetheless doesn't pass. + pickTopOK1: *2 | int @test(eq:todo, *2 | matchN(1, [2]) & int) + pickTopOK2: int @test(eq, matchN(1, [2]) & int) + pickTopErr: *3 | int @test(eq:todo, + hint="or should this be an error? Depends on when value is finalized.", + matchN(1, [2]) & int) @test(debugCheck, """ + (int){ &(matchN(1, (#list){ + 0: (int){ 2 } + }), int) } + """) + + // Nested default values will be evaluated and may not be overridden by + // values in the validator. + [=~"^pickNested1"]: matchN(1, [{a: 2}]) + pickNested1OK1: {a: *2 | int} @test(eq, {a: *2 | int}) + pickNested1OK2: {a: int} @test(eq, {a: int}) + pickNested1Err: { + a: *3 | int + @test(err, code=eval, + hint="should this be an incomplete error, as a may still change and pass?", + contains="does not satisfy matchN", pos=[-3:23, -3:30, 0:19]) + } + + [=~"^pickNested2"]: matchN(1, [{a: <=2}]) + pickNested2OK1: {a: *2 | int} @test(eq, {a: *2 | int}) + pickNested2OK2: {a: int} @test(eq, {a: int}) + pickNested2Err: { + a: *3 | int + @test(err, code=eval, + hint="should this be an incomplete error, as a may still change and pass?", + contains="does not satisfy matchN", pos=[-3:23, -3:30, 0:19]) + } + } + + // Stress test potential exponential behavior. + nestedOK: { + matchN(4, [#A, #A, #A, #A]) + + a: 2 + b: { + matchN(4, [#A, #A, #A, #A]) + + a: 3 + b: matchN(4, [#A, #A, #A, #A]) + b: {a: 4} + c: matchN(4, [#A, #A, #A, #A]) + c: {a: 5} + + @test(eq, {a: 3, b: {a: 4}, c: {a: 5}}) + } + c: { + matchN(4, [#A, #A, #A, #A]) + + a: 3 + b: matchN(4, [#A, #A, #A, #A]) + b: {a: 4} + c: matchN(4, [#A, #A, #A, #A]) + c: {a: 5} + + @test(eq, {a: 3, b: {a: 4}, c: {a: 5}}) + } + } +} + +not: { + [=~"^single"]: matchN(0, [#Foo]) + singleOK: {a: "foo"} @test(eq, {a: "foo"}) + singleErr: { + a: 2 + @test(err, code=eval, contains="does not satisfy matchN", pos=[-2:17, -2:24, 0:13]) + } + + [=~"^double"]: matchN(0, [matchN(0, [#Foo])]) + doubleOK: {a: 2} @test(eq, {a: 2}) + doubleErr: { + a: "foo" + @test(err, code=eval, contains="does not satisfy matchN", pos=[-2:17, -2:24, 0:13]) + } +} + +oneOf: { + [=~"^multiple1"]: matchN(1, [math.MultipleOf(3), math.MultipleOf(5)]) + + multiple1Err1: 1 @test(err, code=eval, contains="does not satisfy matchN", pos=[-2:20, -2:27, 0:17]) + + multiple1OK1: 3 @test(eq, 3) + multiple1OK2: 5 @test(eq, 5) + + multiple1Err2: 15 @test(err, code=eval, contains="does not satisfy matchN", pos=[-7:20, -7:27, 0:17]) +} + +anyOf: { + [=~"^multiple1"]: matchN(>0, [math.MultipleOf(3), math.MultipleOf(5)]) + + multiple1Err1: 1 @test(err, code=eval, contains="does not satisfy matchN", pos=[-2:20, -2:27, 0:17]) + + multiple1OK1: 3 @test(eq, 3) + multiple1OK2: 5 @test(eq, 5) + multiple1OK3: 15 @test(eq, 15) +} + + +allOf: { + [=~"^multiple1"]: matchN(2, [math.MultipleOf(3), math.MultipleOf(5)]) + + multiple1Err1: 1 @test(err, code=eval, contains="does not satisfy matchN", pos=[-2:20, -2:27, 0:17]) + multiple1Err2: 3 @test(err, code=eval, contains="does not satisfy matchN", pos=[-3:20, -3:27, 0:17]) + multiple1Err3: 5 @test(err, code=eval, contains="does not satisfy matchN", pos=[-4:20, -4:27, 0:17]) + + multiple1OK1: 15 @test(eq, 15) +} + +bare: { + embed: t1: { + a: {matchN(1, [>10])} + b: {a} + + @test(eq, { + a: matchN(1, [>10]) + b: matchN(1, [>10]) + }) + } + embed: t2: { + b: {a} + a: {matchN(1, [>10])} + + @test(eq, { + b: matchN(1, [>10]) + a: matchN(1, [>10]) + }) + } + direct: t1: { + a: matchN(1, [>10]) + b: a + + @test(eq, { + a: matchN(1, [>10]) + b: matchN(1, [>10]) + }) + } + direct: t2: { + b: a + a: matchN(1, [>10]) + + @test(eq, { + b: matchN(1, [>10]) + a: matchN(1, [>10]) + }) + } +} + +required: { + ok1: { + x: matchN(0, [{foo!: string}]) + x: bar: 2 + @test(eq, {x: {bar: 2}}) + } + ok2: { + x: matchN(0, [{foo!: string}]) + @test(eq, {x: matchN(0, [{ foo!: string }])}) + } + // not matching for different reasons + ok3: { + x: matchN(0, [{bar!: string}]) + x: bar: 2 + @test(eq, {x: {bar: 2}}) + } +} + +// issue3575: Tests that matchN correctly validates structs with extra fields +// whether inside or outside a list argument. https://cuelang.org/issue/3575 +// A struct with extra fields should match whether or not inside a list. +// evalv2 would get this wrong but evalv3 got it right. +issue3575: { + test1: { + #x: matchN(1, [ + [{}], + ]) + x: #x + x: [{a: 1}] + @test(eq, {#x: matchN(1, [[{}]]), x: [{ a: 1 }]}) + } + test2: { + #x: matchN(1, [ + {}, + ]) + x: #x + x: {a: 1} + @test(eq, {#x: matchN(1, [{}]), x: {a: 1}}) + } +} + +-- incomplete.cue -- +import "math" + +// The errors in this section should be "incomplete" errors. +incomplete: { + // foo could still be provided later. + incomplete1: { + x: matchN(1, [{foo!: string}]) + x: bar: 2 + @test(err, code=incomplete, at=x, + suberr=(code=incomplete, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:18])) + } + // foo could still be provided later. + incomplete2: { + x: matchN(1, [{foo!: string}]) + @test(eq, {x: matchN(1, [{ + foo!: string + }])}) + } + // in case of doubt, we should mark an error as incomplete to be safe. + incomplete3: { + x: matchN(math.MultipleOf(2), [{bar!: int}, {foo!: int}]) + x: bar: 2 + @test(eq, {x: {bar: 2}}) + @test(err, code=incomplete, at=x, + suberr=(code=incomplete, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:48])) + } + incomplete4: { + x: matchN(math.MultipleOf(2), [{bar!: int}, {foo!: int}, {baz!: int}]) + x: bar: 2 + @test(eq, {x: {bar: 2}}) + @test(err, code=incomplete, at=x, + suberr=(code=incomplete, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:61]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:48])) + + } + incomplete5: { + x: matchN(>1 & <=3, [{bar!: int}, {foo!: int}, {baz!: int}]) + x: bar: 2 + @test(eq, {x: {bar: 2}}) + @test(err, code=incomplete, at=x, + suberr=(code=incomplete, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:38]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:51])) + } + incomplete6: { + x: matchN(2|3, [{bar!: int}, {foo!: int}, {baz!: int}]) + x: bar: 2 + @test(eq, {x: {bar: 2}}) + @test(err, code=incomplete, at=x, + suberr=(code=incomplete, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:33]), + suberr=(code=incomplete, contains="field is required but not present", pos=[1:6, 1:46])) + } + + // incorrect type cannot be corrected + err1: { + x: matchN(1, [{bar!: string}]) + x: bar: 2 + @test(err, code=eval, at=x, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]) + } + // additional incomplete matches should not be counted if they can otherwise + // not satisfy the constraint. + err2: { + x: matchN(0, [{bar!: int}, {foo!: int}]) + x: bar: 2 + @test(err, code=eval, at=x, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]) + } + // additional incomplete matches should not be counted if they can otherwise + // not satisfy the constraint. + err3: { + x: matchN(2, [{bar!: string}, {foo!: string}]) + x: bar: 2 + @test(err, code=eval, at=x, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]) + } + // one additional potential match cannot make up to satisfy the bound. + err4: { + x: matchN(>1, [{bar!: string}, {foo!: string}]) + x: bar: 2 + @test(err, code=eval, at=x, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]) + } + err5: { + x: matchN(<1, [{bar!: int}, {foo!: int}]) + x: bar: 2 + @test(err, code=eval, at=x, contains="does not satisfy matchN", pos=[1:6, 1:13, 2:6]) + } +} +// issue3389: Tests that matchN only reports schema errors of lesser severity, +// not all constraint failures. https://cuelang.org/issue/3389 +issue3389: { + // only report schema errors that are of a lesser severity. + // TODO(inline): issue converting to tests. Documented later. + x: bar: 2 + x: matchN(1, [{bar: 3}, {bar: 2, foo!: int}]) + + @test(debug, """ + (struct){ + x: (_|_){ + // [incomplete] issue3389.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: + // incomplete.cue:96:5 + // incomplete.cue:95:5 + // incomplete.cue:96:12 + // issue3389.x.foo: field is required but not present: + // incomplete.cue:96:5 + // incomplete.cue:96:35 + bar: (int){ 2 } + } + } + """) +} +-- closedness.cue -- +ellipsis: ok: { + out: #Schema & { + field: shouldBeAllowed: 123 + } + #Schema: { + field?: #anything + #anything: matchN(1, [{ ... }]) + } + @test(eq, { + out: { + field: {shouldBeAllowed: 123} + #anything: matchN(1, [{ ... }]) + } + #Schema: { + field?: matchN(1, [{ ... }]) + #anything: matchN(1, [{ ... }]) + } + }) +} +// Arguments to function are not closed by enclosing definition. +openArguments: ok1: { + #Schema: {{ + a: matchN(1, ["all", {foo: "bar"}]) + }} + out: #Schema & { + a: baz: "allowed" + } + @test(eq, { + #Schema: {a: matchN(1, ["all", { + foo: "bar" + }])} + out: {a: {baz: "allowed"}} + }) +} +openArguments: err2: { + #Schema: {{ + a?: matchN(1, [ //fails + null, // fail + { [string]: string }, // pass + {b: {...}}, // pass + ]) + }} + out: #Schema & { + a: allowed: "once" + } + @test(err, code=eval, at=out.a, contains="does not satisfy matchN", pos=[2:13, 2:20, 9:6]) +} +explicitClose: err1: { + #Schema: {{ + a: matchN(1, ["all", close({foo: "bar"})]) + }} + out: #Schema & { + a: baz: "notAllowed" + } + @test(err, code=eval, at=out.a, contains="does not satisfy matchN", pos=[2:6, 2:13, 5:6]) +} +explicitClose: ok2: { + #Schema: {{ + a?: matchN(1, [ + null, // fail + close({ [string]: string }), // pass + close({b: {...}}), // fail + ]) + }} + out: #Schema & { + a: allowed: "once" + } @test(eq, {a: {allowed: "once"}}) +} +mixed: ok3: { + #Schema: { + exports?: matchN(1, [ + close({ never?: _ }), // fail + #exportsObject, // pass + ]) + + #exports: matchN(1, [string, #exportsObject]) + #exportsObject: exp1?: #exports + } + + out: #Schema & { + exports: exp1: "./main-module.js" + } + // TODO(inline): the errors here are legal structural cycles. We need to + // be able to print those. + @test(eq, { + #Schema: { + exports?: matchN(1, [close({ + never?: _ + }), _|_]) + #exports: matchN(1, [string, _|_]) + #exportsObject: { + exp1?: matchN(1, [string, _|_]) + } + } + out: { + exports: {exp1: "./main-module.js"} + #exports: matchN(1, [string, _|_]) + #exportsObject: { + exp1?: matchN(1, [string, _|_]) + } + } + }) +} + +closedByDefinition: ok4: { + #Schema: { + exports?: matchN(1, [string, #exportsObject]) + #exports: matchN(1, [string, #exportsObject]) + #exportsObject: exp1?: #exports + } + + out: #Schema & { + exports: exp1: "./main-module.js" + } + // TODO(inline): the errors here are legal structural cycles. We need to + // be able to print those. + @test(eq, { + #Schema: { + exports?: matchN(1, [string, _|_]) + #exports: matchN(1, [string, _|_]) + #exportsObject: { + exp1?: matchN(1, [string, _|_]) + } + } + out: { + exports: {exp1: "./main-module.js"} + #exports: matchN(1, [string, _|_]) + #exportsObject: { + exp1?: matchN(1, [string, _|_]) + } + } + }) +} +closedByDefinition: err5: { + #Schema: { + exports?: matchN(1, [null, #exportsObject]) + #exports: matchN(1, [null, #exportsObject]) + #exportsObject: exp1?: #exports + } + + out: #Schema & { + exports: exp1: "./main-module.js" + } + @test(err, code=eval, at=out.exports, contains="does not satisfy matchN", pos=[2:13, 2:20, 8:12]) +} + +-- issue3694.cue -- +// issue3694: Tests that matchN combined with close() correctly validates schemas +// requiring one of several required fields. https://cuelang.org/issue/3694 +issue3694: full: { + #step: matchN(1, [{ + uses!: _ + ... + }, { + run!: _ + ... + }]) + #step: close({ + uses?: string + run?: string + }) + + s: #step & { + run: "echo hello world" + } + @test(eq, { + #step: {uses?: string, run?: string} + s: {run: "echo hello world", uses?: string} + }) +} +issue3694: simple: { + #step: matchN(1, [{ + uses!: _ + }]) + #step: close({ + uses?: string + }) + @test(eq, {#step: {uses?: string}}) +} +@test(err, code=incomplete, at=issue3694.full.#step, contains="does not satisfy matchN", pos=[-29:9, -29:16, -22:9]) +@test(err, code=incomplete, at=issue3694.simple.#step, contains="does not satisfy matchN", pos=[-9:9, -9:16, -6:9]) +-- out/compile -- +--- closedness.cue +{ + ellipsis: { + ok: { + out: (〈0;#Schema〉 & { + field: { + shouldBeAllowed: 123 + } + }) + #Schema: { + field?: 〈0;#anything〉 + #anything: matchN(1, [ + { + ... + }, + ]) + } + } + } + openArguments: { + ok1: { + #Schema: { + { + a: matchN(1, [ + "all", + { + foo: "bar" + }, + ]) + } + } + out: (〈0;#Schema〉 & { + a: { + baz: "allowed" + } + }) + } + } + openArguments: { + err2: { + #Schema: { + { + a?: matchN(1, [ + null, + { + [string]: string + }, + { + b: { + ... + } + }, + ]) + } + } + out: (〈0;#Schema〉 & { + a: { + allowed: "once" + } + }) + } + } + explicitClose: { + err1: { + #Schema: { + { + a: matchN(1, [ + "all", + close({ + foo: "bar" + }), + ]) + } + } + out: (〈0;#Schema〉 & { + a: { + baz: "notAllowed" + } + }) + } + } + explicitClose: { + ok2: { + #Schema: { + { + a?: matchN(1, [ + null, + close({ + [string]: string + }), + close({ + b: { + ... + } + }), + ]) + } + } + out: (〈0;#Schema〉 & { + a: { + allowed: "once" + } + }) + } + } + mixed: { + ok3: { + #Schema: { + exports?: matchN(1, [ + close({ + never?: _ + }), + 〈1;#exportsObject〉, + ]) + #exports: matchN(1, [ + string, + 〈1;#exportsObject〉, + ]) + #exportsObject: { + exp1?: 〈1;#exports〉 + } + } + out: (〈0;#Schema〉 & { + exports: { + exp1: "./main-module.js" + } + }) + } + } + closedByDefinition: { + ok4: { + #Schema: { + exports?: matchN(1, [ + string, + 〈1;#exportsObject〉, + ]) + #exports: matchN(1, [ + string, + 〈1;#exportsObject〉, + ]) + #exportsObject: { + exp1?: 〈1;#exports〉 + } + } + out: (〈0;#Schema〉 & { + exports: { + exp1: "./main-module.js" + } + }) + } + } + closedByDefinition: { + err5: { + #Schema: { + exports?: matchN(1, [ + null, + 〈1;#exportsObject〉, + ]) + #exports: matchN(1, [ + null, + 〈1;#exportsObject〉, + ]) + #exportsObject: { + exp1?: 〈1;#exports〉 + } + } + out: (〈0;#Schema〉 & { + exports: { + exp1: "./main-module.js" + } + }) + } + } +} +--- in.cue +{ + #Foo: { + a: int + } + match: { + [=~"^single"]: matchN(1, [ + 〈2;#Foo〉, + ]) + singleOK: { + a: 2 + } + singleErr: { + a: "foo" + } + [=~"^incomplete"]: matchN(1, [ + 〈2;#Foo〉, + ]) + incompleteOK: { + a: int + } + incompleteErr: { + a: string + } + #A: { + a: int + b: _ + ... + } + defaults: { + [=~"^pickTop"]: matchN(1, [ + 2, + ]) + pickTopOK1: (*2|int) + pickTopOK2: int + pickTopErr: (*3|int) + [=~"^pickNested1"]: matchN(1, [ + { + a: 2 + }, + ]) + pickNested1OK1: { + a: (*2|int) + } + pickNested1OK2: { + a: int + } + pickNested1Err: { + a: (*3|int) + } + [=~"^pickNested2"]: matchN(1, [ + { + a: <=2 + }, + ]) + pickNested2OK1: { + a: (*2|int) + } + pickNested2OK2: { + a: int + } + pickNested2Err: { + a: (*3|int) + } + } + nestedOK: { + matchN(4, [ + 〈2;#A〉, + 〈2;#A〉, + 〈2;#A〉, + 〈2;#A〉, + ]) + a: 2 + b: { + matchN(4, [ + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + ]) + a: 3 + b: matchN(4, [ + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + ]) + b: { + a: 4 + } + c: matchN(4, [ + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + ]) + c: { + a: 5 + } + } + c: { + matchN(4, [ + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + ]) + a: 3 + b: matchN(4, [ + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + ]) + b: { + a: 4 + } + c: matchN(4, [ + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + 〈3;#A〉, + ]) + c: { + a: 5 + } + } + } + } + not: { + [=~"^single"]: matchN(0, [ + 〈2;#Foo〉, + ]) + singleOK: { + a: "foo" + } + singleErr: { + a: 2 + } + [=~"^double"]: matchN(0, [ + matchN(0, [ + 〈3;#Foo〉, + ]), + ]) + doubleOK: { + a: 2 + } + doubleErr: { + a: "foo" + } + } + oneOf: { + [=~"^multiple1"]: matchN(1, [ + 〈import;math〉.MultipleOf(3), + 〈import;math〉.MultipleOf(5), + ]) + multiple1Err1: 1 + multiple1OK1: 3 + multiple1OK2: 5 + multiple1Err2: 15 + } + anyOf: { + [=~"^multiple1"]: matchN(>0, [ + 〈import;math〉.MultipleOf(3), + 〈import;math〉.MultipleOf(5), + ]) + multiple1Err1: 1 + multiple1OK1: 3 + multiple1OK2: 5 + multiple1OK3: 15 + } + allOf: { + [=~"^multiple1"]: matchN(2, [ + 〈import;math〉.MultipleOf(3), + 〈import;math〉.MultipleOf(5), + ]) + multiple1Err1: 1 + multiple1Err2: 3 + multiple1Err3: 5 + multiple1OK1: 15 + } + bare: { + embed: { + t1: { + a: { + matchN(1, [ + >10, + ]) + } + b: { + 〈1;a〉 + } + } + } + embed: { + t2: { + b: { + 〈1;a〉 + } + a: { + matchN(1, [ + >10, + ]) + } + } + } + direct: { + t1: { + a: matchN(1, [ + >10, + ]) + b: 〈0;a〉 + } + } + direct: { + t2: { + b: 〈0;a〉 + a: matchN(1, [ + >10, + ]) + } + } + } + required: { + ok1: { + x: matchN(0, [ + { + foo!: string + }, + ]) + x: { + bar: 2 + } + } + ok2: { + x: matchN(0, [ + { + foo!: string + }, + ]) + } + ok3: { + x: matchN(0, [ + { + bar!: string + }, + ]) + x: { + bar: 2 + } + } + } + issue3575: { + test1: { + #x: matchN(1, [ + [ + {}, + ], + ]) + x: 〈0;#x〉 + x: [ + { + a: 1 + }, + ] + } + test2: { + #x: matchN(1, [ + {}, + ]) + x: 〈0;#x〉 + x: { + a: 1 + } + } + } +} +--- incomplete.cue +{ + incomplete: { + incomplete1: { + x: matchN(1, [ + { + foo!: string + }, + ]) + x: { + bar: 2 + } + } + incomplete2: { + x: matchN(1, [ + { + foo!: string + }, + ]) + } + incomplete3: { + x: matchN(〈import;math〉.MultipleOf(2), [ + { + bar!: int + }, + { + foo!: int + }, + ]) + x: { + bar: 2 + } + } + incomplete4: { + x: matchN(〈import;math〉.MultipleOf(2), [ + { + bar!: int + }, + { + foo!: int + }, + { + baz!: int + }, + ]) + x: { + bar: 2 + } + } + incomplete5: { + x: matchN((>1 & <=3), [ + { + bar!: int + }, + { + foo!: int + }, + { + baz!: int + }, + ]) + x: { + bar: 2 + } + } + incomplete6: { + x: matchN((2|3), [ + { + bar!: int + }, + { + foo!: int + }, + { + baz!: int + }, + ]) + x: { + bar: 2 + } + } + err1: { + x: matchN(1, [ + { + bar!: string + }, + ]) + x: { + bar: 2 + } + } + err2: { + x: matchN(0, [ + { + bar!: int + }, + { + foo!: int + }, + ]) + x: { + bar: 2 + } + } + err3: { + x: matchN(2, [ + { + bar!: string + }, + { + foo!: string + }, + ]) + x: { + bar: 2 + } + } + err4: { + x: matchN(>1, [ + { + bar!: string + }, + { + foo!: string + }, + ]) + x: { + bar: 2 + } + } + err5: { + x: matchN(<1, [ + { + bar!: int + }, + { + foo!: int + }, + ]) + x: { + bar: 2 + } + } + } + issue3389: { + x: { + bar: 2 + } + x: matchN(1, [ + { + bar: 3 + }, + { + bar: 2 + foo!: int + }, + ]) + } +} +--- issue3694.cue +{ + issue3694: { + full: { + #step: matchN(1, [ + { + uses!: _ + ... + }, + { + run!: _ + ... + }, + ]) + #step: close({ + uses?: string + run?: string + }) + s: (〈0;#step〉 & { + run: "echo hello world" + }) + } + } + issue3694: { + simple: { + #step: matchN(1, [ + { + uses!: _ + }, + ]) + #step: close({ + uses?: string + }) + } + } +} diff --git a/internal/core/compile/testdata/sync/builtins/or.txtar b/internal/core/compile/testdata/sync/builtins/or.txtar new file mode 100644 index 000000000..247da0619 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/or.txtar @@ -0,0 +1,47 @@ +-- in.cue -- +// unwrap into single value +unwrap: or([1, 1, 1]) @test(eq, 1) + +// unique duplicate values +unique1: or([2, 1, 1, 2]) @test(eq, 2 | 1) + +unique2: or([{a: 1}, {a: 1}, {a: 2}]) @test(eq, {a: 1} | {a: 2}) + +// do not unique embedded scalars with differing values for child definitions. +embed1: or([{2, #x: 1}, {2, #x: 2}]) @test(eq, {2, #x: 1} | {2, #x: 2}) +-- out/compile -- +--- in.cue +{ + unwrap: or([ + 1, + 1, + 1, + ]) + unique1: or([ + 2, + 1, + 1, + 2, + ]) + unique2: or([ + { + a: 1 + }, + { + a: 1 + }, + { + a: 2 + }, + ]) + embed1: or([ + { + 2 + #x: 1 + }, + { + 2 + #x: 2 + }, + ]) +} diff --git a/internal/core/compile/testdata/sync/builtins/reclose.txtar b/internal/core/compile/testdata/sync/builtins/reclose.txtar new file mode 100644 index 000000000..b221ddaa7 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/reclose.txtar @@ -0,0 +1,329 @@ +-- in.cue -- +@experiment(explicitopen) + +noClose: { + foo: a: int + a: __reclose({ + foo... + }) + + t1: ok: a & {b: 1} + @test(eq, { + foo: {a: int} + a: {a: int} + t1: {ok: {b: 1, a: int}} + }) +} + +recursive: { + #x: { foo: int} + // Basic usage of __reclose - makes structs recursively closed + a: __reclose({ + #x... + nested: field2: int + }) + + // Test that extra fields are not allowed (should error) + t1: err: a & {extra: "not allowed"} @test(err, code=eval, path=extra, contains="field not allowed", pos=[0:16]) + + t2: ok: a & {nested: field2: 5} @test(eq, {nested: {field2: 5}, foo: int}) + t3: ok: a & {foo: 5} @test(eq, {foo: 5, nested: {field2: int}}) + + + // Test that nested extra fields are not allowed (should error) + t4: err: a & { + nested: { + field2: 1 + extra: "not allowed" + } + } @test(err, code=eval, path=nested.extra, contains="field not allowed", pos=[3:4]) + + // Test with empty struct + // TODO(eval): is this correct? + e: __reclose({}) + t5: err: e & {extra: "not allowed"} @test(eq, {extra: "not allowed"}) +} + + +nonRecursive: { + x: __reclose({ + close({b: int})... + c: int + d: e: int + }) + y: err: x & {f: int} @test(err, code=eval, path=f, contains="field not allowed", pos=[0:15]) + z: ok: x & {d: f: int} @test(eq, {d: {f: int, e: int}, c: int, b: int}) +} + +// Test that __reclose detects and restores non-recursive closing from +// an embedded close()-d value that was opened with .... +nonRecursiveDetect: { + foo: close({b: {}}) + a: __reclose({ + foo... + }) + // Top-level field not allowed: non-recursive close restored by __reclose. + t1: err: a & {f: int} @test(err, code=eval, path=f, contains="field not allowed", pos=[0:16]) + // Nested field allowed: close was non-recursive, so b is still open. + t2: ok: a & {b: c: 1} @test(eq, {b: {c: 1}}) +} + +// Test that __reclose handles both recursive and non-recursive closing +// when both are present. +// +// NOTE: one would expect that with the old semantics, b.c is allowed in t2. +// But it is NOT. To mimic the old behavior, cue fix _could_ just use __closeAll +// in this case. Users can than chose to use __reclose instead to relax the +// condition. +mixedClose: { + #D: {x: y: int} + foo: close({b: {}}) + a: __reclose({ + #D... + foo... + }) + // Top-level extra field not allowed. + t1: err: a & {f: int} @test(err, code=eval, path=f, contains="field not allowed", pos=[0:16]) + // Allowed fields work. + t2: ok: a & {x: y: 5, b: c: 1} @test(eq, {x: {y: 5}, b: {c: 1}}) +} + +// Test that __reclose can wrap a close() call and conditionally add +// recursive closing on top. This is the pattern generated by cue fix +// when a close() at field-value level wraps a struct with embeddings. +recloseWrapsClose: { + #def: {a: b: int} + a: __reclose(close({ + #def... + })) + // Top-level extra field not allowed (close provides non-recursive). + t1: err: a & {f: int} @test(err, code=eval, path=f, contains="field not allowed", pos=[0:16]) + // Nested extra field not allowed (__reclose detects recursive from #def). + t2: err: a & {a: c: 1} @test(err, code=eval, path=a.c, contains="field not allowed", pos=[0:19]) + // Allowed nested field works. + t3: ok: a & {a: b: 5} @test(eq, {a: {b: 5}}) +} + +nonStructLiterals: { + // Test with non-struct should error + t1: err: __reclose("not a struct") @test(err, code=eval, contains="error in call to %s", args=[__reclose], pos=[0:11]) + + + #A: a: int + t4: err: __reclose(#A) @test(err, code=eval, contains="error in call to %s", args=[__reclose], pos=[0:11]) +} + +nonStructDefinitions: { + #Def: 1 + + a: __reclose({ + #Def... + }) + + t1: ok: a & 1 @test(eq, 1) + + // errors because of regular field + embedded scalar + t2: err: a & {b: 1} @test(err, code=eval, + contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[{b:1}, 1, struct, int], pos=[-9:8, 0:11, 0:15]) +} + +-- old.cue -- +retro: { + // May not be used if explicitopen is not set. + t1: err: __reclose({}) @test(err, code=eval, contains="error in call to %s", args=[__reclose], pos=[0:11]) +} + +-- out/compile -- +--- in.cue +{ + noClose: { + foo: { + a: int + } + a: __reclose({ + 〈1;foo〉... + }) + t1: { + ok: (〈1;a〉 & { + b: 1 + }) + } + } + recursive: { + #x: { + foo: int + } + a: __reclose({ + 〈1;#x〉... + nested: { + field2: int + } + }) + t1: { + err: (〈1;a〉 & { + extra: "not allowed" + }) + } + t2: { + ok: (〈1;a〉 & { + nested: { + field2: 5 + } + }) + } + t3: { + ok: (〈1;a〉 & { + foo: 5 + }) + } + t4: { + err: (〈1;a〉 & { + nested: { + field2: 1 + extra: "not allowed" + } + }) + } + e: __reclose({}) + t5: { + err: (〈1;e〉 & { + extra: "not allowed" + }) + } + } + nonRecursive: { + x: __reclose({ + close({ + b: int + })... + c: int + d: { + e: int + } + }) + y: { + err: (〈1;x〉 & { + f: int + }) + } + z: { + ok: (〈1;x〉 & { + d: { + f: int + } + }) + } + } + nonRecursiveDetect: { + foo: close({ + b: {} + }) + a: __reclose({ + 〈1;foo〉... + }) + t1: { + err: (〈1;a〉 & { + f: int + }) + } + t2: { + ok: (〈1;a〉 & { + b: { + c: 1 + } + }) + } + } + mixedClose: { + #D: { + x: { + y: int + } + } + foo: close({ + b: {} + }) + a: __reclose({ + 〈1;#D〉... + 〈1;foo〉... + }) + t1: { + err: (〈1;a〉 & { + f: int + }) + } + t2: { + ok: (〈1;a〉 & { + x: { + y: 5 + } + b: { + c: 1 + } + }) + } + } + recloseWrapsClose: { + #def: { + a: { + b: int + } + } + a: __reclose(close({ + 〈1;#def〉... + })) + t1: { + err: (〈1;a〉 & { + f: int + }) + } + t2: { + err: (〈1;a〉 & { + a: { + c: 1 + } + }) + } + t3: { + ok: (〈1;a〉 & { + a: { + b: 5 + } + }) + } + } + nonStructLiterals: { + t1: { + err: __reclose("not a struct") + } + #A: { + a: int + } + t4: { + err: __reclose(〈1;#A〉) + } + } + nonStructDefinitions: { + #Def: 1 + a: __reclose({ + 〈1;#Def〉... + }) + t1: { + ok: (〈1;a〉 & 1) + } + t2: { + err: (〈1;a〉 & { + b: 1 + }) + } + } +} +--- old.cue +{ + retro: { + t1: { + err: __reclose({}) + } + } +} diff --git a/internal/core/compile/testdata/sync/builtins/validators.txtar b/internal/core/compile/testdata/sync/builtins/validators.txtar new file mode 100644 index 000000000..ba49e83a2 --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/validators.txtar @@ -0,0 +1,600 @@ +-- in.cue -- +import ( + "encoding/json" + "list" + "struct" +) + +// non-monotonic builtins must fail with an "incomplete" error if there +// is a possibility the constraint can get resolved by becoming more specific. +incompleteError1: { + MyType: { + kv: struct.MinFields(1) + } + + foo: MyType & { + kv: joel: "testing" + } + @test(eq, { + MyType: {kv: struct.MinFields(1)} + foo: {kv: {joel: "testing"}} + }) +} + +incompleteError2: { + MyType: { + kv: [string]: string + kv: struct.MinFields(1) @test(err, code=incomplete, + contains="does not satisfy struct.MinFields(1)", pos=[0:7, -1:7, 0:24]) + } + + foo: MyType & { + kv: joel: "testing" + } @test(eq, { + kv: {joel: "testing"} + }) +} + +incompleteError3: { + t: string + t: json.Validate(string) + @test(eq, {t: string & json.Validate(string)}) +} + +uniqueConstrains1: { + t: string + t: json.Validate(string) + t: json.Validate(string) + @test(eq, {t: json.Validate(string) & string}) +} + +uniqueConstrains2: { + t: struct.MaxFields(1) + t: struct.MaxFields(1) + @test(eq, {t: struct.MaxFields(1)}) +} + +violation: { + #MyType: { + kv: [string]: string + kv: struct.MinFields(1) @test(err, code=incomplete, contains="does not satisfy struct.MinFields(1)", pos=[0:7, -1:7, 0:24]) + } + + foo: #MyType & { + kv: joel: "testing" + kv: tony: "testing" + } @test(eq, {kv: {joel: "testing", tony: "testing"}}) +} + +conjuncts: { + kv: struct.MinFields(1) + kv: struct.MaxFields(3) + @test(eq, {kv: struct.MinFields(1) & struct.MaxFields(3)}) +} + +// TODO: stripe off conflicting pairs +// conflicting: { +// kv: struct.MinFields(3) +// kv: struct.MaxFields(1) +// } + +// Builtins with bool return that can be used as validator. + +bareBuiltin: { + a: json.Valid + a: json.Valid + @test(eq, { a: json.Valid() }) +} + +bareBuiltinCheck: { + a: json.Valid + a: "3" + @test(eq, {a: "3"}) +} + +builtinValidator: { + a: json.Valid() + a: json.Valid() + @test(eq, {a: json.Valid()}) +} + +builtinValidatorCheck: { + a: json.Valid() + a: "3" + @test(eq, {a: "3"}) +} + +callOfCallToValidator: { + a: json.Valid + b: a() @test(eq, { json.Valid() }) + e: b() @test(err, code=eval, contains="cannot call previously called validator", pos=[0:5]) + e: "5" +} + +validatorAsFunction: { + a: json.Valid + b: a("3") + c: json.Valid("3") + @test(eq, {a: json.Valid(), b: true, c: true}) +} + +// issue2098: Tests that list.MinItems() does not panic when combined with list +// embedding and index access. https://cuelang.org/issue/2098 +issue2098: ok1: { + _a: [1, ...] + _a: list.MinItems(1) + _a[0] + @test(eq, {_a: [1], 1}) +} + +issue2098: incomplete1: { + _a: [...] + _a: list.MinItems(1) + _a[0] + @test(err, code=incomplete, contains="index out of range", pos=[3:5]) +} + +-- issue3418.cue -- +// issue3418: Tests that matchN correctly reports validation failures when +// combined with conflicting constraints, regardless of operand order. +// https://cuelang.org/issue/3418 +issue3418: t1: "foo" & matchN(1, [1&2]) & matchN(1, [_]) @test(err, code=eval, + contains="does not satisfy matchN", pos=[0:24, 0:16, 0:31, 0:35, 0:37]) + +issue3418: t2: "foo" & matchN(1, [_]) & matchN(1, [1&2]) @test(err, code=eval, + contains="does not satisfy matchN", pos=[0:41, 0:16, 0:48, 0:52, 0:54]) + +issue3418: t3: { + x: "foo" + x: matchN(1, [_]) + x: matchN(1, [1&2]) + + @test(err, code=eval, at=x, contains="does not satisfy matchN", pos=[3:5, 1:5, 2:5, 3:12, 3:16, 3:18]) + +} +issue3418: t4: { + x: "foo" + x: matchN(1, [1&2]) + x: matchN(1, [_]) + + @test(err, code=eval, at=x, contains="does not satisfy matchN", pos=[2:5, 1:5, 2:12, 2:16, 2:18, 3:5]) +} + + +-- issue3474.cue -- +import "struct" + +// issue3474: Tests that struct.MinFields/MaxFields validators correctly handle +// fields added by conditional comprehensions. https://cuelang.org/issue/3474 +issue3474: structValidator: ok: { + // Passes only after the comprehension is evaluated. + A: struct.MinFields(1) + A: { + if true {B: true} + } + @test(eq, {A: {B: true}}) +} +issue3474: structValidator: failAfter: { + // Passes only before the comprehension is evaluated. + A: struct.MaxFields(1) + A: { + C: true + if true {B: true} + } @test(err, code=eval, contains="does not satisfy struct.MaxFields(1)", pos=[-1:5, -1:22, 0:5]) +} +issue3474: structValidator: incomplete: { + // Passes neither before nor after the comprehension is evaluated. + A: struct.MinFields(1) + A: { + if true {} + } @test(err, code=incomplete, contains="len(fields) < MinFields(1) (0 < 1)", pos=[-1:5, -1:22, 0:5]) +} +issue3474: structValidator: failClosed: { + // Passes neither before nor after the comprehension is evaluated. + #A: struct.MinFields(1) + #A: { + if true {} + } @test(err, code=eval, contains="does not satisfy struct.MinFields", pos=[-1:6, -1:23, 0:6]) +} + + +issue3474: topValidator: ok: { + A: matchN(1, [>10]) + A: { + if true {100} + } + @test(eq, {A: 100}) +} +issue3474: topValidator: fail: { + A: matchN(1, [>10]) + A: { + if true {1} + } @test(err, code=eval, contains="does not satisfy matchN", pos=[-1:5, -1:12, 0:5, 1:12]) + +} +issue3474: topValidator: incomplete: { + A: matchN(1, [>10]) + A: { + if true {int} + } + @test(eq, {A: matchN(1, [>10]) & int}) +} +issue3474: topValidator: failType: { + A: matchN(1, [>10]) + A: { + if true {C: 1} + } @test(err, code=eval, contains="does not satisfy matchN", pos=[-1:5, -1:12, 0:5]) +} + +-- validator_is_top.cue -- +// issue3639: Tests that embedding a matchN validator struct alongside direct +// application does not cause "field not allowed" errors. https://cuelang.org/issue/3639 +issue3639: { + a: {#X} & #X + a: b: 1 + #X: matchN(1, [{b: int}]) + @test(eq, { + a: {b: 1} + #X: matchN(1, [{ b: int }]) + }) +} +// issue3661: Tests that matchN with a required field validator works when +// applied via a pattern constraint. https://cuelang.org/issue/3661 +issue3661: { + #X: matchN(1, [{ b!: int }]) + a: b: 1 + a: #X + ["a"]: #X + @test(eq, { + #X: matchN(1, [{ b!: int }]) + a: {b: 1} + }) +} +// issue3678: Tests that matchN with multiple required-field alternatives does not +// produce spurious "field not allowed" errors. https://cuelang.org/issue/3678 +issue3678: { + #X: matchN(1, [{ + a!: string + }, { + c!: string + }]) + + x: c: "c" + + y: #X + y: x + x: #X + @test(eq, { + #X: matchN(1, [{ a!: string }, { c!: string }]) + x: {c: "c"} + y: {c: "c"} + }) +} +// issue3981: Tests that matchN combined with close() correctly handles open +// struct arguments without topological sort regressions. https://cuelang.org/issue/3981 +issue3981: matchWithClose: { + out: { + close({ + f1: matchN(1, [#openStruct]) + }) + #openStruct: {...} + } + out: f1: foo: ["bar"] + @test(eq, { + out: {#openStruct: {}, f1: {foo: ["bar"]}} + }) +} +-- out/compile -- +--- in.cue +{ + incompleteError1: { + MyType: { + kv: 〈import;struct〉.MinFields(1) + } + foo: (〈0;MyType〉 & { + kv: { + joel: "testing" + } + }) + } + incompleteError2: { + MyType: { + kv: { + [string]: string + } + kv: 〈import;struct〉.MinFields(1) + } + foo: (〈0;MyType〉 & { + kv: { + joel: "testing" + } + }) + } + incompleteError3: { + t: string + t: 〈import;"encoding/json"〉.Validate(string) + } + uniqueConstrains1: { + t: string + t: 〈import;"encoding/json"〉.Validate(string) + t: 〈import;"encoding/json"〉.Validate(string) + } + uniqueConstrains2: { + t: 〈import;struct〉.MaxFields(1) + t: 〈import;struct〉.MaxFields(1) + } + violation: { + #MyType: { + kv: { + [string]: string + } + kv: 〈import;struct〉.MinFields(1) + } + foo: (〈0;#MyType〉 & { + kv: { + joel: "testing" + } + kv: { + tony: "testing" + } + }) + } + conjuncts: { + kv: 〈import;struct〉.MinFields(1) + kv: 〈import;struct〉.MaxFields(3) + } + bareBuiltin: { + a: 〈import;"encoding/json"〉.Valid + a: 〈import;"encoding/json"〉.Valid + } + bareBuiltinCheck: { + a: 〈import;"encoding/json"〉.Valid + a: "3" + } + builtinValidator: { + a: 〈import;"encoding/json"〉.Valid() + a: 〈import;"encoding/json"〉.Valid() + } + builtinValidatorCheck: { + a: 〈import;"encoding/json"〉.Valid() + a: "3" + } + callOfCallToValidator: { + a: 〈import;"encoding/json"〉.Valid + b: 〈0;a〉() + e: 〈0;b〉() + e: "5" + } + validatorAsFunction: { + a: 〈import;"encoding/json"〉.Valid + b: 〈0;a〉("3") + c: 〈import;"encoding/json"〉.Valid("3") + } + issue2098: { + ok1: { + _a: [ + 1, + ..., + ] + _a: 〈import;list〉.MinItems(1) + 〈0;_a〉[0] + } + } + issue2098: { + incomplete1: { + _a: [ + ..., + ] + _a: 〈import;list〉.MinItems(1) + 〈0;_a〉[0] + } + } +} +--- issue3418.cue +{ + issue3418: { + t1: (("foo" & matchN(1, [ + (1 & 2), + ])) & matchN(1, [ + _, + ])) + } + issue3418: { + t2: (("foo" & matchN(1, [ + _, + ])) & matchN(1, [ + (1 & 2), + ])) + } + issue3418: { + t3: { + x: "foo" + x: matchN(1, [ + _, + ]) + x: matchN(1, [ + (1 & 2), + ]) + } + } + issue3418: { + t4: { + x: "foo" + x: matchN(1, [ + (1 & 2), + ]) + x: matchN(1, [ + _, + ]) + } + } +} +--- issue3474.cue +{ + issue3474: { + structValidator: { + ok: { + A: 〈import;struct〉.MinFields(1) + A: { + if true { + B: true + } + } + } + } + } + issue3474: { + structValidator: { + failAfter: { + A: 〈import;struct〉.MaxFields(1) + A: { + C: true + if true { + B: true + } + } + } + } + } + issue3474: { + structValidator: { + incomplete: { + A: 〈import;struct〉.MinFields(1) + A: { + if true {} + } + } + } + } + issue3474: { + structValidator: { + failClosed: { + #A: 〈import;struct〉.MinFields(1) + #A: { + if true {} + } + } + } + } + issue3474: { + topValidator: { + ok: { + A: matchN(1, [ + >10, + ]) + A: { + if true { + 100 + } + } + } + } + } + issue3474: { + topValidator: { + fail: { + A: matchN(1, [ + >10, + ]) + A: { + if true { + 1 + } + } + } + } + } + issue3474: { + topValidator: { + incomplete: { + A: matchN(1, [ + >10, + ]) + A: { + if true { + int + } + } + } + } + } + issue3474: { + topValidator: { + failType: { + A: matchN(1, [ + >10, + ]) + A: { + if true { + C: 1 + } + } + } + } + } +} +--- validator_is_top.cue +{ + issue3639: { + a: ({ + 〈1;#X〉 + } & 〈0;#X〉) + a: { + b: 1 + } + #X: matchN(1, [ + { + b: int + }, + ]) + } + issue3661: { + #X: matchN(1, [ + { + b!: int + }, + ]) + a: { + b: 1 + } + a: 〈0;#X〉 + ["a"]: 〈0;#X〉 + } + issue3678: { + #X: matchN(1, [ + { + a!: string + }, + { + c!: string + }, + ]) + x: { + c: "c" + } + y: 〈0;#X〉 + y: 〈0;x〉 + x: 〈0;#X〉 + } + issue3981: { + matchWithClose: { + out: { + close({ + f1: matchN(1, [ + 〈2;#openStruct〉, + ]) + }) + #openStruct: { + ... + } + } + out: { + f1: { + foo: [ + "bar", + ] + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/builtins/versionchk.txtar b/internal/core/compile/testdata/sync/builtins/versionchk.txtar new file mode 100644 index 000000000..4034a09cd --- /dev/null +++ b/internal/core/compile/testdata/sync/builtins/versionchk.txtar @@ -0,0 +1,15 @@ +#inlinetest:exclude the CUE source triggers a compile-time version error which +# prevents the inline runner from compiling the source. +-- cue.mod/module.cue -- +module: "cuelang.org/go/internal/core/adt/eval_test" +language: version: "v0.8.0" +-- in.cue -- +// error is not yet available in v0.8.0. +a: error("msg") +-- out/compile -- +a: builtin "error" is not available in version v0.8.0; it was added in version "v0.14.0": + ./in.cue:2:4 +--- in.cue +{ + a: _|_(builtin "error" is not available in version v0.8.0; it was added in version "v0.14.0")("msg") +} diff --git a/internal/core/compile/testdata/sync/choosedefault/000_pick_first.txtar b/internal/core/compile/testdata/sync/choosedefault/000_pick_first.txtar new file mode 100644 index 000000000..4e6f9a18e --- /dev/null +++ b/internal/core/compile/testdata/sync/choosedefault/000_pick_first.txtar @@ -0,0 +1,19 @@ +-- in.cue -- +a: *5 | "a" | true @test(eq, *5 | "a" | true) +b: c: *{ + a: 2 +} | { + a: 3 +} @test(eq, *{a: 2} | {a: 3}) +-- out/compile -- +--- in.cue +{ + a: (*5|"a"|true) + b: { + c: (*{ + a: 2 + }|{ + a: 3 + }) + } +} diff --git a/internal/core/compile/testdata/sync/choosedefault/001_simple_disambiguation_conflict.txtar b/internal/core/compile/testdata/sync/choosedefault/001_simple_disambiguation_conflict.txtar new file mode 100644 index 000000000..666f73a86 --- /dev/null +++ b/internal/core/compile/testdata/sync/choosedefault/001_simple_disambiguation_conflict.txtar @@ -0,0 +1,11 @@ +-- in.cue -- +a: *"a" | "b" @test(eq, *"a" | "b") +b: *"b" | "a" @test(eq, *"b" | "a") +c: a & b @test(eq, "a" | "b") +-- out/compile -- +--- in.cue +{ + a: (*"a"|"b") + b: (*"b"|"a") + c: (〈0;a〉 & 〈0;b〉) +} diff --git a/internal/core/compile/testdata/sync/choosedefault/002_associativity_of_defaults.txtar b/internal/core/compile/testdata/sync/choosedefault/002_associativity_of_defaults.txtar new file mode 100644 index 000000000..96a1c67ae --- /dev/null +++ b/internal/core/compile/testdata/sync/choosedefault/002_associativity_of_defaults.txtar @@ -0,0 +1,143 @@ +#name: associativity of defaults +#evalFull +-- in.cue -- +a: *"a" | ("b" | "c") @test(eq, *"a" | "b" | "c") +b: (*"a" | "b") | "c" @test(eq, *"a" | "b" | "c") +c: *"a" | (*"b" | "c") @test(eq, *"a" | "b" | "c") +x: a & b @test(eq, *"a" | "b" | "c") +y: b & c @test(eq, *"a" | "b" | "c") + +s1: *1 | ((*2 | 3) & (2 | *3)) @test(eq, *1 | 2 | 3) +s2: *1 | ((*2 | 3) & (*2 | 3)) @test(eq, *1 | 2 | 3) +s3: *1 | ((*2 | 3) & 3) @test(eq, *1 | 3) +s4: *1 | ((*2 | 3) & 2) @test(eq, *1 | 2) +s5: *1 | *(*2 | 3) @test(eq, *1 | *2 | 3) + +e1: *(1&2) | (*"x" | string) @test(eq, "x" | string) +e2: (*"x" | string) | *(1&2) @test(eq, "x" | string) + +-- complex.cue -- +// add some test cases suggested by an automated prover based on this pattern: +// 1. ValK = (ValA & ValB_ND) & ValC_D \neq _|_ (the element we track must exist). +// 2. ValC_D & (ValA & ValB_D) = _|_ (for Path 1 Cond(ValC_D, Disj_AB) to be true). +// 3. ValC_D & ValB_D \neq _|_ (for Path 2 Cond(ValC_D, Disj_B) to be false). + +// Let's define these CUE values. The trick is that ValA must introduce a +// component that causes ValC_D to conflict with (ValA & ValB_D), +// but ValC_D must *not* conflict with ValB_D on its own. +t1: { + va: {a: 1, b: 2} + vb1: {c: 3} + vb2: {c: 4} + vc : {c: 4} + vd: string + + A: va | vd @test(eq, {a: 1, b: 2} | string) + B: *vb1 | vb2 | vd @test(eq, *{c: 3} | {c: 4} | string) + C: *vc | vd @test(eq, *{c: 4} | string) + + p1: (A & B) & C @test(eq, *{a: 1, b: 2, c: 4} | string) + p2: A & (B & C) @test(eq, *{a: 1, b: 2, c: 4} | string) +} +t2: { + va: 0 | 1 | 2 + vb1: 2 | 3 + vb2: 0 | 1 | 4 + vc: 0 | 3 | 4 + vd: string + + A: va | vd @test(eq, 0 | 1 | 2 | string) + B: *vb1 | vb2 | vd @test(eq, *2 | *3 |0 | 1 | 4 | string) + C: *vc | vd @test(eq, *0 | *3 | *4 | string) + + p1: (A & B) & C @test(eq, *0 | string) + p2: A & (B & C) @test(eq, *0 | string) +} +-- issue3908.cue -- +// issue3908: Tests that nested defaults (e.g. null default overridden by a +// string default) are handled correctly in evalv3. https://cuelang.org/issue/3908 +issue3908: reduced: { + @test(permute) + string | *null + string | *"str" + @test(eq, *"str" | string) +} +issue3908: full: { + out: #Schema & { field: string | *"dataDefault" } + #Schema: field: string | *null + @test(eq, { + out: field: *"dataDefault" | string + #Schema: field: *null | string + }) +} +-- out/compile -- +--- complex.cue +{ + t1: { + va: { + a: 1 + b: 2 + } + vb1: { + c: 3 + } + vb2: { + c: 4 + } + vc: { + c: 4 + } + vd: string + A: (〈0;va〉|〈0;vd〉) + B: (*〈0;vb1〉|〈0;vb2〉|〈0;vd〉) + C: (*〈0;vc〉|〈0;vd〉) + p1: ((〈0;A〉 & 〈0;B〉) & 〈0;C〉) + p2: (〈0;A〉 & (〈0;B〉 & 〈0;C〉)) + } + t2: { + va: (0|1|2) + vb1: (2|3) + vb2: (0|1|4) + vc: (0|3|4) + vd: string + A: (〈0;va〉|〈0;vd〉) + B: (*〈0;vb1〉|〈0;vb2〉|〈0;vd〉) + C: (*〈0;vc〉|〈0;vd〉) + p1: ((〈0;A〉 & 〈0;B〉) & 〈0;C〉) + p2: (〈0;A〉 & (〈0;B〉 & 〈0;C〉)) + } +} +--- in.cue +{ + a: (*"a"|("b"|"c")) + b: ((*"a"|"b")|"c") + c: (*"a"|(*"b"|"c")) + x: (〈0;a〉 & 〈0;b〉) + y: (〈0;b〉 & 〈0;c〉) + s1: (*1|((*2|3) & (2|*3))) + s2: (*1|((*2|3) & (*2|3))) + s3: (*1|((*2|3) & 3)) + s4: (*1|((*2|3) & 2)) + s5: (*1|*(*2|3)) + e1: (*(1 & 2)|(*"x"|string)) + e2: ((*"x"|string)|*(1 & 2)) +} +--- issue3908.cue +{ + issue3908: { + reduced: { + (string|*null) + (string|*"str") + } + } + issue3908: { + full: { + out: (〈0;#Schema〉 & { + field: (string|*"dataDefault") + }) + #Schema: { + field: (string|*null) + } + } + } +} diff --git a/internal/core/compile/testdata/sync/compile/alias.txtar b/internal/core/compile/testdata/sync/compile/alias.txtar new file mode 100644 index 000000000..e9bdb6b9a --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/alias.txtar @@ -0,0 +1,18 @@ +-- in.cue -- +dynamic: { + @test(permute, count=6) + + X=(a): 1 + x: X + a: "name" + @test(eq, {x: 1, a: "name", name: 1}) +} +-- out/compile -- +--- in.cue +{ + dynamic: { + 〈0;a〉: 1 + x: 〈0;(〈0;a〉)〉 + a: "name" + } +} diff --git a/internal/core/compile/testdata/sync/compile/err_top.txtar b/internal/core/compile/testdata/sync/compile/err_top.txtar new file mode 100644 index 000000000..a1dd41a07 --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/err_top.txtar @@ -0,0 +1,69 @@ +#inlinetest:exclude skip — compile errors. +-- in.cue -- +disallowTopAsAlias: { + _=X: 1 +} + +disallowTopAsLet: { + let _ = 1 +} + +disallowTopAsLabel: { + _: 1 + a: _ // Should not compile to a reference. +} + +// TODO: disallow dollar as label? This is according to the spec, but it +// will be a breaking change and $ was reserved for referring to the root of +// a file, which we very likely will never implement. +// disallowDollarAsLabel: { +// $: 1 +// } + +// When printing errors with paths from the compiler or evaluator, +// ensure that odd string labels get quoted correctly. +nested: "_": _: 1 +nested: "_foo": _: 1 +nested: "#foo": _: 1 + +-- out/compile -- +disallowTopAsAlias: cannot use _ as alias or let clause: + ./in.cue:2:2 +disallowTopAsLet: cannot use _ as alias or let clause: + ./in.cue:6:6 +disallowTopAsLabel: cannot use _ as label: + ./in.cue:10:2 +nested."_": cannot use _ as label: + ./in.cue:23:14 +nested."_foo": cannot use _ as label: + ./in.cue:24:17 +nested."#foo": cannot use _ as label: + ./in.cue:25:17 +--- in.cue +{ + disallowTopAsAlias: { + X: 1 + } + disallowTopAsLet: { + let _ = 1 + } + disallowTopAsLabel: { + _|_(cannot use _ as label) + a: _ + } + nested: { + "_": { + _|_(cannot use _ as label) + } + } + nested: { + "_foo": { + _|_(cannot use _ as label) + } + } + nested: { + "#foo": { + _|_(cannot use _ as label) + } + } +} diff --git a/internal/core/compile/testdata/sync/compile/erralias.txtar b/internal/core/compile/testdata/sync/compile/erralias.txtar new file mode 100644 index 000000000..fb421f4aa --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/erralias.txtar @@ -0,0 +1,30 @@ +// Caused a stack overflow on evalv2. +#inlinetest:exclude skip: compile errors. +-- in.cue -- + let X = {} + +[Y="foo"]: 3 +a: Y + +c: {} +for x in c {a: E} + +Z1=[Z2=string]: Z1 + Z2 +-- out/compile -- +unreferenced alias or let clause X: + ./in.cue:1:2 +a: reference "Y" not found: + ./in.cue:4:12 +for[].a: reference "E" not found: + ./in.cue:7:16 +--- in.cue +{ + let X#1 = {} + ["foo"]: 3 + a: _|_(reference "Y" not found) + c: {} + for _, x in 〈0;c〉 { + a: _|_(reference "E" not found) + } + [string]: (〈0;(〈0;-〉)〉 + 〈0;-〉) +} diff --git a/internal/core/compile/testdata/sync/compile/experiment.txtar b/internal/core/compile/testdata/sync/compile/experiment.txtar new file mode 100644 index 000000000..8e4d41f05 --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/experiment.txtar @@ -0,0 +1,20 @@ +-- cue.mod/module.cue -- +module: "x.test" +language: version: "v0.13.0" +-- off.cue -- +off: __test_experiment("off") @test(err, code=eval, contains="testing experiment disabled", pos=[0:6]) + +-- on.cue -- +@experiment(testing) + +on: __test_experiment("on") @test(eq, "on") + +-- out/compile -- +--- off.cue +{ + off: testExperiment("off") +} +--- on.cue +{ + on: testExperiment("on") +} diff --git a/internal/core/compile/testdata/sync/compile/fields.txtar b/internal/core/compile/testdata/sync/compile/fields.txtar new file mode 100644 index 000000000..c96f0bd6d --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/fields.txtar @@ -0,0 +1,13 @@ +-- in.cue -- +#dev: int @test(eq, int) +"#dev": int @test(eq, int) +_dev: int @test(eq, int) +_#dev: int @test(eq, int) +-- out/compile -- +--- in.cue +{ + #dev: int + "#dev": int + _dev: int + _#dev: int +} diff --git a/internal/core/compile/testdata/sync/compile/files.txtar b/internal/core/compile/testdata/sync/compile/files.txtar new file mode 100644 index 000000000..afd94d0f6 --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/files.txtar @@ -0,0 +1,30 @@ +# Issue #946: Tests that a for comprehension variable that shadows the source +# name (for a in a) compiles correctly and resolves scoping at the right depth. +# https://cuelang.org/issue/946 +-- in.cue -- +package repro + +a: [] @test(eq, []) +-- out.cue -- +package repro + +x: {for a in a {}} @test(eq, {}) +y: {{{for a in a {}}}} @test(eq, {}) +-- out/compile -- +--- in.cue +{ + a: [] +} +--- out.cue +{ + x: { + for _, a in 〈1;a〉 {} + } + y: { + { + { + for _, a in 〈3;a〉 {} + } + } + } +} diff --git a/internal/core/compile/testdata/sync/compile/json.txtar b/internal/core/compile/testdata/sync/compile/json.txtar new file mode 100644 index 000000000..d6017252f --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/json.txtar @@ -0,0 +1,44 @@ +# Issue #721: Tests that front-style (leading) commas are allowed in CUE source. +# https://cuelang.org/issue/721 +#noformat +-- in.cue -- +// allow front-style commas +a +: { "key": "value" +, "key2" +: "value2" +} + +, b: [ + 0 +, 1 +, 2 + ,3, + 4 + + , 5 +] + +@test(eq, { + a: { + key: "value" + key2: "value2" + } + b: [0, 1, 2, 3, 4, 5] +}) +-- out/compile -- +--- in.cue +{ + a: { + key: "value" + key2: "value2" + } + b: [ + 0, + 1, + 2, + 3, + 4, + 5, + ] +} diff --git a/internal/core/compile/testdata/sync/compile/labels.txtar b/internal/core/compile/testdata/sync/compile/labels.txtar new file mode 100644 index 000000000..fa59420eb --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/labels.txtar @@ -0,0 +1,92 @@ +#inlinetest:exclude skip: compile errors. +-- in.cue -- +package compile + +import "list" + +dis1: "dev" | "prd" +dis2: *"dev" | "prd" + +con1: string +let con2 = string + +ok0: [string]: string +ok1: [name=string]: string +ok2: [con1]: string +ok3: [con2]: string +ok4: ["foo"]: string +ok5: [1]: string // disallowed in evaluator +ok6: [name=1]: string // disallowed in evaluator +ok7: [dis1]: string +ok8: [dis2]: string +ok9: [name=dis2]: string +ok10: [{foo: "bar"}]: string // disallowed in evaluator +ok11: [list.FlattenN([string], 1)]: string // disallowed in evaluator + +bad1: [for x in [1, 2, 3] {x}]: string + +saneReferencesInComprehensions: { + for _ in [1] { + a: _ // Should not compile to a reference. + } +} +-- out/compile -- +bad1: comprehension values not allowed in this position: + ./in.cue:24:8 +--- in.cue +{ + dis1: ("dev"|"prd") + dis2: (*"dev"|"prd") + con1: string + let con2#1 = string + ok0: { + [string]: string + } + ok1: { + [string]: string + } + ok2: { + [〈1;con1〉]: string + } + ok3: { + [〈1;let con2#1〉]: string + } + ok4: { + ["foo"]: string + } + ok5: { + [1]: string + } + ok6: { + [1]: string + } + ok7: { + [〈1;dis1〉]: string + } + ok8: { + [〈1;dis2〉]: string + } + ok9: { + [〈1;dis2〉]: string + } + ok10: { + [{ + foo: "bar" + }]: string + } + ok11: { + [〈import;list〉.FlattenN([ + string, + ], 1)]: string + } + bad1: { + [_|_(comprehension values not allowed in this position)]: string + } + saneReferencesInComprehensions: { + for _, _ in [ + 1, + ] { + a: _ + } + } +} diff --git a/internal/core/compile/testdata/sync/compile/let.txtar b/internal/core/compile/testdata/sync/compile/let.txtar new file mode 100644 index 000000000..542348161 --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/let.txtar @@ -0,0 +1,200 @@ +#expandLetExpr: true +#inlinetest:exclude skip: compile errors. +-- in.cue -- +a: { + let X = Y + let Y = c + + b: X + c: 5 +} + +b: { + let X = Y + let Y = X + + b: X + c: 5 +} + +fieldOffset: { + a: { + p1: { + let X = {value: Y} + let Y = 2 + x: X + } + p2: { + x: X + let Y = 2 + let X = {value: Y} + } + } + b: { + p1: { + let X = {x: y: Y} + let Y = 2 + x: X + } + p2: { + x: X + let Y = 2 + let X = {x: y: Y} + } + } +} + +issue767: { + #Foo: { + let _#bar = { + value: "" + } + let _#volmnts = { + x: _#baz.value + } + let _#baz = { + _#bar + } + out: _#volmnts + } +} +-- alignstack.cue -- +issue4051: full: { + #app: name: "foo" + + let N = #app.name + + out: (N): [{f1: f2: N}] +} +issue4051: reduced: { + (N): [{ f1: f2: N }] + let N = x + x: "s" +} +-- out/compile -- +b.let[]: cyclic references in let clause or alias: + ./in.cue:10:10 +--- alignstack.cue +{ + issue4051: { + full: { + #app: { + name: "foo" + } + let N#1 = 〈0;#app〉.name + out: { + 〈1;let N#1〉=>〈0;#app〉.name: [ + { + f1: { + f2: 〈4;let N#1〉=>〈0;#app〉.name + } + }, + ] + } + } + } + issue4051: { + reduced: { + 〈0;let N#2〉=>〈0;x〉: [ + { + f1: { + f2: 〈3;let N#2〉=>〈0;x〉 + } + }, + ] + let N#2 = 〈0;x〉 + x: "s" + } + } +} +--- in.cue +{ + a: { + let X#3 = 〈0;let Y#4〉=>〈0;c〉 + let Y#4 = 〈0;c〉 + b: 〈0;let X#3〉=>〈0;let Y#4〉=>〈0;c〉 + c: 5 + } + b: { + let X#5 = 〈0;let Y#6〉=>〈0;let X#5〉=>〈0;let Y#6〉=>_|_(cyclic references in let clause or alias) + let Y#6 = 〈0;let X#5〉=>〈0;let Y#6〉=>_|_(cyclic references in let clause or alias) + b: 〈0;let X#5〉=>〈0;let Y#6〉=>_|_(cyclic references in let clause or alias) + c: 5 + } + fieldOffset: { + a: { + p1: { + let X#7 = { + value: 〈1;let Y#8〉=>2 + } + let Y#8 = 2 + x: 〈0;let X#7〉=>{ + value: 〈1;let Y#8〉=>2 + } + } + p2: { + x: 〈0;let X#A〉=>{ + value: 〈1;let Y#9〉=>2 + } + let Y#9 = 2 + let X#A = { + value: 〈1;let Y#9〉=>2 + } + } + } + b: { + p1: { + let X#B = { + x: { + y: 〈2;let Y#C〉=>2 + } + } + let Y#C = 2 + x: 〈0;let X#B〉=>{ + x: { + y: 〈2;let Y#C〉=>2 + } + } + } + p2: { + x: 〈0;let X#E〉=>{ + x: { + y: 〈2;let Y#D〉=>2 + } + } + let Y#D = 2 + let X#E = { + x: { + y: 〈2;let Y#D〉=>2 + } + } + } + } + } + issue767: { + #Foo: { + let _#bar#F = { + value: "" + } + let _#volmnts#10 = { + x: 〈1;let _#baz#11〉=>{ + 〈1;let _#bar#F〉=>{ + value: "" + } + }.value + } + let _#baz#11 = { + 〈1;let _#bar#F〉=>{ + value: "" + } + } + out: 〈0;let _#volmnts#10〉=>{ + x: 〈1;let _#baz#11〉=>{ + 〈1;let _#bar#F〉=>{ + value: "" + } + }.value + } + } + } +} diff --git a/internal/core/compile/testdata/sync/compile/postfixexpr.txtar b/internal/core/compile/testdata/sync/compile/postfixexpr.txtar new file mode 100644 index 000000000..2d2d43917 --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/postfixexpr.txtar @@ -0,0 +1,50 @@ +-- cue.mod/module.cue -- +module: "test.example" +language: version: "v0.15.0" + +-- with_experiment.cue -- +@experiment(explicitopen) + +#Base: { + x: int +} @test(shareID=Base) + +// Test postfix ... operator with struct +a: #Base... @test(shareID=Base) + +// Test with selector +b: foo.bar... @test(err, code=incomplete, contains="undefined field: bar", pos=[0:8]) + +// Test with parentheses +c: (x & y)... @test(eq, _) + +// Test with function call +d: fn()... @test(err, code=incomplete, contains="cannot call non-concrete value fn", pos=[0:4]) + +// As an expression +e: #Base... & {y: int} @test(eq, {y: int, x: int}) + +foo: {} @test(eq, {}) + +x: _ @test(eq, _) +y: _ @test(eq, _) +fn: _ @test(eq, _) + +-- out/compile -- +--- with_experiment.cue +{ + #Base: { + x: int + } + a: 〈0;#Base〉... + b: 〈0;foo〉.bar... + c: (〈0;x〉 & 〈0;y〉)... + d: 〈0;fn〉()... + e: (〈0;#Base〉... & { + y: int + }) + foo: {} + x: _ + y: _ + fn: _ +} diff --git a/internal/core/compile/testdata/sync/compile/scope.txtar b/internal/core/compile/testdata/sync/compile/scope.txtar new file mode 100644 index 000000000..a2231306c --- /dev/null +++ b/internal/core/compile/testdata/sync/compile/scope.txtar @@ -0,0 +1,91 @@ +-- in.cue -- +a: { + {{ + b + c + d: b + e: c + }} + c: {} +} @test(eq, {d: {}, e: {}, c: {}}) +b: {} @test(eq, {}) +s: "foo" @test(eq, "foo") +c: s @test(eq, "foo") + +// s is technically in a new struct here so it will have a one higher count than +// the one before. +d: [s]: 3 @test(eq, {["foo"]: 3}) + +e: {} @test(eq, {}, hint="not the worst if this is not allowed") + +e & { + e: {} +} + +p: { + {X=["foo"]: b: X | null} + {[Y="bar"]: b: Y} + + @test(eq, { + ["foo"]: b: null @test(final) + ["bar"]: b: string + }, incorrect) + @test(eq:todo, { + ["foo"]: b: null @test(final) + ["bar"]: b: "bar" + }) +} + +let B = {open: int} +f: B @test(eq, {open: int}) + +schema: { + next: _schema_1 @test(err, code=structural_cycle) +} + +let _schema_1 = schema +-- out/compile -- +--- in.cue +{ + a: { + { + { + 〈3;b〉 + 〈2;c〉 + d: 〈3;b〉 + e: 〈2;c〉 + } + } + c: {} + } + b: {} + s: "foo" + c: 〈0;s〉 + d: { + [〈1;s〉]: 3 + } + e: {} + (〈0;e〉 & { + e: {} + }) + p: { + { + ["foo"]: { + b: (〈1;(〈0;-〉)〉|null) + } + } + { + ["bar"]: { + b: 〈1;-〉 + } + } + } + let B#1 = { + open: int + } + f: 〈0;let B#1〉 + schema: { + next: 〈1;let _schema_1#2〉 + } + let _schema_1#2 = 〈0;schema〉 +} diff --git a/internal/core/compile/testdata/sync/comprehensions/015_list_comprehension.txtar b/internal/core/compile/testdata/sync/comprehensions/015_list_comprehension.txtar new file mode 100644 index 000000000..1fa1e10a8 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/015_list_comprehension.txtar @@ -0,0 +1,41 @@ +-- in.cue -- +b: { + a: 1 + b: 2 + c: 3 + d: 4 +} + +a: [for k, v in b if k < "d" if v > b.a {k}] @test(eq, ["b", "c"]) +c: { + [for _, x in b for _, y in b if x < y {x}] + @test(eq, [1, 1, 1, 2, 2, 3]) +} +d: [for x, _ in a {x}] @test(eq, [0, 1]) +-- out/compile -- +--- in.cue +{ + b: { + a: 1 + b: 2 + c: 3 + d: 4 + } + a: [ + for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { + 〈1;k〉 + }, + ] + c: { + [ + for _, x in 〈2;b〉 for _, y in 〈3;b〉 if (〈1;x〉 < 〈0;y〉) { + 〈2;x〉 + }, + ] + } + d: [ + for x, _ in 〈1;a〉 { + 〈1;x〉 + }, + ] +} diff --git a/internal/core/compile/testdata/sync/comprehensions/045_comprehension_and_skipped_field.txtar b/internal/core/compile/testdata/sync/comprehensions/045_comprehension_and_skipped_field.txtar new file mode 100644 index 000000000..fff1e8142 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/045_comprehension_and_skipped_field.txtar @@ -0,0 +1,33 @@ +#name: comprehension and skipped field +#bug: true +#evalFull +# Tests that a comprehension iterating over a struct whose values contain +# a hidden field (_p) correctly skips that hidden field and still evaluates +# the visible result field using a disjunction with a comprehension body. +-- in.cue -- + +for key, value in {x: v: 1} { + "\(key)": { + v: *{for pod, _ in value.v {}} | {"\(value.v)": 2} + _p: 3 + } +} +@test(eq, {x: {v: {"1": 2}, _p: 3}}) +-- out/compile -- +--- in.cue +{ + for key, value in { + x: { + v: 1 + } + } { + "\(〈1;key〉)": { + v: (*{ + for pod, _ in 〈3;value〉.v {} + }|{ + "\(〈3;value〉.v)": 2 + }) + _p: 3 + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/checkdefined.txtar b/internal/core/compile/testdata/sync/comprehensions/checkdefined.txtar new file mode 100644 index 000000000..08936fed2 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/checkdefined.txtar @@ -0,0 +1,316 @@ + +Issue #1969 +# Tests that undefined field comparisons with _|_ work correctly in +# comprehension conditions, including with close(), for loops, and let bindings. +# Issue #1969 and #2245. +-- in.cue -- +import "list" + +// All tests here should pass and the result of the okcN tests should be +// identical to those of the okoN tests. + +xc: close({field: {}}) +xo: field: {} + +okc0: { + if xc.undefined == _|_ {a: 1} + @test(eq, {a: 1}) +} +oko0: { + if xo.undefined == _|_ {a: 1} + @test(eq, {a: 1}) +} + +okc1: { + if xc.undefined != _|_ {a: 1} + @test(eq, {}) +} +oko1: { + if xo.undefined != _|_ {a: 1} + @test(eq, {}) +} + +okc2: { + if ({} & {s: [for y in xc.undefined {}]}) != _|_ {a: 1} + @test(eq, {}) +} + +oko2: { + if ({} & {s: [for y in xo.undefined {}]}) != _|_ {a: 1} + @test(eq, {a: 1}) +} + +okc3: { + if ({s: [for y in xc.undefined {}]}) != _|_ {a: 1} + @test(eq, {}) +} + +oko3: { + if ({s: [for y in xo.undefined {}]}) != _|_ {a: 1} + @test(eq, {a: 1}) +} + +// Should Field s exist in okc or not? Depends on whether comparison to bottom +// is recursive or not. It probably should not. +// TODO: fix for new evaluator. But possibly address this with new builtins. +// issue1969: Tests that comparing let-bound expressions involving undefined +// fields to _|_ works correctly with list comprehensions. +// https://cuelang.org/issue/1969 +issue1969: okc: { + let X = xc.undefined + let Y = {} & {s: [for y in list.Range(0, X, 1) {}]} + + if Y != _|_ {Y} + @test(eq, {}) +} + +issue1969: oko: { + let X = xo.undefined + let Y = {} & {s: [for y in list.Range(0, X, 1) {}]} + + if Y != _|_ {Y} + @test(eq, { + s: _|_ @test(err, code=incomplete, contains="issue1969.oko.X: undefined field: undefined", pos=[62:13]) + }) +} +-- issue2245.cue -- +// Evaluator regression where comparing an incomplete struct to bottom in a +// comprehension condition produced incorrect results. +// https://cuelang.org/issue/2245 +yo: { + f: int + g: f < 10 + @test(eq, { + f: int + g: _|_ @test(err, code=incomplete, contains="yo.g: non-concrete value int in operand to <", pos=[6:5, 5:5]) + }) +} +okyo: { + if yo != _|_ {a: 1} + @test(eq, {a: 1}) +} +okyog: { + if yo.g != _|_ {a: 1} + @test(eq, {}) +} + +-- incomplete.cue -- +// Comparing to string is not an error. But for legacy reasons we want to still +// support this. We intend to have more clean and precise behavior with the +// builtins isdefined, isvalid, and isconcrete. +checkIncomplete: t1: { + f: [string]: { + if a != _|_ { + b: "d\(a)" + } + a: string + } + f: blah: {} + @test(eq, {f: {blah: {a: string}}}) +} + +-- structs.cue -- +structs: { + bare: t1: ({y: 2} & {x: 3}) != _|_ @test(eq, true) + bare: f2: ({y: 2} & {x: 3}) == _|_ @test(eq, false) + bare: f3: ({x: 1, y: 2} & {x: 3}) != _|_ @test(eq, false) + bare: t4: ({x: 1, y: 2} & {x: 3}) == _|_ @test(eq, true) + + select: t1: ({y: 2} & {x: 3}).y != _|_ @test(eq, true) + select: f2: ({y: 2} & {x: 3}).y == _|_ @test(eq, false) + select: f3: ({x: 1, y: 2} & {x: 3}).y != _|_ @test(eq, false) + select: t4: ({x: 1, y: 2} & {x: 3}).y == _|_ @test(eq, true) +} + +-- out/compile -- +--- in.cue +{ + xc: close({ + field: {} + }) + xo: { + field: {} + } + okc0: { + if (〈1;xc〉.undefined == _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + oko0: { + if (〈1;xo〉.undefined == _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + okc1: { + if (〈1;xc〉.undefined != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + oko1: { + if (〈1;xo〉.undefined != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + okc2: { + if (({} & { + s: [ + for _, y in 〈3;xc〉.undefined {}, + ] + }) != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + oko2: { + if (({} & { + s: [ + for _, y in 〈3;xo〉.undefined {}, + ] + }) != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + okc3: { + if ({ + s: [ + for _, y in 〈3;xc〉.undefined {}, + ] + } != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + oko3: { + if ({ + s: [ + for _, y in 〈3;xo〉.undefined {}, + ] + } != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + issue1969: { + okc: { + let X#1 = 〈2;xc〉.undefined + let Y#2 = ({} & { + s: [ + for _, y in 〈import;list〉.Range(0, 〈2;let X#1〉, 1) {}, + ] + }) + if (〈0;let Y#2〉 != _|_(explicit error (_|_ literal) in source)) { + 〈1;let Y#2〉 + } + } + } + issue1969: { + oko: { + let X#3 = 〈2;xo〉.undefined + let Y#4 = ({} & { + s: [ + for _, y in 〈import;list〉.Range(0, 〈2;let X#3〉, 1) {}, + ] + }) + if (〈0;let Y#4〉 != _|_(explicit error (_|_ literal) in source)) { + 〈1;let Y#4〉 + } + } + } +} +--- incomplete.cue +{ + checkIncomplete: { + t1: { + f: { + [string]: { + if (〈0;a〉 != _|_(explicit error (_|_ literal) in source)) { + b: "d\(〈1;a〉)" + } + a: string + } + } + f: { + blah: {} + } + } + } +} +--- issue2245.cue +{ + yo: { + f: int + g: (〈0;f〉 < 10) + } + okyo: { + if (〈1;yo〉 != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } + okyog: { + if (〈1;yo〉.g != _|_(explicit error (_|_ literal) in source)) { + a: 1 + } + } +} +--- structs.cue +{ + structs: { + bare: { + t1: (({ + y: 2 + } & { + x: 3 + }) != _|_(explicit error (_|_ literal) in source)) + } + bare: { + f2: (({ + y: 2 + } & { + x: 3 + }) == _|_(explicit error (_|_ literal) in source)) + } + bare: { + f3: (({ + x: 1 + y: 2 + } & { + x: 3 + }) != _|_(explicit error (_|_ literal) in source)) + } + bare: { + t4: (({ + x: 1 + y: 2 + } & { + x: 3 + }) == _|_(explicit error (_|_ literal) in source)) + } + select: { + t1: (({ + y: 2 + } & { + x: 3 + }).y != _|_(explicit error (_|_ literal) in source)) + } + select: { + f2: (({ + y: 2 + } & { + x: 3 + }).y == _|_(explicit error (_|_ literal) in source)) + } + select: { + f3: (({ + x: 1 + y: 2 + } & { + x: 3 + }).y != _|_(explicit error (_|_ literal) in source)) + } + select: { + t4: (({ + x: 1 + y: 2 + } & { + x: 3 + }).y == _|_(explicit error (_|_ literal) in source)) + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/closed.txtar b/internal/core/compile/testdata/sync/comprehensions/closed.txtar new file mode 100644 index 000000000..738dd049f --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/closed.txtar @@ -0,0 +1,275 @@ +-- in.cue -- +dynamicTop: { + #D: { + for k, v in {foo: 123} {(k): v} + @test(eq, {foo: 123}) + } +} + +// Issue #1404 +dynamicDepth1: { + #D: { + a: foo: 123 + b: {for k, v in a {(k): v}} + @test(eq, {a: {foo: 123}, b: {foo: 123}}) + } +} + +allowed: { + #D: { + if true { + d: int + } + } + + vErr: #D & {d: 5} + @test(eq, {#D: {d: int}, vErr: {d: 5}}) +} + +disallowed: { + #D: { + if false { + d: int + } + } + + vErr: #D & {d: 5} + @test(err, code=eval, at=vErr.d, contains="field not allowed", pos=[7:14]) +} + +// Interpret comprehensions as embeddings. +// Issue #1956 +comprehensionIsEmbed: { + #A: size: int | *1 + #B: { + kind: string + + // Should be identical to just #A. That is, #A is treated as open. + if true { + #A + } + } + x: #B & { + kind: "A" + } + @test(eq, { + #A: {size: *1 | int} + #B: {kind: string, size: *1 | int} + x: {kind: "A", size: *1 | int} + }) +} + +// This comprehension is inside a definition and should still disallow b. +noEraseDefinition: { + #Foo: [if true {a: int}] + a: { #Foo & [{ b: 2 }] } // Error + @test(err, code=eval, at=a.0.b, contains="field not allowed", pos=[2:17]) +} + +// issue1956: Tests that conditional comprehensions correctly embed definitions +// inside a closed struct without spuriously rejecting fields. +// https://cuelang.org/issue/1956 +issue1956: { + #Details: { + size: int | *1 + } + + #Thing: { + kind: "KindA" | "KindB" + if kind == "KindA" { + #Details + } + } + + x: #Thing & { + kind: "KindA" + } + @test(eq, { + #Details: {size: *1 | int} + #Thing: {kind: "KindA" | "KindB"} + x: {kind: "KindA", size: *1 | int} + }) +} + +// This triggers adding the same "closedInfo" twice, potentially causing +// a cyclic linked list in the todo list. +dedupTodo: { + #sub: { + c: _ + if c.n == "c" { + X: test: c + } + } + + out: #sub // needs to be definition + out: { + c: n: "c" // Do not combine with &, as the original issue relies on this. + c: n: string + } + @test(eq, { + #sub: {c: _} + out: {c: {n: "c"}, X: {test: {n: "c"}}} + }) +} + +-- v3issues.cue -- +// issue3483: Tests that a falsy if comprehension inside a definition does not +// incorrectly produce "field not allowed" in evalv3. +// https://cuelang.org/issue/3483 +issue3483: { + #Schema: schemaField: int + out1: out2: #Schema & { + if false { + schemaField: 3 + } + } + @test(eq, { + #Schema: {schemaField: int} + out1: {out2: {schemaField: int}} + }) +} +// issue3486: Tests that embedding a definition inside an if comprehension does +// not produce spurious "field not allowed" errors. +// https://cuelang.org/issue/3486 +issue3486: { + #schema: {} + + if true { + out: { + #schema + // This field should be allowed as #schema is embedded. + extra: "foo" + } + } + @test(eq, {#schema: {}, out: {extra: "foo"}}) +} +-- out/compile -- +--- in.cue +{ + dynamicTop: { + #D: { + for k, v in { + foo: 123 + } { + 〈1;k〉: 〈1;v〉 + } + } + } + dynamicDepth1: { + #D: { + a: { + foo: 123 + } + b: { + for k, v in 〈1;a〉 { + 〈1;k〉: 〈1;v〉 + } + } + } + } + allowed: { + #D: { + if true { + d: int + } + } + vErr: (〈0;#D〉 & { + d: 5 + }) + } + disallowed: { + #D: { + if false { + d: int + } + } + vErr: (〈0;#D〉 & { + d: 5 + }) + } + comprehensionIsEmbed: { + #A: { + size: (int|*1) + } + #B: { + kind: string + if true { + 〈2;#A〉 + } + } + x: (〈0;#B〉 & { + kind: "A" + }) + } + noEraseDefinition: { + #Foo: [ + if true { + a: int + }, + ] + a: { + (〈1;#Foo〉 & [ + { + b: 2 + }, + ]) + } + } + issue1956: { + #Details: { + size: (int|*1) + } + #Thing: { + kind: ("KindA"|"KindB") + if (〈0;kind〉 == "KindA") { + 〈2;#Details〉 + } + } + x: (〈0;#Thing〉 & { + kind: "KindA" + }) + } + dedupTodo: { + #sub: { + c: _ + if (〈0;c〉.n == "c") { + X: { + test: 〈2;c〉 + } + } + } + out: 〈0;#sub〉 + out: { + c: { + n: "c" + } + c: { + n: string + } + } + } +} +--- v3issues.cue +{ + issue3483: { + #Schema: { + schemaField: int + } + out1: { + out2: (〈1;#Schema〉 & { + if false { + schemaField: 3 + } + }) + } + } + issue3486: { + #schema: {} + if true { + out: { + 〈2;#schema〉 + extra: "foo" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/deferfieldsetknown.txtar b/internal/core/compile/testdata/sync/comprehensions/deferfieldsetknown.txtar new file mode 100644 index 000000000..d5d5b1d75 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/deferfieldsetknown.txtar @@ -0,0 +1,43 @@ +-- in.cue -- +package x + +#PDB: {y: int} + +result: resources: { + if true { + x: #PDB & {y: 1} + } +} + +out: ({ + cfg: resources: _ + out: {for n, _ in cfg.resources {(n): "x"}} +} & {cfg: result}).out @test(eq, {x: "x"}) +-- out/compile -- +--- in.cue +{ + #PDB: { + y: int + } + result: { + resources: { + if true { + x: (〈3;#PDB〉 & { + y: 1 + }) + } + } + } + out: ({ + cfg: { + resources: _ + } + out: { + for n, _ in 〈1;cfg〉.resources { + 〈1;n〉: "x" + } + } + } & { + cfg: 〈1;result〉 + }).out +} diff --git a/internal/core/compile/testdata/sync/comprehensions/else.txtar b/internal/core/compile/testdata/sync/comprehensions/else.txtar new file mode 100644 index 000000000..c2ea89560 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/else.txtar @@ -0,0 +1,474 @@ +-- in.cue -- +@experiment(try) + +// if-else: condition true - no else +ifTrue: { + if true { a: 1 } else { b: 2 } + @test(eq, {a: 1}) +} + +// if-else: condition false - else yields +ifFalse: { + if false { a: 1 } else { b: 2 } + @test(eq, {b: 2}) +} + +// for-else: non-empty source - no else +forNonEmpty: { + for x in [1, 2] { "\(x)": x } fallback { empty: true } + @test(eq, {"1": 1, "2": 2}) +} + +// for-else: empty source - else yields +forEmpty: { + for x in [] { "\(x)": x } fallback { empty: true } + @test(eq, {empty: true}) +} + +// for-else with filter: filter removes all - else yields +forFilteredAll: { + for x in [1, 2, 3] if x > 10 { "\(x)": x } fallback { empty: true } + @test(eq, {empty: true}) +} + +// for-else with filter: filter keeps some - no else +forFilteredSome: { + for x in [1, 2, 3] if x > 1 { "\(x)": x } fallback { empty: true } + @test(eq, {"2": 2, "3": 3}) +} + +// if-for-fallback: if true, for empty - fallback yields +ifTrueForEmpty: { + if true for x in [] { "\(x)": x } fallback { empty: true } + @test(eq, {empty: true}) +} + +// if-for-fallback: if false, for non-empty - fallback yields (if blocks iteration) +ifFalseForNonEmpty: { + if false for x in [1, 2] { "\(x)": x } fallback { empty: true } + @test(eq, {empty: true}) +} + +// if-for-fallback: if true, for non-empty - no fallback +ifTrueForNonEmpty: { + if true for x in [1, 2] { "\(x)": x } fallback { empty: true } + @test(eq, {"1": 1, "2": 2}) +} + +// if-if-fallback: both true - no fallback +ifIfBothTrue: { + if true if true { a: 1 } fallback { b: 2 } + @test(eq, {a: 1}) +} + +// if-if-fallback: first false - fallback yields +ifIfFirstFalse: { + if false if true { a: 1 } fallback { b: 2 } + @test(eq, {b: 2}) +} + +// if-if-fallback: second false - fallback yields +ifIfSecondFalse: { + if true if false { a: 1 } fallback { b: 2 } + @test(eq, {b: 2}) +} + +// try-try-fallback: both succeed - no fallback +tryTryBothSucceed: { + a: 1 + b: 2 + try x = a? try y = b? { result: x + y } fallback { default: 0 } + @test(eq, {a: 1, b: 2, result: 3}) +} + +missing?: int + +// try-try-fallback: first fails - fallback yields +tryTryFirstFails: { + b: 2 + try x = missing? try y = b? { result: x + y } fallback { default: -1 } + @test(eq, {b: 2, default: -1}) +} + +// try-try-fallback: second fails - fallback yields +tryTrySecondFails: { + a: 1 + try x = a? try y = missing? { result: x + y } fallback { default: -2 } + @test(eq, {a: 1, default: -2}) +} + +// list if-else: true +listIfTrue: [ + if true { 1 } else { 2 } +] @test(eq, [1]) + +// list if-else: false +listIfFalse: [ + if false { 1 } else { 2 } +] @test(eq, [2]) + +// list for-else: empty +listForEmpty: [ + for x in [] { x } fallback { 0 } +] @test(eq, [0]) + +// list for-else: non-empty +listForNonEmpty: [ + for x in [1, 2] { x * 2 } fallback { 0 } +] @test(eq, [2, 4]) + +// else with multiple fields +elseMultipleFields: { + if false { a: 1 } else { b: 2, c: 3 } + @test(eq, {b: 2, c: 3}) +} + +// else embeds into existing struct +elseEmbeds: { + existing: 1 + if false { added: 2 } else { fallback: 3 } + @test(eq, {existing: 1, fallback: 3}) +} + +// fallback with outer scope access +outerScope: { + let threshold = 10 + for x in [] { x } fallback { fallbackField: threshold } + @test(eq, {fallbackField: 10}) +} + +// if-else: nested body fields - else yields once +ifNestedBody: { + if false { a: b: 1 } else { c: 2 } + @test(eq, {c: 2}) +} + +// if-else: nested else fields +ifNestedElse: { + if false { a: 1 } else { b: c: 2 } + @test(eq, {b: {c: 2}}) +} + +// if-else: nested fields in both +ifNestedBoth: { + if false { a: b: 1 } else { c: d: 2 } + @test(eq, {c: {d: 2}}) +} + +// if-else: deeply nested fields +ifDeeplyNested: { + if false { a: b: c: 1 } else { a: b: c: 2 } + @test(eq, {a: {b: {c: 2}}}) +} + +// for-fallback: nested body fields, empty source +forNestedEmpty: { + for x in [] { a: b: (x): x } fallback { a: b: none: true } + @test(eq, {a: {b: {none: true}}}) +} + +// for-fallback: nested body fields, non-empty source - no fallback +forNestedNonEmpty: { + for x in [1] { a: b: "\(x)": x } fallback { a: b: none: true } + @test(eq, {a: {b: {"1": 1}}}) +} + +// nested comprehensions - outer fallback triggers +nestedOuterFallback: { + for x in [] { for y in [1] { y } fallback { inner: true } } fallback { outer: true } + @test(eq, {outer: true}) +} + +// nested comprehensions - inner fallback triggers +nestedInnerFallback: { + for x in [1] { for y in [] { y } fallback { inner: true } } fallback { outer: true } + @test(eq, {inner: true}) +} +-- out/compile -- +--- in.cue +{ + ifTrue: { + if true { + a: 1 + } else { + b: 2 + } + } + ifFalse: { + if false { + a: 1 + } else { + b: 2 + } + } + forNonEmpty: { + for _, x in [ + 1, + 2, + ] { + "\(〈1;x〉)": 〈1;x〉 + } else { + empty: true + } + } + forEmpty: { + for _, x in [] { + "\(〈1;x〉)": 〈1;x〉 + } else { + empty: true + } + } + forFilteredAll: { + for _, x in [ + 1, + 2, + 3, + ] if (〈0;x〉 > 10) { + "\(〈1;x〉)": 〈1;x〉 + } else { + empty: true + } + } + forFilteredSome: { + for _, x in [ + 1, + 2, + 3, + ] if (〈0;x〉 > 1) { + "\(〈1;x〉)": 〈1;x〉 + } else { + empty: true + } + } + ifTrueForEmpty: { + if true for _, x in [] { + "\(〈1;x〉)": 〈1;x〉 + } else { + empty: true + } + } + ifFalseForNonEmpty: { + if false for _, x in [ + 1, + 2, + ] { + "\(〈1;x〉)": 〈1;x〉 + } else { + empty: true + } + } + ifTrueForNonEmpty: { + if true for _, x in [ + 1, + 2, + ] { + "\(〈1;x〉)": 〈1;x〉 + } else { + empty: true + } + } + ifIfBothTrue: { + if true if true { + a: 1 + } else { + b: 2 + } + } + ifIfFirstFalse: { + if false if true { + a: 1 + } else { + b: 2 + } + } + ifIfSecondFalse: { + if true if false { + a: 1 + } else { + b: 2 + } + } + tryTryBothSucceed: { + a: 1 + b: 2 + try x = 〈0;a〉? try y = 〈1;b〉? { + result: (〈2;x〉 + 〈1;y〉) + } else { + default: 0 + } + } + missing?: int + tryTryFirstFails: { + b: 2 + try x = 〈1;missing〉? try y = 〈1;b〉? { + result: (〈2;x〉 + 〈1;y〉) + } else { + default: -1 + } + } + tryTrySecondFails: { + a: 1 + try x = 〈0;a〉? try y = 〈2;missing〉? { + result: (〈2;x〉 + 〈1;y〉) + } else { + default: -2 + } + } + listIfTrue: [ + if true { + 1 + } else { + 2 + }, + ] + listIfFalse: [ + if false { + 1 + } else { + 2 + }, + ] + listForEmpty: [ + for _, x in [] { + 〈1;x〉 + } else { + 0 + }, + ] + listForNonEmpty: [ + for _, x in [ + 1, + 2, + ] { + (〈1;x〉 * 2) + } else { + 0 + }, + ] + elseMultipleFields: { + if false { + a: 1 + } else { + b: 2 + c: 3 + } + } + elseEmbeds: { + existing: 1 + if false { + added: 2 + } else { + fallback: 3 + } + } + outerScope: { + let threshold#1 = 10 + for _, x in [] { + 〈1;x〉 + } else { + fallbackField: 〈1;let threshold#1〉 + } + } + ifNestedBody: { + if false { + a: { + b: 1 + } + } else { + c: 2 + } + } + ifNestedElse: { + if false { + a: 1 + } else { + b: { + c: 2 + } + } + } + ifNestedBoth: { + if false { + a: { + b: 1 + } + } else { + c: { + d: 2 + } + } + } + ifDeeplyNested: { + if false { + a: { + b: { + c: 1 + } + } + } else { + a: { + b: { + c: 2 + } + } + } + } + forNestedEmpty: { + for _, x in [] { + a: { + b: { + 〈3;x〉: 〈3;x〉 + } + } + } else { + a: { + b: { + none: true + } + } + } + } + forNestedNonEmpty: { + for _, x in [ + 1, + ] { + a: { + b: { + "\(〈3;x〉)": 〈3;x〉 + } + } + } else { + a: { + b: { + none: true + } + } + } + } + nestedOuterFallback: { + for _, x in [] { + for _, y in [ + 1, + ] { + 〈1;y〉 + } else { + inner: true + } + } else { + outer: true + } + } + nestedInnerFallback: { + for _, x in [ + 1, + ] { + for _, y in [] { + 〈1;y〉 + } else { + inner: true + } + } else { + outer: true + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/else_compile_errors.txtar b/internal/core/compile/testdata/sync/comprehensions/else_compile_errors.txtar new file mode 100644 index 000000000..1cee67385 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/else_compile_errors.txtar @@ -0,0 +1,53 @@ +#inlinetest:exclude CUE source contains compile-time errors (out-of-scope references) +# which prevent the inline test runner from compiling the source. +-- in.cue -- +@experiment(try) + +// else cannot access for variable +forVarInElse: { + for i in [1,2,3] { "\(i)": i } fallback { bad: i } +} + +// else cannot access let variable from comprehension +letVarInElse: { + for x in [1,2,3] let y = x*2 { "\(x)": y } fallback { bad: y } +} + +// Note: Multiple clause cases with else are caught at parse time, not compile time: +// - if + let with else: if cond let x = val { ... } else { ... } +// - Two if clauses with else: if cond1 if cond2 { x } else { y } +// - Chained try with else: try x = a? try y = b? { ... } else { ... } +// - Mixed if/try with else: if cond try { x } else { y } +// - if + for with else: if cond for x in [] { x } else { y } +// These all produce parser error: "else clause only allowed with single 'if' or 'try' clause" +// or "use 'otherwise' with 'for' clauses" +-- out/compile -- +forVarInElse.bad: reference "i" not found: + ./in.cue:5:49 +letVarInElse.bad: reference "y" not found: + ./in.cue:10:61 +--- in.cue +{ + forVarInElse: { + for _, i in [ + 1, + 2, + 3, + ] { + "\(〈1;i〉)": 〈1;i〉 + } else { + bad: _|_(reference "i" not found) + } + } + letVarInElse: { + for _, x in [ + 1, + 2, + 3, + ] let y = (〈0;x〉 * 2) { + "\(〈2;x〉)": 〈1;y〉 + } else { + bad: _|_(reference "y" not found) + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/else_on_error.txtar b/internal/core/compile/testdata/sync/comprehensions/else_on_error.txtar new file mode 100644 index 000000000..7e355774e --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/else_on_error.txtar @@ -0,0 +1,48 @@ +-- in.cue -- +@experiment(try) + +// When the source expression has an error, the error propagates +// rather than triggering the else clause. + +// Error in for source - else should NOT trigger +forSourceError: { + @test(err, code=eval, pos=[2:11], contains="cannot range") + for x in "not-a-list" { "\(x)": x } fallback { fallbackField: true } +} + +// Error in if condition - else should NOT trigger +ifConditionError: { + @test(err, code=eval, pos=[2:6, 2:14], contains="invalid operands") + if ("not" + 1) { a: 1 } else { b: 2 } +} + +// Bottom value in for source - else should NOT trigger +forSourceBottom: { + @test(err, code=user, pos=[2:11], contains="explicit error") + for x in _|_ { "\(x)": x } fallback { fallbackField: true } +} +-- out/compile -- +--- in.cue +{ + forSourceError: { + for _, x in "not-a-list" { + "\(〈1;x〉)": 〈1;x〉 + } else { + fallbackField: true + } + } + ifConditionError: { + if ("not" + 1) { + a: 1 + } else { + b: 2 + } + } + forSourceBottom: { + for _, x in _|_(explicit error (_|_ literal) in source) { + "\(〈1;x〉)": 〈1;x〉 + } else { + fallbackField: true + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/errors.txtar b/internal/core/compile/testdata/sync/comprehensions/errors.txtar new file mode 100644 index 000000000..325751c61 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/errors.txtar @@ -0,0 +1,94 @@ +-- in.cue -- +circularIf: { + #list: { + tail: #list | *null + if tail != null { + } + @test(eq, {tail: null}) + } +} + +circularFor: { + #list: { + tail: #list | *null + for x in tail != null { + } + @test(err, code=eval, + contains="cannot range over %s (found %s, want list or struct)", + args=[tail != null, bool], pos=[2:12]) + } +} + +// Print a bit more sensible error message than "empty disjunction" here. +// Issue #465 +userError: { + a: string | *_|_ + if a != "" { + } + @test(err, code=incomplete, contains="non-concrete value string", pos=[2:5, 1:5]) +} + +intField: { + for i, _ in [1, 2] { + (i): { + } + } + @test(err, code=eval, contains="integer fields not supported", pos=[2:4]) +} + +// Issue #2403 +conflictRangingOverSelf: { + x: { + name: string + age: int + } + + x: { + for k, _ in x { + (k): k + } + } + @test(err, code=eval, at=x.age, + contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[int, "age", int, string], + pos=[3:9, 6:5, 7:3, 8:9]) +} +-- out/compile -- +--- in.cue +{ + circularIf: { + #list: { + tail: (〈1;#list〉|*null) + if (〈0;tail〉 != null) {} + } + } + circularFor: { + #list: { + tail: (〈1;#list〉|*null) + for _, x in (〈0;tail〉 != null) {} + } + } + userError: { + a: (string|*_|_(explicit error (_|_ literal) in source)) + if (〈0;a〉 != "") {} + } + intField: { + for i, _ in [ + 1, + 2, + ] { + 〈1;i〉: {} + } + } + conflictRangingOverSelf: { + x: { + name: string + age: int + } + x: { + for k, _ in 〈1;x〉 { + 〈1;k〉: 〈1;k〉 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/fields.txtar b/internal/core/compile/testdata/sync/comprehensions/fields.txtar new file mode 100644 index 000000000..9170c3354 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/fields.txtar @@ -0,0 +1,137 @@ +Issue #560 +# Issue #560: Tests that for comprehensions correctly iterate over struct fields, +# skipping optionals, and that missing required fields produce errors. +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- in.cue -- +import "strings" + +dynamic: { + for _, s in ["foo"] { + (s): 1 + "\(s)bar": 2 + } + @test(eq, {foo: 1, foobar: 2}) +} + +ignoreOptional: { + #x: { + a?: string + b?: string + c: string + } + + y: { + for k,v in #x { + (k): "exists" + } + } + @test(eq, { + #x: {a?: string, b?: string, c: string} + y: {c: "exists"} + }) +} + +missingRequiredError: { + // Issue #2369 + #x: { + a!: string + b?: string + c: string + } + + y: { + for k,v in #x { + (k): "exists" + } + } + @test(err, code=incomplete, at=y, contains="missing required field", pos=[9:3, 3:3, 9:14]) +} + +// issue560: Tests that for comprehensions over definitions with interpolated +// field names correctly produce all expected output fields. +// https://cuelang.org/issue/560 +issue560: { + #User: { + tags_str: string + tags_map: { + for k, v in strings.Split(tags_str, " ") { + "\(v)": string + } + "{a}": string + } @test(err, code=incomplete, + contains="error in call to %s", args=[strings.Split], + pos=[1:16, -1:13]) + } + + user: { + #User + tags_str: "b {c}" + } + @test(eq, { + #User: { + tags_str: string + tags_map: {"{a}": string} + } + user: { + tags_str: "b {c}" + tags_map: { + "{a}": string + b: string + "{c}": string + } + } + }) +} +-- out/compile -- +--- in.cue +{ + dynamic: { + for _, s in [ + "foo", + ] { + 〈1;s〉: 1 + "\(〈1;s〉)bar": 2 + } + } + ignoreOptional: { + #x: { + a?: string + b?: string + c: string + } + y: { + for k, v in 〈1;#x〉 { + 〈1;k〉: "exists" + } + } + } + missingRequiredError: { + #x: { + a!: string + b?: string + c: string + } + y: { + for k, v in 〈1;#x〉 { + 〈1;k〉: "exists" + } + } + } + issue560: { + #User: { + tags_str: string + tags_map: { + for k, v in 〈import;strings〉.Split(〈1;tags_str〉, " ") { + "\(〈1;v〉)": string + } + "{a}": string + } + } + user: { + 〈1;#User〉 + tags_str: "b {c}" + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/for.txtar b/internal/core/compile/testdata/sync/comprehensions/for.txtar new file mode 100644 index 000000000..d7836e251 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/for.txtar @@ -0,0 +1,56 @@ +-- in.cue -- +b: {for k, v in a {"\(k)": v + 1}} @test(eq, {b: 2, c: 3}) +a: {b: 1, c: 2} @test(eq, {b: 1, c: 2}) + +x: {for k, v in y {"\(k)": v}} @test(eq, {}) +y: {} // check that empty struct after reference works. + +k: {for v in e {v}} @test(err, code=eval, pos=[0:14], contains="cannot range") +e: int @test(eq, int) + +comprehensionBinds: { + @test(eq, {a: a: _, b: a: _}) + a: {for _ in [1] {a: _}} + b: {for _, _ in [1] {a: _}} +} +-- out/compile -- +--- in.cue +{ + b: { + for k, v in 〈1;a〉 { + "\(〈1;k〉)": (〈1;v〉 + 1) + } + } + a: { + b: 1 + c: 2 + } + x: { + for k, v in 〈1;y〉 { + "\(〈1;k〉)": 〈1;v〉 + } + } + y: {} + k: { + for _, v in 〈1;e〉 { + 〈1;v〉 + } + } + e: int + comprehensionBinds: { + a: { + for _, _ in [ + 1, + ] { + a: _ + } + } + b: { + for _, _ in [ + 1, + ] { + a: _ + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/iferror.txtar b/internal/core/compile/testdata/sync/comprehensions/iferror.txtar new file mode 100644 index 000000000..4c05be083 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/iferror.txtar @@ -0,0 +1,217 @@ +-- in.cue -- +a: {b: 2, c: int} + +wrongConcreteType: { + if a.b { + 2 + } + @test(err, code=eval, contains="cannot use 2 (type int) as type bool", pos=[1:2, -2:8]) +} + +wrongType: { + if a.c { + 2 + } + @test(err, code=eval, contains="cannot use int (type int) as type bool", pos=[1:2, -9:14]) +} + +incomplete: err1: { + if a.d { + 2 + } + @test(err, code=incomplete, contains="undefined field: d", pos=[1:7]) +} +incomplete: err2: { + list: [1, 2, 3] + for x in list if a.d { + x + } + @test(err, code=incomplete, contains="undefined field: d", pos=[2:21]) +} + +// issue809: Tests that comprehension guards using `!= _|_` work correctly +// when the guarded field has a default value. In both cases below the field +// being tested is non-bottom (it carries a default), so the guard should +// pass and the comprehension should yield the entry. +// https://cuelang.org/issue/809 +useDefault: { + a: { + x: *"foo" | string + if x != _|_ { + y: x + } + } + + issue809: { + #A: { + a: string + b: *a | string + } + + s: [Name=string]: #A & {a: Name} + s: bar: _ + + foo: [ + for _, a in s if a.b != _|_ {a}, + ] + + @test(eq, { + #A: { + a: string + b: string + } + s: bar: { + a: "bar" + b: *"bar" | string + } + foo: [{ + a: "bar" + b: *"bar" | string + }] + }) + } +} + +// issue1972: Tests that mixing a list value with struct fields in a +// comprehension correctly produces a conflict error rather than a panic. +// https://cuelang.org/issue/1972 +issue1972: { + err1: { + #patchs: [] + #patchs + + #someCondition: _ + if #someCondition { + } + } + err1: { + someCondition: _ + patchs: [...{}] + patchs + if someCondition { + patchs: _ + } + } @test(err, code=eval, + contains="conflicting values %s and %s (mismatched types %s and %s)", + pos=[0:8, 2:11, 3:3] + ) + err2: { + #patchs: [] + #patchs + + #someCondition: _ + if #someCondition { + } + } @test(err, code=incomplete, contains="incomplete %s: %s", args=[bool, _], pos=[]) + err3: { + someCondition: _ + patchs: [...{}] + patchs + if someCondition { + patchs: _ + } + + // TODO(inline): support commas in arguments + @test(err, code=eval, contains="conflicting values %s and %s (mismatched types %s and %s)", + pos=[0:8, 2:11, 3:3] + ) + } +} +-- out/compile -- +--- in.cue +{ + a: { + b: 2 + c: int + } + wrongConcreteType: { + if 〈1;a〉.b { + 2 + } + } + wrongType: { + if 〈1;a〉.c { + 2 + } + } + incomplete: { + err1: { + if 〈2;a〉.d { + 2 + } + } + } + incomplete: { + err2: { + list: [ + 1, + 2, + 3, + ] + for _, x in 〈0;list〉 if 〈3;a〉.d { + 〈1;x〉 + } + } + } + useDefault: { + a: { + x: (*"foo"|string) + if (〈0;x〉 != _|_(explicit error (_|_ literal) in source)) { + y: 〈1;x〉 + } + } + issue809: { + #A: { + a: string + b: (*〈0;a〉|string) + } + s: { + [string]: (〈1;#A〉 & { + a: 〈1;-〉 + }) + } + s: { + bar: _ + } + foo: [ + for _, a in 〈1;s〉 if (〈0;a〉.b != _|_(explicit error (_|_ literal) in source)) { + 〈1;a〉 + }, + ] + } + } + issue1972: { + err1: { + #patchs: [] + 〈0;#patchs〉 + #someCondition: _ + if 〈0;#someCondition〉 {} + } + err1: { + someCondition: _ + patchs: [ + ...{}, + ] + 〈0;patchs〉 + if 〈0;someCondition〉 { + patchs: _ + } + } + err2: { + #patchs: [] + 〈0;#patchs〉 + #someCondition: _ + if 〈0;#someCondition〉 {} + } + err3: { + someCondition: _ + patchs: [ + ...{}, + ] + 〈0;patchs〉 + if 〈0;someCondition〉 { + patchs: _ + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/incomplete.txtar b/internal/core/compile/testdata/sync/comprehensions/incomplete.txtar new file mode 100644 index 000000000..e2acd9900 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/incomplete.txtar @@ -0,0 +1,23 @@ +-- in.cue -- +cond: bool +src: {} +top: _ +a: [ if cond {}] @test(err, code=incomplete, pos=[-3:7], contains="incomplete bool") +b: [for x in src.foo {}] @test(err, code=incomplete, pos=[0:18], contains="undefined field") +c: {for x in top {}} @test(err, code=incomplete, pos=[0:14], contains="cannot range") +-- out/compile -- +--- in.cue +{ + cond: bool + src: {} + top: _ + a: [ + if 〈1;cond〉 {}, + ] + b: [ + for _, x in 〈1;src〉.foo {}, + ] + c: { + for _, x in 〈1;top〉 {} + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue1732.txtar b/internal/core/compile/testdata/sync/comprehensions/issue1732.txtar new file mode 100644 index 000000000..a4f14da7d --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue1732.txtar @@ -0,0 +1,351 @@ +# Tests comprehensions with definitions that use incomplete boolean conditions, +# including nested definition references and cross-struct comprehensions. +# Issue #1732: comprehension with abstract bool condition in definitions causes +# "incomplete bool" error propagation through nested structs. +-- in.cue -- +package config + +networkingv1: { + metav1: { + #LabelSelector: { + matchLabels: {[string]: string} + } + } + + #NetworkPolicy: { + spec: #NetworkPolicySpec + } + + #NetworkPolicySpec: { + ingress: [...#NetworkPolicyIngressRule] + egress: [...#NetworkPolicyEgressRule] + } + + #NetworkPolicyIngressRule: { + from: [...#NetworkPolicyPeer] + } + + #NetworkPolicyEgressRule: { + to: [...#NetworkPolicyPeer] + } + + #NetworkPolicyPeer: { + namespaceSelector: null | metav1.#LabelSelector + } +} + +global_config: { + #GlobalConfig: { + auth0: { + enabled: bool + } + } +} +common: { + #SomeConfig: { + enabled: bool + if enabled { + foo: string + } + @test(err, code=incomplete, contains="incomplete bool", pos=[1:12]) + } +} + +foo: { + #Values: { + global: global_config.#GlobalConfig + } +} + +#Config: R={ + tenant: id: string + + auth0: common.#SomeConfig & { + enabled: bool + if (enabled) { + foo: "\(tenant.id)-value" + } + } + + charts: { + "foo": foo.#Values & { + global: R.global + } + } + + global: global_config.#GlobalConfig & { + auth0: enabled: R.auth0.enabled + } +} + +#NetworkPolicy: networkingv1.#NetworkPolicy + +#Flux: R={ + #Config + + charts: _ + + formatOutput: {...} + + _outputs: {...} + + for _chartName, _chartValues in charts { + _outputs: "\(_chartName)": {} + } + + _outputs: { + for ns in ["ns"] { + "\(ns)/network": #NetworkPolicy & { + spec: { + ingress: [ + { + from: [{ + namespaceSelector: matchLabels: { + tenant: R.tenant.id + } + }] + }, + ] + egress: [ + { + to: [{ + namespaceSelector: matchLabels: { + tenant: R.tenant.id + } + }] + }, + ] + } + } + } + } + + for ns in ["ns"] { + for k, v in _outputs { + formatOutput: "\(k)": v + } + } +} +@test(eq, { + networkingv1: { + metav1: {#LabelSelector: {matchLabels: {}}} + #NetworkPolicy: {spec: {ingress: [], egress: []}} + #NetworkPolicySpec: {ingress: [], egress: []} + #NetworkPolicyIngressRule: {from: []} + #NetworkPolicyEgressRule: {to: []} + #NetworkPolicyPeer: { + namespaceSelector: null | {matchLabels: {}} + } + } + global_config: { + #GlobalConfig: {auth0: {enabled: bool}} + } + common: {#SomeConfig: {_|_, enabled: bool}} + foo: { + #Values: {global: {auth0: {enabled: bool}}} + } + #Config: { + tenant: {id: string} + auth0: {_|_, enabled: bool} + charts: { + foo: { + global: { + auth0: { + enabled: _|_ @test(err, code=incomplete, contains="#Config.auth0: incomplete bool: bool (and 1 more errors)", pos=[59:12]) + } + } + } + } + global: { + auth0: { + enabled: _|_ @test(err, code=incomplete, contains="#Config.auth0: incomplete bool: bool (and 1 more errors)", pos=[59:12]) + } + } + } + #NetworkPolicy: {spec: {ingress: [], egress: []}} + #Flux: { + charts: { + foo: {global: {auth0: {enabled: bool}}} + } + formatOutput: { + foo: {} + "ns/network": { + spec: { + ingress: [{ + from: [{ + namespaceSelector: {matchLabels: {tenant: string}} + }] + }] + egress: [{ + to: [{ + namespaceSelector: {matchLabels: {tenant: string}} + }] + }] + } + } + } + _outputs$config: { + foo: {} + "ns/network": { + spec: { + ingress: [{ + from: [{ + namespaceSelector: {matchLabels: {tenant: string}} + }] + }] + egress: [{ + to: [{ + namespaceSelector: {matchLabels: {tenant: string}} + }] + }] + } + } + } + tenant: {id: string} + auth0: {_|_, enabled: bool} + global: { + auth0: { + enabled: _|_ @test(err, code=incomplete, contains="#Flux.auth0: incomplete bool: bool (and 1 more errors)", pos=[59:12]) + } + } + } +}) +-- out/compile -- +--- in.cue +{ + networkingv1: { + metav1: { + #LabelSelector: { + matchLabels: { + [string]: string + } + } + } + #NetworkPolicy: { + spec: 〈1;#NetworkPolicySpec〉 + } + #NetworkPolicySpec: { + ingress: [ + ...〈2;#NetworkPolicyIngressRule〉, + ] + egress: [ + ...〈2;#NetworkPolicyEgressRule〉, + ] + } + #NetworkPolicyIngressRule: { + from: [ + ...〈2;#NetworkPolicyPeer〉, + ] + } + #NetworkPolicyEgressRule: { + to: [ + ...〈2;#NetworkPolicyPeer〉, + ] + } + #NetworkPolicyPeer: { + namespaceSelector: (null|〈1;metav1〉.#LabelSelector) + } + } + global_config: { + #GlobalConfig: { + auth0: { + enabled: bool + } + } + } + common: { + #SomeConfig: { + enabled: bool + if 〈0;enabled〉 { + foo: string + } + } + } + foo: { + #Values: { + global: 〈2;global_config〉.#GlobalConfig + } + } + #Config: { + tenant: { + id: string + } + auth0: (〈1;common〉.#SomeConfig & { + enabled: bool + if 〈0;enabled〉 { + foo: "\(〈2;tenant〉.id)-value" + } + }) + charts: { + foo: (〈2;foo〉.#Values & { + global: 〈3〉.global + }) + } + global: (〈1;global_config〉.#GlobalConfig & { + auth0: { + enabled: 〈3〉.auth0.enabled + } + }) + } + #NetworkPolicy: 〈0;networkingv1〉.#NetworkPolicy + #Flux: { + 〈1;#Config〉 + charts: _ + formatOutput: { + ... + } + _outputs(:config): { + ... + } + for _chartName, _chartValues in 〈0;charts〉 { + _outputs(:config): { + "\(〈2;_chartName(:config)〉)": {} + } + } + _outputs(:config): { + for _, ns in [ + "ns", + ] { + "\(〈1;ns〉)/network": (〈4;#NetworkPolicy〉 & { + spec: { + ingress: [ + { + from: [ + { + namespaceSelector: { + matchLabels: { + tenant: 〈12〉.tenant.id + } + } + }, + ] + }, + ] + egress: [ + { + to: [ + { + namespaceSelector: { + matchLabels: { + tenant: 〈12〉.tenant.id + } + } + }, + ] + }, + ] + } + }) + } + } + for _, ns in [ + "ns", + ] { + for k, v in 〈2;_outputs(:config)〉 { + formatOutput: { + "\(〈2;k〉)": 〈2;v〉 + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue2171.txtar b/internal/core/compile/testdata/sync/comprehensions/issue2171.txtar new file mode 100644 index 000000000..4c794d116 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue2171.txtar @@ -0,0 +1,23 @@ +// Sometimes an arc should not "Finalize" itself. See Issue #2171 in eval.go. +-- in.cue -- +package x + +do: { + hello: { + } +} + +for k, v in do {do: (k): v} +@test(eq, {do: hello: {}}) +-- out/compile -- +--- in.cue +{ + do: { + hello: {} + } + for k, v in 〈0;do〉 { + do: { + 〈2;k〉: 〈2;v〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue2481.txtar b/internal/core/compile/testdata/sync/comprehensions/issue2481.txtar new file mode 100644 index 000000000..3c639c3ef --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue2481.txtar @@ -0,0 +1,134 @@ +# Tests that mixing struct fields and embedded scalars in a comprehension body +# correctly reports an error. Issue #2481: nested for/if/let comprehensions +# triggered a spurious "circular dependency" error in the evaluator. +# https://cuelang.org/issue/2481 +// Mixing struct fields and embedded scalars should error. Using comprehensions +// this follows a different path which may miss the error. +// TODO: fix +-- in.cue -- +// Mixing struct fields and embedded scalars should error. Using comprehensions +// this follows a different path which may miss the error. +// TODO: fix +out: { + for k in keys { + if values[k] != _|_ { + val: k + if val != _|_ { + k + } + } + } + @test(err, code=eval, hint="string with struct") +} + +// multiple lets are mapped to the same location and will conflict. This is +// fine, though, as lets do not represent a single data field. This should +// therefore not error. +// TODO: fix +multiLets: { + for k in keys { + if values[k] != _|_ { + let val = k + if val != _|_ { + k + } + } + } + @test(eq, "b") +} + +keys: [ + // order matters + "a", + "b", +] @test(eq, ["a", "b"]) + +values: { + // order does not matter + "b": "member" + "c": "foo" + @test(eq, {b: "member", c: "foo"}) +} + +full: { + out: { + + // changing this to a list of the keys "fixes" things, i.e. this comprehension is required + for k, _ in #github_team_membership { + + // Remove this comprehension to trigger a different type of cycle error + if ( values[k] != _|_ ) { + + // This let is also required + let val = values[k] + + if val != null && ((val & string) != _|_) { + (k): val + } + } + } + } + + #github_team_membership: { + team_id: string + role: string + } + + values: { + "role": "member" + "username": "foo" + } + @test(eq, {out: {role: "member"}, #github_team_membership: {team_id: string, role: string}, values: {role: "member", username: "foo"}}) +} +-- out/compile -- +--- in.cue +{ + out: { + for _, k in 〈1;keys〉 { + if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { + val: 〈2;k〉 + if (〈0;val〉 != _|_(explicit error (_|_ literal) in source)) { + 〈3;k〉 + } + } + } + } + multiLets: { + for _, k in 〈1;keys〉 { + if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { + let val#1multi = 〈2;k〉 + if (〈0;let val#1〉 != _|_(explicit error (_|_ literal) in source)) { + 〈3;k〉 + } + } + } + } + keys: [ + "a", + "b", + ] + values: { + b: "member" + c: "foo" + } + full: { + out: { + for k, _ in 〈1;#github_team_membership〉 { + if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { + let val#2multi = 〈4;values〉[〈2;k〉] + if ((〈0;let val#2〉 != null) && ((〈0;let val#2〉 & string) != _|_(explicit error (_|_ literal) in source))) { + 〈3;k〉: 〈1;let val#2〉 + } + } + } + } + #github_team_membership: { + team_id: string + role: string + } + values: { + role: "member" + username: "foo" + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue287.txtar b/internal/core/compile/testdata/sync/comprehensions/issue287.txtar new file mode 100644 index 000000000..027fb24ed --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue287.txtar @@ -0,0 +1,31 @@ +-- in.cue -- +if #E["x"] != _|_ { + #E: {y: true} +} +if #E["y"] != _|_ { + z: true +} +#E: [_]: bool +#E: x: true +#E: _ @test(eq, {y: true, x: true}) +z: _ @test(eq, true) +-- out/compile -- +--- in.cue +{ + if (〈0;#E〉["x"] != _|_(explicit error (_|_ literal) in source)) { + #E: { + y: true + } + } + if (〈0;#E〉["y"] != _|_(explicit error (_|_ literal) in source)) { + z: true + } + #E: { + [_]: bool + } + #E: { + x: true + } + #E: _ + z: _ +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue293.txtar b/internal/core/compile/testdata/sync/comprehensions/issue293.txtar new file mode 100644 index 000000000..6fa23bfd3 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue293.txtar @@ -0,0 +1,82 @@ +# Issue #1969: Tests that comparing fields to _|_ (checking if defined) works +# correctly for both closed and open structs, including edge cases with +# comprehensions and let clauses. +-- in.cue -- +#T: { + if true { + // We'd like to restrict the possible members of x in this case, + // but this doesn't work. + x: close({ + f1: int + }) + } + x: _ +// All tests here should pass and the result of the okcN tests should be +// identical to those of the okoN tests. +// Should Field s exist in okc or not? Depends on whether comparison to bottom +// is recursive or not. It probably should not. +// TODO: fix for new evaluator. But possibly address this with new builtins. +} +z: #T & { + x: { + f1: 99 + f2: "i want to disallow this" + } +} @test(err, code=eval, at=x.f2, contains="field not allowed", pos=[3:3]) + + +t: #C @test(eq, {p: "foo"}) +#C: { + if true { + p: _ +// Comparing to string is not an error. But for legacy reasons we want to still +// support this. We intend to have more clean and precise behavior with the +// builtins isdefined, isvalid, and isconcrete. + } +} +t: p: "foo" + +-- variant1.cue -- +#V1: { + x: close({ f1: int }) + x: f2: 2 @test(err, code=eval, contains="field not allowed", pos=[0:5]) +} + +-- out/compile -- +--- in.cue +{ + #T: { + if true { + x: close({ + f1: int + }) + } + x: _ + } + z: (〈0;#T〉 & { + x: { + f1: 99 + f2: "i want to disallow this" + } + }) + t: 〈0;#C〉 + #C: { + if true { + p: _ + } + } + t: { + p: "foo" + } +} +--- variant1.cue +{ + #V1: { + x: close({ + f1: int + }) + x: { + f2: 2 + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue3762.txtar b/internal/core/compile/testdata/sync/comprehensions/issue3762.txtar new file mode 100644 index 000000000..79fd4e3b9 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue3762.txtar @@ -0,0 +1,238 @@ +# Tests that comprehensions over intersections of hidden fields work correctly. +# Issue #3762: for comprehensions over _a & _b where both have patterns. +-- in.cue -- +full: { + kube: node: n1: { + _CL: "l" + _cs: (_CL): _a[(_CL)] + _cs: (_CL): { + opts: {} + } + } + + _a: "l": { + _ba?: string + opts: { + if _ba != _|_ {b: (_ba)} + } + } + + for k, _ in _a & _b { + x: 5 + } + + _a: [ID=_]: vms: [{ name: "hello" }] + _b: [ID=_]: vms: [{ name: "again" }] + @test(eq, { + kube: node: n1: { + _CL: "l" + _cs: l: { + opts: {} + _ba?: string + vms: [{ + name: "hello" + }] + } + } + _a: l: { + _ba?: string + opts: {} + vms: [{ + name: "hello" + }] + } + x: 5 + _b: {} + }) +} +reduced: p1: { + _cs: _a.l & { + opts: {} + } + + _a: l: { + _ba?: string + opts: { + if _ba != _|_ { + b: _ba + } + } + vms: "hello" + } + + _b: l: vms: "again" + + for k, _ in _a & _b { + x: 5 + } + @test(eq, { + _cs: {opts: {}, _ba?: string, vms: "hello"} + _a: { + l: {_ba?: string, opts: {}, vms: "hello"} + } + _b: {l: {vms: "again"}} + x: 5 + }) +} +reduced: p2: { + for k, _ in _a & _b { + x: 5 + } + + _cs: _a.l & { + opts: {} + } + + _a: l: { + _ba?: string + opts: { + if _ba != _|_ { + b: _ba + } + } + vms: "hello" + } + + _b: l: vms: "again" + @test(eq, { + x: 5 + _cs: {opts: {}, _ba?: string, vms: "hello"} + _a: { + l: {_ba?: string, opts: {}, vms: "hello"} + } + _b: {l: {vms: "again"}} + }) +} +reference: { + _x: { + f: true + } + + _y: { + f: false + } + + for k, _ in _x & _y { + ok: true + } + @test(eq, { + _x: {f: true} + _y: {f: false} + ok: true + }) +} +-- out/compile -- +--- in.cue +{ + full: { + kube: { + node: { + n1: { + _CL: "l" + _cs: { + 〈1;_CL〉: 〈4;_a〉[〈1;_CL〉] + } + _cs: { + 〈1;_CL〉: { + opts: {} + } + } + } + } + } + _a: { + l: { + _ba?: string + opts: { + if (〈1;_ba〉 != _|_(explicit error (_|_ literal) in source)) { + b: 〈2;_ba〉 + } + } + } + } + for k, _ in (〈0;_a〉 & 〈0;_b〉) { + x: 5 + } + _a: { + [_]: { + vms: [ + { + name: "hello" + }, + ] + } + } + _b: { + [_]: { + vms: [ + { + name: "again" + }, + ] + } + } + } + reduced: { + p1: { + _cs: (〈0;_a〉.l & { + opts: {} + }) + _a: { + l: { + _ba?: string + opts: { + if (〈1;_ba〉 != _|_(explicit error (_|_ literal) in source)) { + b: 〈2;_ba〉 + } + } + vms: "hello" + } + } + _b: { + l: { + vms: "again" + } + } + for k, _ in (〈0;_a〉 & 〈0;_b〉) { + x: 5 + } + } + } + reduced: { + p2: { + for k, _ in (〈0;_a〉 & 〈0;_b〉) { + x: 5 + } + _cs: (〈0;_a〉.l & { + opts: {} + }) + _a: { + l: { + _ba?: string + opts: { + if (〈1;_ba〉 != _|_(explicit error (_|_ literal) in source)) { + b: 〈2;_ba〉 + } + } + vms: "hello" + } + } + _b: { + l: { + vms: "again" + } + } + } + } + reference: { + _x: { + f: true + } + _y: { + f: false + } + for k, _ in (〈0;_x〉 & 〈0;_y〉) { + ok: true + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue3763.txtar b/internal/core/compile/testdata/sync/comprehensions/issue3763.txtar new file mode 100644 index 000000000..6cfbd807c --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue3763.txtar @@ -0,0 +1,189 @@ +# Tests that nested comprehensions with let bindings across multiple files work. +# Issue #3763: for comprehension with multi-level let bindings and pattern constraints. +-- reduced.cue -- +reduced: { + A: x1: y?: int // needs to be optional + A: x2: y?: int + A: x3: y?: int + + if true { + let Z = [for _, x in A {x}] + B: [for z in Z if z.y != _|_ { b: 1 }] + } + @test(eq, { + A: { + x1: {y?: int} + x2: {y?: int} + x3: {y?: int} + } + B: [] + }) +} +-- full.cue -- +full: { + _core_v1: { + #cp: { + hostPort?: int32 + cp: int32 + } + } + + @test(shareID=L, at=k.n.n1._cs.l) + k: n: n1: { + _CL: "l" + } + + let nc = { + _ports: [ID=_]: _core_v1.#cp + } + + _cl: [ID=_]: nc & { + _ports: { + "1": {} + "2": {} + "3": {} + } + } + + k: n: [ID=_]: { + _CL: string + _cs: (_CL): _cl[(_CL)] + } + + for _, n in k.n { + let cps = [for _, c in n._cs for _, cps in c._ports {cps}] + ports: [for cp in cps if cp.hostPort != _|_ { + port: "\(cp.hostPort)" + }] + } + + _cl: l: {} @test(shareID=L) + @test(eq, { + _core_v1: #cp: { + hostPort?: >=-2147483648 & <=2147483647 & int + cp: >=-2147483648 & <=2147483647 & int + } + k: n: n1: { + _CL: "l" + _cs: l: _ports: { + "1": { + hostPort?: >=-2147483648 & <=2147483647 & int + cp: >=-2147483648 & <=2147483647 & int + } + "2": { + hostPort?: >=-2147483648 & <=2147483647 & int + cp: >=-2147483648 & <=2147483647 & int + } + "3": { + hostPort?: >=-2147483648 & <=2147483647 & int + cp: >=-2147483648 & <=2147483647 & int + } + } + } + _cl: l: _ports: { + "1": { + hostPort?: >=-2147483648 & <=2147483647 & int + cp: >=-2147483648 & <=2147483647 & int + } + "2": { + hostPort?: >=-2147483648 & <=2147483647 & int + cp: >=-2147483648 & <=2147483647 & int + } + "3": { + hostPort?: >=-2147483648 & <=2147483647 & int + cp: >=-2147483648 & <=2147483647 & int + } + } + ports: [] + }) +} +-- out/compile -- +--- full.cue +{ + full: { + _core_v1: { + #cp: { + hostPort?: &(int, >=-2147483648, <=2147483647) + cp: &(int, >=-2147483648, <=2147483647) + } + } + k: { + n: { + n1: { + _CL: "l" + } + } + } + let nc#1 = { + _ports: { + [_]: 〈2;_core_v1〉.#cp + } + } + _cl: { + [_]: (〈1;let nc#1〉 & { + _ports: { + "1": {} + "2": {} + "3": {} + } + }) + } + k: { + n: { + [_]: { + _CL: string + _cs: { + 〈1;_CL〉: 〈4;_cl〉[〈1;_CL〉] + } + } + } + } + for _, n in 〈0;k〉.n { + let cps#2multi = [ + for _, c in 〈2;n〉._cs for _, cps in 〈0;c〉._ports { + 〈1;cps〉 + }, + ] + ports: [ + for _, cp in 〈1;let cps#2〉 if (〈0;cp〉.hostPort != _|_(explicit error (_|_ literal) in source)) { + port: "\(〈1;cp〉.hostPort)" + }, + ] + } + _cl: { + l: {} + } + } +} +--- reduced.cue +{ + reduced: { + A: { + x1: { + y?: int + } + } + A: { + x2: { + y?: int + } + } + A: { + x3: { + y?: int + } + } + if true { + let Z#3 = [ + for _, x in 〈2;A〉 { + 〈1;x〉 + }, + ] + B: [ + for _, z in 〈1;let Z#3〉 if (〈0;z〉.y != _|_(explicit error (_|_ literal) in source)) { + b: 1 + }, + ] + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue3929.txtar b/internal/core/compile/testdata/sync/comprehensions/issue3929.txtar new file mode 100644 index 000000000..2b7b56935 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue3929.txtar @@ -0,0 +1,299 @@ +# evalv3 regression: nested if-comprehensions inside a definition accessed via +# a for-comprehension over a pattern-constrained struct incorrectly produced an +# "incomplete value" error. The if-comprehensions (e.g. strings.HasSuffix +# guards) failed to evaluate when the definition was reached through multiple +# layers of embedding (_#cronjob → _#pod → _#container). evalv2 (v0.12.1) +# accepted the code correctly. +# https://cuelang.org/issue/3929 +-- in.cue -- +package main + +import "strings" + +reduced: { + #Input: { + @test(shareID=reducedInput) + name: string + age: "one" | "two" + if name != _|_ { + if true { + age: "one" + } + } + } + + #def1: { + IN=_in: _ + def1: #def2 & {_in: IN} + } + + #def2: { + IN=_in: _ + def2: #def3 & {_in: IN} + } + + #def3: { + _in: #Input @test(shareID=reducedInput) + def3: _in.age + } + + in: name: "foobar" + + out: (#def1 & {_in: in}).def1 + @test(eq, { + #Input: {name: string, age: "one" | "two"} + #def1: { + _in$main: _ + def1: { + _in$main: _ + def2: { + _in$main: {name: string, age: "one" | "two"} + def3: "one" | "two" + } + } + } + #def2: { + _in$main: _ + def2: { + _in$main: {name: string, age: "one" | "two"} + def3: "one" | "two" + } + } + #def3: { + _in$main: {name: string, age: "one" | "two"} + def3: "one" | "two" + } + in: {name: "foobar"} + out: { + _in$main: {name: "foobar"} + def2: { + _in$main: {name: "foobar", age: "one"} + def3: "one" + } + } + }) +} + +full: { + cronjob: [string]: #CronjobConfig + + #CronjobConfig: { + @test(shareID=cronjobConfig) + #PodConfig + } + + #PodConfig: { + @test(shareID=podConfig) + #ContainerConfig + } + + #ContainerConfig: { + @test(shareID=containerConfig) + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + if image != _|_ { + if strings.HasSuffix(image, ":latest") == true { + imagePullPolicy: "IfNotPresent" | *"Always" | "Never" + } + if strings.HasSuffix(image, ":latest") != true { + imagePullPolicy: *"IfNotPresent" | "Always" | "Never" + } + } + } + + _#cronjob: { + c=_config: #CronjobConfig @test(shareID=cronjobConfig) + + out: spec: jobTemplate: spec: template: _#pod & {_config: c} + } + + _#pod: { + c=_config: #PodConfig @test(shareID=podConfig) + + spec: containers: [{ + _#container & { + _config: c + } + }] + } + + _#container: { + c=_config: #ContainerConfig @test(shareID=containerConfig) + + imagePullPolicy: c.imagePullPolicy + } + + cronjob: "foobar": image: "foobar:latest" + + for k, v in cronjob { + objects: cronjob: "\(k)": (_#cronjob & {_config: v}).out + } + @test(eq, hint="update this once todo is fixed", { + cronjob: foobar: { + image: "foobar:latest" + imagePullPolicy: *"Always" | "IfNotPresent" | "Never" + } + #CronjobConfig: { + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + #PodConfig: { + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + #ContainerConfig: { + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + _#cronjob$main: { + _config$main: { + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + out: spec: jobTemplate: spec: template: { + _config$main: { + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + spec: containers: [{ + _config$main: _ @test(ignore) + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + }] + } + } + _#pod$main: { + _config$main: { + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + spec: containers: [{ + _config$main: _ @test(ignore) + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + }] + } + _#container$main: { + _config$main: { + image: string + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + imagePullPolicy: "IfNotPresent" | "Always" | "Never" + } + objects: cronjob: foobar: spec: jobTemplate: spec: template: { + _config$main: { + image: "foobar:latest" + imagePullPolicy: *"Always" | "IfNotPresent" | "Never" + } + spec: containers: [{ + _config$main: _ @test(ignore) + imagePullPolicy: *"Always" | "IfNotPresent" | "Never" + }] + } + }) + // TODO(inline) support at for closed. + // @test(closed, at=full.objects.cronjob.foobar) + +} +-- out/compile -- +--- in.cue +{ + reduced: { + #Input: { + name: string + age: ("one"|"two") + if (〈0;name〉 != _|_(explicit error (_|_ literal) in source)) { + if true { + age: "one" + } + } + } + #def1: { + _in(:main): _ + def1: (〈1;#def2〉 & { + _in(:main): 〈1;_in(:main)〉 + }) + } + #def2: { + _in(:main): _ + def2: (〈1;#def3〉 & { + _in(:main): 〈1;_in(:main)〉 + }) + } + #def3: { + _in(:main): 〈1;#Input〉 + def3: 〈0;_in(:main)〉.age + } + in: { + name: "foobar" + } + out: (〈0;#def1〉 & { + _in(:main): 〈1;in〉 + }).def1 + } + full: { + cronjob: { + [string]: 〈1;#CronjobConfig〉 + } + #CronjobConfig: { + 〈1;#PodConfig〉 + } + #PodConfig: { + 〈1;#ContainerConfig〉 + } + #ContainerConfig: { + image: string + imagePullPolicy: ("IfNotPresent"|"Always"|"Never") + if (〈0;image〉 != _|_(explicit error (_|_ literal) in source)) { + if (〈import;strings〉.HasSuffix(〈1;image〉, ":latest") == true) { + imagePullPolicy: ("IfNotPresent"|*"Always"|"Never") + } + if (〈import;strings〉.HasSuffix(〈1;image〉, ":latest") != true) { + imagePullPolicy: (*"IfNotPresent"|"Always"|"Never") + } + } + } + _#cronjob(:main): { + _config(:main): 〈1;#CronjobConfig〉 + out: { + spec: { + jobTemplate: { + spec: { + template: (〈5;_#pod(:main)〉 & { + _config(:main): 〈5;_config(:main)〉 + }) + } + } + } + } + } + _#pod(:main): { + _config(:main): 〈1;#PodConfig〉 + spec: { + containers: [ + { + (〈4;_#container(:main)〉 & { + _config(:main): 〈4;_config(:main)〉 + }) + }, + ] + } + } + _#container(:main): { + _config(:main): 〈1;#ContainerConfig〉 + imagePullPolicy: 〈0;_config(:main)〉.imagePullPolicy + } + cronjob: { + foobar: { + image: "foobar:latest" + } + } + for k, v in 〈0;cronjob〉 { + objects: { + cronjob: { + "\(〈3;k〉)": (〈4;_#cronjob(:main)〉 & { + _config(:main): 〈4;v〉 + }).out + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue436.txtar b/internal/core/compile/testdata/sync/comprehensions/issue436.txtar new file mode 100644 index 000000000..5773037c8 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue436.txtar @@ -0,0 +1,47 @@ +# Tests that if-comprehensions inside a definition correctly match default +# values when the condition is satisfied. Issue #436: conditional in a definition +# unified with a concrete value was not evaluating the condition correctly. +# https://cuelang.org/issue/436 +-- in.cue -- +#a: { + val: string + result: string + @test(closed) +} + +a: #a & { + val: *"default" | string + result: *"not-matched" | string + if (val == "match") { + result: "matched" + } +} @test(eq, {val: *"default" | string, result: *"not-matched" | string}) @test(closed) + +match: a & { + val: "match" +} @test(eq, {val: "match", result: "matched"}) @test(closed) + +not: a & { + val: "other" +} @test(eq, {val: "other", result: *"not-matched" | string}) @test(closed) +-- out/compile -- +--- in.cue +{ + #a: { + val: string + result: string + } + a: (〈0;#a〉 & { + val: (*"default"|string) + result: (*"not-matched"|string) + if (〈0;val〉 == "match") { + result: "matched" + } + }) + match: (〈0;a〉 & { + val: "match" + }) + not: (〈0;a〉 & { + val: "other" + }) +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue507.txtar b/internal/core/compile/testdata/sync/comprehensions/issue507.txtar new file mode 100644 index 000000000..24f54819e --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue507.txtar @@ -0,0 +1,59 @@ +# Tests that list comprehensions work correctly when iterating over lists with +# default values (disjunctions using *). Issue #507: comprehensions over +# [...T] | *[elem] lists failed with "invalid operand" errors. +# https://cuelang.org/issue/507 +-- in.cue -- +package x + +somelist: [...string] | *[] +// Works just fine +foo: [ + for e in somelist { + "hello foo: \(e)" + }, +] @test(eq, []) + +otherlist: ["something"] @test(eq, ["something"]) +// Works fine as well +z: [ + for e in otherlist { + "hello z: \(e)" + }, +] @test(eq, ["hello z: something"]) + +extlist: [...string] | *["something"] +bar: [ + for e in extlist { + "hello bar: \(e)" + }, +] @test(eq, ["hello bar: something"]) +-- out/compile -- +--- in.cue +{ + somelist: ([ + ...string, + ]|*[]) + foo: [ + for _, e in 〈1;somelist〉 { + "hello foo: \(〈1;e〉)" + }, + ] + otherlist: [ + "something", + ] + z: [ + for _, e in 〈1;otherlist〉 { + "hello z: \(〈1;e〉)" + }, + ] + extlist: ([ + ...string, + ]|*[ + "something", + ]) + bar: [ + for _, e in 〈1;extlist〉 { + "hello bar: \(〈1;e〉)" + }, + ] +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue837.txtar b/internal/core/compile/testdata/sync/comprehensions/issue837.txtar new file mode 100644 index 000000000..b2c383735 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue837.txtar @@ -0,0 +1,157 @@ +# Tests that errors in definitions with complex reference chains are reported +# correctly, specifically undefined field errors via let bindings. Issue #837. +-- in.cue -- +#DeploymentManifest: #Manifest & {ref: kind: "deployment"} + +#Manifest: { + ref: #ManifestRef + description: #KumoriKinds[ref.kind] @test(err, code=incomplete, + contains="unresolved disjunction %v (type %s)", + args=["service" | "deployment", string], pos=[0:15]) +} + +#ManifestRef: kind: #KindsNames + +#KindsNames: "service" | "deployment" + +#KumoriKinds: deployment: #Deployment +#KumoriKinds: [string]: {...} + +#DoDeploy: { + _params: manifest: #DeploymentManifest + deployment: { + description: { + let dep = _params.manifest.description + service: (#Configure & { + _params: hsize: dep.hsize + }).service + @test(err, at=service.description.role, code=incomplete, + contains="undefined field: %s", args=[role], pos=[24:19]) + } + } +} + +#Configure: { + $p=_params: { + hsize: [string]: #RoleSize + } + service: { + description: { + let configed = (#RelabelService & { + _params: { + hsize: $p.hsize + } + role: "admin" + }).out + + role: configed.role @test(err, code=incomplete, + contains="undefined field: %s", args=[role], pos=[0:19]) + } + } +} + +#RelabelService: { + $p=_params: { + hsize: #RoleSize + } + + out: { + labstr: $p.label @test(err, code=eval, + contains="undefined field: %s", args=[label], pos=[0:14]) + + } +} @test(err, code=eval) + +#RoleSize: { + $_instances: >=0 | *1 +} + +#Deployment: { + service: #ServiceManifest + hsize: [service.description.#roles]: #RoleSize +} + +#ServiceManifest: #Manifest & {ref: kind: "service"} +@test(err, at=#ServiceManifest.description, code=incomplete, + contains="undefined field: %s", args=[service], pos=[-67:28]) + +-- out/compile -- +--- in.cue +{ + #DeploymentManifest: (〈0;#Manifest〉 & { + ref: { + kind: "deployment" + } + }) + #Manifest: { + ref: 〈1;#ManifestRef〉 + description: 〈1;#KumoriKinds〉[〈0;ref〉.kind] + } + #ManifestRef: { + kind: 〈1;#KindsNames〉 + } + #KindsNames: ("service"|"deployment") + #KumoriKinds: { + deployment: 〈1;#Deployment〉 + } + #KumoriKinds: { + [string]: { + ... + } + } + #DoDeploy: { + _params: { + manifest: 〈2;#DeploymentManifest〉 + } + deployment: { + description: { + let dep#1 = 〈2;_params〉.manifest.description + service: (〈3;#Configure〉 & { + _params: { + hsize: 〈2;let dep#1〉.hsize + } + }).service + } + } + } + #Configure: { + _params: { + hsize: { + [string]: 〈3;#RoleSize〉 + } + } + service: { + description: { + let configed#2 = (〈3;#RelabelService〉 & { + _params: { + hsize: 〈4;_params〉.hsize + } + role: "admin" + }).out + role: 〈0;let configed#2〉.role + } + } + } + #RelabelService: { + _params: { + hsize: 〈2;#RoleSize〉 + } + out: { + labstr: 〈1;_params〉.label + } + } + #RoleSize: { + $_instances: (>=0|*1) + } + #Deployment: { + service: 〈1;#ServiceManifest〉 + hsize: { + [〈1;service〉.description.#roles]: 〈2;#RoleSize〉 + } + } + #ServiceManifest: (〈0;#Manifest〉 & { + ref: { + kind: "service" + } + }) +} diff --git a/internal/core/compile/testdata/sync/comprehensions/issue843.txtar b/internal/core/compile/testdata/sync/comprehensions/issue843.txtar new file mode 100644 index 000000000..9934c3622 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/issue843.txtar @@ -0,0 +1,121 @@ +# Tests that list comprehensions with definitions and nested constraints work. +# Issue #843: complex nested definition with list comprehensions and imports. +-- in.cue -- +package main + +import "list" + +#d1: { + as: [...string] + + #c: [ + #f1 & { + "as": list.Concat([["go"], as]) + }, + ] + @test(eq, { + as: [] + #c: [{ + do: "f1" + as: ["go"] + }] + }) +} + +#d2: { + p: *"." | string + + #c: [ + #f2 & { + from: #d1 & { + as: [p] + } + }, + ] + // TODO(inline): generatign this value is broken: hand-spun. + @test(eq, { + p: *"." | string + #c: [{ + do: "f2" + from: { + as: [*"."| string] + #c: [{ + do: "f1" + as: ["go", *"."| string] + }] + } + }] + }) +} + +#c1: { + #c: [...#o] + _ + ... + @test(eq, {_, #c: []}) +} + +#o: #f1 | #f2 + +#f1: { + do: "f1" + as: [...string] + @test(eq, {do: "f1", as: []}) +} + +@test(shareID=C1, at=#c1) +@test(shareID=C1, at=#f2.from) +#f2: { + do: "f2" + from: #c1 + @test(eq, {do: "f2", from: {_, #c: []}}) +} +-- out/compile -- +--- in.cue +{ + #d1: { + as: [ + ...string, + ] + #c: [ + (〈2;#f1〉 & { + as: 〈import;list〉.Concat([ + [ + "go", + ], + 〈3;as〉, + ]) + }), + ] + } + #d2: { + p: (*"."|string) + #c: [ + (〈2;#f2〉 & { + from: (〈3;#d1〉 & { + as: [ + 〈4;p〉, + ] + }) + }), + ] + } + #c1: { + #c: [ + ...〈2;#o〉, + ] + _ + ... + } + #o: (〈0;#f1〉|〈0;#f2〉) + #f1: { + do: "f1" + as: [ + ...string, + ] + } + #f2: { + do: "f2" + from: 〈1;#c1〉 + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/lists.txtar b/internal/core/compile/testdata/sync/comprehensions/lists.txtar new file mode 100644 index 000000000..5ea0936af --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/lists.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +a: [{a: 1}, {b: 2 & 3}] @test(err, code=eval, pos=[0:17, 0:21], contains="conflicting values") + +b: [for x in a {x}] @test(err, code=eval, pos=[-2:17, -2:21], contains="conflicting values") +-- out/compile -- +--- in.cue +{ + a: [ + { + a: 1 + }, + { + b: (2 & 3) + }, + ] + b: [ + for _, x in 〈1;a〉 { + 〈1;x〉 + }, + ] +} diff --git a/internal/core/compile/testdata/sync/comprehensions/multi.txtar b/internal/core/compile/testdata/sync/comprehensions/multi.txtar new file mode 100644 index 000000000..7598086dc --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/multi.txtar @@ -0,0 +1,78 @@ +-- in.cue -- +list: [2, 3] @test(eq, [2, 3]) +a: [ 3, for x in list {x}, for x in list {x}] @test(eq, [3, 2, 3, 2, 3]) +b: [ 3, if true {3}, for x in list if x > 2 {x}] @test(eq, [3, 3, 3]) + +// issue574: Tests that if and for comprehensions inside list literals +// correctly include or exclude elements based on conditions. +// https://cuelang.org/issue/574 +issue574: { + greet: true + bye: true + + message1: [ + if greet {"hello"}, + "how are you doing?", + "bye", + ] + + message2: [ + if !greet {"hello"}, + "how are you doing?", + if bye { + "bye" + }, + ] + @test(eq, { + greet: true + bye: true + message1: ["hello", "how are you doing?", "bye"] + message2: ["how are you doing?", "bye"] + }) +} +-- out/compile -- +--- in.cue +{ + list: [ + 2, + 3, + ] + a: [ + 3, + for _, x in 〈1;list〉 { + 〈1;x〉 + }, + for _, x in 〈1;list〉 { + 〈1;x〉 + }, + ] + b: [ + 3, + if true { + 3 + }, + for _, x in 〈1;list〉 if (〈0;x〉 > 2) { + 〈1;x〉 + }, + ] + issue574: { + greet: true + bye: true + message1: [ + if 〈1;greet〉 { + "hello" + }, + "how are you doing?", + "bye", + ] + message2: [ + if !〈1;greet〉 { + "hello" + }, + "how are you doing?", + if 〈1;bye〉 { + "bye" + }, + ] + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/nested.txtar b/internal/core/compile/testdata/sync/comprehensions/nested.txtar new file mode 100644 index 000000000..31980d92e --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/nested.txtar @@ -0,0 +1,208 @@ +# Tests that nested for comprehensions within field patterns work correctly. +# The test uses a kubernetes-like structure with services and deployments. +-- in.cue -- +package kube + +service: "node-exporter": { + spec: { + ports: [{ + name: "metrics" + port: 9100 + protocol: "TCP" + }] + } +} +deployment: "node-exporter": { + spec: template: { + spec: { + containers: [{ + ports: [{ + containerPort: 9100 + name: "scrape" + }] + }] + } + } + @test(eq, { + spec: template: spec: containers: [{ + ports: [{ + _export$kube: _ @test(ignore) + containerPort: 9100 + name: "scrape" + }] + name: string + }] + _name$kube: string + }) +} +service: [ID=string]: { + spec: { + ports: [...{ + port: int + protocol: *"TCP" | "UDP" + name: string | *"client" + }] + } +} +deployment: [ID=string]: {} +deployment: [ID=_]: _spec & {} +_spec: { + _name: string + spec: template: { + spec: containers: [{name: _name}] + } +} +_spec: spec: template: spec: containers: [...{ + ports: [...{ + _export: *true | false // include the port in the service + }] +}] +for k, v in deployment { + service: "\(k)": { + spec: selector: v.spec.template.metadata.labels + spec: ports: [ + for c in v.spec.template.spec.containers + for p in c.ports + if p._export { + let Port = p.containerPort // Port is an alias + port: *Port | int + targetPort: *Port | int + }, + ] + } +} +@test(eq, { + service: "node-exporter": spec: { + ports: [{ + name: "metrics" + port: 9100 + protocol: "TCP" + targetPort: *9100 | int + }] + selector: _|_ @test(err, code=incomplete, contains="service.\"node-exporter\".spec.selector: undefined field: metadata", pos=[59:35]) + } + deployment: "node-exporter": { + spec: template: spec: containers: [{ + ports: [{ + containerPort: 9100 + name: "scrape" + _export$kube: *true | false + }] + name: string + }] + _name$kube: string + } + _spec$kube: { + _name$kube: string + spec: template: spec: containers: [{ + name: string + ports: [] + }] + } +}) + +-- out/compile -- +--- in.cue +{ + service: { + "node-exporter": { + spec: { + ports: [ + { + name: "metrics" + port: 9100 + protocol: "TCP" + }, + ] + } + } + } + deployment: { + "node-exporter": { + spec: { + template: { + spec: { + containers: [ + { + ports: [ + { + containerPort: 9100 + name: "scrape" + }, + ] + }, + ] + } + } + } + } + } + service: { + [string]: { + spec: { + ports: [ + ...{ + port: int + protocol: (*"TCP"|"UDP") + name: (string|*"client") + }, + ] + } + } + } + deployment: { + [string]: {} + } + deployment: { + [_]: (〈1;_spec(:kube)〉 & {}) + } + _spec(:kube): { + _name(:kube): string + spec: { + template: { + spec: { + containers: [ + { + name: 〈5;_name(:kube)〉 + }, + ] + } + } + } + } + _spec(:kube): { + spec: { + template: { + spec: { + containers: [ + ...{ + ports: [ + ...{ + _export(:kube): (*true|false) + }, + ] + }, + ] + } + } + } + } + for k, v in 〈0;deployment〉 { + service: { + "\(〈2;k〉)": { + spec: { + selector: 〈4;v〉.spec.template.metadata.labels + } + spec: { + ports: [ + for _, c in 〈5;v〉.spec.template.spec.containers for _, p in 〈0;c〉.ports if 〈0;p〉._export(:kube) { + let Port#1 = 〈1;p〉.containerPort + port: (*〈0;let Port#1〉|int) + targetPort: (*〈0;let Port#1〉|int) + }, + ] + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/nested2.txtar b/internal/core/compile/testdata/sync/comprehensions/nested2.txtar new file mode 100644 index 000000000..6dd72df5a --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/nested2.txtar @@ -0,0 +1,845 @@ +-- in.cue -- +given: { + INC: USD: 2.0 + USD: GBP: 3.0 + @test(eq, {INC: {USD: 2.0}, USD: {GBP: 3.0}}) +} +hydrated: { + for k, v in given { + for k1, r in v { + "\(k)": "\(k)": 1.0 + "\(k1)": "\(k1)": 1.0 + "\(k)": "\(k1)": r + "\(k1)": "\(k)": number + } + } + @test(eq, { + INC: {INC: 1.0, USD: 2.0} + USD: {USD: 1.0, INC: number, GBP: 3.0} + GBP: {GBP: 1.0, USD: number} + }) +} + +foo: { + a: 10 + if a < 20 { + if a < 50 { + b: 20 + } + } + @test(eq, {a: 10, b: 20}) +} + +indirectlyNested: { + a: true // must be declared outside of the nested comprehensions for test. + if true { + b: { + if a { + a + } + } + } + @test(eq, {a: true, b: true}) +} + +directlyNestedEmpty: { + a: true + if true { + if a { + } + } + @test(eq, {a: true}) +} + +directlyDoublyNestedEmpty: { + a: true + if true { + if a { + } + } + @test(eq, {a: true}) +} + +indirectlyDoublyNestedEmpty: { + a: true + b: { + if true { + if a { + if a { + a + } + } + if a { + a + } + } + } + @test(eq, {a: true, b: true}) +} + +indirectlyDoublyNested: { + a: true + if true { + if a { + if a { + b: 1 + } + } + if a { + c: 1 + } + } + @test(eq, {a: true, c: 1, b: 1}) +} + +// This case used to trigger an over-aggressive deduplication. +// issue1974: Tests that two-level nested for comprehensions do not lose keys +// due to over-aggressive deduplication. https://cuelang.org/issue/1974 +issue1974: { + X: { + foo: { + bar: "" + baz: "" + } + } + out: { + for k, v in X for vk, vv in v { + "\(k)": "\(vk)": vv + } + } + @test(eq, { + X: {foo: {bar: "", baz: ""}} + out: {foo: {bar: "", baz: ""}} + }) +} +-- pending.cue -- +// Trigger notification while an arc is still pending. +T: int @test(eq, 1) +for C in Y { + let X = C.M + T: X.V +} +Y: x: { + M: V: 1 + for _ in M { + if true { M: {} } + } + @test(eq, {M: {V: 1}}) +} +-- issue3940.cue -- +// issue3940: Tests that chained comprehension clauses do not trigger spurious +// structural cycle errors in evalv3. https://cuelang.org/issue/3940 +// Test chained comprehension clauses (without braces) +issue3940: reduced1: { + X + a: b: X + a: b: a: b: {y: X @test(shareID=reduced1X)} + + X: { + @test(shareID=reduced1X) + a: {} + + objects: { + for v in a + for _ in ({} & v).objects { + } + } + } + + // The eq:todo value is now the correct result: the pushdown fix + // properly handles chained comprehension clauses, unifying a.b + // into a single struct. + @test(eq, { + a: { + b: { + a: {b: {y: {a: {}, objects: {}}}} + objects: _|_ @test(err, code=incomplete, contains="issue3940.reduced1.a.b.objects: undefined field: objects", pos=[15:22]) + } + } + X: {a: {}, objects: {}} + objects: {} + }) + @test(eq:todo, { + a: b: { + a: {b: {y: {a: {}, objects: {}}}} + objects: {} + } + X: {a: {}, objects: {}} + objects: {} + }) +} + +// Test nested comprehensions (with braces) - should work as before +issue3940: reduced2: { + X + a: b: X + a: b: a: b: {y: X @test(shareID=reduced2X)} + + X: { + @test(shareID=reduced2X) + a: {} + + objects: { + for v in a + for _ in ({} & v).objects { + } + } + } + // The pushdown fix resolves the spurious "undefined field" error + // on objects: reduced2 is structurally identical to reduced1 and + // should produce the same result. + @test(eq, { + a: { + b: { + a: {b: {y: {a: {}, objects: {}}}} + objects: _|_ + } + } + X: {a: {}, objects: {}} + objects: {} + }) + @test(eq:todo, { + a: { + b: { + a: {b: {y: {a: {}, objects: {}}}} + objects: {} + } + } + X: {a: {}, objects: {}} + objects: {} + }) +} +issue3940: reduced3: { + a: E + a: i: x: E + a: i: x: i: x: E + E: { + i: {} + o: [for m in i for v in ({} & m).o {}] + } + @test(eq, { + a: { + i: {x: {i: {x: {i: {}, o: []}}, o: []}} + o: [] + } + E: {i: {}, o: []} + }) + +} +issue3940: reduced4: { + out: Exporter & { + _imports: [{ + objects: {...} + #export: Exporter & { + _imports: [{ #export: Exporter }] + } + }] + } + + Exporter: { + _imports: [...] + objects: [ + for v in _imports for obj in ({} & v.#export).objects { + obj + }, + ] + } + @test(eq, { + out: { + _imports: [{ + objects: {} + #export: { + _imports: [{ + #export: { + _imports: [] + objects: [] + } + }] + objects: [] + } + }] + objects: [] + } + Exporter: {_imports: [], objects: []} + }) +} +issue3940: let: { + X + a: b: X + a: b: a: b: {y: X @test(shareID=letX)} + + X: { + @test(shareID=letX) + a: {} + + objects: { + for v in a + let x = ({} & v) + for _ in x.objects { + } + } + } +} +issue3940: full: { + out: #Exporter & { + _imports: [_branch] + #conf: global: region: "Europe" + } + + _branch: { + objects: branch: { + #conf: {...} + region: #conf.global.region + } + imports: [_leaf] + #export: #Exporter & { + _objects: objects + _imports: imports + } + } + _leaf: { + objects: leaf: { + #conf: {...} + region: #conf.global.region + } + #export: #Exporter & { + _objects: objects + } + } + #Exporter: { + CONF=#conf: {...} + _objects: {...} + _imports: [...] + + objects: [ + // local objects + for name, obj in _objects & {[string]: #conf: CONF} { + (name): obj + }, + + // transitively imported objects + for import in _imports + for obj in ({#conf: CONF} & import.#export).objects { + obj + }, + ] + } + @test(eq, at=out, { + _imports: [{ + objects: branch: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + imports: [{ + objects: leaf: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + #export: { + _objects: leaf: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + #conf: _ @test(ignore) + _imports: [] + objects: [{ + leaf: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + }] + } + }] + #export: { + _objects: branch: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + _imports: [{ + objects: leaf: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + #export: { + _objects: leaf: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + #conf: _ @test(ignore) + _imports: [] + objects: [{ + leaf: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + }] + } + }] + #conf: _ @test(ignore) + objects: [{ + branch: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + }, { + leaf: { + #conf: _ @test(ignore) + region: _|_ @test(err, code=incomplete, contains="undefined field: global") + } + }] + } + }] + #conf: {global: {region: "Europe"}} + _objects: {} + objects: [{ + branch: { + #conf: {global: {region: "Europe"}} + region: "Europe" + } + }, { + leaf: { + #conf: {global: {region: "Europe"}} + region: "Europe" + } + }] + }) +} +-- issue3990.cue -- +// issue3990: Tests that nested comprehensions within struct definitions do not +// trigger "field set was already referenced" errors in evalv3. +// https://cuelang.org/issue/3990 +issue3990: { + _imports: [_noVolumes, _someVolumes] + _noVolumes: { + name: "noVolumes" + exportObjs: deployment: _Deployment & { + volumes: [] + } + } + _someVolumes: { + name: "someVolumes" + exportObjs: deployment: _Deployment & { + volumes: [{name: "data"}] + } + } + + for import in _imports + for _, obj in ({extra: "unused"} & import).exportObjs {(import.name): obj}, + + _Deployment: this={ + _names: { + for _, v in this.volumes { + (v.name): v.name + } + } + // skip volumeNames if empty + if len(_names) > 0 { + volumeNames: [for _, v in _names {v}] + } + } + @test(eq, { + _imports: [{ + name: "noVolumes" + exportObjs: deployment: {volumes: [], _names: {}} + }, { + name: "someVolumes" + exportObjs: deployment: { + _names: {data: "data"} + volumeNames: ["data"] + volumes: [{ + name: "data" + }] + } + }] + _noVolumes: { + name: "noVolumes" + exportObjs: {deployment: {volumes: [], _names: {}}} + } + _someVolumes: { + name: "someVolumes" + exportObjs: { + deployment: { + volumes: [{ name: "data" }] + _names: {data: "data"} + volumeNames: ["data"] + } + } + } + _Deployment: { + _names: _|_ @test(err, code=incomplete) + } + someVolumes: { + volumes: [{ name: "data" }] + _names: {data: "data"} + volumeNames: ["data"] + } + noVolumes: {volumes: [], _names: {}} + }) +} +-- out/compile -- +--- in.cue +{ + given: { + INC: { + USD: 2.0 + } + USD: { + GBP: 3.0 + } + } + hydrated: { + for k, v in 〈1;given〉 { + for k1, r in 〈1;v〉 { + "\(〈3;k〉)": { + "\(〈4;k〉)": 1.0 + } + "\(〈1;k1〉)": { + "\(〈2;k1〉)": 1.0 + } + "\(〈3;k〉)": { + "\(〈2;k1〉)": 〈2;r〉 + } + "\(〈1;k1〉)": { + "\(〈4;k〉)": number + } + } + } + } + foo: { + a: 10 + if (〈0;a〉 < 20) { + if (〈1;a〉 < 50) { + b: 20 + } + } + } + indirectlyNested: { + a: true + if true { + b: { + if 〈2;a〉 { + 〈3;a〉 + } + } + } + } + directlyNestedEmpty: { + a: true + if true { + if 〈1;a〉 {} + } + } + directlyDoublyNestedEmpty: { + a: true + if true { + if 〈1;a〉 {} + } + } + indirectlyDoublyNestedEmpty: { + a: true + b: { + if true { + if 〈2;a〉 { + if 〈3;a〉 { + 〈4;a〉 + } + } + if 〈2;a〉 { + 〈3;a〉 + } + } + } + } + indirectlyDoublyNested: { + a: true + if true { + if 〈1;a〉 { + if 〈2;a〉 { + b: 1 + } + } + if 〈1;a〉 { + c: 1 + } + } + } + issue1974: { + X: { + foo: { + bar: "" + baz: "" + } + } + out: { + for k, v in 〈1;X〉 for vk, vv in 〈0;v〉 { + "\(〈2;k〉)": { + "\(〈2;vk〉)": 〈2;vv〉 + } + } + } + } +} +--- issue3940.cue +{ + issue3940: { + reduced1: { + 〈0;X〉 + a: { + b: 〈1;X〉 + } + a: { + b: { + a: { + b: { + y: 〈4;X〉 + } + } + } + } + X: { + a: {} + objects: { + for _, v in 〈1;a〉 for _, _ in ({} & 〈0;v〉).objects {} + } + } + } + } + issue3940: { + reduced2: { + 〈0;X〉 + a: { + b: 〈1;X〉 + } + a: { + b: { + a: { + b: { + y: 〈4;X〉 + } + } + } + } + X: { + a: {} + objects: { + for _, v in 〈1;a〉 for _, _ in ({} & 〈0;v〉).objects {} + } + } + } + } + issue3940: { + reduced3: { + a: 〈0;E〉 + a: { + i: { + x: 〈2;E〉 + } + } + a: { + i: { + x: { + i: { + x: 〈4;E〉 + } + } + } + } + E: { + i: {} + o: [ + for _, m in 〈1;i〉 for _, v in ({} & 〈0;m〉).o {}, + ] + } + } + } + issue3940: { + reduced4: { + out: (〈0;Exporter〉 & { + _imports: [ + { + objects: { + ... + } + #export: (〈3;Exporter〉 & { + _imports: [ + { + #export: 〈6;Exporter〉 + }, + ] + }) + }, + ] + }) + Exporter: { + _imports: [ + ..., + ] + objects: [ + for _, v in 〈1;_imports〉 for _, obj in ({} & 〈0;v〉.#export).objects { + 〈1;obj〉 + }, + ] + } + } + } + issue3940: { + let: { + 〈0;X〉 + a: { + b: 〈1;X〉 + } + a: { + b: { + a: { + b: { + y: 〈4;X〉 + } + } + } + } + X: { + a: {} + objects: { + for _, v in 〈1;a〉 let x = ({} & 〈0;v〉) for _, _ in 〈0;x〉.objects {} + } + } + } + } + issue3940: { + full: { + out: (〈0;#Exporter〉 & { + _imports: [ + 〈2;_branch〉, + ] + #conf: { + global: { + region: "Europe" + } + } + }) + _branch: { + objects: { + branch: { + #conf: { + ... + } + region: 〈0;#conf〉.global.region + } + } + imports: [ + 〈2;_leaf〉, + ] + #export: (〈1;#Exporter〉 & { + _objects: 〈1;objects〉 + _imports: 〈1;imports〉 + }) + } + _leaf: { + objects: { + leaf: { + #conf: { + ... + } + region: 〈0;#conf〉.global.region + } + } + #export: (〈1;#Exporter〉 & { + _objects: 〈1;objects〉 + }) + } + #Exporter: { + #conf: { + ... + } + _objects: { + ... + } + _imports: [ + ..., + ] + objects: [ + for name, obj in (〈1;_objects〉 & { + [string]: { + #conf: 〈3;#conf〉 + } + }) { + 〈1;name〉: 〈1;obj〉 + }, + for _, import in 〈1;_imports〉 for _, obj in ({ + #conf: 〈3;#conf〉 + } & 〈0;import〉.#export).objects { + 〈1;obj〉 + }, + ] + } + } + } +} +--- issue3990.cue +{ + issue3990: { + _imports: [ + 〈1;_noVolumes〉, + 〈1;_someVolumes〉, + ] + _noVolumes: { + name: "noVolumes" + exportObjs: { + deployment: (〈2;_Deployment〉 & { + volumes: [] + }) + } + } + _someVolumes: { + name: "someVolumes" + exportObjs: { + deployment: (〈2;_Deployment〉 & { + volumes: [ + { + name: "data" + }, + ] + }) + } + } + for _, import in 〈0;_imports〉 for _, obj in ({ + extra: "unused" + } & 〈0;import〉).exportObjs { + 〈2;import〉.name: 〈1;obj〉 + } + _Deployment: { + _names: { + for _, v in 〈2〉.volumes { + 〈1;v〉.name: 〈1;v〉.name + } + } + if (len(〈0;_names〉) > 0) { + volumeNames: [ + for _, v in 〈2;_names〉 { + 〈1;v〉 + }, + ] + } + } + } +} +--- pending.cue +{ + T: int + for _, C in 〈0;Y〉 { + let X#1multi = 〈1;C〉.M + T: 〈0;let X#1〉.V + } + Y: { + x: { + M: { + V: 1 + } + for _, _ in 〈0;M〉 { + if true { + M: {} + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/nestembed.txtar b/internal/core/compile/testdata/sync/comprehensions/nestembed.txtar new file mode 100644 index 000000000..9ee9fe486 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/nestembed.txtar @@ -0,0 +1,51 @@ +Issue #556 +# Issue #556: Tests that nested comprehensions with list.Contains filtering +# correctly produces only the non-deleted entries. +-- in.cue -- +import "list" + +DeleteThis: ["this", "that"] @test(eq, ["this", "that"]) +useful_infra: { + gcp: cluters: 10 + aws: clusters: 20 + this: clusters: 1 + that: clusters: 2 + @test(eq, {gcp: {cluters: 10}, aws: {clusters: 20}, this: {clusters: 1}, that: {clusters: 2}}) +} +New_infra: { + for k, v in useful_infra { + if !list.Contains(DeleteThis, k) { + "\(k)": v + } + } + @test(eq, {gcp: {cluters: 10}, aws: {clusters: 20}}) +} +-- out/compile -- +--- in.cue +{ + DeleteThis: [ + "this", + "that", + ] + useful_infra: { + gcp: { + cluters: 10 + } + aws: { + clusters: 20 + } + this: { + clusters: 1 + } + that: { + clusters: 2 + } + } + New_infra: { + for k, v in 〈1;useful_infra〉 { + if !〈import;list〉.Contains(〈3;DeleteThis〉, 〈1;k〉) { + "\(〈2;k〉)": 〈2;v〉 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/open_iter_writeback.txtar b/internal/core/compile/testdata/sync/comprehensions/open_iter_writeback.txtar new file mode 100644 index 000000000..0511ecc66 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/open_iter_writeback.txtar @@ -0,0 +1,77 @@ +# Regression coverage for the original bug behind deferFieldSetKnown +# (commit f1f0c649f, "adt: fix premature fieldSetKnown freeze for open +# structs"). The motivating pattern: a comprehension iterates an open +# struct (HasEllipsis=true) and the comprehension body adds arcs back +# to that struct. +# +# Two cases: +# - openIter: a sibling comprehension iterates the same open struct +# that another for-clause is writing into. The for-loop must observe +# the source's full final field set, not a snapshot frozen mid- +# evaluation. +# - defOpen: an external conjunct (`inst: #T & { b: 2 }`) adds a field +# to an open definition whose own body conditionally adds another; +# a [for] over `inst` must see both arcs. +-- in.cue -- +openIter: { + src: { + a: 1 + b: 2 + ... + if true { c: 3 } + } + keys: [for k, _ in src { k }] + @test(eq, { + src: {a: 1, b: 2, c: 3, ...} + keys: ["a", "b", "c"] + }) +} + +defOpen: { + #T: { + [string]: int + if true { a: 1 } + } + inst: #T & { b: 2 } + keys: [for k, _ in inst { k }] + @test(eq, { + #T: {[string]: int, a: 1} + inst: {a: 1, b: 2} + keys: ["b", "a"] + }) +} +-- out/compile -- +--- in.cue +{ + openIter: { + src: { + a: 1 + b: 2 + ... + if true { + c: 3 + } + } + keys: [ + for k, _ in 〈1;src〉 { + 〈1;k〉 + }, + ] + } + defOpen: { + #T: { + [string]: int + if true { + a: 1 + } + } + inst: (〈0;#T〉 & { + b: 2 + }) + keys: [ + for k, _ in 〈1;inst〉 { + 〈1;k〉 + }, + ] + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/optional_ref_yield.txtar b/internal/core/compile/testdata/sync/comprehensions/optional_ref_yield.txtar new file mode 100644 index 000000000..c009b0202 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/optional_ref_yield.txtar @@ -0,0 +1,91 @@ +# Tests that the yield-on-running heuristic in OpContext.evalState (expr.go) +# fires uniformly for any IncompleteError whose target node is currently +# being evaluated, regardless of whether the missing field is an +# ArcPending placeholder created by a pushed-down comprehension or an +# ArcOptional declaration that may yet be upgraded to a member. +# +# To exercise the yield, the reference must resolve while the target +# vertex itself is still mid-evaluation. The constructions below place +# the reference *inside* the target struct so its task fires before +# the sibling comprehension/declaration that produces the field. +-- cue.mod/module.cue -- +module: "mod.test" + +language: version: "v0.15.0" + +-- in.cue -- +// Test A: a self-reference picks up an optional field that gets upgraded to +// a member by a sibling comprehension. The reference (bar) fires before the +// comp body has run, so bar's lookup of x.foo initially returns ArcOptional +// (IncompleteError). The yield-on-running heuristic must fire so that bar +// re-resolves once foo is materialized as a member. +optionalUpgradesViaSiblingComp: { + x: { + bar: x.foo + foo?: int + if true { + foo: 5 + } + } + x: bar: int @test(eq, 5) +} + +// Test B: a self-reference to an optional field that stays optional +// permanently. The yield is harmless: after waiting for x's valueKnown the +// field is still optional and the result is the same incomplete error. +optionalStaysOptional: { + x: { + bar: x.foo + foo?: int + } + x: bar: _ @test(err, code=incomplete, contains="cannot reference optional field") +} + +// Test C: regression for the original ArcPending case — a self-reference +// to a member produced by a pushed-down comprehension. This is what the +// yield-on-running heuristic was originally introduced for. +pendingBecomesMember: { + x: { + bar: x.foo + if true { + foo: 5 + } + } + x: bar: int @test(eq, 5) +} +-- out/compile -- +--- in.cue +{ + optionalUpgradesViaSiblingComp: { + x: { + bar: 〈1;x〉.foo + foo?: int + if true { + foo: 5 + } + } + x: { + bar: int + } + } + optionalStaysOptional: { + x: { + bar: 〈1;x〉.foo + foo?: int + } + x: { + bar: _ + } + } + pendingBecomesMember: { + x: { + bar: 〈1;x〉.foo + if true { + foo: 5 + } + } + x: { + bar: int + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/pushdown.txtar b/internal/core/compile/testdata/sync/comprehensions/pushdown.txtar new file mode 100644 index 000000000..503ce15d9 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/pushdown.txtar @@ -0,0 +1,2868 @@ +# Working set of tests that unit test specifics of the aspect of the +# comprehension algorithm that pushes down evaluation to the arcs. +-- in.cue -- +linkChildren: { + w: 1 + v: { + x: 1 + if true { + y: 1 + if true { + z: 1 + + rw: w + rx: x + ry: y + rz: z + + n1a: na: [w, x, y, z] + n2a: n1a: na: [w, x, y, z] + n2z: n1z: nz: z + } + } + } + @test(eq, { + w: 1 + v: { + x: 1 + y: 1 + z: 1 + rw: 1 + rx: 1 + ry: 1 + rz: 1 + n1a: {na: [1, 1, 1, 1]} + n2a: {n1a: {na: [1, 1, 1, 1]}} + n2z: {n1z: {nz: 1}} + } + }) +} + +fail: { + a: { + // Condition of comprehensions must still hold after its evaluation. + // + // `b` is not defined, causing this if comprehension to evaluate to + // true. However, after inserting the corresponding result in curly + // braces, the condition would be true. This is not allowed. + if a.b == _|_ { + b: 1 + } + } @test(err, code=incomplete|cycle) +} + +embed: { + fail1: #C1 @test(err, code=eval, path=p, contains="field not allowed") + #C1: { + // TODO(errors): don't include all positions of p in the normal list of + // positions, or rather categorize the positions to show: + // 1) position of denied fields + // 2) position of structs that deny them + // 3) points at which those structs where mixed in (perhaps as tree) + // 4) conditionals that could enable allowing a field. + if false { + p: _ + } + } + fail1: p: "foo" // this should fail, as p is not present. + + + success2: #C2 @test(eq, {p: "foo"}) + #C2: { + if true { + p: _ + } + } + success2: p: "foo" // this succeeds as p is present. + + success3: #C3 @test(eq, {}) + #C3: {} + success3: { + if false { + // p does not exist in success3, but it is okay, as it is not added. + p: q: 1 + } + } + + success4: { + #X: y: string + x: y: string + x: { + for _ in ["iter-once"] { + #X + if false { + y: "foo" + } + } + } + } @test(eq, {#X: {y: string}, x: {y: string}}) + + fail4: #C4 + #C4: {} + fail4: { + if true { + // error as p is not allowed in fail4 + p: q: 1 + } + } @test(err, code=eval, path=p, contains="field not allowed", pos=[3:4]) + + incomplete5: { + a: bool + if a { + p: q: 1 + } + } @test(err, code=incomplete, contains="incomplete %s: %s", args=[bool, bool], pos=[1:6]) + + incomplete6: { + if false { + p: 1 + } + p: q + 1 + q: int + } @test(eq, { + p: _|_ @test(err, code=incomplete, contains="embed.incomplete6.p: non-concrete value int in operand to +", pos=[117:6, 118:6]) + q: int + }) + incomplete7: { + p: q + 1 + q: int + if false { + q: 1 // do not inadvertently pick up a void arc. + } + } @test(eq, { + p: _|_ @test(err, code=incomplete, contains="non-concrete value int") + // TODO(inline): do not fail on todo with position mismatch. @test(err:todo, pos=[124:6, 125:6, 126:3]) + q: int + }) +} + +// Mix of both dynamic and static fields. +mixedFieldsSuccess: { + a: { + for _, s in ["foo"] { + "\(s)": 1 + X: 1 + } + } + + b: #Def: { + for _, s in ["foo"] { + "\(s)": 1 + X: 1 + } + } + b: x: b.#Def + b: x: X: _ + b: x: foo: _ + + + c: #Def: { + X: int + foo: int + } + c: x: c.#Def + c: x: { + for _, s in ["foo"] { + "\(s)": 1 + X: 1 + } + } + @test(eq, { + a: {X: 1, foo: 1} + b: { + #Def: {X: 1, foo: 1} + x: {X: 1, foo: 1} + } + c: { + #Def: {X: int, foo: int} + x: {X: 1, foo: 1} + } + }) +} + +// fieldMismatch tests that an embedded scalar cannot be mixed with regular +// fields, even if they are added by a comprehension. +fieldMismatch: { + a: { + 2 + if true { + x: 3 + } + } + @test(err, code=eval, at=a, hint="int with struct") +} + +// b12aStructCycle presents a case that can easily lead to stack overflow in +// a naive implementation. It corresponds to test b12a in structural.txtar. +noStackOverflowStructCycle: { + #list: { + tail: #list + + if tail != null { + sum: tail.sum + } + } + + list: { + tail: list + + if tail != null { + sum: tail.sum + } + } + @test(err, code=structural_cycle, at="#list.tail", contains="structural cycle", pos=[]) +} + + +// #a is incomplete, but the missing values are provided by x. +provideIncompleteSuccess: { + t1: { + #a: { + if b { + c: 4 + } + b: bool + } + x: (#a & {b: true}) & {c: 4} + y: x + @test(eq, { + #a: {_|_, b: bool} + x: {b: true, c: 4} + y: {b: true, c: 4} + }) + } + + t2: { + // c should be allowed + #a: { + if b { + c: 4 + } + b: true + } @test(eq, {c: 4, b: true}) + + #c: {} + a: { + if b { + c: d: 4 + } + b: true + // d is disallowed, even though it is added by embedding. + // TODO: this seems right, but it may be good to clarify why. + c: #c @test(err, code=eval, at=d, contains="field not allowed", pos=[-5:8]) + } + } +} + +// voidArcs tests that fields are dropped and reference up counts are adjusted +// appropriately under various rewrite scenario. +voidArcs: { + scopes: { + x: 1 + a: { + y: 2 + if true { + b: x + c: d: x + e: y + f: g: y + } + } + } + + drop: { + x: 1 + a: { + y: 2 + if false { + b: x + c: d: x + e: y + f: g: y + } + } + } + @test(eq, { + scopes: { + x: 1 + a: {y: 2, b: 1, c: {d: 1}, e: 2, f: {g: 2}} + } + drop: {x: 1, a: {y: 2}} + }) +} + +cyclicError: { + a: { + // With pushdown, x and y remain bool (incomplete) rather than + // erroring: the if guards cannot resolve bool to a concrete + // value, so the comprehension bodies simply do not fire. + @test(err, code=incomplete) + x: bool + y: bool + if a.x { + y: true + } + if a.y { + x: true + } + b: {} + } + // With pushdown, evaluating a.b no longer forces a cycle error + // because the comprehension dependencies are pushed down to the + // individual fields rather than blocking the parent. + c: a.b @test(err, code=incomplete|cycle) + @test(eq, { + a: { + x: _|_ + y: _|_ + b: {} + } + c: _|_ + }) +} + +midwayReferences: { + a: { + for i, j in {a: 1, b: 2} { + x: y: z: (i): j + } + x: y: {} + } + b: a.x + c: a.x.y + d: a.x.y.z + @test(eq, { + a: {x: {y: {z: {a: 1, b: 2}}}} + b: {y: {z: {a: 1, b: 2}}} + c: {z: {a: 1, b: 2}} + d: {a: 1, b: 2} + }) +} + +// Ensure first closedness check is done after evaluation of +// comprehensions. +closedCheck: success1: { + a: b: [string]: #D + + #D: { + d: string + if d != "c" { + e: string + } + } + + a: b: c: { + d: "d" + e: "ok" + } + @test(eq, { + a: {b: {c: {d: "d", e: "ok"}}} + #D: {d: string} + }) +} + +closedCheck: success2: { + a: b: [string]: #D + + #D: { + d: string + if d != "c" { + ("foo"+"bar"): string + } + } + + a: b: c: { + d: "d" + foobar: "ok" + } + @test(eq, { + a: {b: {c: {d: "d", foobar: "ok"}}} + #D: {d: string} + }) +} + +closedCheck: success3: { + a: b: [string]: #D + + #D: { + d: string + e: { + if d != "c" { + string + } + @test(err, code=incomplete, contains="non-concrete value", pos=[1:7, -1:6]) + } + } + + a: b: c: { + d: "d" + e: "ok" + } + @test(eq, { + a: {b: {c: {d: "d", e: "ok"}}} + #D: { + d: string + e: _|_ + } + }) +} + +emptyComprehensionIncomplete: { + a: {} + b: { + // b should be an incomplete error + if a.b { + } + } @test(err, code=incomplete, contains="undefined field: %s", args=[b], pos=[2:8]) + @test(eq, { + a: {} + b: _|_ + }) +} + +// voidEliminationSuccess tests that "conditional" or "void" arcs are eliminated +// if their expression does not yield any result. +voidEliminationSuccess: t1: { + [string]: { + b: bool + if !b {} + } + if false { + a: b: true + } + @test(eq, {}) +} + +voidEliminationSuccess: t2: { + components: { + sinks: [string]: #C & { + kind: string + configuration: { + if kind != "source" { + inputs: { + required: true + } + } + } + } + + #C: { + kind: string + configuration: [string]: { + required: bool + if !required { + common: bool + } + } + } + } + + components: sinks: blah: { + kind: "source" + } + @test(eq, { + components: { + sinks: { + blah: {kind: "source", configuration: {}} + } + #C: {kind: string, configuration: {}} + } + }) +} + +voidEliminationSuccess: derefRef1: { + a: [string]: c: [string]: E + + a: b: c: { + if false { + d: e: true // resolves + } + } + + E: { + e: bool + f: !e @test(err, code=incomplete, contains="not concrete", pos=[0:7]) + } + @test(eq, { + a: {b: {c: {}}} + E: { + e: bool + f: _|_ + } + }) +} + +voidEliminationSuccess: derefRef2: { + a: [string]: c: [string]: E + + a: b: c: { + if false { + d: e: true // resolves + } + } + + E: #F + #F: { + e: bool + f: !e @test(err, code=incomplete, contains="not concrete", pos=[0:7]) + } + @test(eq, { + a: {b: {c: {}}} + E: { + e: bool + f: _|_ + } + #F: { + e: bool + f: _|_ @test(err, code=incomplete) + } + }) +} + +voidEliminationSuccess: derefDisj1: { + a: [string]: c: [string]: E + + a: b: c: { + if false { + d: e: true + } + } + + E: { + e: bool + f: !e + } | { + g: bool + h: !g + } + @test(eq, { + a: {b: {c: {}}} + E: _|_ @test(err, code=incomplete, contains="voidEliminationSuccess.derefDisj1.E: 2 errors in empty disjunction: (and 2 more errors)", pos=[]) + }) +} + +voidEliminationSuccess: derefDisj2: { + a: [string]: c: [string]: E & E + + a: b: c: { + if false { + d: e: true + } + } + + E: { + e: bool + f: !e + } | { + g: bool + h: !g + } + @test(eq, { + a: {b: {c: {}}} + E: _|_ @test(err, code=incomplete, contains="voidEliminationSuccess.derefDisj2.E: 2 errors in empty disjunction: (and 2 more errors)", pos=[]) + }) +} + +voidEliminationSuccess: bulk1: { + a: b: {} + a: [string]: { + c: { + e: string + if false { + e: "" + } + } + d: c.e + } + @test(eq, {a: {b: {c: {e: string}, d: string}}}) +} + +voidEliminationSuccess: opt1: { + a: b: {} + a: b?: { + c: { + e: string + if false { + e: "" + } + } + d: c.e + } + @test(eq, {a: {b: {c: {e: string}, d: string}}}) +} + +voidEliminationSuccess: noCycle1: { + _x: a.b + a: { + c: h: "stream" + b: { + if c.g != _|_ {} + } + c: { + if false {g: _} + } + } + @test(eq, {_x: {}, a: {c: {h: "stream"}, b: {}}}) +} + +voidEliminationSuccess: noCycle2: { + a: { + c: h: "stream" + b: { + if c.g != _|_ {} + } + c: { + if false {g: _} + } + } + _x: a.b + @test(eq, {a: {c: {h: "stream"}, b: {}}, _x: {}}) +} + +voidLookup: { + a: x: z: a.y.z.void + + a: y: { + c: _ + z: {} + } + + a: [string]: { + c: { + for k, v in z { + (k): null // don't add this arc anywhere + } + } + z: { + if false { + err: {} + } + } + } + @test(eq, { + a: { + x: { + z: _|_ + c: _|_ + } + y: {c: _, z: {}} + } + }) + @test(err, at=a.x.z, code=incomplete, + contains="undefined field: %s", args=[void], pos=[1:17]) + @test(err, at=a.x.c, code=incomplete, + path=voidLookup.a.x.z, contains="undefined field: %s", args=[void], pos=[1:17]) +} + + +// Eliminate the top value even if there is an error (especially incomplete +// errors). +topElimination: { + a: int + _ + if true { + x: a+1 + } + @test(eq, { + a: int + x: _|_ + }) + @test(err, at=x, code=incomplete, contains="non-concrete value %v in operand to %s", args=[int, +], pos=[4:6, 1:5]) +} + +voidEliminationSuccess: drop1: { + // Do not include x in s. + t: { + #ok: *true | bool + if #ok { + x: int + } + } + s: t & { + #ok: false + } + @test(eq, { + t: {#ok: *true | bool, x: int} + s: {#ok: false} + }) +} + +// should be error +// issue #465 +explicitDefaultError: { + a: string | *_|_ + + if a != "" { + } + @test(err, code=incomplete, contains="non-concrete value string", pos=[3:5, 1:5]) +} + +// Remove arcs for with no for comprehension results. +allArcsSuccess: p1: { + x: { + for k, _ in y { + (k): null + } + } + y: { + if false { + x: {} + } + } + @test(eq, {x: {}, y: {}}) +} + +allArcsSuccess: p2: { + y: { + if false { + x: {} + } + } + x: { + for k, _ in y { + (k): null + } + } + @test(eq, {y: {}, x: {}}) +} + +structShare: ok1: { + a: [string]: E + E: {} + + a: { + if true { + d: e: true // resolves + } + } + @test(eq, {a: {d: {e: true}}, E: {}}) +} + +structShare: err1: { + x: [string]: x.#E + x: #E: {} + if true { + x: d: e: true + } + @test(err, code=eval, at=x.d.e, contains="field not allowed", pos=[4:9]) +} + +-- issue2208.cue -- +// Regression where definitions that compiled correctly with 0.4.3 failed to +// compile with 0.5.0-beta.2 due to incorrect handling of void errors. +// https://cuelang.org/issue/2208 +voidErrorIncomplete: { + #Schema: [string]: { + required: bool + if !required { + } + } + + root: #Schema + root: { + if false { + child: required: false + } + } + @test(eq, {#Schema: {}, root: {}}) +} + +// TODO: should these always be errors, or only for cue vet? +// voidErrorFatal: pattern: { +// #Schema: [string]: { +// if "str" + 3 { +// } +// } +// +// root: #Schema +// root: { +// if false { +// child: required: false +// } +// } +// } +// +// voidErrorFatal: field: { +// root: { +// if false { +// child: 2 + "str" +// } +// } +// } + + +-- issue1759.cue -- +// Tests that len() and comprehensions correctly see the full struct/list value. +// https://cuelang.org/issue/1759 +// Tests derived from Unity. +unity: success1: { + #Config: { + name: string + type: string + } + + #AnyConfig: { + #Config + ... + } + + #Env: { + name: string + configurations: [string]: #AnyConfig + } + + envs: "e1": #Env & { + configurations: c1: #Config + } + + envs: [string]: configurations: [string]: { + type: "foo" + if type == "terraform" { + backend: { + type: "s3" + } + } + } + @test(eq, { + #Config: {name: string, type: string} + #AnyConfig: {name: string, type: string} + #Env: {name: string, configurations: {}} + envs: { + e1: { + configurations: {c1: {type: "foo", name: string}} + name: string + } + } + }) +} + +// issue1759: Tests that len() correctly sees the full struct value when +// used as a comprehension condition. https://cuelang.org/issue/1759 +issue1759: { + _ports_map: {} + if len(_ports_map) > 0 { + port: _ports_map.a.port + } + if true { + _ports_map: a: {port: "80"} + } + @test(eq, { + _ports_map: {a: {port: "80"}} + port: "80" + }) +} + +arcAlignment: t1: { + [string]: { + if true { } + } + if false { + c: _ + } + @test(eq, {}) +} + +-- issue2111.cue -- +// Evaluator regression where circular dependency in evaluation of conditionals +// caused incorrect results. All arc types, not just regular fields, should be pushed down. +// https://cuelang.org/issue/2111 +letPushdown: { + _c: y: 1 + + a: { + for k, v in _c { + let x = v + if x != _|_ { + } + } + } + @test(eq, {_c: {y: 1}, a: {}}) +} + +-- issue2113.cue -- +// Evaluator regression where a nested comprehension caused "was already used" +// errors when the enclosing value was not yet fully evaluated. +// https://cuelang.org/issue/2113 +// Ensure that an enclosing Value clause of a nested comprehension is evaluated +// before the nested comprehension itself is evaluated. +nestedWithEmbeddingOK: { + c: [1] + a: { + for k, v in c { + {x: 1} + if a.x != _|_ { + } + } + } + @test(eq, {c: [1], a: {x: 1}}) +} + +nestedWithDynamicFieldOK: { + _c: y: 1 + + a: { + for k, v in _c { + if x != _|_ { + } + x="\(k)": 1 + } + } + @test(eq, {_c: {y: 1}, a: {y: 1}}) +} + +// Errors in nested comprehensions should also be reported. +errorPropagation: { + deployment: _ + for k, v in deployment { + for k1, v2 in v.env2 { // Report this error. + deployment: (k): x1: 1 + } + } + for id in ["elem"] { deployment: (id): x2: 2 } + @test(err, code=incomplete, contains="undefined field: env2", pos=[3:19]) +} + +-- issue2131.cue -- +// issue2131: Tests that chained for comprehensions correctly produce output +// fields when iterating over nested structs. https://cuelang.org/issue/2131 +issue2131: tests: { + windows: { + eg1: in: #"c:\d"# + eg2: in: #"c:\test"# + eg3: in: #"c:\test\d"# + } + + for os, examples in tests for k, v in examples { + (os): (k): out: "test" + } + @test(eq, { + windows: { + eg1: {in: "c:\\d", out: "test"} + eg2: {in: "c:\\test", out: "test"} + eg3: {in: "c:\\test\\d", out: "test"} + } + }) +} +-- issue3533.cue -- +// issue3533: Tests that fields under two levels of comprehensions are not +// incorrectly rejected as "field not allowed" in evalv3. +// https://cuelang.org/issue/3533 +issue3533: { + #ObjectMeta: namespace?: string + out: { + for i, _ in ["iter-once"] { + metadata: #ObjectMeta + if false { + metadata: namespace: "foo" + } + } + } + out: metadata: namespace: *"default" | string + @test(eq, { + #ObjectMeta: {namespace?: string} + out: { + metadata: {namespace: *"default" | string} + } + }) +} +-- issue3535.cue -- +// issue3535: Tests that hidden fields inside if comprehensions do not +// trigger "field not allowed" errors in evalv3. +// https://cuelang.org/issue/3535 +issue3535: hidden: { + #X: { + kind: string + output: {} + } + foo: #X & { + kind: string + if kind == "foo" { + _hidden: {} + } + } + foo: kind: "foo" + @test(eq, { + #X: {kind: string, output: {}} + foo: {kind: "foo", _hidden: {}, output: {}} + }) +} +issue3535: regular: { + #X: { + kind: string + output: {} + } + foo: #X & { + kind: string + if kind == "foo" { + regular: {} + } + } + foo: kind: "foo" + @test(err, code=eval, at=foo.regular, contains="field not allowed", pos=[8:4]) +} +issue3535: def: { + #X: { + kind: string + output: {} + } + foo: #X & { + kind: string + if kind == "foo" { + #def: {} + } + } + foo: kind: "foo" + @test(eq, { + #X: {kind: string, output: {}} + foo: {kind: "foo", #def: {}, output: {}} + }) +} +-- reflect.cue -- +import "encoding/json" + + +unifyDynamicReflectSuccess: { + for _, s in ["foo"] { + X: {...} + "\(s)": { + X: {...} // cannot be _ + Y: json.Marshal(X) // cannot be yaml, X cannot be literal + } + } + + [string]: X: { + if true {// must be there + x: y: {} // at least 2 nestings needed to expose problem + } + } + @test(eq, { + X: {X: {x: {y: {}}}} + foo: { + X: {x: {y: {}}} + Y: "{\"x\":{\"y\":{}}}" + } + }) +} +-- issue3621.cue -- +// issue3621: evalv3 regression producing false "cyclic reference" errors for +// comprehensions with nested field definitions and references that evalv2 handles correctly. +// https://cuelang.org/issue/3621 +issue3621: reduced: t1: { + // This test ensures that when a reference is made within a comprehension, + // with vertices marked as "pending", that these are not completed the + // respective pushed-down comprehension is evaluated as well. + if true { + a: b1.b2.b3 + b1: b2: b3: "Foo" + } + @test(eq, {a: "Foo", b1: {b2: {b3: "Foo"}}}) +} +issue3621: reduced: t2: { + outer: {} + if true { + inner: inner2: name: "Foo" + outer: b: inner.inner2.name + } + @test(eq, { + outer: {b: "Foo"} + inner: {inner2: {name: "Foo"}} + }) +} +issue3621: full: { + hello: "world" + outer: [Name=string]: name: Name + if true { + inner: inner2: { + name: "Employees" + description: "All employees" + privacy: "secret" + create_default: false + } + outer: outer2: { + bar: (inner.inner2.name) + } + } + @test(eq, { + hello: "world" + outer: { + outer2: {bar: "Employees", name: "outer2"} + } + inner: { + inner2: { + name: "Employees" + description: "All employees" + privacy: "secret" + create_default: false + } + } + }) +} +-- issue3708.cue -- +// issue3708: evalv3 regression reporting a cyclic reference error when fields are +// accessed inside a comprehension using optional field patterns with if conditionals. +// https://cuelang.org/issue/3708 +issue3708: { + out: people.bob.kind + + // pattern constraint marks 'name' as member, which should not preclude name + // from being futher evaluated to determine whether 'people' is pending. + people: [string]: { + kind: "person" + name?: string + } + + if true { + people: bob: name: "Bob" + } + @test(eq, { + out: "person" + people: {bob: {name: "Bob", kind: "person"}} + }) +} +-- issue3729.cue -- +// issue3729: evalv3 incorrectly reports "incomplete value null" for fields typed +// as a disjunction containing null (e.g. null | #T) inside if comprehensions. +// https://cuelang.org/issue/3729 +issue3729: withDisjunction: { + #Root: sub1?: #sub2?: bool + root?: null | #Root + if true { + root: sub1?: #sub2: true + } + @test(eq, { + #Root: {sub1?: {#sub2?: bool}} + root: {sub1?: {#sub2: true}} + }) +} +issue3729: withoutDisjunction: { + root?: null + if true { + root: #sub1?: #sub2: true + } + @test(err, code=eval, contains="conflicting values null", pos=[0:32, 1:9, 2:2, 3:9]) +} +issue3729: withoutDisjunctionWithEmbed: { + root?: null + if true { + root: {_, #sub1?: #sub2: true} + } + @test(eq, {root: {null, #sub1?: {#sub2: true}}}) +} +issue3729: definitionsOnly: { + #Root: #sub1?: #sub2?: bool + root?: null | #Root + if true { + root: #sub1?: #sub2: true + } + @test(eq, { + #Root: {#sub1?: {#sub2?: bool}} + root: {#sub1?: {#sub2: true}} + }) +} +issue3729: withEmbed: incomplete: { + #Root: #sub1?: #sub2?: bool + root?: null | #Root + if true { + root: {_, #sub1?: #sub2: true} + } + @test(eq, { + #Root: {#sub1?: {#sub2?: bool}} + root: {null, #sub1?: {#sub2: true}} | {#sub1?: {#sub2: true}} + }) +} +issue3729: full: { + #Application: spec: #ApplicationSpec + #ApplicationSpec: syncPolicy?: null | #SyncPolicy + #SyncPolicy: automated?: null | #SyncPolicyAutomated + #SyncPolicyAutomated: { + prune?: bool + selfHeal?: bool + } + argoApp: #Application & { + spec: { + if true { + syncPolicy: automated: { + prune: true + selfHeal: true + } + } + } + } + argoApp: spec: _syncpolicy: "selfhealprune" + @test(eq, { + #Application: { + spec: { + syncPolicy?: null | {automated?: null | {prune?: bool, selfHeal?: bool}} + } + } + #ApplicationSpec: { + syncPolicy?: null | {automated?: null | {prune?: bool, selfHeal?: bool}} + } + #SyncPolicy: { + automated?: null | {prune?: bool, selfHeal?: bool} + } + #SyncPolicyAutomated: {prune?: bool, selfHeal?: bool} + argoApp: { + spec: { + syncPolicy: { + automated: {prune: true, selfHeal: true} + } + _syncpolicy: "selfhealprune" + } + } + }) +} +-- pending.cue -- +// resolving comprehensions arcs across disjunctions. +arcTypeAcrossTwo: { + a?: b?: { + c?: null | {} + } | null + if true { + a: b: c: d: true + } + @test(eq, {a: {b: {c: {d: true}}}}) +} +// issue3894: evalv3 regression where an if comprehension affecting an optional +// field with a disjunction returns an incorrect result instead of the properly +// constrained value. https://cuelang.org/issue/3894 +issue3894: reduced: p1: { + {a: string} | {b: value: string} + if true { b: value: "true" } + @test(eq, {b: {value: "true"}, a: string} | {b: {value: "true"}}) +} +issue3894: reduced: p2: { + {b: value: string} | {a: string} + if true { b: value: "true" } + @test(eq, {b: {value: "true"}} | {b: {value: "true"}, a: string}) +} +issue3894: full: { + #Output: {a?: string} | {b?: {value: string}} + out: #Output + out: { + if true == true { + b: {value: "true"} + } + } + @test(eq, { + #Output: {a?: string} | {b?: {value: string}} + out: {b: {value: "true"}} + }) +} +-- issue3935.cue -- +// issue3935: evalv3 incorrectly reports "field not allowed" when a schema defined +// with a disjunction is intersected with additional constraints. +// https://cuelang.org/issue/3935 +issue3935: reduced: { + out: #A | #B + out: #B & { + y: x: "bar" + } + #A: y: other: int + #B: { + if true { + x: y.x + } + y!: x!: _ + } + @test(eq, { + out: {y: {x: "bar"}, x: "bar"} + #A: {y: {other: int}} + #B: { + x: _|_ @test(err, code=incomplete, contains="issue3935.reduced.#B.x: required field missing: y", pos=[12:7]) + y!: {x!: _} + } + }) +} +issue3935: full: { + out: #SchemaOther | #SchemaSelected + out: #SchemaSelected & { + spec: { + name: "foo" + config: namespace: "bar" + } + } + #SchemaOther: { + spec: { + otherOptional?: int + otherRegular: int + otherRequired!: int + } + } + #SchemaSelected: { + spec!: { + name!: string + config!: _ + } + + if true { + namespace: _specConfig.namespace + } + + _specConfig: spec.config + } + @test(eq, { + out: { + spec: { + name: "foo" + config: {namespace: "bar"} + } + namespace: "bar" + _specConfig: {namespace: "bar"} + } + #SchemaOther: { + spec: { + otherOptional?: int + otherRegular: int + otherRequired!: int + } + } + #SchemaSelected: { + spec!: {name!: string, config!: _} + namespace: _|_ @test(err, code=incomplete, contains="issue3935.full.#SchemaSelected.namespace: undefined field: namespace", pos=[47:27]) + _specConfig: _|_ @test(err, code=incomplete, contains="issue3935.full.#SchemaSelected._specConfig: required field missing: spec", pos=[50:16]) + } + }) +} +-- rework.cue -- +regression1: { + #Primary: { + _Y: _ + let _X = _Y + if len(_X.spec.command) > 0 { + command: _X.spec.command + } + } + #Rollout: { + _X: _ + out: #Primary & {_Y: _X} & _X.patch + } + x: { + spec: command: ["a"] + patch: {} + } + out: #Rollout & {_X: x} @test(eq, at=out,{ + _Y: {spec: {command: ["a"]}, patch: {}} + command: ["a"] + }) +} +regression2: { + #Primary: { + _Y: _ + if len(_Y.spec.command) > 0 { + command: _Y.spec.command + } + } + #Rollout: { + _X: _ + out: #Primary & {_Y: _X} & _X.patch + } + x: { + spec: command: ["a"] + patch: {} + } + out: #Rollout & {_X: x} @test(eq, at=out,{ + _Y: {spec: {command: ["a"]}, patch: {}} + command: ["a"] + }) +} +letCycleSelf: { + #X: X={ + let this = X + hosts: [string]: _ + for h, _ in this.hosts {out: (h): 1} + for h, _ in this.hosts {out: (h): 2} + } + + x: [string]: #X + x: a: {} + + @test(eq, {#X: {hosts: {}}, x: {a: {hosts: {}}}}) +} +-- rework2.cue -- +@experiment(aliasv2) + +letCycleSelfKeyword: { + #E: { + let s = self + hosts: _ + for hv in s.hosts {out: (hv.x): "a"} + } + + env: #E & {hosts: h1: x: "k"} + + @test(eq, { + #E: _|_ @test(err, code=incomplete, path=letCycleSelf2.#E, + contains="cannot range over s.hosts (incomplete type _)", pos=[7:13]) + env: {hosts: {h1: {x: "k"}}, out: {k: "a"}} + }) +} +letCycleSelfKeyword2: { + #E: { + let s = self + ... + for hv in s.hosts { + let n = s.networks + a: n + } + } + + env: #E & { + hosts: h1: 1 + networks: n1: "x" + } + + @test(eq, { + #E: _|_ @test(err, code=incomplete, path=regression_let3.#E, + contains="cannot range over s.hosts (incomplete)", pos=[22:13]) + env: { + hosts: {h1: 1} + networks: {n1: "x"} + a: {n1: "x"} + } + }) +} +-- out/compile -- +--- in.cue +{ + linkChildren: { + w: 1 + v: { + x: 1 + if true { + y: 1 + if true { + z: 1 + rw: 〈3;w〉 + rx: 〈2;x〉 + ry: 〈1;y〉 + rz: 〈0;z〉 + n1a: { + na: [ + 〈5;w〉, + 〈4;x〉, + 〈3;y〉, + 〈2;z〉, + ] + } + n2a: { + n1a: { + na: [ + 〈6;w〉, + 〈5;x〉, + 〈4;y〉, + 〈3;z〉, + ] + } + } + n2z: { + n1z: { + nz: 〈2;z〉 + } + } + } + } + } + } + fail: { + a: { + if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { + b: 1 + } + } + } + embed: { + fail1: 〈0;#C1〉 + #C1: { + if false { + p: _ + } + } + fail1: { + p: "foo" + } + success2: 〈0;#C2〉 + #C2: { + if true { + p: _ + } + } + success2: { + p: "foo" + } + success3: 〈0;#C3〉 + #C3: {} + success3: { + if false { + p: { + q: 1 + } + } + } + success4: { + #X: { + y: string + } + x: { + y: string + } + x: { + for _, _ in [ + "iter-once", + ] { + 〈3;#X〉 + if false { + y: "foo" + } + } + } + } + fail4: 〈0;#C4〉 + #C4: {} + fail4: { + if true { + p: { + q: 1 + } + } + } + incomplete5: { + a: bool + if 〈0;a〉 { + p: { + q: 1 + } + } + } + incomplete6: { + if false { + p: 1 + } + p: (〈0;q〉 + 1) + q: int + } + incomplete7: { + p: (〈0;q〉 + 1) + q: int + if false { + q: 1 + } + } + } + mixedFieldsSuccess: { + a: { + for _, s in [ + "foo", + ] { + "\(〈1;s〉)": 1 + X: 1 + } + } + b: { + #Def: { + for _, s in [ + "foo", + ] { + "\(〈1;s〉)": 1 + X: 1 + } + } + } + b: { + x: 〈1;b〉.#Def + } + b: { + x: { + X: _ + } + } + b: { + x: { + foo: _ + } + } + c: { + #Def: { + X: int + foo: int + } + } + c: { + x: 〈1;c〉.#Def + } + c: { + x: { + for _, s in [ + "foo", + ] { + "\(〈1;s〉)": 1 + X: 1 + } + } + } + } + fieldMismatch: { + a: { + 2 + if true { + x: 3 + } + } + } + noStackOverflowStructCycle: { + #list: { + tail: 〈1;#list〉 + if (〈0;tail〉 != null) { + sum: 〈1;tail〉.sum + } + } + list: { + tail: 〈1;list〉 + if (〈0;tail〉 != null) { + sum: 〈1;tail〉.sum + } + } + } + provideIncompleteSuccess: { + t1: { + #a: { + if 〈0;b〉 { + c: 4 + } + b: bool + } + x: ((〈0;#a〉 & { + b: true + }) & { + c: 4 + }) + y: 〈0;x〉 + } + t2: { + #a: { + if 〈0;b〉 { + c: 4 + } + b: true + } + #c: {} + a: { + if 〈0;b〉 { + c: { + d: 4 + } + } + b: true + c: 〈1;#c〉 + } + } + } + voidArcs: { + scopes: { + x: 1 + a: { + y: 2 + if true { + b: 〈2;x〉 + c: { + d: 〈3;x〉 + } + e: 〈1;y〉 + f: { + g: 〈2;y〉 + } + } + } + } + drop: { + x: 1 + a: { + y: 2 + if false { + b: 〈2;x〉 + c: { + d: 〈3;x〉 + } + e: 〈1;y〉 + f: { + g: 〈2;y〉 + } + } + } + } + } + cyclicError: { + a: { + x: bool + y: bool + if 〈1;a〉.x { + y: true + } + if 〈1;a〉.y { + x: true + } + b: {} + } + c: 〈0;a〉.b + } + midwayReferences: { + a: { + for i, j in { + a: 1 + b: 2 + } { + x: { + y: { + z: { + 〈4;i〉: 〈4;j〉 + } + } + } + } + x: { + y: {} + } + } + b: 〈0;a〉.x + c: 〈0;a〉.x.y + d: 〈0;a〉.x.y.z + } + closedCheck: { + success1: { + a: { + b: { + [string]: 〈2;#D〉 + } + } + #D: { + d: string + if (〈0;d〉 != "c") { + e: string + } + } + a: { + b: { + c: { + d: "d" + e: "ok" + } + } + } + } + } + closedCheck: { + success2: { + a: { + b: { + [string]: 〈2;#D〉 + } + } + #D: { + d: string + if (〈0;d〉 != "c") { + ("foo" + "bar"): string + } + } + a: { + b: { + c: { + d: "d" + foobar: "ok" + } + } + } + } + } + closedCheck: { + success3: { + a: { + b: { + [string]: 〈2;#D〉 + } + } + #D: { + d: string + e: { + if (〈1;d〉 != "c") { + string + } + } + } + a: { + b: { + c: { + d: "d" + e: "ok" + } + } + } + } + } + emptyComprehensionIncomplete: { + a: {} + b: { + if 〈1;a〉.b {} + } + } + voidEliminationSuccess: { + t1: { + [string]: { + b: bool + if !〈0;b〉 {} + } + if false { + a: { + b: true + } + } + } + } + voidEliminationSuccess: { + t2: { + components: { + sinks: { + [string]: (〈1;#C〉 & { + kind: string + configuration: { + if (〈1;kind〉 != "source") { + inputs: { + required: true + } + } + } + }) + } + #C: { + kind: string + configuration: { + [string]: { + required: bool + if !〈0;required〉 { + common: bool + } + } + } + } + } + components: { + sinks: { + blah: { + kind: "source" + } + } + } + } + } + voidEliminationSuccess: { + derefRef1: { + a: { + [string]: { + c: { + [string]: 〈3;E〉 + } + } + } + a: { + b: { + c: { + if false { + d: { + e: true + } + } + } + } + } + E: { + e: bool + f: !〈0;e〉 + } + } + } + voidEliminationSuccess: { + derefRef2: { + a: { + [string]: { + c: { + [string]: 〈3;E〉 + } + } + } + a: { + b: { + c: { + if false { + d: { + e: true + } + } + } + } + } + E: 〈0;#F〉 + #F: { + e: bool + f: !〈0;e〉 + } + } + } + voidEliminationSuccess: { + derefDisj1: { + a: { + [string]: { + c: { + [string]: 〈3;E〉 + } + } + } + a: { + b: { + c: { + if false { + d: { + e: true + } + } + } + } + } + E: ({ + e: bool + f: !〈0;e〉 + }|{ + g: bool + h: !〈0;g〉 + }) + } + } + voidEliminationSuccess: { + derefDisj2: { + a: { + [string]: { + c: { + [string]: (〈3;E〉 & 〈3;E〉) + } + } + } + a: { + b: { + c: { + if false { + d: { + e: true + } + } + } + } + } + E: ({ + e: bool + f: !〈0;e〉 + }|{ + g: bool + h: !〈0;g〉 + }) + } + } + voidEliminationSuccess: { + bulk1: { + a: { + b: {} + } + a: { + [string]: { + c: { + e: string + if false { + e: "" + } + } + d: 〈0;c〉.e + } + } + } + } + voidEliminationSuccess: { + opt1: { + a: { + b: {} + } + a: { + b?: { + c: { + e: string + if false { + e: "" + } + } + d: 〈0;c〉.e + } + } + } + } + voidEliminationSuccess: { + noCycle1: { + _x: 〈0;a〉.b + a: { + c: { + h: "stream" + } + b: { + if (〈1;c〉.g != _|_(explicit error (_|_ literal) in source)) {} + } + c: { + if false { + g: _ + } + } + } + } + } + voidEliminationSuccess: { + noCycle2: { + a: { + c: { + h: "stream" + } + b: { + if (〈1;c〉.g != _|_(explicit error (_|_ literal) in source)) {} + } + c: { + if false { + g: _ + } + } + } + _x: 〈0;a〉.b + } + } + voidLookup: { + a: { + x: { + z: 〈2;a〉.y.z.void + } + } + a: { + y: { + c: _ + z: {} + } + } + a: { + [string]: { + c: { + for k, v in 〈1;z〉 { + 〈1;k〉: null + } + } + z: { + if false { + err: {} + } + } + } + } + } + topElimination: { + a: int + _ + if true { + x: (〈1;a〉 + 1) + } + } + voidEliminationSuccess: { + drop1: { + t: { + #ok: (*true|bool) + if 〈0;#ok〉 { + x: int + } + } + s: (〈0;t〉 & { + #ok: false + }) + } + } + explicitDefaultError: { + a: (string|*_|_(explicit error (_|_ literal) in source)) + if (〈0;a〉 != "") {} + } + allArcsSuccess: { + p1: { + x: { + for k, _ in 〈1;y〉 { + 〈1;k〉: null + } + } + y: { + if false { + x: {} + } + } + } + } + allArcsSuccess: { + p2: { + y: { + if false { + x: {} + } + } + x: { + for k, _ in 〈1;y〉 { + 〈1;k〉: null + } + } + } + } + structShare: { + ok1: { + a: { + [string]: 〈1;E〉 + } + E: {} + a: { + if true { + d: { + e: true + } + } + } + } + } + structShare: { + err1: { + x: { + [string]: 〈1;x〉.#E + } + x: { + #E: {} + } + if true { + x: { + d: { + e: true + } + } + } + } + } +} +--- issue1759.cue +{ + unity: { + success1: { + #Config: { + name: string + type: string + } + #AnyConfig: { + 〈1;#Config〉 + ... + } + #Env: { + name: string + configurations: { + [string]: 〈2;#AnyConfig〉 + } + } + envs: { + e1: (〈1;#Env〉 & { + configurations: { + c1: 〈3;#Config〉 + } + }) + } + envs: { + [string]: { + configurations: { + [string]: { + type: "foo" + if (〈0;type〉 == "terraform") { + backend: { + type: "s3" + } + } + } + } + } + } + } + } + issue1759: { + _ports_map: {} + if (len(〈0;_ports_map〉) > 0) { + port: 〈1;_ports_map〉.a.port + } + if true { + _ports_map: { + a: { + port: "80" + } + } + } + } + arcAlignment: { + t1: { + [string]: { + if true {} + } + if false { + c: _ + } + } + } +} +--- issue2111.cue +{ + letPushdown: { + _c: { + y: 1 + } + a: { + for k, v in 〈1;_c〉 { + let x#1multi = 〈1;v〉 + if (〈0;let x#1〉 != _|_(explicit error (_|_ literal) in source)) {} + } + } + } +} +--- issue2113.cue +{ + nestedWithEmbeddingOK: { + c: [ + 1, + ] + a: { + for k, v in 〈1;c〉 { + { + x: 1 + } + if (〈3;a〉.x != _|_(explicit error (_|_ literal) in source)) {} + } + } + } + nestedWithDynamicFieldOK: { + _c: { + y: 1 + } + a: { + for k, v in 〈1;_c〉 { + if (〈0;("\(〈1;k〉)")〉 != _|_(explicit error (_|_ literal) in source)) {} + "\(〈1;k〉)": 1 + } + } + } + errorPropagation: { + deployment: _ + for k, v in 〈0;deployment〉 { + for k1, v2 in 〈1;v〉.env2 { + deployment: { + 〈4;k〉: { + x1: 1 + } + } + } + } + for _, id in [ + "elem", + ] { + deployment: { + 〈2;id〉: { + x2: 2 + } + } + } + } +} +--- issue2131.cue +{ + issue2131: { + tests: { + windows: { + eg1: { + in: "c:\\d" + } + eg2: { + in: "c:\\test" + } + eg3: { + in: "c:\\test\\d" + } + } + for os, examples in 〈1;tests〉 for k, v in 〈0;examples〉 { + 〈2;os〉: { + 〈2;k〉: { + out: "test" + } + } + } + } + } +} +--- issue2208.cue +{ + voidErrorIncomplete: { + #Schema: { + [string]: { + required: bool + if !〈0;required〉 {} + } + } + root: 〈0;#Schema〉 + root: { + if false { + child: { + required: false + } + } + } + } +} +--- issue3533.cue +{ + issue3533: { + #ObjectMeta: { + namespace?: string + } + out: { + for i, _ in [ + "iter-once", + ] { + metadata: 〈3;#ObjectMeta〉 + if false { + metadata: { + namespace: "foo" + } + } + } + } + out: { + metadata: { + namespace: (*"default"|string) + } + } + } +} +--- issue3535.cue +{ + issue3535: { + hidden: { + #X: { + kind: string + output: {} + } + foo: (〈0;#X〉 & { + kind: string + if (〈0;kind〉 == "foo") { + _hidden: {} + } + }) + foo: { + kind: "foo" + } + } + } + issue3535: { + regular: { + #X: { + kind: string + output: {} + } + foo: (〈0;#X〉 & { + kind: string + if (〈0;kind〉 == "foo") { + regular: {} + } + }) + foo: { + kind: "foo" + } + } + } + issue3535: { + def: { + #X: { + kind: string + output: {} + } + foo: (〈0;#X〉 & { + kind: string + if (〈0;kind〉 == "foo") { + #def: {} + } + }) + foo: { + kind: "foo" + } + } + } +} +--- issue3621.cue +{ + issue3621: { + reduced: { + t1: { + if true { + a: 〈0;b1〉.b2.b3 + b1: { + b2: { + b3: "Foo" + } + } + } + } + } + } + issue3621: { + reduced: { + t2: { + outer: {} + if true { + inner: { + inner2: { + name: "Foo" + } + } + outer: { + b: 〈1;inner〉.inner2.name + } + } + } + } + } + issue3621: { + full: { + hello: "world" + outer: { + [string]: { + name: 〈1;-〉 + } + } + if true { + inner: { + inner2: { + name: "Employees" + description: "All employees" + privacy: "secret" + create_default: false + } + } + outer: { + outer2: { + bar: 〈2;inner〉.inner2.name + } + } + } + } + } +} +--- issue3708.cue +{ + issue3708: { + out: 〈0;people〉.bob.kind + people: { + [string]: { + kind: "person" + name?: string + } + } + if true { + people: { + bob: { + name: "Bob" + } + } + } + } +} +--- issue3729.cue +{ + issue3729: { + withDisjunction: { + #Root: { + sub1?: { + #sub2?: bool + } + } + root?: (null|〈0;#Root〉) + if true { + root: { + sub1?: { + #sub2: true + } + } + } + } + } + issue3729: { + withoutDisjunction: { + root?: null + if true { + root: { + #sub1?: { + #sub2: true + } + } + } + } + } + issue3729: { + withoutDisjunctionWithEmbed: { + root?: null + if true { + root: { + _ + #sub1?: { + #sub2: true + } + } + } + } + } + issue3729: { + definitionsOnly: { + #Root: { + #sub1?: { + #sub2?: bool + } + } + root?: (null|〈0;#Root〉) + if true { + root: { + #sub1?: { + #sub2: true + } + } + } + } + } + issue3729: { + withEmbed: { + incomplete: { + #Root: { + #sub1?: { + #sub2?: bool + } + } + root?: (null|〈0;#Root〉) + if true { + root: { + _ + #sub1?: { + #sub2: true + } + } + } + } + } + } + issue3729: { + full: { + #Application: { + spec: 〈1;#ApplicationSpec〉 + } + #ApplicationSpec: { + syncPolicy?: (null|〈1;#SyncPolicy〉) + } + #SyncPolicy: { + automated?: (null|〈1;#SyncPolicyAutomated〉) + } + #SyncPolicyAutomated: { + prune?: bool + selfHeal?: bool + } + argoApp: (〈0;#Application〉 & { + spec: { + if true { + syncPolicy: { + automated: { + prune: true + selfHeal: true + } + } + } + } + }) + argoApp: { + spec: { + _syncpolicy: "selfhealprune" + } + } + } + } +} +--- issue3935.cue +{ + issue3935: { + reduced: { + out: (〈0;#A〉|〈0;#B〉) + out: (〈0;#B〉 & { + y: { + x: "bar" + } + }) + #A: { + y: { + other: int + } + } + #B: { + if true { + x: 〈1;y〉.x + } + y!: { + x!: _ + } + } + } + } + issue3935: { + full: { + out: (〈0;#SchemaOther〉|〈0;#SchemaSelected〉) + out: (〈0;#SchemaSelected〉 & { + spec: { + name: "foo" + config: { + namespace: "bar" + } + } + }) + #SchemaOther: { + spec: { + otherOptional?: int + otherRegular: int + otherRequired!: int + } + } + #SchemaSelected: { + spec!: { + name!: string + config!: _ + } + if true { + namespace: 〈1;_specConfig〉.namespace + } + _specConfig: 〈0;spec〉.config + } + } + } +} +--- pending.cue +{ + arcTypeAcrossTwo: { + a?: { + b?: ({ + c?: (null|{}) + }|null) + } + if true { + a: { + b: { + c: { + d: true + } + } + } + } + } + issue3894: { + reduced: { + p1: { + ({ + a: string + }|{ + b: { + value: string + } + }) + if true { + b: { + value: "true" + } + } + } + } + } + issue3894: { + reduced: { + p2: { + ({ + b: { + value: string + } + }|{ + a: string + }) + if true { + b: { + value: "true" + } + } + } + } + } + issue3894: { + full: { + #Output: ({ + a?: string + }|{ + b?: { + value: string + } + }) + out: 〈0;#Output〉 + out: { + if (true == true) { + b: { + value: "true" + } + } + } + } + } +} +--- reflect.cue +{ + unifyDynamicReflectSuccess: { + for _, s in [ + "foo", + ] { + X: { + ... + } + "\(〈1;s〉)": { + X: { + ... + } + Y: 〈import;"encoding/json"〉.Marshal(〈0;X〉) + } + } + [string]: { + X: { + if true { + x: { + y: {} + } + } + } + } + } +} +--- rework.cue +{ + regression1: { + #Primary: { + _Y: _ + let _X#2 = 〈0;_Y〉 + if (len(〈0;let _X#2〉.spec.command) > 0) { + command: 〈1;let _X#2〉.spec.command + } + } + #Rollout: { + _X: _ + out: ((〈1;#Primary〉 & { + _Y: 〈1;_X〉 + }) & 〈0;_X〉.patch) + } + x: { + spec: { + command: [ + "a", + ] + } + patch: {} + } + out: (〈0;#Rollout〉 & { + _X: 〈1;x〉 + }) + } + regression2: { + #Primary: { + _Y: _ + if (len(〈0;_Y〉.spec.command) > 0) { + command: 〈1;_Y〉.spec.command + } + } + #Rollout: { + _X: _ + out: ((〈1;#Primary〉 & { + _Y: 〈1;_X〉 + }) & 〈0;_X〉.patch) + } + x: { + spec: { + command: [ + "a", + ] + } + patch: {} + } + out: (〈0;#Rollout〉 & { + _X: 〈1;x〉 + }) + } + letCycleSelf: { + #X: { + let this#3 = 〈1〉 + hosts: { + [string]: _ + } + for h, _ in 〈0;let this#3〉.hosts { + out: { + 〈2;h〉: 1 + } + } + for h, _ in 〈0;let this#3〉.hosts { + out: { + 〈2;h〉: 2 + } + } + } + x: { + [string]: 〈1;#X〉 + } + x: { + a: {} + } + } +} +--- rework2.cue +{ + letCycleSelfKeyword: { + #E: { + let s#4 = 〈1〉 + hosts: _ + for _, hv in 〈0;let s#4〉.hosts { + out: { + 〈2;hv〉.x: "a" + } + } + } + env: (〈0;#E〉 & { + hosts: { + h1: { + x: "k" + } + } + }) + } + letCycleSelfKeyword2: { + #E: { + let s#5 = 〈1〉 + ... + for _, hv in 〈0;let s#5〉.hosts { + let n#6 = 〈2;let s#5〉.networks + a: 〈0;let n#6〉 + } + } + env: (〈0;#E〉 & { + hosts: { + h1: 1 + } + networks: { + n1: "x" + } + }) + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/try.txtar b/internal/core/compile/testdata/sync/comprehensions/try.txtar new file mode 100644 index 000000000..46ab04092 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/try.txtar @@ -0,0 +1,1099 @@ +-- in.cue -- +@experiment(try) + +// ============================================================================= +// Basic try with successful evaluation +// ============================================================================= + +a: 1 @test(eq, 1) +b: 2 @test(eq, 2) +c?: int // undefined optional field +incomplete: int + +// Try with successful optional references (both defined) +success: { + try { result: a? + b? } + @test(eq, {result: 3}) +} + +// Try with single optional reference +single: { + x: 5 + try { y: x? * 2 } + @test(eq, {x: 5, y: 10}) +} + +// ============================================================================= +// Try with else clause +// ============================================================================= + +// Else NOT triggered when try succeeds (value is defined) +fallbackDef: 42 +elseNotTriggered: { + try { v: fallbackDef? } else { fallback: 0 } + @test(eq, {v: 42}) +} + +// Else triggered when try fails (optional field undefined) +// Note: else uses different field name to avoid merge conflicts with trial evaluation +elseTriggered: { + try { v: c? } else { fallback: -1 } + @test(eq, {fallback: -1}) +} + +// Else with different field names (avoids conflict with trial evaluation) +elseMultiField: { + try { x: c?, y: c? } else { fallback: true } + @test(eq, {fallback: true}) +} + +// ============================================================================= +// Try with undefined optional references +// ============================================================================= + +// Try produces empty struct when optional fails (no else) +emptyOnFail: { + try { z: c? + 1 } + @test(eq, {}) +} + +// Try with mix of defined and undefined - all must succeed +mixedRefs: { + try { x: a?, y: c? } else { fallback: true } + @test(eq, {fallback: true}) +} + +incompleteOK: { + try { x: incomplete? } else { fallback: 23 } + @test(eq, {x: int}) +} + +// Nested struct in try body with incomplete value +incompleteNestedBody: { + try { x: y: incomplete? } else { fallback: 23 } + @test(eq, {x: {y: int}}) +} + +// ============================================================================= +// Required fields +// ============================================================================= + +// Unfilled required field triggers else +requiredUnfilled: { + a!: _ + try { x: a? } else { fallback: 23 } + @test(eq, { + a!: _ + x: _|_ @test(err, code=incomplete, contains="requiredUnfilled.x: required field missing: a", pos=[83:11]) + }) +} + +// Filled required field succeeds +requiredFilled: { + a!: _ + a: 5 + try { x: a? } else { fallback: 23 } + @test(eq, {a: 5, x: 5}) +} + +// Required field with type constraint triggers else +requiredWithType: { + a!: int + try { x: a? } else { fallback: 23 } + @test(eq, { + a!: int + x: _|_ @test(err, code=incomplete, contains="requiredWithType.x: required field missing: a", pos=[101:11]) + }) +} + +// ============================================================================= +// Try with for comprehension +// ============================================================================= + +// For with optional source that exists +forWithDefinedSource: { + try { for x in [b?] { val: x } } + @test(eq, {val: 2}) +} + +// For with optional source that's undefined +forWithUndefinedSource: { + try { for x in [c?] { val: x } } else { empty: true } + @test(eq, {empty: true}) +} + +// ============================================================================= +// Nested structures +// ============================================================================= + +nested: { + // Try inside struct + outer: { + try { inner: a? } + @test(eq, {inner: 1}) + } + + // Multiple try clauses in same struct + multi: { + try { first: a? } + try { second: b? } + @test(eq, {first: 1, second: 2}) + } + + // Try with nested struct in body + deepNested: { + try { + level1: { + level2: a? + } + } + @test(eq, {level1: {level2: 1}}) + } +} + +// ============================================================================= +// Complex expressions in try +// ============================================================================= + +complexExpr: { + // Binary operations + binOp: { + try { sum: a? + b?, prod: a? * b? } + @test(eq, {sum: 3, prod: 2}) + } + + // Conditional with optional + list: { + try { items: [a?, b?, a? + b?] } + @test(eq, {items: [1, 2, 3]}) + } +} + +// ============================================================================= +// Selector expressions with optional +// ============================================================================= + + selectorTests: { + data: { + nested: { + value: 100 + } + } + + // Selector on defined path + definedSelector: { + try { v: data.nested.value? } + } + + @test(eq, { + data: {nested: {value: 100}} + definedSelector: {v: 100} + }) + + // Note: selector on undefined path would be compile error +} + +// ============================================================================= +// Refer to closed structs +// ============================================================================= +closedness: { + #Def: {f: int} + + d: #Def + + exists: { + try { v: #Def.f? } + @test(eq, {v: int}) + } + notExistsDef: { + try { v: #Def.g? } + @test(err, code=eval, path=v, contains="undefined field: %s", args=[g], pos=[1:17]) + } + notExistsValue: { + try { v: d.g? } + @test(err, code=eval, path=v, contains="undefined field: %s", args=[g], pos=[1:14]) + } +} + + +// ============================================================================= +// Index expressions with optional +// ============================================================================= + +indexTests: { + closedList: [10, 20, 30] + openList: [10, 20, 30, ...] + + // Index on defined position (closed list) + definedIndex: { + try { v: closedList[0]? } + @test(eq, {v: 10}) + } + + // Index on defined position (middle) + middleIndex: { + try { v: closedList[1]? } + @test(eq, {v: 20}) + } + + // Index out of range on CLOSED list - should ERROR (can never be satisfied) + outOfRangeClosed: { + try { v: closedList[10]? } else { fallback: -1 } + @test(err, code=eval, path=v, contains="index out of range [%d] with length %d", args=[10, 3], pos=[1:23]) + } + + // Index out of range on CLOSED list without else - should ERROR + outOfRangeClosedNoElse: { + try { v: closedList[100]? } + @test(err, code=eval, path=v, contains="index out of range [%d] with length %d", args=[100, 3], pos=[1:23]) + } + + // Index out of range on OPEN list - should trigger else (list might grow) + outOfRangeOpen: { + try { v: openList[10]? } else { fallback: -1 } + @test(eq, {fallback: -1}) + } + + // Index out of range on OPEN list without else - empty struct + outOfRangeOpenNoElse: { + try { v: openList[100]? } + @test(eq, {}) + } + + // Multiple index accesses on closed list + multipleIndex: { + try { x: closedList[0]?, y: closedList[1]?, z: closedList[2]? } + @test(eq, {x: 10, y: 20, z: 30}) + } +} + +// ============================================================================= +// Edge cases +// ============================================================================= + +edgeCases: { + // Empty try body (should produce empty struct) + emptyBody: { + try { } + @test(eq, {}) + } + + // Try with only literal (no optional refs) - should always succeed + literalOnly: { + try { x: 42 } + @test(eq, {x: 42}) + } + + // Multiple optional refs, first fails + firstFails: { + try { x: c?, y: a? } else { skipped: true } + @test(eq, {skipped: true}) + } + + // Multiple optional refs, second fails + secondFails: { + try { x: a?, y: c? } else { skipped: true } + @test(eq, {skipped: true}) + } + + referenceError: { + a: 1 / 0 + a: _b: 2 + + direct: { + try { v: a? } else { skipped: true } + @test(err, code=eval, path=edgeCases.referenceError.a, contains="failed arithmetic: %v", args=[division by zero], pos=[-3:6]) + // v shares the error from a + } + dontSkipError1: { + try { a._b? } else { skipped: true } + @test(err, code=eval, path=edgeCases.referenceError.a, contains="failed arithmetic: %v", args=[division by zero], pos=[-8:6]) + } + dontSkipError2: { + try { a?._b? } else { skipped: true } + @test(err, code=eval, path=edgeCases.referenceError.a, contains="failed arithmetic: %v", args=[division by zero], pos=[-12:6]) + } + } +} + +// ============================================================================= +// Referencing into try results +// ============================================================================= + +// When referencing a field from a successful try, the field is guaranteed +// to exist and be concrete. No ? needed outside of try context. + +refIntoTry: { + // Try that succeeds - inner fields are accessible + source: { + try { val: a? } + @test(eq, {val: 1}) + } + // Reference into successful try result (no ? needed) + ref: source.val @test(eq, 1) // Should resolve to 1 + + // Nested try - outer succeeds, inner may or may not + nestedSource: { + try { + inner: { + try { deep: b? } + } + } + @test(eq, {inner: {deep: 2}}) + } + // Reference into nested try result (no ? needed) + nestedRef: nestedSource.inner.deep @test(eq, 2) // Should resolve to 2 + + // Try that fails - struct is empty, reference fails + nestedSkipped?: { try { c? } } @test(err, code=incomplete, path=refIntoTry, contains="field not found: %v", args=[nestedSkipped], pos=[]) + mixedSource: { + try { foo: nestedSkipped? } + bar?: 1 + baz: 1 + @test(eq, {bar?: 1, baz: 1}) + } + // Reference into failed try - use try to handle the missing field + skippedRef: { + try { v: mixedSource.foo? } else { missing: true } + @test(eq, {missing: true}) + } + failedRef1: { + try { v: mixedSource.foo } else { missing: true } + @test(eq, { + v: _|_ @test(err, code=incomplete, contains="refIntoTry.failedRef1.v: undefined field: foo", pos=[360:24]) + }) + } + failedRef2: { + try { v: mixedSource.foo } else { missing: true } + @test(eq, { + v: _|_ @test(err, code=incomplete, contains="refIntoTry.failedRef2.v: undefined field: foo", pos=[366:24]) + }) + } + successRef: { + try { v: mixedSource.baz? } else { missing: true } + @test(eq, {v: 1}) + } +} + +// ============================================================================= +// Error precedence: real errors should not be masked by OptionalUndefined +// ============================================================================= + +errorPrecedence: { + // Type error with optional that exists - should error + typeErrorDefined: { + try { v: a? + "string" } else { fallback: "ok" } + @test(err, code=eval, path=v, + contains="invalid operands %s and %s to '%s' (type %s and %s)", + args=[1, "string", +, int, string], pos=[1:12, -376:4, 1:17]) + } + + // Type error AND undefined optional - depends on evaluation order + // If c? is evaluated first and fails, the type error is never reached + typeErrorUndefined: { + try { v: c? + "string" } else { fallback: "ok" } + @test(eq, {fallback: "ok"}) + } + + // Division by zero with optional + divByZero: { + try { v: a? / 0 } else { fallback: "ok" } + @test(err, code=eval, path=v, contains="failed arithmetic: %v", + args=[division by zero], pos=[1:12]) + } + + // Error from conflicting values + conflictError: { + try { v: a? & "notanint" } else { fallback: "ok" } + @test(err, code=eval, path=v, + contains="conflicting values %s and %s (mismatched types %s and %s)", + args=["notanint", 1, string, int], + pos=[-398:4, 0:17, 1:3, 1:12, 1:17]) + } + + // Mixed case: OptionalUndefined in one field, real error in another + // The real error should still propagate + mixedError: { + try { + x: c? // undefined + y: 1 / 0 // real error (independent) + } else { fallback: "ok" } + @test(eq, {fallback: "ok"}) + } + + // Mixed case 2: multiple optionals, one undefined, one with error + mixedErrorMultiple: { + try { + x: a? // defined (1) + y: c? // undefined + z: a? / 0 // real error + } else { fallback: "ok" } + @test(eq, {fallback: "ok"}) + } +} + +// ============================================================================= +// Assignment form: try x = expr +// ============================================================================= + +assignmentForm: { + // Basic assignment with defined value + basicDefined: { + try x = a? { result: x } + @test(eq, {result: 1}) + } + + // Assignment with undefined optional - should trigger else + basicUndefined: { + try x = c? { result: x } else { fallback: 0 } + @test(eq, {fallback: 0}) + } + + // Assignment without else - should produce empty struct + noElseUndefined: { + try x = c? { result: x } + @test(eq, {}) + } + + // Assignment with expression + withExpression: { + try sum = a? + b? { result: sum } + @test(eq, {result: 3}) + } + + // Assignment with failing expression - triggers else + withFailingExpr: { + try sum = a? + c? { result: sum } else { fallback: -1 } + @test(eq, {fallback: -1}) + } + + // Chained assignments + chained: { + try x = a? try y = b? { result: x + y } + @test(eq, {result: 3}) + } + + // Assignment with selector + withSelector: { + data: { inner: 42 } + try v = data.inner? { result: v } + @test(eq, {data: {inner: 42}, result: 42}) + } + + // Assignment with index + withIndex: { + list: [10, 20, 30] + try v = list[1]? { result: v } + @test(eq, {list: [10, 20, 30], result: 20}) + } + + // Assignment with out-of-range index on closed list - should ERROR + withOutOfRangeIndex: { + list: [10, 20, 30] + try v = list[10]? { result: v } else { fallback: -1 } + @test(err, code=eval, path=result, + contains="index out of range [%d] with length %d", args=[10, 3], pos=[2:16]) + } + + // Assignment with out-of-range index on open list - should trigger else + withOutOfRangeIndexOpen: { + list: [10, 20, 30, ...] + try v = list[10]? { result: v } else { fallback: -1 } + @test(eq, {list: [10, 20, 30], fallback: -1}) + } + + // Assignment used in nested expression + nestedUse: { + try x = a? { inner: { value: x * 2 } } + @test(eq, {inner: {value: 2}}) + } + + // Multiple chained try assignments with one failing + chainedOneFails: { + try x = a? try y = c? { result: x + y } + @test(eq, {}) + } + + // Assignment with real error - should propagate + withRealError: { + try x = a? / 0 { result: x } else { fallback: "ok" } + @test(err, code=eval, path=result, + contains="failed arithmetic: %v", args=[division by zero], pos=[1:11]) + } + + // Assignment combined with for + withFor: { + try x = b? for i, v in [1, 2] { "\(i)": x + v } + @test(eq, {"0": 3, "1": 4}) + } + + // Assignment combined with if + withIf: { + try x = a? if x > 0 { positive: x } + @test(eq, {positive: 1}) + } + + // Assignment combined with let + withLet: { + try x = a? let y = x * 2 { doubled: y } + @test(eq, {doubled: 2}) + } +} + +// ============================================================================= +// Original recursive tests +// ============================================================================= + +recursive: t1: { try { for x in [b?] { x } } } @test(eq, 2) +recursive: t2: { try { {x: b?, y: c?} } } @test(eq, {}) +recursive: t3: { try { {x: b?, y: c?} } else { z: 23 }} @test(eq, {z: 23}) + +-- out/compile -- +--- in.cue +{ + a: 1 + b: 2 + c?: int + incomplete: int + success: { + try { + result: (〈2;a〉? + 〈2;b〉?) + } + } + single: { + x: 5 + try { + y: (〈1;x〉? * 2) + } + } + fallbackDef: 42 + elseNotTriggered: { + try { + v: 〈2;fallbackDef〉? + } else { + fallback: 0 + } + } + elseTriggered: { + try { + v: 〈2;c〉? + } else { + fallback: -1 + } + } + elseMultiField: { + try { + x: 〈2;c〉? + y: 〈2;c〉? + } else { + fallback: true + } + } + emptyOnFail: { + try { + z: (〈2;c〉? + 1) + } + } + mixedRefs: { + try { + x: 〈2;a〉? + y: 〈2;c〉? + } else { + fallback: true + } + } + incompleteOK: { + try { + x: 〈2;incomplete〉? + } else { + fallback: 23 + } + } + incompleteNestedBody: { + try { + x: { + y: 〈3;incomplete〉? + } + } else { + fallback: 23 + } + } + requiredUnfilled: { + a!: _ + try { + x: 〈1;a〉? + } else { + fallback: 23 + } + } + requiredFilled: { + a!: _ + a: 5 + try { + x: 〈1;a〉? + } else { + fallback: 23 + } + } + requiredWithType: { + a!: int + try { + x: 〈1;a〉? + } else { + fallback: 23 + } + } + forWithDefinedSource: { + try { + for _, x in [ + 〈3;b〉?, + ] { + val: 〈1;x〉 + } + } + } + forWithUndefinedSource: { + try { + for _, x in [ + 〈3;c〉?, + ] { + val: 〈1;x〉 + } + } else { + empty: true + } + } + nested: { + outer: { + try { + inner: 〈3;a〉? + } + } + multi: { + try { + first: 〈3;a〉? + } + try { + second: 〈3;b〉? + } + } + deepNested: { + try { + level1: { + level2: 〈4;a〉? + } + } + } + } + complexExpr: { + binOp: { + try { + sum: (〈3;a〉? + 〈3;b〉?) + prod: (〈3;a〉? * 〈3;b〉?) + } + } + list: { + try { + items: [ + 〈4;a〉?, + 〈4;b〉?, + (〈4;a〉? + 〈4;b〉?), + ] + } + } + } + selectorTests: { + data: { + nested: { + value: 100 + } + } + definedSelector: { + try { + v: 〈2;data〉.nested.value? + } + } + } + closedness: { + #Def: { + f: int + } + d: 〈0;#Def〉 + exists: { + try { + v: 〈2;#Def〉.f? + } + } + notExistsDef: { + try { + v: 〈2;#Def〉.g? + } + } + notExistsValue: { + try { + v: 〈2;d〉.g? + } + } + } + indexTests: { + closedList: [ + 10, + 20, + 30, + ] + openList: [ + 10, + 20, + 30, + ..., + ] + definedIndex: { + try { + v: 〈2;closedList〉[0]? + } + } + middleIndex: { + try { + v: 〈2;closedList〉[1]? + } + } + outOfRangeClosed: { + try { + v: 〈2;closedList〉[10]? + } else { + fallback: -1 + } + } + outOfRangeClosedNoElse: { + try { + v: 〈2;closedList〉[100]? + } + } + outOfRangeOpen: { + try { + v: 〈2;openList〉[10]? + } else { + fallback: -1 + } + } + outOfRangeOpenNoElse: { + try { + v: 〈2;openList〉[100]? + } + } + multipleIndex: { + try { + x: 〈2;closedList〉[0]? + y: 〈2;closedList〉[1]? + z: 〈2;closedList〉[2]? + } + } + } + edgeCases: { + emptyBody: { + try {} + } + literalOnly: { + try { + x: 42 + } + } + firstFails: { + try { + x: 〈3;c〉? + y: 〈3;a〉? + } else { + skipped: true + } + } + secondFails: { + try { + x: 〈3;a〉? + y: 〈3;c〉? + } else { + skipped: true + } + } + referenceError: { + a: (1 / 0) + a: { + _b: 2 + } + direct: { + try { + v: 〈2;a〉? + } else { + skipped: true + } + } + dontSkipError1: { + try { + 〈2;a〉._b? + } else { + skipped: true + } + } + dontSkipError2: { + try { + 〈2;a〉?._b? + } else { + skipped: true + } + } + } + } + refIntoTry: { + source: { + try { + val: 〈3;a〉? + } + } + ref: 〈0;source〉.val + nestedSource: { + try { + inner: { + try { + deep: 〈5;b〉? + } + } + } + } + nestedRef: 〈0;nestedSource〉.inner.deep + nestedSkipped?: { + try { + 〈3;c〉? + } + } + mixedSource: { + try { + foo: 〈2;nestedSkipped〉? + } + bar?: 1 + baz: 1 + } + skippedRef: { + try { + v: 〈2;mixedSource〉.foo? + } else { + missing: true + } + } + failedRef1: { + try { + v: 〈2;mixedSource〉.foo + } else { + missing: true + } + } + failedRef2: { + try { + v: 〈2;mixedSource〉.foo + } else { + missing: true + } + } + successRef: { + try { + v: 〈2;mixedSource〉.baz? + } else { + missing: true + } + } + } + errorPrecedence: { + typeErrorDefined: { + try { + v: (〈3;a〉? + "string") + } else { + fallback: "ok" + } + } + typeErrorUndefined: { + try { + v: (〈3;c〉? + "string") + } else { + fallback: "ok" + } + } + divByZero: { + try { + v: (〈3;a〉? / 0) + } else { + fallback: "ok" + } + } + conflictError: { + try { + v: (〈3;a〉? & "notanint") + } else { + fallback: "ok" + } + } + mixedError: { + try { + x: 〈3;c〉? + y: (1 / 0) + } else { + fallback: "ok" + } + } + mixedErrorMultiple: { + try { + x: 〈3;a〉? + y: 〈3;c〉? + z: (〈3;a〉? / 0) + } else { + fallback: "ok" + } + } + } + assignmentForm: { + basicDefined: { + try x = 〈2;a〉? { + result: 〈1;x〉 + } + } + basicUndefined: { + try x = 〈2;c〉? { + result: 〈1;x〉 + } else { + fallback: 0 + } + } + noElseUndefined: { + try x = 〈2;c〉? { + result: 〈1;x〉 + } + } + withExpression: { + try sum = (〈2;a〉? + 〈2;b〉?) { + result: 〈1;sum〉 + } + } + withFailingExpr: { + try sum = (〈2;a〉? + 〈2;c〉?) { + result: 〈1;sum〉 + } else { + fallback: -1 + } + } + chained: { + try x = 〈2;a〉? try y = 〈3;b〉? { + result: (〈2;x〉 + 〈1;y〉) + } + } + withSelector: { + data: { + inner: 42 + } + try v = 〈0;data〉.inner? { + result: 〈1;v〉 + } + } + withIndex: { + list: [ + 10, + 20, + 30, + ] + try v = 〈0;list〉[1]? { + result: 〈1;v〉 + } + } + withOutOfRangeIndex: { + list: [ + 10, + 20, + 30, + ] + try v = 〈0;list〉[10]? { + result: 〈1;v〉 + } else { + fallback: -1 + } + } + withOutOfRangeIndexOpen: { + list: [ + 10, + 20, + 30, + ..., + ] + try v = 〈0;list〉[10]? { + result: 〈1;v〉 + } else { + fallback: -1 + } + } + nestedUse: { + try x = 〈2;a〉? { + inner: { + value: (〈2;x〉 * 2) + } + } + } + chainedOneFails: { + try x = 〈2;a〉? try y = 〈3;c〉? { + result: (〈2;x〉 + 〈1;y〉) + } + } + withRealError: { + try x = (〈2;a〉? / 0) { + result: 〈1;x〉 + } else { + fallback: "ok" + } + } + withFor: { + try x = 〈2;b〉? for i, v in [ + 1, + 2, + ] { + "\(〈1;i〉)": (〈2;x〉 + 〈1;v〉) + } + } + withIf: { + try x = 〈2;a〉? if (〈0;x〉 > 0) { + positive: 〈1;x〉 + } + } + withLet: { + try x = 〈2;a〉? let y = (〈0;x〉 * 2) { + doubled: 〈1;y〉 + } + } + } + recursive: { + t1: { + try { + for _, x in [ + 〈4;b〉?, + ] { + 〈1;x〉 + } + } + } + } + recursive: { + t2: { + try { + { + x: 〈4;b〉? + y: 〈4;c〉? + } + } + } + } + recursive: { + t3: { + try { + { + x: 〈4;b〉? + y: 〈4;c〉? + } + } else { + z: 23 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/comprehensions/try_compile_errors.txtar b/internal/core/compile/testdata/sync/comprehensions/try_compile_errors.txtar new file mode 100644 index 000000000..f482cf5a8 --- /dev/null +++ b/internal/core/compile/testdata/sync/comprehensions/try_compile_errors.txtar @@ -0,0 +1,79 @@ +#inlinetest:exclude CUE source contains compile-time errors (try-clause syntax, missing +# references) which prevent the inline runner from compiling the source. +-- in.cue -- +@experiment(try) + +// Struct-form try must be the last clause +structFormNotLast: { + try if true { x: 1 } +} + +// ? marker outside try context +optionalOutsideTry: { + a: 1 + b: a? +} + +// ? marker in for clause source (outside try) +optionalInForSource: { + a?: [1, 2, 3] + for x in a? { "\(x)": x } +} + +// ? marker in body of assignment-form try +optionalInAssignmentBody: { + a: 1 + b: 2 + try y = a? { x: b? } else { fallback: 23 } +} + +// Struct-form try must be the last clause +invalidUseOfOptional: { + try { x: c? } +} + +-- out/compile -- +structFormNotLast: struct-form try clause must be the last clause in a comprehension: + ./in.cue:5:5 +optionalOutsideTry.b: optional marker (?) is only valid within a try clause: + ./in.cue:11:8 +optionalInForSource: optional marker (?) is only valid within a try clause: + ./in.cue:17:14 +optionalInAssignmentBody.try[].x: optional marker (?) is only valid within a try clause: + ./in.cue:24:21 +invalidUseOfOptional.x: reference "c" not found: + ./in.cue:29:14 +--- in.cue +{ + structFormNotLast: { + _|_(struct-form try clause must be the last clause in a comprehension) + } + optionalOutsideTry: { + a: 1 + b: 〈0;a〉? + } + optionalInForSource: { + a?: [ + 1, + 2, + 3, + ] + for _, x in 〈0;a〉? { + "\(〈1;x〉)": 〈1;x〉 + } + } + optionalInAssignmentBody: { + a: 1 + b: 2 + try y = 〈0;a〉? { + x: 〈2;b〉? + } else { + fallback: 23 + } + } + invalidUseOfOptional: { + try { + x: _|_(reference "c" not found) + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/015_reference_across_tuples_and_back.txtar b/internal/core/compile/testdata/sync/cycle/015_reference_across_tuples_and_back.txtar new file mode 100644 index 000000000..f73a200e2 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/015_reference_across_tuples_and_back.txtar @@ -0,0 +1,23 @@ +-- in.cue -- +t1: { + a: {c: b.e, d: b.f} + b: {e: 3, f: a.c} + @test(eq, { + a: {c: 3, d: 3} + b: {e: 3, f: 3} + }) +} +-- out/compile -- +--- in.cue +{ + t1: { + a: { + c: 〈1;b〉.e + d: 〈1;b〉.f + } + b: { + e: 3 + f: 〈1;a〉.c + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/021_delayed_constraint_failure.txtar b/internal/core/compile/testdata/sync/cycle/021_delayed_constraint_failure.txtar new file mode 100644 index 000000000..50cb46c19 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/021_delayed_constraint_failure.txtar @@ -0,0 +1,20 @@ +#name: delayed constraint failure +#evalPartial +# Tests that cycles resolved by defaults produce correct values, while +# conflicting constraints on the same field produce errors. +-- in.cue -- +a: b - 100 @test(eq, 100) // Okay to have no error here, as long as there is an error with b. +b: a + 110 +b: 200 @test(err, code=eval, pos=[-1:4, 0:4]) + +x: 100 +x: x + 1 @test(err, code=eval, pos=[-1:4, 0:4]) +-- out/compile -- +--- in.cue +{ + a: (〈0;b〉 - 100) + b: (〈0;a〉 + 110) + b: 200 + x: 100 + x: (〈0;x〉 + 1) +} diff --git a/internal/core/compile/testdata/sync/cycle/023_reentrance.txtar b/internal/core/compile/testdata/sync/cycle/023_reentrance.txtar new file mode 100644 index 000000000..ca898f25d --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/023_reentrance.txtar @@ -0,0 +1,65 @@ +#name: reentrance +#evalFull +-- in.cue -- +// This indirection is needed to avoid binding references to fib +// within fib to the instantiated version. +fibRec: { + nn: int + out: (fib & {n: nn}).out + @test(err, code=incomplete, at=out) +} +fib: { + n: int + + if n >= 2 { + out: (fibRec & {nn: n - 2}).out + (fibRec & {nn: n - 1}).out + } + if n < 2 { + out: n + } + @test(err, code=incomplete) +} +fib1: (fib & {n: 1}).out @test(eq, 1) // MAY NOT be an error +fib2: (fib & {n: 2}).out @test(eq, 1) // MAY be an error +fib3: (fib & {n: 3}).out @test(err, code=structural_cycle) // SHOULD be an error +fib7: (fib & {n: 7}).out @test(err, code=structural_cycle) // Error +fib12: (fib & {n: 12}).out @test(err, code=structural_cycle) // Error + +-- out/compile -- +--- in.cue +{ + fibRec: { + nn: int + out: (〈1;fib〉 & { + n: 〈1;nn〉 + }).out + } + fib: { + n: int + if (〈0;n〉 >= 2) { + out: ((〈2;fibRec〉 & { + nn: (〈2;n〉 - 2) + }).out + (〈2;fibRec〉 & { + nn: (〈2;n〉 - 1) + }).out) + } + if (〈0;n〉 < 2) { + out: 〈1;n〉 + } + } + fib1: (〈0;fib〉 & { + n: 1 + }).out + fib2: (〈0;fib〉 & { + n: 2 + }).out + fib3: (〈0;fib〉 & { + n: 3 + }).out + fib7: (〈0;fib〉 & { + n: 7 + }).out + fib12: (〈0;fib〉 & { + n: 12 + }).out +} diff --git a/internal/core/compile/testdata/sync/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar b/internal/core/compile/testdata/sync/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar new file mode 100644 index 000000000..2e08b475e --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar @@ -0,0 +1,35 @@ +#name: cannot resolve references that would be ambiguous +#evalFull +-- in.cue -- +a1: *0 | 1 +a1: a3 - a2 @test(err, code=cycle, pos=[2:10]) +a2: *0 | 1 +a2: a3 - a1 @test(err, code=cycle, pos=[0:10]) +a3: 1 @test(eq, 1) + +b1: (*0 | 1) & b2 @test(eq, 0|1) +b2: (0 | *1) & b1 @test(eq, 0|1) + +c1: (*{a: 1} | {b: 1}) & c2 @test(eq, {a: 1, b: 2} | {b: 1, a: 2}) +c2: (*{a: 2} | {b: 2}) & c1 @test(eq, {a: 2, b: 1} | {b: 2, a: 1}) +-- out/compile -- +--- in.cue +{ + a1: (*0|1) + a1: (〈0;a3〉 - 〈0;a2〉) + a2: (*0|1) + a2: (〈0;a3〉 - 〈0;a1〉) + a3: 1 + b1: ((*0|1) & 〈0;b2〉) + b2: ((0|*1) & 〈0;b1〉) + c1: ((*{ + a: 1 + }|{ + b: 1 + }) & 〈0;c2〉) + c2: ((*{ + a: 2 + }|{ + b: 2 + }) & 〈0;c1〉) +} diff --git a/internal/core/compile/testdata/sync/cycle/049_self-reference_cycles_conflicts_with_strings.txtar b/internal/core/compile/testdata/sync/cycle/049_self-reference_cycles_conflicts_with_strings.txtar new file mode 100644 index 000000000..8fb86a6aa --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/049_self-reference_cycles_conflicts_with_strings.txtar @@ -0,0 +1,19 @@ +#name: self-reference cycles conflicts with strings +#evalPartial +-- in.cue -- +a: { + x: y + "?" + y: x + "!" @test(eq, "hey!") +} +a: x: "hey" @test(err, code=eval, contains="conflicting values", pos=[-3:5, 0:7]) +-- out/compile -- +--- in.cue +{ + a: { + x: (〈0;y〉 + "?") + y: (〈0;x〉 + "!") + } + a: { + x: "hey" + } +} diff --git a/internal/core/compile/testdata/sync/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar b/internal/core/compile/testdata/sync/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar new file mode 100644 index 000000000..aeee608b7 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar @@ -0,0 +1,31 @@ +#name: resolved self-reference cycles with disjunctions +#evalPartial +-- in.cue -- +a: b & {x: 1} | {y: 1} // {x:1,y:3,z:2} | {y:1} +b: {x: 2} | c & {z: 2} // {x:2} | {x:1,y:3,z:2} +c: a & {y: 3} | {z: 3} // {x:1,y:3,z:2} | {z:3} + +@test(eq, { + a: {x: 1, z: 2, y: 3} | {y: 1} + b: {x: 2} | {z: 2, y: 3, x: 1} + c: {y: 3, x: 1, z: 2} | {z: 3} +}) +-- out/compile -- +--- in.cue +{ + a: ((〈0;b〉 & { + x: 1 + })|{ + y: 1 + }) + b: ({ + x: 2 + }|(〈0;c〉 & { + z: 2 + })) + c: ((〈0;a〉 & { + y: 3 + })|{ + z: 3 + }) +} diff --git a/internal/core/compile/testdata/sync/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar b/internal/core/compile/testdata/sync/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar new file mode 100644 index 000000000..c6dc31469 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar @@ -0,0 +1,124 @@ +#name: resolved self-reference cycles with disjunction +#evalPartial + +// TODO(cycle) +// +// Some of these examples used to work, but the changes corresponding to this +// addition, it ceased to do so. Fixing these cycle issues seemed more +// important than keeping this esoteric case working, which was already broken +// in the last release anyway. +// +// Reproducer of underlying problem. Still works, but triggers unexpected +// condition. +// +// xb1: xb2 +// xb2: xb3 +// xb3: xb2 + 0 +-- in.cue -- +// The second disjunct in xa1 is not resolvable and can be +// eliminated: +// xa4 & 9 +// (xa2 + 2) & 9 +// ((xa3 + 2) + 2) & 9 +// (((6 & xa1-2) + 2) + 2) & 9 +// ((6 + 2) + 2) & 9 // 6 == xa1-2 +// 10 & 9 => _|_ +// The remaining values resolve. +xa1: (xa2 & 8) | (xa4 & 9) @test(eq, 8) +xa2: xa3 + 2 @test(eq, 8) +xa3: 6 & xa1-2 @test(eq, 6) +xa4: xa2 + 2 @test(eq, 10) + +// TODO(inline): make positions work here. +xb1: (xb2 & 8) | (xb4 & 9) @test(err, code=cycle, + suberr=(code=cycle, path=xb2, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, path=xb3, contains="%d errors in empty disjunction:", args=[3]), + suberr=(code=cycle, path=xb3, contains="unresolved disjunction: %v", args=[xb1]), + suberr=(code=cycle, path=xb3, contains="cycle with field: %v", args=[xb2])) +xb2: xb3 + 2 @test(err, code=cycle, + suberr=(code=cycle, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, path=xb3, contains="cycle with field: %v", args=[xb2])) +xb3: (6 & (xb1 - 2)) | (xb4 & 9) @test(err, code=cycle, + suberr=(code=cycle, path=xb2, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, contains="unresolved disjunction: %v", args=[xb1]), + suberr=(code=cycle, contains="cycle with field: %v", args=[xb2])) +xb4: xb2 + 2 @test(err, code=cycle, + suberr=(code=cycle, path=xb2, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, path=xb3, contains="cycle with field: %v", args=[xb2])) + +// Another variant with more disjunctions. xc1 remains with two +// possibilities. Technically, only the first value is valid. +// However, to fully determine that, all options of the remaining +// disjunction will have to be evaluated algebraically, which is +// not done. +xc1: xc2 & 8 | xc4 & 9 | xc5 & 9 @test(eq, 8|9) +xc2: xc3 + 2 @test(eq, 8) +xc3: 6 & xc1-2 @test(err, code=incomplete, + contains="unresolved disjunction %v (type %s)", args=[8 | 9, int], pos=[0:10]) +xc4: xc2 + 1 @test(eq, 9) +xc5: xc2 + 2 @test(eq, 10) + +// The below is resolved by setting xd1 explicitly. +xd1: xd2 & 8 | xd4 & 9 | xd5 & 9 // 8 see below +xd2: xd3 + 2 @test(eq, 8) +xd3: 6 & xd1-2 @test(eq, 6) +xd4: xd2 + 1 @test(eq, 9) +xd5: xd2 + 2 @test(eq, 10) +xd1: 8 @test(eq, 8) + +// The below is resolved by setting xd1 explicitly to the wrong +// value, resulting in an error. +xe1: xe2 & 8 | xe4 & 9 | xe5 & 9 +xe2: xe3 + 2 @test(eq, 8) +xe3: 6 & xe1-2 @test(err, code=eval, pos=[0:6, 0:10]) +xe4: xe2 + 1 @test(eq, 9) +xe5: xe2 + 2 @test(eq, 10) +xe1: 9 @test(eq, 9) + +xf1: xf2 & 8 | xf4 & 9 @test(err, code=cycle, pos=[]) +xf2: xf3 + 2 @test(err, code=cycle, pos=[0:6]) +xf3: 6 & xf1-2 | xf4 & 9 @test(err, code=cycle, pos=[-1:6]) +xf4: xf2 + 2 @test(err, code=cycle, pos=[-2:6]) + +z1: z2+1 | z3+5 @test(eq, 11|13) // +3 for fun +z2: z3 + 2 @test(eq, 10) +z3: z1 - 3 +z3: 8 @test(err, code=incomplete, + contains="unresolved disjunction %v (type %s)", args=[11 | 13, int], pos=[-1:5]) +-- out/compile -- +--- in.cue +{ + xa1: ((〈0;xa2〉 & 8)|(〈0;xa4〉 & 9)) + xa2: (〈0;xa3〉 + 2) + xa3: (6 & (〈0;xa1〉 - 2)) + xa4: (〈0;xa2〉 + 2) + xb1: ((〈0;xb2〉 & 8)|(〈0;xb4〉 & 9)) + xb2: (〈0;xb3〉 + 2) + xb3: ((6 & (〈0;xb1〉 - 2))|(〈0;xb4〉 & 9)) + xb4: (〈0;xb2〉 + 2) + xc1: ((〈0;xc2〉 & 8)|(〈0;xc4〉 & 9)|(〈0;xc5〉 & 9)) + xc2: (〈0;xc3〉 + 2) + xc3: (6 & (〈0;xc1〉 - 2)) + xc4: (〈0;xc2〉 + 1) + xc5: (〈0;xc2〉 + 2) + xd1: ((〈0;xd2〉 & 8)|(〈0;xd4〉 & 9)|(〈0;xd5〉 & 9)) + xd2: (〈0;xd3〉 + 2) + xd3: (6 & (〈0;xd1〉 - 2)) + xd4: (〈0;xd2〉 + 1) + xd5: (〈0;xd2〉 + 2) + xd1: 8 + xe1: ((〈0;xe2〉 & 8)|(〈0;xe4〉 & 9)|(〈0;xe5〉 & 9)) + xe2: (〈0;xe3〉 + 2) + xe3: (6 & (〈0;xe1〉 - 2)) + xe4: (〈0;xe2〉 + 1) + xe5: (〈0;xe2〉 + 2) + xe1: 9 + xf1: ((〈0;xf2〉 & 8)|(〈0;xf4〉 & 9)) + xf2: (〈0;xf3〉 + 2) + xf3: ((6 & (〈0;xf1〉 - 2))|(〈0;xf4〉 & 9)) + xf4: (〈0;xf2〉 + 2) + z1: ((〈0;z2〉 + 1)|(〈0;z3〉 + 5)) + z2: (〈0;z3〉 + 2) + z3: (〈0;z1〉 - 3) + z3: 8 +} diff --git a/internal/core/compile/testdata/sync/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar b/internal/core/compile/testdata/sync/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar new file mode 100644 index 000000000..f9a636594 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar @@ -0,0 +1,90 @@ +#name: resolved self-reference cycles with disjunction with defaults +#evalPartial +-- in.cue -- +// The disjunction in xa could be resolved, but as disjunctions +// are not resolved for expression, it remains unresolved. +xa1: (xa2 & 8) | *(xa4 & 9) @test(eq, 8) +xa2: xa3 + 2 @test(eq, 8) +xa3: 6 & xa1-2 @test(eq, 6) +xa4: xa2 + 2 @test(eq, 10) + +// TODO(inline): make positions work here. +xb1: *(xb2 & 8) | (xb4 & 9) @test(err, code=cycle, pos=[], + suberr=(code=cycle, path=xb2, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, path=xb3, contains="%d errors in empty disjunction:", args=[3]), + suberr=(code=cycle, path=xb3, contains="unresolved disjunction: %v", args=[xb1],), + suberr=(code=cycle, path=xb3, contains="cycle with field: %v", args=[xb2])) +xb2: xb3 + 2 @test(err, code=cycle, + suberr=(code=cycle, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, path=xb3, contains="cycle with field: %v", args=[xb2])) +xb3: *(6 & (xb1 - 2)) | (xb4 & 9) @test(err, code=cycle, + suberr=(code=cycle, path=xb2, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, contains="unresolved disjunction: %v", args=[xb1]), + suberr=(code=cycle, contains="cycle with field: %v", args=[xb2])) +xb4: xb2 + 2 @test(err, code=cycle, + suberr=(code=cycle, path=xb2, contains="unresolved disjunction: %v", args=[xb3]), + suberr=(code=cycle, path=xb3, contains="cycle with field: %v", args=[xb2])) + +// Another variant with more disjunctions. xc1 remains with two +// possibilities. Technically, only the first value is valid. +// However, to fully determine that, all options of the remaining +// disjunction will have to be evaluated algebraically, which is +// not done. +xc1: *(xc2 & 8) | (xc4 & 9) | (xc5 & 9) @test(eq, *8|9) +xc2: xc3 + 2 @test(eq, 8) +xc3: 6 & xc1-2 @test(eq, 6) +xc4: xc2 + 1 @test(eq, 9) +xc5: xc2 + 2 @test(eq, 10) + +// The above is resolved by setting xd1 explicitly. +xd1: *(xd2 & 8) | xd4 & 9 | xd5 & 9 @test(eq, *8|9) +xd2: xd3 + 2 @test(eq, 8) +xd3: 6 & xd1-2 @test(eq, 6) +xd4: xd2 + 1 @test(eq, 9) +xd5: xd2 + 2 @test(eq, 10) + +// The above is resolved by setting xd1 explicitly to the wrong +// value, resulting in an error. +xe1: *(xe2 & 8) | xe4 & 9 | xe5 & 9 +xe2: xe3 + 2 @test(eq, 8) +xe3: 6 & xe1-2 @test(err, code=eval, pos=[0:6, 0:10]) +xe4: xe2 + 1 @test(eq, 9) +xe5: xe2 + 2 @test(eq, 10) +xe1: 9 @test(eq, 9) + +z1: *(z2 + 1) | z3+5 @test(eq, *11|13) +z2: z3 + 2 @test(eq, 10) +z3: z1 - 3 +z3: 8 @test(eq, 8) +-- out/compile -- +--- in.cue +{ + xa1: ((〈0;xa2〉 & 8)|*(〈0;xa4〉 & 9)) + xa2: (〈0;xa3〉 + 2) + xa3: (6 & (〈0;xa1〉 - 2)) + xa4: (〈0;xa2〉 + 2) + xb1: (*(〈0;xb2〉 & 8)|(〈0;xb4〉 & 9)) + xb2: (〈0;xb3〉 + 2) + xb3: (*(6 & (〈0;xb1〉 - 2))|(〈0;xb4〉 & 9)) + xb4: (〈0;xb2〉 + 2) + xc1: (*(〈0;xc2〉 & 8)|(〈0;xc4〉 & 9)|(〈0;xc5〉 & 9)) + xc2: (〈0;xc3〉 + 2) + xc3: (6 & (〈0;xc1〉 - 2)) + xc4: (〈0;xc2〉 + 1) + xc5: (〈0;xc2〉 + 2) + xd1: (*(〈0;xd2〉 & 8)|(〈0;xd4〉 & 9)|(〈0;xd5〉 & 9)) + xd2: (〈0;xd3〉 + 2) + xd3: (6 & (〈0;xd1〉 - 2)) + xd4: (〈0;xd2〉 + 1) + xd5: (〈0;xd2〉 + 2) + xe1: (*(〈0;xe2〉 & 8)|(〈0;xe4〉 & 9)|(〈0;xe5〉 & 9)) + xe2: (〈0;xe3〉 + 2) + xe3: (6 & (〈0;xe1〉 - 2)) + xe4: (〈0;xe2〉 + 1) + xe5: (〈0;xe2〉 + 2) + xe1: 9 + z1: (*(〈0;z2〉 + 1)|(〈0;z3〉 + 5)) + z2: (〈0;z3〉 + 2) + z3: (〈0;z1〉 - 3) + z3: 8 +} diff --git a/internal/core/compile/testdata/sync/cycle/builtins.txtar b/internal/core/compile/testdata/sync/cycle/builtins.txtar new file mode 100644 index 000000000..c8d945c21 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/builtins.txtar @@ -0,0 +1,776 @@ +# Tests that evaluating a value through a builtin (regexp.FindNamedSubmatch) +# and then back into a value does not cause incorrect cycle detection. +-- in.cue -- +import "regexp" + +// Issue #655 +// When evaluating a value into a struct, and then back into a value, the +// evaluation mode flips from Partial to AllConjunctsDone to Back. This is +// typically not an issue, but if a referred field is within a struct generated +// by a builtin, effectively the entire struct needs to be evaluated and special +// care should be taking to not evaluate too early. +builtinCyclePerm: { + @test(permute, count=6) + X: "mod.test" + + Y: { + #components: regexp.FindNamedSubmatch(#"^(?P[[:alnum:].]+)$"#, X) + host: #components.host + } + + X: Y.host + + @test(eq, { + X: "mod.test" + Y: { + #components: {host: "mod.test"} + host: "mod.test" + } + }) +} +-- matchn.cue -- +// This should not be a structural cycle, as the list type is "optional". +issue3410: { + _s + _s: { + #x: matchN(1, [_s, [..._s]]) + } + // TODO(inline): inline test outputs references in calls. This was crafted + // by hand. + @test(eq, { + _s: {#x: matchN(1, [_|_, []])} + #x: matchN(1, [_|_, []]) + }) +} +issue3420: { + matches1: { + #S: matchN(1, [_, _|_]) + s: 2 + } + @test(eq, { + matches1: {#S: matchN(1, [_, _|_]), s: 2} + }) +} +issue3443: { + matchIf: { + #S: matchIf({x?: "b"}, {n?: #S & (int | {})}, _) + } + noCycle: { + // This is not a structural cycle, and should not hang, as n? is optional. + #S: matchN(1, [{n?: #S & (int | {})}]) + + noHang: { + s: #S + s: n: n: _ + } + } + + noCycle2: { + #S: matchN(1, [{n?: (int | #S)}]) + } + + cycle1: { + // This correct CUE, as matchN allows for schema to be errors. We should + // probably have a vet rule to catch this,though. + #S: matchN(1, [{n: #S}]) + + // This is not an error as the result is structure shared. Not sure if + // this should be accepted. + ok: { + s: #S + s: _ + } + + // This unifies deep enough to cause a structural cycle. It probably + // should not. + cycle: { + s: #S + s: n: n: _ + } + } + + cycle2: { + // TODO: this should probably fail, or at least be consistent with + // cycle1.cycle. + fail: #S: matchN(1, [{n: #S}]) & {n: n: n: _} + } + @test(err, pos=[2:7]) +} +issue3633: final: { + // With nested matchNs as below, the schema will become an incomplete error + // as a value of the root vertex. Make sure this edge case is properly + // handled. + data: {} & #s @test(err, code=incomplete, pos=[1:6, 0:8, 1:13]) + #s: matchN(1, [matchN(1, [{a!: _}])]) +} +issue3842: reduced: { + #recursive: [...matchIf({ + source?: "multi" + }, #recursive, _) & { + source?: string + }] + @test(eq, {#recursive: []}) +} +-- cycle.cue -- +import "strconv" + +noCycle: t1: { + _s + _s: { + #x: matchN(1, [_s]) + #x: {} // insert concrete value to trigger application of validator. + } + @test(err, pos=[3:7, 3:14, 4:13]) +} +issue3649: noCycle: t1: { + data: #c + data: a: b: "foo" + #c: { + // There should be no cycle because of these optional fields. + b?: string + a?: matchN(1, [#c]) + } + // Cannot use @test(eq) with self-referential #c in expected value. + @test(eq, "foo", at=data.a.b) + @test(debug, """ + (struct){ + data: (#struct){ + a: (#struct){ + b: (string){ "foo" } + } + b?: (string){ string } + } + #c: (#struct){ + b?: (string){ string } + a?: (_){ matchN(1, (#list){ + 0: (_|_){// 〈2;#c〉 + } + }) } + } + } + """) +} +// Same as above, but with longer paths. +issue3649: noCycle: t2: { + x: c + x: y: a: d: b: "foo" + c: { + b?: string + y: a?: matchN(1, [{d: c}]) + } + // Cannot use @test(eq) with self-referential c in expected value. + @test(eq, {a: {d: {b: "foo"}}}, at=x.y) + @test(debug, """ + (struct){ + x: (struct){ + y: (struct){ + a: (struct){ + d: (struct){ + b: (string){ "foo" } + } + } + } + b?: (string){ string } + } + c: (struct){ + b?: (string){ string } + y: (struct){ + a?: (_){ matchN(1, (#list){ + 0: (_|_){// { + // d: 〈4;c〉 + // } + } + }) } + } + } + } + """) +} +issue3649: cycle: t1: { + data: #c + data: a: b: "foo" + #c: { + b: string + a: matchN(1, [#c]) + } + @test(err, pos=[5:6, 2:11, 5:13]) +} + +// This used to cause a stack overflow. +issue4037: cycle: { + _intlike: x=matchN(1, [strconv.Atoi(x)]) + f: "1233" & _intlike + @test(err, pos=[1:14, 1:21, 2:5]) +} +-- yamlcycle.cue -- +import "encoding/yaml" + +yamlNoCycle: { + // the validator is invoked recursively and also unifies with a concrete + // value. This should nonetheless not result in a cycle error. + #c: { + b?: string + a?: yaml.Validate(#c) + } + data: #c + data: a: #"{a: "b: foo"}"# + @test(eq, { + #c: { + b?: string + a?: yaml.Validate({ + b?: string + a?: _ + }) + } + data: {a: "{a: \"b: foo\"}", b?: string} + }) +} +selfCycle: t1: { + c: matchN(1, [{d: c}]) + c: d: {} + @test(err, pos=[1:5, 1:12, 2:5]) +} +selfCycle: t2: { + // Even though only part of the path is unified with concrete data, this + // should still result in a cycle error. + c: matchN(1, [{d: c}]) + c: {} + @test(eq, {c: {}}) +} +selfCycle: yamlVal: t1: { + x: y: yaml.Validate(x) + x: y: "{}" + @test(err, pos=[1:8, 2:8]) +} +selfCycle: yamlVal: t2: { + // Duplicating validators can cause some tricky code paths, like finalizing + // a node while still in the middle of validation. + x: y: yaml.Validate(x) + x: y: "{}" + x: y: yaml.Validate(x) + x: y: "{}" + @test(err, pos=[3:8, 4:8, 5:8, 6:8]) +} +selfCycle: yamlFun: t1:{ + x: y?: yaml.Validate("{}", x) + @test(eq, {x: {y?: true}}) +} +selfCycle: yamlFun: t2: { + z: x & __no_sharing + z: y: "{}" + x: y: yaml.Validate("{}", x) + @test(err, pos=[3:8]) +} +selfCycle: yamlValidatePartial: { + x: y: yaml.ValidatePartial(x) + x: y: "{}" + @test(err, pos=[1:8, 2:8]) +} +-- jsoncycle.cue -- +import "encoding/json" + +jsonCycle: t1: { + x: y: json.Validate(x) + x: y: "{}" + @test(err, pos=[1:8, 2:8]) +} +-- listmatchncycle.cue -- +import "list" + +listMatchN: structCycle: { + x: y: list.MatchN(1, x) + x: y: [{}] + @test(err, pos=[1:8, 1:5, 1:20, 2:5, 2:8]) +} +listMatchN: ok: { + x: y?: list.MatchN(1, x) + z: x + z: y: [{}] + // x.y? is non-concrete (list.MatchN validator); only check z.y which is concrete. + @test(eq, [{}], at=z.y) + @test(debug, """ + (struct){ + x: (struct){ + y?: (list){ list.MatchN(1, listMatchN.ok.x) } + } + z: (struct){ + y: (#list){ + 0: (struct){ + } + } + } + } + """) +} +-- issue3634.cue -- +// evalv3 structural cycle regression: using `len(...)` with a `#Schema` +// embedding inside `list.Repeat` caused a spurious structural cycle error +// that did not occur in evalv2. +// https://cuelang.org/issue/3634 +import "list" + +issue3634: full: { + #Schema: { + required?: [...string] + properties?: [string]: null | #Schema + } + + out: len([...#Schema] & list.Repeat([{ + #Schema // removing this fixes the bug! + properties: foo: required: ["bar", "baz"] + }], 3)) + + @test(eq, { + #Schema: {required?: [], properties?: {}} + out: 3 + }) +} +issue3634: reduced: { + #D: { + b?: int + a?: #D + } + out: len(#D & list.Repeat([#D & { a: b: 1 }], 1)[0]) + + @test(eq, { + #D: { + b?: int + a?: _|_ @test(err, code=structural_cycle, contains="issue3634.reduced.#D.a: structural cycle", pos=[]) + } + out: 1 + }) +} +-- issue3743.cue -- +// Passing a cyclic value to `yaml.MarshalStream` caused a stack overflow +// instead of a clean structural cycle error. +// https://cuelang.org/issue/3743 +import "encoding/yaml" + +issue3743: { + #transform: { + in: _ + out: [ + if false {out}, // note that this is a cycle + in, + ] + } + + docs: [ (#transform & {in: "x"}).out ] + out: yaml.MarshalStream(docs) + + @test(eq, { + #transform: {in: _, out: [_]} + docs: [["x"]] + out: "- x\n" + }) +} +-- out/compile -- +--- cycle.cue +{ + noCycle: { + t1: { + 〈0;_s〉 + _s: { + #x: matchN(1, [ + 〈2;_s〉, + ]) + #x: {} + } + } + } + issue3649: { + noCycle: { + t1: { + data: 〈0;#c〉 + data: { + a: { + b: "foo" + } + } + #c: { + b?: string + a?: matchN(1, [ + 〈2;#c〉, + ]) + } + } + } + } + issue3649: { + noCycle: { + t2: { + x: 〈0;c〉 + x: { + y: { + a: { + d: { + b: "foo" + } + } + } + } + c: { + b?: string + y: { + a?: matchN(1, [ + { + d: 〈4;c〉 + }, + ]) + } + } + } + } + } + issue3649: { + cycle: { + t1: { + data: 〈0;#c〉 + data: { + a: { + b: "foo" + } + } + #c: { + b: string + a: matchN(1, [ + 〈2;#c〉, + ]) + } + } + } + } + issue4037: { + cycle: { + _intlike: matchN(1, [ + 〈import;strconv〉.Atoi(〈1〉), + ]) + f: ("1233" & 〈0;_intlike〉) + } + } +} +--- in.cue +{ + builtinCyclePerm: { + X: "mod.test" + Y: { + #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) + host: 〈0;#components〉.host + } + X: 〈0;Y〉.host + } +} +--- issue3634.cue +{ + issue3634: { + full: { + #Schema: { + required?: [ + ...string, + ] + properties?: { + [string]: (null|〈2;#Schema〉) + } + } + out: len(([ + ...〈1;#Schema〉, + ] & 〈import;list〉.Repeat([ + { + 〈2;#Schema〉 + properties: { + foo: { + required: [ + "bar", + "baz", + ] + } + } + }, + ], 3))) + } + } + issue3634: { + reduced: { + #D: { + b?: int + a?: 〈1;#D〉 + } + out: len((〈0;#D〉 & 〈import;list〉.Repeat([ + (〈1;#D〉 & { + a: { + b: 1 + } + }), + ], 1)[0])) + } + } +} +--- issue3743.cue +{ + issue3743: { + #transform: { + in: _ + out: [ + if false { + 〈2;out〉 + }, + 〈1;in〉, + ] + } + docs: [ + (〈1;#transform〉 & { + in: "x" + }).out, + ] + out: 〈import;"encoding/yaml"〉.MarshalStream(〈0;docs〉) + } +} +--- jsoncycle.cue +{ + jsonCycle: { + t1: { + x: { + y: 〈import;"encoding/json"〉.Validate(〈1;x〉) + } + x: { + y: "{}" + } + } + } +} +--- listmatchncycle.cue +{ + listMatchN: { + structCycle: { + x: { + y: 〈import;list〉.MatchN(1, 〈1;x〉) + } + x: { + y: [ + {}, + ] + } + } + } + listMatchN: { + ok: { + x: { + y?: 〈import;list〉.MatchN(1, 〈1;x〉) + } + z: 〈0;x〉 + z: { + y: [ + {}, + ] + } + } + } +} +--- matchn.cue +{ + issue3410: { + 〈0;_s〉 + _s: { + #x: matchN(1, [ + 〈2;_s〉, + [ + ...〈3;_s〉, + ], + ]) + } + } + issue3420: { + matches1: { + #S: matchN(1, [ + _, + _|_(explicit error (_|_ literal) in source), + ]) + s: 2 + } + } + issue3443: { + matchIf: { + #S: 〈1;matchIf〉({ + x?: "b" + }, { + n?: (〈1;#S〉 & (int|{})) + }, _) + } + noCycle: { + #S: matchN(1, [ + { + n?: (〈2;#S〉 & (int|{})) + }, + ]) + noHang: { + s: 〈1;#S〉 + s: { + n: { + n: _ + } + } + } + } + noCycle2: { + #S: matchN(1, [ + { + n?: (int|〈2;#S〉) + }, + ]) + } + cycle1: { + #S: matchN(1, [ + { + n: 〈2;#S〉 + }, + ]) + ok: { + s: 〈1;#S〉 + s: _ + } + cycle: { + s: 〈1;#S〉 + s: { + n: { + n: _ + } + } + } + } + cycle2: { + fail: { + #S: (matchN(1, [ + { + n: 〈2;#S〉 + }, + ]) & { + n: { + n: { + n: _ + } + } + }) + } + } + } + issue3633: { + final: { + data: ({} & 〈0;#s〉) + #s: matchN(1, [ + matchN(1, [ + { + a!: _ + }, + ]), + ]) + } + } + issue3842: { + reduced: { + #recursive: [ + ...(matchIf({ + source?: "multi" + }, 〈1;#recursive〉, _) & { + source?: string + }), + ] + } + } +} +--- yamlcycle.cue +{ + yamlNoCycle: { + #c: { + b?: string + a?: 〈import;"encoding/yaml"〉.Validate(〈1;#c〉) + } + data: 〈0;#c〉 + data: { + a: "{a: \"b: foo\"}" + } + } + selfCycle: { + t1: { + c: matchN(1, [ + { + d: 〈2;c〉 + }, + ]) + c: { + d: {} + } + } + } + selfCycle: { + t2: { + c: matchN(1, [ + { + d: 〈2;c〉 + }, + ]) + c: {} + } + } + selfCycle: { + yamlVal: { + t1: { + x: { + y: 〈import;"encoding/yaml"〉.Validate(〈1;x〉) + } + x: { + y: "{}" + } + } + } + } + selfCycle: { + yamlVal: { + t2: { + x: { + y: 〈import;"encoding/yaml"〉.Validate(〈1;x〉) + } + x: { + y: "{}" + } + x: { + y: 〈import;"encoding/yaml"〉.Validate(〈1;x〉) + } + x: { + y: "{}" + } + } + } + } + selfCycle: { + yamlFun: { + t1: { + x: { + y?: 〈import;"encoding/yaml"〉.Validate("{}", 〈1;x〉) + } + } + } + } + selfCycle: { + yamlFun: { + t2: { + z: (〈0;x〉 & _|_(no sharing)) + z: { + y: "{}" + } + x: { + y: 〈import;"encoding/yaml"〉.Validate("{}", 〈1;x〉) + } + } + } + } + selfCycle: { + yamlValidatePartial: { + x: { + y: 〈import;"encoding/yaml"〉.ValidatePartial(〈1;x〉) + } + x: { + y: "{}" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/chain.txtar b/internal/core/compile/testdata/sync/cycle/chain.txtar new file mode 100644 index 000000000..b88cb62e9 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/chain.txtar @@ -0,0 +1,792 @@ +# Tests that chaining existing fields through comprehensions and builtins does +# not trigger spurious cycle detection errors. +-- in.cue -- +import "list" + +// The following just chains existing fields and should NOT trigger a cycle +// detection error. + + +chain: t1: { + #maxiter: 2 + + // Trigger lookup of a.x0 before the "regular" evaluation of a. + x: a.x0 + + a: { + for k, _ in [0, 1] { + "x\(k)": (#DepthF & {#in: a["x\(k+1)"]}).#out + } + } + + a: x2: null + + + #DepthF: { + #in: _ + #out: {} + } + @test(eq, { + #maxiter: 2 + x: {} + a: {x2: null, x0: {}, x1: {}} + #DepthF: {#in: _, #out: {}} + }) +} + +chain: t2: p1: { + X: 1 + + // Reference X through x.x0 before X is inserted. + for v in list.Concat([[0, X], []]) { + x: "x\(v)": {} + } + + x: _ + + x.x0 + @test(eq, {X: 1, x: {x0: {}, x1: {}}}) +} + +chain: t2: p2: { + // Reference X through x.x0 before X is inserted. + for v in list.Concat([[0, X], []]) { + x: "x\(v)": {} + } + + x: _ + + x.x0 + + X: 1 + @test(eq, {x: {x0: {}, x1: {}}, X: 1}) +} + +chain: t3: p1: { + X: 1 + + for v in list.Range(0, X, 1) { + x: "x\(v)": {} + } + + x: _ + + x.x0 +} + +chain: t3: p1: { + for v in list.Range(0, X, 1) { + x: "x\(v)": {} + } + + x: _ + + x.x0 + + X: 1 + @test(eq, {X: 1, x: {x0: {}}}) +} + +-- issue2052.cue -- +// Bounded recursion regression: a pattern that evaluated correctly in v0.4.3 +// began failing in v0.5.0-alpha.1 with spurious unbounded recursion errors. +// https://cuelang.org/issue/2052 +import ( + "list" + "math" +) +issue2052: reduced: t1: { + A: a: _ + Depth: { + #maxiter: 1 + if math.Abs(#maxiter) == 1 { + funcs: "\(0)": A + } + funcs: {} + funcs["0"] + } + @test(eq, { + A: {a: _} + Depth: { + #maxiter: 1 + funcs: {"0": {a: _}} + a: _ + } + }) +} +issue2052: reduced: t2: { + A: a: _ + Depth: { + maxiter: 1 + for k, v in list.Range(0, maxiter, 1) { + funcs: "\(0)": A + } + funcs: {} + funcs["0"] + } + @test(eq, { + A: {a: _} + Depth: {maxiter: 1, funcs: {"0": {a: _}}, a: _} + }) +} +issue2052: medium: t1: { + #Depth: { + #maxiter: 4 + + for k, v in list.Range(0, #maxiter, 1) { + #funcs: "\(k)": (#DepthF & {#next: #funcs["\(k+1)"]}).#func + } + + #funcs: "\(#maxiter)": null + + #funcs["0"] + } + + #DepthF: { + #next: _ + #func: { + #in: _ + #basic: string | null + out: { + if (#in & #basic) != _|_ {1} + if (#in & #basic) == _|_ { + list.Max([for k, v in #in {(#next & {#in: v}).out}]) + 1 + } + } + } + } + + tree: "bar" + + d: #Depth & {#in: tree} + + @test(eq, { + #Depth: { + #maxiter: 4 + #funcs: { + "4": null + "0": {#in: _, #basic: string | null, out: 1} + "1": {#in: _, #basic: string | null, out: 1} + "2": {#in: _, #basic: string | null, out: 1} + "3": {#in: _, #basic: string | null, out: 1} + } + #in: _ + #basic: string | null + out: 1 + } + #DepthF: { + #next: _ + #func: {#in: _, #basic: string | null, out: 1} + } + tree: "bar" + d: { + #in: "bar" + #maxiter: 4 + #funcs: { + "4": null + "0": {#in: _, #basic: string | null, out: 1} + "1": {#in: _, #basic: string | null, out: 1} + "2": {#in: _, #basic: string | null, out: 1} + "3": {#in: _, #basic: string | null, out: 1} + } + #basic: string | null + out: 1 + } + }) +} + +issue2052: medium: t2: { + #Depth: { + #maxiter: 4 + + for k, v in list.Range(0, #maxiter, 1) { + #funcs: "\(k)": (#DepthF & {#next: #funcs["\(k+1)"]}).#func + } + + #funcs:{ + for k, v in list.Range(0, #maxiter, 1) { + "\(k)": (#DepthF & {#next: #funcs["\(k+1)"]}).#func + } + } + + #funcs: "\(#maxiter)": null + + #funcs["0"] + } + + #DepthF: { + #next: _ + #func: { + #in: _ + #basic: string | null + out: { + if (#in & #basic) != _|_ {1} + if (#in & #basic) == _|_ { + list.Max([for k, v in #in {(#next & {#in: v}).out}]) + 1 + } + } + } + } + + tree: "bar" + + d: #Depth & {#in: tree} + @test(eq, { + #Depth: { + #maxiter: 4 + #funcs: { + "4": null + "0": {#in: _, #basic: string | null, out: 1} + "1": {#in: _, #basic: string | null, out: 1} + "2": {#in: _, #basic: string | null, out: 1} + "3": {#in: _, #basic: string | null, out: 1} + } + #in: _ + #basic: string | null + out: 1 + } + #DepthF: { + #next: _ + #func: {#in: _, #basic: string | null, out: 1} + } + tree: "bar" + d: { + #in: "bar" + #maxiter: 4 + #funcs: { + "4": null + "0": {#in: _, #basic: string | null, out: 1} + "1": {#in: _, #basic: string | null, out: 1} + "2": {#in: _, #basic: string | null, out: 1} + "3": {#in: _, #basic: string | null, out: 1} + } + #basic: string | null + out: 1 + } + }) +} + +issue2052: full: { + #RecurseN: { + // this is the bound on our recursion + #maxiter: uint | *4 + + // This is the function list element + // we generate this to simulate recursion + #funcFactory: { + #next: _ + #func: _ + } + + // this is our "recursion unrolling" + for k, v in list.Range(0, #maxiter, 1) { + // this is where we build up our indexed functions and the references between them + #funcs: "\(k)": (#funcFactory & {#next: #funcs["\(k+1)"]}).#func + } + + // our final value needs to be null + #funcs: "\(#maxiter)": null + + // we embed the head of the list so that the values + // we write this into can be used like other CUE "functions" + #funcs["0"] + } + + #DepthF: { + #next: _ + #func: { + #in: _ + #basic: int | number | string | bytes | null + out: { + // if we have a basic type, we are at a leaf, depth is 1 + if (#in & #basic) != _|_ {1} + + // if we are not a basic type, then we are 1 + the max of children + if (#in & #basic) == _|_ { + // this is our "recursion" for each child + let depths = [for k, v in #in {(#next & {#in: v}).out}] + list.Max(depths) + 1 + } + } + } + } + + #Depth: #RecurseN & {#maxiter: 11, #funcFactory: #DepthF} + + tree: { + a: { + foo: "bar" + a: b: c: "d" + } + cow: "moo" + } + + d: #Depth & {#in: tree} + @test(eq, { + #RecurseN: { + #maxiter: *4 | >=0 & int + #funcFactory: {#next: _, #func: _} + #funcs: { + "4": null + "0": _ + "1": _ + "2": _ + "3": _ + } + } + #DepthF: { + #next: _ + #func: { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + } + #Depth: { + #maxiter: 11 + #funcFactory: { + #next: _ + #func: { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + } + #funcs: { + "11": null + "0": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "1": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "2": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "3": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "4": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "5": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "6": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "7": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "8": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "9": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "10": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + } + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + tree: { + a: {foo: "bar", a: {b: {c: "d"}}} + cow: "moo" + } + d: { + #in: { + a: {foo: "bar", a: {b: {c: "d"}}} + cow: "moo" + } + #maxiter: 11 + #funcFactory: { + #next: _ + #func: { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + } + #funcs: { + "11": null + "0": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "1": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "2": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "3": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "4": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "5": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "6": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "7": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "8": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "9": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + "10": { + #in: _ + #basic: int | number | string | bytes | null + out: {1} + } + } + #basic: int | number | string | bytes | null + out: {5} + } + }) +} +-- out/compile -- +--- in.cue +{ + chain: { + t1: { + #maxiter: 2 + x: 〈0;a〉.x0 + a: { + for k, _ in [ + 0, + 1, + ] { + "x\(〈1;k〉)": (〈3;#DepthF〉 & { + #in: 〈4;a〉["x\((〈2;k〉 + 1))"] + }).#out + } + } + a: { + x2: null + } + #DepthF: { + #in: _ + #out: {} + } + } + } + chain: { + t2: { + p1: { + X: 1 + for _, v in 〈import;list〉.Concat([ + [ + 0, + 〈2;X〉, + ], + [], + ]) { + x: { + "x\(〈2;v〉)": {} + } + } + x: _ + 〈0;x〉.x0 + } + } + } + chain: { + t2: { + p2: { + for _, v in 〈import;list〉.Concat([ + [ + 0, + 〈2;X〉, + ], + [], + ]) { + x: { + "x\(〈2;v〉)": {} + } + } + x: _ + 〈0;x〉.x0 + X: 1 + } + } + } + chain: { + t3: { + p1: { + X: 1 + for _, v in 〈import;list〉.Range(0, 〈0;X〉, 1) { + x: { + "x\(〈2;v〉)": {} + } + } + x: _ + 〈0;x〉.x0 + } + } + } + chain: { + t3: { + p1: { + for _, v in 〈import;list〉.Range(0, 〈0;X〉, 1) { + x: { + "x\(〈2;v〉)": {} + } + } + x: _ + 〈0;x〉.x0 + X: 1 + } + } + } +} +--- issue2052.cue +{ + issue2052: { + reduced: { + t1: { + A: { + a: _ + } + Depth: { + #maxiter: 1 + if (〈import;math〉.Abs(〈0;#maxiter〉) == 1) { + funcs: { + "\(0)": 〈3;A〉 + } + } + funcs: {} + 〈0;funcs〉["0"] + } + } + } + } + issue2052: { + reduced: { + t2: { + A: { + a: _ + } + Depth: { + maxiter: 1 + for k, v in 〈import;list〉.Range(0, 〈0;maxiter〉, 1) { + funcs: { + "\(0)": 〈4;A〉 + } + } + funcs: {} + 〈0;funcs〉["0"] + } + } + } + } + issue2052: { + medium: { + t1: { + #Depth: { + #maxiter: 4 + for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { + #funcs: { + "\(〈2;k〉)": (〈4;#DepthF〉 & { + #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] + }).#func + } + } + #funcs: { + "\(〈1;#maxiter〉)": null + } + 〈0;#funcs〉["0"] + } + #DepthF: { + #next: _ + #func: { + #in: _ + #basic: (string|null) + out: { + if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { + 1 + } + if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { + (〈import;list〉.Max([ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ]) + 1) + } + } + } + } + tree: "bar" + d: (〈0;#Depth〉 & { + #in: 〈1;tree〉 + }) + } + } + } + issue2052: { + medium: { + t2: { + #Depth: { + #maxiter: 4 + for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { + #funcs: { + "\(〈2;k〉)": (〈4;#DepthF〉 & { + #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] + }).#func + } + } + #funcs: { + for k, v in 〈import;list〉.Range(0, 〈1;#maxiter〉, 1) { + "\(〈1;k〉)": (〈4;#DepthF〉 & { + #next: 〈4;#funcs〉["\((〈2;k〉 + 1))"] + }).#func + } + } + #funcs: { + "\(〈1;#maxiter〉)": null + } + 〈0;#funcs〉["0"] + } + #DepthF: { + #next: _ + #func: { + #in: _ + #basic: (string|null) + out: { + if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { + 1 + } + if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { + (〈import;list〉.Max([ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ]) + 1) + } + } + } + } + tree: "bar" + d: (〈0;#Depth〉 & { + #in: 〈1;tree〉 + }) + } + } + } + issue2052: { + full: { + #RecurseN: { + #maxiter: (&(int, >=0)|*4) + #funcFactory: { + #next: _ + #func: _ + } + for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { + #funcs: { + "\(〈2;k〉)": (〈3;#funcFactory〉 & { + #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] + }).#func + } + } + #funcs: { + "\(〈1;#maxiter〉)": null + } + 〈0;#funcs〉["0"] + } + #DepthF: { + #next: _ + #func: { + #in: _ + #basic: (int|number|string|bytes|null) + out: { + if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { + 1 + } + if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { + let depths#1 = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + (〈import;list〉.Max(〈0;let depths#1〉) + 1) + } + } + } + } + #Depth: (〈0;#RecurseN〉 & { + #maxiter: 11 + #funcFactory: 〈1;#DepthF〉 + }) + tree: { + a: { + foo: "bar" + a: { + b: { + c: "d" + } + } + } + cow: "moo" + } + d: (〈0;#Depth〉 & { + #in: 〈1;tree〉 + }) + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/compbottom.txtar b/internal/core/compile/testdata/sync/cycle/compbottom.txtar new file mode 100644 index 000000000..eddb316a6 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/compbottom.txtar @@ -0,0 +1,148 @@ +// Issues: #667, #695, #622 + +// Comparing against bottom is not officially supported by the spec. +// In practice it is used for a variety of purposes. +// +// TODO: It should really be replaced with two builtins: +// +// - exists(reference): check if a certain field exists. +// - isvalid(value): check if a certain value is valid (recursively). +// +// For now it implements something in between these two: it fails if a value +// resolves to an error, but not necessarily if it does so recursively. +// Although adding a recursive check is easy, it will break existing +// configurations, as a recursive evaluation will trigger cycles where these +// are perhaps not expected. + +// To verify these tests, each result should have a field +// +// X: "user@example.com" +// +// for the large and medium examples and +// +// X: "message: hello" +// +// for the simple example. +-- in.cue -- +import "regexp" + +simple: { + #message: #"^(message: (?P.*))?$"# + + p1: { + @test(permute, count=24) + + X: "message: hello" + #aux: { + if Y.message == _|_ { + message: "" + } + if Y.message != _|_ { + message: "message: " + Y.message + } + } + + Y: regexp.FindNamedSubmatch(#message, X) + X: #aux.message + @test(eq, { + X: "message: hello" + #aux: {message: "message: hello"} + Y: {message: "hello"} + }) + } +} + +medium: { + #userHostPort: #"^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)$"# + + p1: { + @test(permute, count=120) + + Y: { + userinfo: "user" + host: "mod.test" + } + + // X: "user@example.com" + X: #X.userinfo + #X.host + + #X: { + // userinfo: "user@" + // host: "mod.test" + + if Y.userinfo == _|_ { + userinfo: "" + } + if Y.userinfo != _|_ { + userinfo: Y.userinfo + "@" + } + + host: Y.host + } + + Y: { + // userinfo: "user" + // host: "mod.test" + + if #Y.userinfo != _|_ { + userinfo: #Y.userinfo + } + + host: #Y.host + } + + #Y: regexp.FindNamedSubmatch(#userHostPort, X) + @test(eq, { + Y: {userinfo: "user", host: "mod.test"} + X: "user@mod.test" + #X: {userinfo: "user@", host: "mod.test"} + #Y: {host: "mod.test", userinfo: "user"} + }) + } +} +-- out/compile -- +--- in.cue +{ + simple: { + #message: "^(message: (?P.*))?$" + p1: { + X: "message: hello" + #aux: { + if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { + message: "" + } + if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { + message: ("message: " + 〈2;Y〉.message) + } + } + Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) + X: 〈0;#aux〉.message + } + } + medium: { + #userHostPort: "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)$" + p1: { + Y: { + userinfo: "user" + host: "mod.test" + } + X: (〈0;#X〉.userinfo + 〈0;#X〉.host) + #X: { + if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { + userinfo: "" + } + if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { + userinfo: (〈2;Y〉.userinfo + "@") + } + host: 〈1;Y〉.host + } + Y: { + if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { + userinfo: 〈2;#Y〉.userinfo + } + host: 〈1;#Y〉.host + } + #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/compbottom2.txtar b/internal/core/compile/testdata/sync/cycle/compbottom2.txtar new file mode 100644 index 000000000..4c74c6ff1 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/compbottom2.txtar @@ -0,0 +1,813 @@ +-- in.cue -- +self: { + // This is an incomplete error, as it may succeed when the user + // explicitly specifies a value for fail.a.b. + fail: { + a: { + if a.b == _|_ { + b: 1 + } + @test(err, code=incomplete|cycle) + } + } + + // This is an incomplete error, as it may succeed when the user + // explicitly specifies a value for a.b. + isConcreteFail: t1:{ + a: { + if a.b == _|_ { + b: 1 + } + b: int + @test(eq, {b: 1}) + } + } + + isConcreteFail: t2:{ + a: { + if a.b == _|_ { + b: 1 + } + b?: int + @test(err, code=cycle, + contains="circular dependency in evaluation of conditionals: %v changed after evaluation", args=[a.b], pos=[1:7]) + } + } + + // This is an incomplete error, as it may succeed when the user + // explicitly specifies a value for a.b. + // TODO: new builtin semantics. + // if isconcrete(a.b) -->> cyclic error evaluating isconcrete. + // if isdefined(a.b) -->> evaluate to true as a.b is int, result is 1 + // if !isdefined(a.b) -->> evaluate to false, a.b remains int + isNotConcrete: t1: { + a: { + if a.b != _|_ { + b: 1 + } + b: int + @test(eq, {b: int}) + } + } + isNotConcrete: t2: { + a: { + if a.b != _|_ { + b: 1 + } + b?: int + @test(eq, {b?: int}) + } + } + +} + +-- mutual.cue -- +mutual: { + noConflicts: { + a: {if b.foo == _|_ {new: ""}} + b: {if a.bar == _|_ {new: ""}} + @test(eq, {a: {new: ""}, b: {new: ""}}) + } + + mutualCycleFail: { + b: { + if a.bar == _|_ {foo: ""} + @test(err, code=incomplete|cycle) + } + a: { + if b.foo == _|_ {bar: ""} + @test(err, code=incomplete|cycle) + } + } + + brokenCycleSuccess: { + a: { if b.foo == _|_ { foo: "" } } + b: { if a.bar == _|_ { bar: "" } } + a: bar: "" + @test(eq, {a: {foo: "", bar: ""}, b: {}}) + } + + allowOneDirectionalDependency: { + p1: { + a: { if b.foo == _|_ { bar: "" } } // added + b: { if a.bar == _|_ { new: "" } } // not added + @test(eq, {a: {bar: ""}, b: {}}) + } + p2: { + a: { if b.foo == _|_ { new: "" } } + b: { if a.bar == _|_ { foo: "" } } + @test(eq, {a: {}, b: {foo: ""}}) + } + } + + oneDirectionalBrokenConflictSuccess: { + @test(permute, count=6) + b: foo: "" + a: { if b.foo == _|_ { bar: "" } } + b: { if a.bar == _|_ { new: "" } } + @test(eq, {b: {foo: "", new: ""}, a: {}}) + } +} + +-- mutualsamestruct.cue -- +sameStruct: { + chainSuccess: a: { + raises?: {} + if raises == _|_ { + ret: a: 1 + } + ret?: {} + if ret != _|_ { + foo: a: 1 + } + @test(eq, {raises?: {}, ret: {a: 1}, foo: {a: 1}}) + } + + chainSuccess: b: { + if ret != _|_ { + foo: a: 1 + } + raises?: {} + if raises == _|_ { + ret: a: 1 + } + ret?: {} + @test(eq, {foo: {a: 1}, raises?: {}, ret: {a: 1}}) + } + + cycleFail: t1: p1: { + raises?: {} + if raises == _|_ { + ret: a: 1 + } + ret?: {} + if ret != _|_ { + raises: a: 1 + } + @test(err, code=cycle|incomplete, any, contains="circular dependency in evaluation of conditionals: %v changed after evaluation", args=[raises]) + } + + cycleFail: t1: p2: { + ret?: {} + if ret != _|_ { + raises: a: 1 + } + raises?: {} + if raises == _|_ { + ret: a: 1 + } + @test(err, code=cycle, contains="circular dependency in evaluation of conditionals: %v changed after evaluation", args=[ret], pos=[2:6]) + } + + // This test should fail with a cycle error. Even though raises and ret are + // both known to be defined, comparison against bottom requires that the + // structs be recursively checked for errors. We disallow that here, because + // the structs mutually depend on each other. + // TODO: consider allowing a specific postCheck for determining if an arc + // is erroneous. + // Pushdown improvement: raises and ret are both defined as {} (not + // optional), so their bottom checks resolve eagerly without a cycle. + // raises == _|_ is false (raises is {}), so ret: a: 1 is NOT added. + // ret != _|_ is true (ret is {}), so raises: a: 1 IS added. + // ret still has a sub-field cyclic reference error. + cycleFail: t2: p1: { + raises: {} + if raises == _|_ { + ret: a: 1 + } + ret: {} + if ret != _|_ { + raises: a: 1 + } + @test(err, any, code=cycle|incomplete) + } + + // Pushdown improvement: with this ordering, ret != _|_ fires first + // (ret is {}), so raises: a: 1 is added. But raises has a sub-field + // cyclic reference error. Result is ordering-dependent (compare p1). + cycleFail: t2: p2: { + ret: {} + if ret != _|_ { + raises: a: 1 + } + raises: {} + if raises == _|_ { + ret: a: 1 + } + @test(err, any, code=cycle|incomplete) + } + + // Pushdown improvement: raises is _ (top), raises == _|_ is false, + // so ret: a: 1 is NOT added. ret is _ (top), ret != _|_ is true, + // so raises: a: 1 IS added. ret has a sub-field cyclic reference. + // Result is ordering-dependent (compare with p2 below). + cycleFail: t3: p1: { + raises: _ + if raises == _|_ { + ret: a: 1 + } + ret: _ + if ret != _|_ { + raises: a: 1 + } + @test(err, any, code=cycle|incomplete) + } + + // Pushdown improvement: different ordering gives different result. + // Only raises has a sub-field cyclic reference error. + cycleFail: t3: p2: { + ret: _ + if ret != _|_ { + raises: a: 1 + } + raises: _ + if raises == _|_ { + ret: a: 1 + } + @test(err, any, code=cycle|incomplete) + } + + defCloseSuccess: { + #Example: { + raises?: { + runtime?: string + } + + if raises == _|_ { + ret?: _ + } + } + + expr: #Example & { + ret: 2 + } + @test(eq, { + #Example: {raises?: {runtime?: string}, ret?: _} + expr: {ret: 2, raises?: {runtime?: string}} + }) + } +} + +-- nestedchain.cue -- +// Issue +nestedChain: { + cycleFail: { + if #E.x != _|_ { + #E: y: true + } + if #E.y == _|_ { + #E: x: true + } + @test(err, code=incomplete|cycle) + #E: [_]: bool + } + + brokenCycleSuccess: { + if #E.x != _|_ { + #E: y: true + } + if #E.y == _|_ { + #E: x: true + } + #E: [_]: bool + #E: x: true + @test(eq, {#E: {y: true, x: true}}) + } + + doubleAddfail: { + if #E.x == _|_ { + #E: y: true + } + if #E.y == _|_ { + #E: x: true + } + #E: [_]: bool + @test(err, code=incomplete|cycle) + } + + trippleSuccess: { + if #E.x != _|_ { + #E: y: true + } + if #E.y != _|_ { + z: true + } + #E: x: true + @test(eq, {#E: {y: true, x: true}, z: true}) + } +} +-- issue3836.cue -- +// evalv3 regression: a conditional checking `(foo | bar) == _|_` (comparison +// to bottom) stopped working; the branch that fires when no optional field is +// set no longer triggers correctly. +// https://cuelang.org/issue/3836 +issue3836: hidden: { + _Value: { + foo?: _ + bar?: _ + if (foo | bar) == _|_ { + bar: type: "bar" + } + out: [if bar != _|_ {"bar is set"}] + } + _Value.out + // Pushdown improvement: the comprehension guard (foo|bar) == _|_ now + // correctly fires and sets bar, where previously (without pushdown) the + // guard saw a spurious non-bottom value and did not fire. + @test(eq, { + _Value: {foo?: _, bar: type: "bar", out: ["bar is set"]} + ["bar is set"] + }) +} +issue3836: exposed: { + foo?: _ + bar?: _ + if (foo | bar) == _|_ { + bar: type: "bar" + } + out: [if bar != _|_ {"bar is set"}] + @test(err, code=cycle, contains="circular dependency in evaluation of conditionals: %v changed after evaluation", args=[(foo|bar)], pos=[3:6]) +} +-- issue3838.cue -- +// evalv3 regression: `if in.opt != _|_` inside a list expression stopped +// evaluating correctly; evalv2 exported cleanly but evalv3 produced wrong output. +// https://cuelang.org/issue/3838 +issue3838: { + #T: { + subject: { + in: opt?: foo: int + out: [ + if in.opt != _|_ {in.opt.foo}, + 0, + ][0] + } + _test: { + assert: { + pass: bool + } + assert: { + notOk: _ + pass: false + } | { + invoke: _ + res: subject.out + pass: true + } + } + results: _test.assert.pass + } + (#T & { + _test: assert: invoke: "foo" + }).results + @test(eq, { + true + #T: { + subject: {in: {opt?: {foo: int}}, out: 0} + _test: { + assert: {pass: false, notOk: _} | {pass: true, invoke: _, res: 0} + } + results: _|_ @test(err, code=incomplete, contains="issue3838.#T.results: unresolved disjunction {pass:false,notOk:_} | {pass:true,invoke:_,res:0} (type struct)", pos=[26:12]) + } + }) +} +-- out/compile -- +--- in.cue +{ + self: { + fail: { + a: { + if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { + b: 1 + } + } + } + isConcreteFail: { + t1: { + a: { + if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { + b: 1 + } + b: int + } + } + } + isConcreteFail: { + t2: { + a: { + if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { + b: 1 + } + b?: int + } + } + } + isNotConcrete: { + t1: { + a: { + if (〈1;a〉.b != _|_(explicit error (_|_ literal) in source)) { + b: 1 + } + b: int + } + } + } + isNotConcrete: { + t2: { + a: { + if (〈1;a〉.b != _|_(explicit error (_|_ literal) in source)) { + b: 1 + } + b?: int + } + } + } + } +} +--- issue3836.cue +{ + issue3836: { + hidden: { + _Value: { + foo?: _ + bar?: _ + if ((〈0;foo〉|〈0;bar〉) == _|_(explicit error (_|_ literal) in source)) { + bar: { + type: "bar" + } + } + out: [ + if (〈1;bar〉 != _|_(explicit error (_|_ literal) in source)) { + "bar is set" + }, + ] + } + 〈0;_Value〉.out + } + } + issue3836: { + exposed: { + foo?: _ + bar?: _ + if ((〈0;foo〉|〈0;bar〉) == _|_(explicit error (_|_ literal) in source)) { + bar: { + type: "bar" + } + } + out: [ + if (〈1;bar〉 != _|_(explicit error (_|_ literal) in source)) { + "bar is set" + }, + ] + } + } +} +--- issue3838.cue +{ + issue3838: { + #T: { + subject: { + in: { + opt?: { + foo: int + } + } + out: [ + if (〈1;in〉.opt != _|_(explicit error (_|_ literal) in source)) { + 〈2;in〉.opt.foo + }, + 0, + ][0] + } + _test: { + assert: { + pass: bool + } + assert: ({ + notOk: _ + pass: false + }|{ + invoke: _ + res: 〈2;subject〉.out + pass: true + }) + } + results: 〈0;_test〉.assert.pass + } + (〈0;#T〉 & { + _test: { + assert: { + invoke: "foo" + } + } + }).results + } +} +--- mutual.cue +{ + mutual: { + noConflicts: { + a: { + if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { + new: "" + } + } + b: { + if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { + new: "" + } + } + } + mutualCycleFail: { + b: { + if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { + foo: "" + } + } + a: { + if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { + bar: "" + } + } + } + brokenCycleSuccess: { + a: { + if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { + foo: "" + } + } + b: { + if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { + bar: "" + } + } + a: { + bar: "" + } + } + allowOneDirectionalDependency: { + p1: { + a: { + if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { + bar: "" + } + } + b: { + if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { + new: "" + } + } + } + p2: { + a: { + if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { + new: "" + } + } + b: { + if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { + foo: "" + } + } + } + } + oneDirectionalBrokenConflictSuccess: { + b: { + foo: "" + } + a: { + if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { + bar: "" + } + } + b: { + if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { + new: "" + } + } + } + } +} +--- mutualsamestruct.cue +{ + sameStruct: { + chainSuccess: { + a: { + raises?: {} + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + ret?: {} + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + foo: { + a: 1 + } + } + } + } + chainSuccess: { + b: { + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + foo: { + a: 1 + } + } + raises?: {} + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + ret?: {} + } + } + cycleFail: { + t1: { + p1: { + raises?: {} + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + ret?: {} + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + raises: { + a: 1 + } + } + } + } + } + cycleFail: { + t1: { + p2: { + ret?: {} + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + raises: { + a: 1 + } + } + raises?: {} + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + } + } + } + cycleFail: { + t2: { + p1: { + raises: {} + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + ret: {} + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + raises: { + a: 1 + } + } + } + } + } + cycleFail: { + t2: { + p2: { + ret: {} + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + raises: { + a: 1 + } + } + raises: {} + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + } + } + } + cycleFail: { + t3: { + p1: { + raises: _ + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + ret: _ + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + raises: { + a: 1 + } + } + } + } + } + cycleFail: { + t3: { + p2: { + ret: _ + if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { + raises: { + a: 1 + } + } + raises: _ + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret: { + a: 1 + } + } + } + } + } + defCloseSuccess: { + #Example: { + raises?: { + runtime?: string + } + if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { + ret?: _ + } + } + expr: (〈0;#Example〉 & { + ret: 2 + }) + } + } +} +--- nestedchain.cue +{ + nestedChain: { + cycleFail: { + if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { + #E: { + y: true + } + } + if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { + #E: { + x: true + } + } + #E: { + [_]: bool + } + } + brokenCycleSuccess: { + if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { + #E: { + y: true + } + } + if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { + #E: { + x: true + } + } + #E: { + [_]: bool + } + #E: { + x: true + } + } + doubleAddfail: { + if (〈0;#E〉.x == _|_(explicit error (_|_ literal) in source)) { + #E: { + y: true + } + } + if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { + #E: { + x: true + } + } + #E: { + [_]: bool + } + } + trippleSuccess: { + if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { + #E: { + y: true + } + } + if (〈0;#E〉.y != _|_(explicit error (_|_ literal) in source)) { + z: true + } + #E: { + x: true + } + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/compbottomnofinal.txtar b/internal/core/compile/testdata/sync/cycle/compbottomnofinal.txtar new file mode 100644 index 000000000..05b6c7b2e --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/compbottomnofinal.txtar @@ -0,0 +1,219 @@ +// Issues: #667, #695, #622 +-- in.cue -- +import ( + "strconv" + "regexp" +) + +// In these test, it is impossible to determine the existence of some arcs due +// to mutual dependence on becoming concrete. +// +// This tests shows the essences of when an existence check cannot be resolved. +minimal: { + a: { + if b.port == _|_ { + port: "" + } + // Pushdown produces cycle error instead of incomplete. + @test(err, code=cycle|incomplete) + } + + b: { + if a.port == _|_ { + port: "" + } + // Pushdown produces cycle error instead of incomplete. + @test(err, code=cycle|incomplete) + } +} + +small: { + #userHostPort: #"^(:(?P\d+))?$"# + + p1: { + @test(permute, count=2) + #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) + + #X: { + if #Y.port == _|_ { + port: "" + } + if #Y.port != _|_ { + port: ":" + strconv.FormatInt(#Y.port, 10) + } + } + // Yield-on-running heuristic: the comp's referenced node + // #Y is not currently being processed (only scheduled), so + // the comp does not yield and instead reports a cycle error. + @test(eq, { + #Y: _|_ @test(err, code=cycle|incomplete) + #X: _|_ @test(err, code=cycle|incomplete) + }) + } +} + +medium: { + #userHostPort: #"^(:(?P\d+))?$"# + + p1: { + @test(permute, count=6) + + #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) @test(err, code=incomplete|cycle) + + // Yield-on-running heuristic: the comp's referenced node Y + // is not currently being processed, so the comp does not + // yield and instead reports a cycle error. + + Y: { + if #Y.port != _|_ { + port: strconv.Atoi(#Y.port) + } + } @test(err, code=incomplete|cycle) + + #X: { + // Can never determine whether Y.port exists as its resolution + // depends on #Y becoming finalized, which, in turn, depends on #X + // becoming finalized. + if Y.port == _|_ { + port: "" + } + if Y.port != _|_ { + port: ":" + strconv.FormatInt(Y.port, 10) + } + } @test(err, code=incomplete|cycle) + } +} + +large: { + #userHostPort: #"^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\d+))?$"# + + p1: { + @test(permute, count=120) + // Pushdown improvement: #Y, #X, and X now resolve successfully. + // Y gets a cycle error because #Y.port changed after evaluation. + // Permute disabled: pushdown introduces ordering sensitivity. + + Y: { + userinfo: "user" + host: "mod.test" + } + + X: #X.userinfo + #X.host + #X.port @test(err, any, code=incomplete|cycle) + + #X: { + if Y.userinfo == _|_ { + userinfo: "" + } + if Y.userinfo != _|_ { + userinfo: Y.userinfo + "@" + } + + host: Y.host + + if Y.port == _|_ { + port: "" + } + if Y.port != _|_ { + port: ":" + strconv.FormatInt(Y.port, 10) + } + } @test(err, any, code=incomplete|cycle) + + Y: { + if #Y.userinfo != _|_ { + userinfo: #Y.userinfo + } + + host: #Y.host + + if #Y.port != _|_ { + port: strconv.Atoi(#Y.port) + } + } @test(err, any, code=incomplete|cycle) + + #Y: regexp.FindNamedSubmatch(#userHostPort, X) @test(err, any, code=incomplete|cycle) + } +} +-- out/compile -- +--- in.cue +{ + minimal: { + a: { + if (〈1;b〉.port == _|_(explicit error (_|_ literal) in source)) { + port: "" + } + } + b: { + if (〈1;a〉.port == _|_(explicit error (_|_ literal) in source)) { + port: "" + } + } + } + small: { + #userHostPort: "^(:(?P\\d+))?$" + p1: { + #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) + #X: { + if (〈1;#Y〉.port == _|_(explicit error (_|_ literal) in source)) { + port: "" + } + if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { + port: (":" + 〈import;strconv〉.FormatInt(〈2;#Y〉.port, 10)) + } + } + } + } + medium: { + #userHostPort: "^(:(?P\\d+))?$" + p1: { + #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) + Y: { + if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { + port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) + } + } + #X: { + if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { + port: "" + } + if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { + port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) + } + } + } + } + large: { + #userHostPort: "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\\d+))?$" + p1: { + Y: { + userinfo: "user" + host: "mod.test" + } + X: ((〈0;#X〉.userinfo + 〈0;#X〉.host) + 〈0;#X〉.port) + #X: { + if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { + userinfo: "" + } + if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { + userinfo: (〈2;Y〉.userinfo + "@") + } + host: 〈1;Y〉.host + if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { + port: "" + } + if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { + port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) + } + } + Y: { + if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { + userinfo: 〈2;#Y〉.userinfo + } + host: 〈1;#Y〉.host + if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { + port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) + } + } + #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/comprehension.txtar b/internal/core/compile/testdata/sync/cycle/comprehension.txtar new file mode 100644 index 000000000..274af9980 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/comprehension.txtar @@ -0,0 +1,1511 @@ +-- in.cue -- +import ( + "list" + "strings" +) + +// Allow lookup in partially evaluated struct as long as the end result is +// concrete. +A: { + a: { + parent: "" + children: [for k, v in A if v.parent == k {k}] + } @test(eq, {parent: "", children: []}) + b: { + parent: "a" + children: [for k, v in A if v.parent == k {k}] + } @test(eq, {parent: "a", children: []}) +} + +// This should result in an incomplete error (a reference cycle error classifies +// as incomplete). +B: { + a: { + parent: "" + children: [for k, v in B for _, w in v.children {k}] + } @test(eq, { + parent: "" + children: _|_ @test(err, code=incomplete, contains="B.a.children: cannot range over v.children (incomplete type list)", pos=[24:40]) + }) +} + +// Issue #486: stack overflow in v0.3.0 when evaluating parametric fields with +// conditional comprehensions; the same code worked correctly in v0.2.0. +// https://cuelang.org/issue/486 +Issue486: { + A: { + a: { + parent: "" + children: [...string] + } + b: { + parent: "a" + children: [...string] + } + c: { + parent: "b" + children: [...string] + } + } + + A: [Name=string]: { + children: [ + for k, v in A + if v.parent == Name { + k + }, + ] + } + @test(eq, { + A: { + a: {parent: "", children: ["b"]} + b: {parent: "a", children: ["c"]} + c: {parent: "b", children: []} + } + }) +} + +// Issue #1666: evaluator hangs indefinitely when combining disjunctions with +// for comprehensions iterating over mapped fields. +// https://cuelang.org/issue/1666 +issue1666: { + #E: { + f1: [string]: #E | [...#E] + f2: [string]: t: #E + } + + _e: #E + _e: f2: a: _ + + e: _e & { + f1: { + for fk, s in _e.f2 { + (fk): s.t + } + } + } + @test(eq, { + #E: {f1: {}, f2: {}} + _e: {f2: {a: {t: {f1: {}, f2: {}}}}, f1: {}} + e: { + f1: {a: {f1: {}, f2: {}}} + f2: {a: {t: {f1: {}, f2: {}}}} + } + }) +} + +// Issue #779: for comprehension incorrectly rejected valid bidirectional +// projection patterns, reporting a cycle error even when no true cycle exists. +// Should be allowed as long as the set of fields is not modified as a result +// of a comprehension. +// https://cuelang.org/issue/779 +issue779: { + X: Y.message + STATE: { + for k, v in Y { + if k != "message" { + "\(k)": v + } + } + } + Y: STATE & { message: X } + X: "test" + STATE: { code: 101 } + @test(eq, { + X: "test" + STATE: {code: 101} + Y: {message: "test", code: 101} + }) +} + +// Issue #1934: regression in v0.4.1 where nested comprehensions referencing +// fields within the same struct were incorrectly reported as cycles. +// Comprehension ends up inserting in the same arcs over which it +// is iterating. This is fine as long as the set is not altered. +// https://cuelang.org/issue/1934 +selfReferential: T1: { + S: d: "bar" + + T: e: S: a: "foo" + + for s, v in S for t, _ in T { + T: (t): S: (s): v + } + @test(eq, { + S: {d: "bar"} + T: {e: {S: {a: "foo", d: "bar"}}} + }) +} + +// selfReferential comprehension for list. +// https://cuelang.org/issue/1934 +selfReferential: list: { + panels: [ + for i, _ in panels { + id: i + } + ] + panels: [{}, {}, {}] + @test(eq, {panels: [{id: 0}, {id: 1}, {id: 2}]}) +} + +selfReferential: insertionError: { + A: { + foo: 1 + for x in A { + // May not insert foo3. Use dynamic references to force the + // comprehension to be evaluated in the struct in which it is + // defined. + ("foo3"): 1 + } + @test(err, code=eval, contains="adding field foo3 not allowed as field set was already referenced", pos=[6:14]) + } +} + +// A comprehension should not recursively evaluated arcs, so that a +// structural cycle can be avoided when unnecessary. +selfReferential: acrossOr: t1: p1: { + o: #Output & { retry: reject: "ok" } + + #AllOutputs: { + reject: string + resource: string + retry: #Output + } + + #Output: or([for name, config in #AllOutputs { + (name): config + }]) + @test(eq, { + o: {retry: {reject: "ok"}} + #AllOutputs: { + reject: string + resource: string + retry: {reject: string} | {resource: string} + } + #Output: {reject: string} | {resource: string} + }) +} + +selfReferential: acrossOr: t1: p2: { + #Output: or([for name, config in #AllOutputs { + (name): config + }]) + + o: #Output & { retry: reject: "ok" } + + #AllOutputs: { + reject: string + resource: string + retry: #Output + } + @test(eq, { + #Output: {reject: string} | {resource: string} + o: {retry: {reject: "ok"}} + #AllOutputs: { + reject: string + resource: string + retry: {reject: string} | {resource: string} + } + }) +} + +selfReferential: acrossOr: t1: p3: { + #Output: or([for name, config in #AllOutputs { + (name): config + }]) + + #AllOutputs: { + reject: string + resource: string + retry: #Output + } + + o: #Output & { retry: reject: "ok" } + @test(eq, { + #Output: {reject: string} | {resource: string} + #AllOutputs: { + reject: string + resource: string + retry: {reject: string} | {resource: string} + } + o: {retry: {reject: "ok"}} + }) +} + +selfReferential: acrossOr: t2: p1: { + d: or([for x, y in #A { y }]) + o: d & { b: 2 } + #A: { + d1: int + d2: string + d3: b: d + } + @test(eq, { + d: int | string + o: {b: 2} + #A: { + d1: int + d2: string + d3: {b: int | string} + } + }) +} + +selfReferential: acrossOr: t2: p2: { + o: d & { b: 2 } + d: or([for x, y in #A { y }]) + #A: { + d1: int + d2: string + d3: b: d + } + @test(eq, { + o: {b: 2} + d: int | string + #A: { + d1: int + d2: string + d3: {b: int | string} + } + }) +} + +selfReferential: acrossOr: t2: p3: { + o: d & { b: 2 } + #A: { + d1: int + d2: string + d3: b: d + } + d: or([for x, y in #A { y }]) + @test(eq, { + o: {b: 2} + #A: { + d1: int + d2: string + d3: {b: int | string} + } + d: int | string + }) +} + +// Issue #1881: evaluator required the source of a for comprehension to be +// fully evaluated before iterating, causing false structural cycle errors. +// https://cuelang.org/issue/1881 +issue1881: p1: { + o: #Output & { retry: output: reject: "ok" } + + #AllOutputs: { + reject: string + resource: string + retry: output: #Output + } + + #Output: or([for name, config in #AllOutputs { + (name): config + }]) + @test(eq, { + o: {retry: {output: {reject: "ok"}}} + #AllOutputs: { + reject: string + resource: string + retry: { + output: {reject: string} | {resource: string} + } + } + #Output: {reject: string} | {resource: string} + }) +} + +issue1881: p2: { + #AllOutputs: { + reject: string + resource: string + retry: output: #Output + } + + o: #Output & { retry: output: reject: "ok" } + + #Output: or([for name, config in #AllOutputs { + (name): config + }]) + @test(eq, { + #AllOutputs: { + reject: string + resource: string + retry: { + output: {reject: string} | {resource: string} + } + } + o: {retry: {output: {reject: "ok"}}} + #Output: {reject: string} | {resource: string} + }) +} + +issue1881: p3: { + #AllOutputs: { + reject: string + resource: string + retry: output: #Output + } + + #Output: or([for name, config in #AllOutputs { + (name): config + }]) + + o: #Output & { retry: output: reject: "ok" } + @test(eq, { + #AllOutputs: { + reject: string + resource: string + retry: { + output: {reject: string} | {resource: string} + } + } + #Output: {reject: string} | {resource: string} + o: {retry: {output: {reject: "ok"}}} + }) +} + +siblingInsertion: t1: p1: { + D: "logging": _ + deployment: _ + + for k, v in deployment + for k1, v2 in v.env2 { + deployment: (k): env: (k1): v2 + } + + for id, v in D { + deployment: (id): env2: ENV: "True" + } + @test(eq, { + D: {logging: _} + deployment: { + logging: { + env2: {ENV: "True"} + env: {ENV: "True"} + } + } + }) +} + +siblingInsertion: t1: p2: { + D: "logging": _ + deployment: _ + + for id, v in D { + deployment: (id): env2: ENV: "True" + } + + for k, v in deployment + for k1, v2 in v.env2 { + deployment: (k): env: (k1): v2 + } + @test(eq, { + D: {logging: _} + deployment: { + logging: { + env2: {ENV: "True"} + env: {ENV: "True"} + } + } + }) +} + +siblingInsertion: t2: p1: { + D: "logging": _ + deployment: _ + + for k, v in deployment { + for k1, v2 in v.env2 { + deployment: (k): env: (k1): v2 + } + } + + for id, v in D { + deployment: (id): env2: ENV: "True" + } + @test(eq, { + D: {logging: _} + deployment: { + logging: { + env2: {ENV: "True"} + env: {ENV: "True"} + } + } + }) +} + +siblingInsertion: t2: p2: { + D: "logging": _ + deployment: _ + + for k, v in deployment { + for k1, v2 in v.env2 { + deployment: (k): env: (k1): v2 + } + } + + for id, v in D { + deployment: (id): env2: ENV: "True" + } + @test(eq, { + D: {logging: _} + deployment: { + logging: { + env2: {ENV: "True"} + env: {ENV: "True"} + } + } + }) +} + +// Issue #1407: cue export produced a misleading, location-free "cycle error" +// for incomplete values; the actual problem was an incomplete value, not a +// true cycle. Ensure there is a useful error message. +// https://cuelang.org/issue/1407 +selfReferential: fail: { + a: {} + b: a.x != "" + if b { + } + @test(err, code=incomplete, contains="undefined field: x", pos=[2:7]) +} + +// Issue #2367: stack overflow triggered by a comprehension that inserts into +// the same field it iterates over; the evaluator recurses infinitely instead +// of returning an error. +// https://cuelang.org/issue/2367 +issue2367: { + a: _ + for x in [a] {a: x} + @test(eq, {a: _}) +} + +// Issue #2310: evalv2 incorrectly reported a structural cycle when a +// comprehension contained three or more identical substitutions, despite the +// same pattern working with two substitutions. +// https://cuelang.org/issue/2310 +issue2310: original: { + #s: {#_1: string, #_2: string, #_3: string, strings.Replace(#_1, #_2, #_3, -1)} + + #sub: { + #a: string + + // We can't use X=[#a, ...] yet because that is still disallowed + _#X: [#a, for i in list.Range(0, len(#subs), 1) {#subs[i] & {#_1: _#X[i], _}}] + + // Embedding would not be necessary if the X=[] form was allowed + _#X[len(_#X)-1] + } + + res: #sub & {#a: "aaa", _} + + // subs is a series of string substitutions we want to apply + #subs: [ + #s & {#_2: "a", #_3: "b", _}, + #s & {#_2: "c", #_3: "d", _}, + #s & {#_2: "e", #_3: "f", _}, + ] + @test(eq, { + #s: { + _|_ + #_1: string + #_2: string + #_3: string + } + #sub: { + _|_ + #a: string + _#X: [string, + {_|_, #_1: string, #_2: "a", #_3: "b"}, + { + _|_ + #_1: {_|_, #_1: string, #_2: "a", #_3: "b"} + #_2: "c" + #_3: "d" + }, + { + _|_ + #_1: { + _|_ + #_1: {_|_, #_1: string, #_2: "a", #_3: "b"} + #_2: "c" + #_3: "d" + } + #_2: "e" + #_3: "f" + }] + #_1: { + _|_ + #_1: {_|_, #_1: string, #_2: "a", #_3: "b"} + #_2: "c" + #_3: "d" + } + #_2: "e" + #_3: "f" + } + res: { + "bbb" + #a: "aaa" + _#X: ["aaa", + {"bbb", #_1: "aaa", #_2: "a", #_3: "b"}, + { + "bbb" + #_1: {"bbb", #_1: "aaa", #_2: "a", #_3: "b"} + #_2: "c" + #_3: "d" + }, + { + "bbb" + #_1: { + "bbb" + #_1: {"bbb", #_1: "aaa", #_2: "a", #_3: "b"} + #_2: "c" + #_3: "d" + } + #_2: "e" + #_3: "f" + }] + #_1: { + "bbb" + #_1: {"bbb", #_1: "aaa", #_2: "a", #_3: "b"} + #_2: "c" + #_3: "d" + } + #_2: "e" + #_3: "f" + } + #subs: [{_|_, #_2: "a", #_3: "b", #_1: string}, + {_|_, #_2: "c", #_3: "d", #_1: string}, + {_|_, #_2: "e", #_3: "f", #_1: string}] + }) +} +issue2310: reduced: { + res: { + #X[3] // Must be at least 3 to cause structural cycle. + + // expanding comprehension eliminates cycle. + #X: ["X", for i, _ in #subs {#s, #str: #X[i]}] + } + + #s: {#str: string, #str + "a"} + #subs: [0, 1, 2] + @test(eq, { + res: { + "Xaaa" + #X: ["X", + {"Xa", #str: "X"}, + {"Xaa", #str: {"Xa", #str: "X"}}, + { + "Xaaa" + #str: {"Xaa", #str: {"Xa", #str: "X"}} + }] + #str: {"Xaa", #str: {"Xa", #str: "X"}} + } + #s: {_|_, #str: string} + #subs: [0, 1, 2] + }) +} + +-- issue3903.cue -- +// evalv3 structural cycle regression: a schema with `_deps` and comprehensions +// over those deps triggered a spurious structural cycle error that exported +// successfully under evalv2. +// https://cuelang.org/issue/3903 +issue3903: reduced: { + s1: #Schema + s1: _deps: [#Schema] + #Schema: { + _deps: [...] + + objs: [ + for dep in _deps + for obj in (dep & {}).objs { + obj + } + ] + } + @test(eq, { + s1: { + _deps: [{_deps: [], objs: []}] + objs: [] + } + #Schema: {_deps: [], objs: []} + }) +} +issue3903: full: { + s1: #Schema & { + _deps: [s2] + _local: ["s1 local"] + } + s2: #Schema & { + _local: ["s2 local"] + } + + #Schema: { + _local: [...string] + _deps: [...] + + objs: [ + for obj in _local { obj }, + + for dep in _deps + for obj in (dep & {}).objs { + obj + }, + ] + } + @test(eq, { + s1: { + _deps: [{ + _local: ["s2 local"] + _deps: [] + objs: ["s2 local"] + }] + _local: ["s1 local"] + objs: ["s1 local", "s2 local"] + } + s2: { + _local: ["s2 local"] + _deps: [] + objs: ["s2 local"] + } + #Schema: {_local: [], _deps: [], objs: []} + }) +} +-- issue2405.cue -- +// A recursive disjunction type (`#Copy` with struct/list/scalar alternatives) +// was rejected as a structural cycle even though the structure is bounded and +// should evaluate successfully. +// https://cuelang.org/issue/2405 +issue2405: { + #Copy: { + param: {...} + result: { + for k, v in param { + (k): (#Copy & {param: v}).result + } + } + } | { + param: [...] + result: [ + for v in param { + (#Copy & {param: v}).result + }, + ] + } | { + param: number + result: param + } + + foo: #Copy + foo: param: a: [{b: 134}] + @test(eq, { + #Copy: {param: {}, result: {}} | {param: [], result: []} | {param: number, result: number} + foo: { + param: {a: [{b: 134}]} + result: {a: [{b: 134}]} + } + }) +} +-- issue3941.cue -- +// evalv3 regression: a comprehension iterating over a pattern-constrained field +// (`resource: [string]: [string]: #Resource`) produced a spurious "field set was +// already referenced" error that evalv2 did not emit. +// https://cuelang.org/issue/3941 +issue3941: full: { + #Metadata: name: string + #Resource: metadata: #Metadata + + out: { + _metadata: name: "foo" + resource: [string]: [string]: #Resource + + _names: [_metadata.name] + + for name in _names { + resource: level1: (name): { + metadata: _metadata + } + } + } + @test(eq, { + #Metadata: {name: string} + #Resource: {metadata: {name: string}} + out: { + _metadata: {name: "foo"} + resource: { + level1: {foo: {metadata: {name: "foo"}}} + } + _names: ["foo"] + } + }) +} +-- issue2229.cue -- +// A list comprehension whose result was unified back into the same list caused +// an endless recursion and panic rather than being caught as a structural cycle. +// https://cuelang.org/issue/2229 +issue2229: full_ok: X={ + build: bool | *true + test: bool | *true + + make: [ for k, v in X if (v & true) != _|_ { k } ] +} @test(eq, { + build: *true | bool + test: *true | bool + make: ["build", "test"] +}) +issue2229: reduced_fail: X={ + x: true + y: [ for _, v in X if v & true { _ } ] +} @test(err, code=eval, + suberr=(code=eval, contains="conflicting values", pos=[2:5, 2:24, 2:28]), + suberr=(code=eval, contains="conflicting values", pos=[2:5, 2:24, 2:28]), + suberr=(code=eval, contains="structural cycle", pos=[2:24]), +) +-- issue4100.cue -- +// Segmentation fault in `adt.(*OpContext).freeNodeContext` in v0.14.1, +// triggered by a let binding inside a conditional that feeds into a for loop. +// https://cuelang.org/issue/4100 +issue4100: { + a: { + let l = [0] + if l != _|_ { + l[:] + } + } + for _ in a {} + @test(eq, {a: [0]}) +} +-- out/compile -- +--- in.cue +{ + A: { + a: { + parent: "" + children: [ + for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { + 〈1;k〉 + }, + ] + } + b: { + parent: "a" + children: [ + for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { + 〈1;k〉 + }, + ] + } + } + B: { + a: { + parent: "" + children: [ + for k, v in 〈3;B〉 for _, w in 〈0;v〉.children { + 〈2;k〉 + }, + ] + } + } + Issue486: { + A: { + a: { + parent: "" + children: [ + ...string, + ] + } + b: { + parent: "a" + children: [ + ...string, + ] + } + c: { + parent: "b" + children: [ + ...string, + ] + } + } + A: { + [string]: { + children: [ + for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈3;-〉) { + 〈1;k〉 + }, + ] + } + } + } + issue1666: { + #E: { + f1: { + [string]: (〈2;#E〉|[ + ...〈3;#E〉, + ]) + } + f2: { + [string]: { + t: 〈3;#E〉 + } + } + } + _e: 〈0;#E〉 + _e: { + f2: { + a: _ + } + } + e: (〈0;_e〉 & { + f1: { + for fk, s in 〈2;_e〉.f2 { + 〈1;fk〉: 〈1;s〉.t + } + } + }) + } + issue779: { + X: 〈0;Y〉.message + STATE: { + for k, v in 〈1;Y〉 { + if (〈1;k〉 != "message") { + "\(〈2;k〉)": 〈2;v〉 + } + } + } + Y: (〈0;STATE〉 & { + message: 〈1;X〉 + }) + X: "test" + STATE: { + code: 101 + } + } + selfReferential: { + T1: { + S: { + d: "bar" + } + T: { + e: { + S: { + a: "foo" + } + } + } + for s, v in 〈0;S〉 for t, _ in 〈1;T〉 { + T: { + 〈2;t〉: { + S: { + 〈5;s〉: 〈5;v〉 + } + } + } + } + } + } + selfReferential: { + list: { + panels: [ + for i, _ in 〈1;panels〉 { + id: 〈1;i〉 + }, + ] + panels: [ + {}, + {}, + {}, + ] + } + } + selfReferential: { + insertionError: { + A: { + foo: 1 + for _, x in 〈1;A〉 { + "foo3": 1 + } + } + } + } + selfReferential: { + acrossOr: { + t1: { + p1: { + o: (〈0;#Output〉 & { + retry: { + reject: "ok" + } + }) + #AllOutputs: { + reject: string + resource: string + retry: 〈1;#Output〉 + } + #Output: or([ + for name, config in 〈1;#AllOutputs〉 { + 〈1;name〉: 〈1;config〉 + }, + ]) + } + } + } + } + selfReferential: { + acrossOr: { + t1: { + p2: { + #Output: or([ + for name, config in 〈1;#AllOutputs〉 { + 〈1;name〉: 〈1;config〉 + }, + ]) + o: (〈0;#Output〉 & { + retry: { + reject: "ok" + } + }) + #AllOutputs: { + reject: string + resource: string + retry: 〈1;#Output〉 + } + } + } + } + } + selfReferential: { + acrossOr: { + t1: { + p3: { + #Output: or([ + for name, config in 〈1;#AllOutputs〉 { + 〈1;name〉: 〈1;config〉 + }, + ]) + #AllOutputs: { + reject: string + resource: string + retry: 〈1;#Output〉 + } + o: (〈0;#Output〉 & { + retry: { + reject: "ok" + } + }) + } + } + } + } + selfReferential: { + acrossOr: { + t2: { + p1: { + d: or([ + for x, y in 〈1;#A〉 { + 〈1;y〉 + }, + ]) + o: (〈0;d〉 & { + b: 2 + }) + #A: { + d1: int + d2: string + d3: { + b: 〈2;d〉 + } + } + } + } + } + } + selfReferential: { + acrossOr: { + t2: { + p2: { + o: (〈0;d〉 & { + b: 2 + }) + d: or([ + for x, y in 〈1;#A〉 { + 〈1;y〉 + }, + ]) + #A: { + d1: int + d2: string + d3: { + b: 〈2;d〉 + } + } + } + } + } + } + selfReferential: { + acrossOr: { + t2: { + p3: { + o: (〈0;d〉 & { + b: 2 + }) + #A: { + d1: int + d2: string + d3: { + b: 〈2;d〉 + } + } + d: or([ + for x, y in 〈1;#A〉 { + 〈1;y〉 + }, + ]) + } + } + } + } + issue1881: { + p1: { + o: (〈0;#Output〉 & { + retry: { + output: { + reject: "ok" + } + } + }) + #AllOutputs: { + reject: string + resource: string + retry: { + output: 〈2;#Output〉 + } + } + #Output: or([ + for name, config in 〈1;#AllOutputs〉 { + 〈1;name〉: 〈1;config〉 + }, + ]) + } + } + issue1881: { + p2: { + #AllOutputs: { + reject: string + resource: string + retry: { + output: 〈2;#Output〉 + } + } + o: (〈0;#Output〉 & { + retry: { + output: { + reject: "ok" + } + } + }) + #Output: or([ + for name, config in 〈1;#AllOutputs〉 { + 〈1;name〉: 〈1;config〉 + }, + ]) + } + } + issue1881: { + p3: { + #AllOutputs: { + reject: string + resource: string + retry: { + output: 〈2;#Output〉 + } + } + #Output: or([ + for name, config in 〈1;#AllOutputs〉 { + 〈1;name〉: 〈1;config〉 + }, + ]) + o: (〈0;#Output〉 & { + retry: { + output: { + reject: "ok" + } + } + }) + } + } + siblingInsertion: { + t1: { + p1: { + D: { + logging: _ + } + deployment: _ + for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { + deployment: { + 〈3;k〉: { + env: { + 〈4;k1〉: 〈4;v2〉 + } + } + } + } + for id, v in 〈0;D〉 { + deployment: { + 〈2;id〉: { + env2: { + ENV: "True" + } + } + } + } + } + } + } + siblingInsertion: { + t1: { + p2: { + D: { + logging: _ + } + deployment: _ + for id, v in 〈0;D〉 { + deployment: { + 〈2;id〉: { + env2: { + ENV: "True" + } + } + } + } + for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { + deployment: { + 〈3;k〉: { + env: { + 〈4;k1〉: 〈4;v2〉 + } + } + } + } + } + } + } + siblingInsertion: { + t2: { + p1: { + D: { + logging: _ + } + deployment: _ + for k, v in 〈0;deployment〉 { + for k1, v2 in 〈1;v〉.env2 { + deployment: { + 〈4;k〉: { + env: { + 〈4;k1〉: 〈4;v2〉 + } + } + } + } + } + for id, v in 〈0;D〉 { + deployment: { + 〈2;id〉: { + env2: { + ENV: "True" + } + } + } + } + } + } + } + siblingInsertion: { + t2: { + p2: { + D: { + logging: _ + } + deployment: _ + for k, v in 〈0;deployment〉 { + for k1, v2 in 〈1;v〉.env2 { + deployment: { + 〈4;k〉: { + env: { + 〈4;k1〉: 〈4;v2〉 + } + } + } + } + } + for id, v in 〈0;D〉 { + deployment: { + 〈2;id〉: { + env2: { + ENV: "True" + } + } + } + } + } + } + } + selfReferential: { + fail: { + a: {} + b: (〈0;a〉.x != "") + if 〈0;b〉 {} + } + } + issue2367: { + a: _ + for _, x in [ + 〈1;a〉, + ] { + a: 〈1;x〉 + } + } + issue2310: { + original: { + #s: { + #_1: string + #_2: string + #_3: string + 〈import;strings〉.Replace(〈0;#_1〉, 〈0;#_2〉, 〈0;#_3〉, -1) + } + #sub: { + #a: string + _#X: [ + 〈1;#a〉, + for _, i in 〈import;list〉.Range(0, len(〈2;#subs〉), 1) { + (〈4;#subs〉[〈1;i〉] & { + #_1: 〈4;_#X〉[〈2;i〉] + _ + }) + }, + ] + 〈0;_#X〉[(len(〈0;_#X〉) - 1)] + } + res: (〈0;#sub〉 & { + #a: "aaa" + _ + }) + #subs: [ + (〈1;#s〉 & { + #_2: "a" + #_3: "b" + _ + }), + (〈1;#s〉 & { + #_2: "c" + #_3: "d" + _ + }), + (〈1;#s〉 & { + #_2: "e" + #_3: "f" + _ + }), + ] + } + } + issue2310: { + reduced: { + res: { + 〈0;#X〉[3] + #X: [ + "X", + for i, _ in 〈2;#subs〉 { + 〈4;#s〉 + #str: 〈3;#X〉[〈1;i〉] + }, + ] + } + #s: { + #str: string + (〈0;#str〉 + "a") + } + #subs: [ + 0, + 1, + 2, + ] + } + } +} +--- issue2229.cue +{ + issue2229: { + full_ok: { + build: (bool|*true) + test: (bool|*true) + make: [ + for k, v in 〈2〉 if ((〈0;v〉 & true) != _|_(explicit error (_|_ literal) in source)) { + 〈1;k〉 + }, + ] + } + } + issue2229: { + reduced_fail: { + x: true + y: [ + for _, v in 〈2〉 if (〈0;v〉 & true) { + _ + }, + ] + } + } +} +--- issue2405.cue +{ + issue2405: { + #Copy: ({ + param: { + ... + } + result: { + for k, v in 〈1;param〉 { + 〈1;k〉: (〈4;#Copy〉 & { + param: 〈2;v〉 + }).result + } + } + }|{ + param: [ + ..., + ] + result: [ + for _, v in 〈1;param〉 { + (〈4;#Copy〉 & { + param: 〈2;v〉 + }).result + }, + ] + }|{ + param: number + result: 〈0;param〉 + }) + foo: 〈0;#Copy〉 + foo: { + param: { + a: [ + { + b: 134 + }, + ] + } + } + } +} +--- issue3903.cue +{ + issue3903: { + reduced: { + s1: 〈0;#Schema〉 + s1: { + _deps: [ + 〈2;#Schema〉, + ] + } + #Schema: { + _deps: [ + ..., + ] + objs: [ + for _, dep in 〈1;_deps〉 for _, obj in (〈0;dep〉 & {}).objs { + 〈1;obj〉 + }, + ] + } + } + } + issue3903: { + full: { + s1: (〈0;#Schema〉 & { + _deps: [ + 〈2;s2〉, + ] + _local: [ + "s1 local", + ] + }) + s2: (〈0;#Schema〉 & { + _local: [ + "s2 local", + ] + }) + #Schema: { + _local: [ + ...string, + ] + _deps: [ + ..., + ] + objs: [ + for _, obj in 〈1;_local〉 { + 〈1;obj〉 + }, + for _, dep in 〈1;_deps〉 for _, obj in (〈0;dep〉 & {}).objs { + 〈1;obj〉 + }, + ] + } + } + } +} +--- issue3941.cue +{ + issue3941: { + full: { + #Metadata: { + name: string + } + #Resource: { + metadata: 〈1;#Metadata〉 + } + out: { + _metadata: { + name: "foo" + } + resource: { + [string]: { + [string]: 〈3;#Resource〉 + } + } + _names: [ + 〈1;_metadata〉.name, + ] + for _, name in 〈0;_names〉 { + resource: { + level1: { + 〈3;name〉: { + metadata: 〈5;_metadata〉 + } + } + } + } + } + } + } +} +--- issue4100.cue +{ + issue4100: { + a: { + let l#1 = [ + 0, + ] + if (〈0;let l#1〉 != _|_(explicit error (_|_ literal) in source)) { + 〈1;let l#1〉[:] + } + } + for _, _ in 〈0;a〉 {} + } +} diff --git a/internal/core/compile/testdata/sync/cycle/constraints.txtar b/internal/core/compile/testdata/sync/cycle/constraints.txtar new file mode 100644 index 000000000..eacb13aa3 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/constraints.txtar @@ -0,0 +1,673 @@ +# Tests various cycle patterns involving constraint propagation through pattern +# constraints, self-triggering cycles, and mutually triggering cycles. +-- in.cue -- +// Not a cycle: the structure in x (c) only triggers one further +// instantiation of y, but not enough to trigger another round. +safeCycle: simple2: { + y: [string]: b: c: y + x: y + x: c: y + @test(eq, { + y: {} + x: {c: {b: {c: {}, b: {c: {}}}}} + }) +} + +// Not a cycle: the structure in x (c) only triggers one further +// instantiation of y, but not enough to trigger another round. +safeCycle: long1: { + y: [string]: b: y + x: y + x: c: b: e: b: c: _ + @test(eq, { + y: {} + x: {c: {b: {e: {b: {c: {b: {}}}}}}} + }) +} + +// Not a cycle: the structure in x (c) only triggers one further +// instantiation of y, but not enough to trigger another round. +safeCycle: long2: { + a: [string]: b: a + x: a + x: c: b: c: b: c: {} + @test(eq, { + a: {} + x: {c: {b: {c: {b: {c: {b: {}}}}}}} + }) +} + +// noCyclePattern is similar to the above cases, but involving more patterns +// and various lengths. +noCyclePattern: _ + +noCyclePattern: t1: { + #D: [string]: #D + a: {} + [string]: #D + [string]: b: c: {} + @test(eq, {#D: {}, a: {b: {c: {}}}}) +} + +noCyclePattern: t2: { + #D: [string]: x: #D + a: {} + [string]: #D + [string]: b: x: c: {} + @test(eq, {#D: {}, a: {b: {x: {c: {x: {}}}}}}) +} + +noCyclePattern: t3: { + _D: [string]: _T + _T: x: _D + [string]: _D + [string]: b: x: c: {} + a: {} + @test(eq, { + _D: {} + _T: {x: {}} + a: {b: {x: {c: {x: {}}}}} + }) +} + +noCyclePattern: t4: { + _D: [string]: x: _T + _T: y: _D + [string]: _D + [string]: b: x: {} + a: {} + @test(eq, { + _D: {} + _T: {y: {}} + a: {b: {x: {y: {}}}} + }) +} + +noCyclePattern: t5: { + _D: [string]: x: _T + _T: y: _D + [string]: _D + [string]: b: x: y: c: x: {} + a: {} + @test(eq, { + _D: {} + _T: {y: {}} + a: {b: {x: {y: {c: {x: {y: {}}}}}}} + }) +} + +// This example also has an embedding, in which case it should still behave +// the same. +noCyclePattern: t6: { + #D: [string]: #E + + #E: t: #T + + #T: { + { object: #S } + } + + #S: y: #D + [string]: x: #D + [string]: x: r: t: object: y: foo: t: object: { + } + bar: {} + @test(eq, { + #D: {} + #E: {t: {object: {y: {}}}} + #T: {object: {y: {}}} + #S: {y: {}} + bar: { + x: { + r: { + t: { + object: {y: {foo: {t: {object: {y: {}}}}}} + } + } + } + } + }) +} + +// Cycle: x cyclic. The pattern constraint should not be seen as +// "adding new structure", thereby permitting the cycle. +noCancelSelfInvoke: t1: { + y: [string]: b: y + x: y + x: c: x @test(err, at=b.b, code=structural_cycle) @test(err, at=c, code=structural_cycle) + @test(err, code=structural_cycle) +} + + +// Even though these cycles cross pattern boundaries, they are still structural +// cycles as the reference includes a field that triggers the pattern. +selfTriggerCycle: _ + +// TODO: This does not show an explicit cycle within `a`, only a "child" cycle. +// However, upon investigation this error is present in the tree. Either way, +// the error only needs to be reported once, so this is not a huge problem. +selfTriggerCycle: t1: { + a: #T @test(shareID=T) + #T: { + [string]: #T + b: {} @test(err, at=b, code=structural_cycle) + } @test(shareID=T) +} + +selfTriggerCycle: t2: { + #T: [string]: X={ + a: X + } + b: #T + b: c: {} @test(err, at=a, code=structural_cycle) +} + +selfTriggerCycle: long1: { + // The long string of nested fields will initially exempt the structural + // cycle, but they will eventually run out, causing the cycle to be + // triggered. + a: [string]: b: a // -> record conjunct from pattern per field. + a: c: b: c: b: c: {} // -> track if any of the fields is not a cycle. + @test(err, at=a.c.b.c.b.c.b, code=structural_cycle) +} + +// TODO: see comment at selfTriggerCycle.t1 +selfTriggerCycle: issue1503: { + a: #T & { + a: one: link: a: two: {} + } + #T: { + a: [string]: link: #T + a: b: {} + } + @test(err, at=#T.a.b.link, code=structural_cycle) + @test(err, at=a.a.b.link, code=structural_cycle) + @test(err, at=a.a.one.link.a.b.link, code=structural_cycle) + @test(err, at=a.a.one.link.a.two.link, code=structural_cycle) +} + +mutuallyTriggeringCycle: t1: { + // Even though y itself, as well as each of the x fields are not cyclic, + // the combination of the two x conjuncts are, as the b fields of y will + // trigger the pattern constraints in an interleaved fashion. + y: [string]: b: y + x: y + x: c: y + @test(err, at=x.c.b.b.b.b.b, code=structural_cycle) +} +-- ring.cue -- +brokenRing: t1: { + // NOTE that two permutations here have different results. That is less + // of an issue than it seems, as the structural cycle is hidden behind + // an optional path, which we generally allow. + // TODO: it would be nicer, though, if the representation were consistent. + p1: { + D: a?: T + T: b: D + @test(err, code=structural_cycle) + // @test(debug) + } + p2: { + // TODO(eval): fix permute or eval: error messages differ based on path in the two cases. + // @test(permute, count=2) + T: b: D + D: a?: T + @test(eq, { + T: { + b: { + a?: _|_ @test(err, code=structural_cycle, contains="structural cycle", pos=[]) + } + } + D: { + a?: _|_ @test(err, code=structural_cycle, contains="structural cycle", pos=[]) + } + }) + } +} + +brokenRing: t2: p1: { + D: [string]: T + T: b: D + @test(eq, {D: {}, T: {b: {}}}) +} + +brokenRing: t2: p2: { + T: b: D + D: [string]: T + @test(eq, {T: {b: {}}, D: {}}) +} + +cyclicRing: t1: { + D: a: T + T: b: D + @test(err, at=T.b, code=structural_cycle) + @test(err, at=D.a.b, code=structural_cycle) + // TODO(inline): fix shareID here. + // @test(shareID=T, at=D.a) + // @test(shareID=T, at=T) +} +-- issue3476.cue -- +// `cue def -e '#a'` causes a stack overflow. The definition #a selects a +// field from a conjunction `(#b & {x: _}).x` where #b contains a +// self-referential pattern `#c: [string]: #c`. This combination causes the +// exporter to recurse infinitely instead of detecting the cycle. +// https://cuelang.org/issue/3476 +issue3476: { + #a: (#b & {x: _}).x + #b: { + x?: #c + #c: [string]: #c + } + @test(eq, {#a: {}, #b: {x?: {}, #c: {}}}) +} +-- issue3509.cue -- +// evalv3 causes infinite work and OOM panic where evalv2 is fast. A +// self-referential list constraint `#matrixConfig: [...#matrixConfig] | string` +// combined with indirect field access `#job: (#Workflow & {job: _}).job` causes +// the new evaluator to loop indefinitely. +// https://cuelang.org/issue/3509 +issue3509: { + out: #job.step & "foo" + + #job: (#Workflow & {job: _}).job + + #Workflow: { + job: step: string + + #matrixConfig: [...#matrixConfig] | string + matrix?: [string]: [...#matrixConfig] + } + + @test(eq, { + out: "foo" + #job: {step: string} + #Workflow: { + job: {step: string} + #matrixConfig: [] | string + matrix?: {} + } + }) +} +-- out/compile -- +--- in.cue +{ + safeCycle: { + simple2: { + y: { + [string]: { + b: { + c: 〈3;y〉 + } + } + } + x: 〈0;y〉 + x: { + c: 〈1;y〉 + } + } + } + safeCycle: { + long1: { + y: { + [string]: { + b: 〈2;y〉 + } + } + x: 〈0;y〉 + x: { + c: { + b: { + e: { + b: { + c: _ + } + } + } + } + } + } + } + safeCycle: { + long2: { + a: { + [string]: { + b: 〈2;a〉 + } + } + x: 〈0;a〉 + x: { + c: { + b: { + c: { + b: { + c: {} + } + } + } + } + } + } + } + noCyclePattern: _ + noCyclePattern: { + t1: { + #D: { + [string]: 〈1;#D〉 + } + a: {} + [string]: 〈0;#D〉 + [string]: { + b: { + c: {} + } + } + } + } + noCyclePattern: { + t2: { + #D: { + [string]: { + x: 〈2;#D〉 + } + } + a: {} + [string]: 〈0;#D〉 + [string]: { + b: { + x: { + c: {} + } + } + } + } + } + noCyclePattern: { + t3: { + _D: { + [string]: 〈1;_T〉 + } + _T: { + x: 〈1;_D〉 + } + [string]: 〈0;_D〉 + [string]: { + b: { + x: { + c: {} + } + } + } + a: {} + } + } + noCyclePattern: { + t4: { + _D: { + [string]: { + x: 〈2;_T〉 + } + } + _T: { + y: 〈1;_D〉 + } + [string]: 〈0;_D〉 + [string]: { + b: { + x: {} + } + } + a: {} + } + } + noCyclePattern: { + t5: { + _D: { + [string]: { + x: 〈2;_T〉 + } + } + _T: { + y: 〈1;_D〉 + } + [string]: 〈0;_D〉 + [string]: { + b: { + x: { + y: { + c: { + x: {} + } + } + } + } + } + a: {} + } + } + noCyclePattern: { + t6: { + #D: { + [string]: 〈1;#E〉 + } + #E: { + t: 〈1;#T〉 + } + #T: { + { + object: 〈2;#S〉 + } + } + #S: { + y: 〈1;#D〉 + } + [string]: { + x: 〈1;#D〉 + } + [string]: { + x: { + r: { + t: { + object: { + y: { + foo: { + t: { + object: {} + } + } + } + } + } + } + } + } + bar: {} + } + } + noCancelSelfInvoke: { + t1: { + y: { + [string]: { + b: 〈2;y〉 + } + } + x: 〈0;y〉 + x: { + c: 〈1;x〉 + } + } + } + selfTriggerCycle: _ + selfTriggerCycle: { + t1: { + a: 〈0;#T〉 + #T: { + [string]: 〈1;#T〉 + b: {} + } + } + } + selfTriggerCycle: { + t2: { + #T: { + [string]: { + a: 〈1〉 + } + } + b: 〈0;#T〉 + b: { + c: {} + } + } + } + selfTriggerCycle: { + long1: { + a: { + [string]: { + b: 〈2;a〉 + } + } + a: { + c: { + b: { + c: { + b: { + c: {} + } + } + } + } + } + } + } + selfTriggerCycle: { + issue1503: { + a: (〈0;#T〉 & { + a: { + one: { + link: { + a: { + two: {} + } + } + } + } + }) + #T: { + a: { + [string]: { + link: 〈3;#T〉 + } + } + a: { + b: {} + } + } + } + } + mutuallyTriggeringCycle: { + t1: { + y: { + [string]: { + b: 〈2;y〉 + } + } + x: 〈0;y〉 + x: { + c: 〈1;y〉 + } + } + } +} +--- issue3476.cue +{ + issue3476: { + #a: (〈0;#b〉 & { + x: _ + }).x + #b: { + x?: 〈0;#c〉 + #c: { + [string]: 〈1;#c〉 + } + } + } +} +--- issue3509.cue +{ + issue3509: { + out: (〈0;#job〉.step & "foo") + #job: (〈0;#Workflow〉 & { + job: _ + }).job + #Workflow: { + job: { + step: string + } + #matrixConfig: ([ + ...〈1;#matrixConfig〉, + ]|string) + matrix?: { + [string]: [ + ...〈2;#matrixConfig〉, + ] + } + } + } +} +--- ring.cue +{ + brokenRing: { + t1: { + p1: { + D: { + a?: 〈1;T〉 + } + T: { + b: 〈1;D〉 + } + } + p2: { + T: { + b: 〈1;D〉 + } + D: { + a?: 〈1;T〉 + } + } + } + } + brokenRing: { + t2: { + p1: { + D: { + [string]: 〈1;T〉 + } + T: { + b: 〈1;D〉 + } + } + } + } + brokenRing: { + t2: { + p2: { + T: { + b: 〈1;D〉 + } + D: { + [string]: 〈1;T〉 + } + } + } + } + cyclicRing: { + t1: { + D: { + a: 〈1;T〉 + } + T: { + b: 〈1;D〉 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/cycle_with_bounds.txtar b/internal/core/compile/testdata/sync/cycle/cycle_with_bounds.txtar new file mode 100644 index 000000000..8a20d4b3c --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/cycle_with_bounds.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +#Value: int + +foo: #Value +foo: !=bar +bar: #Value +bar: !=foo + +bar: 0 @test(eq, 0) +foo: 1 @test(eq, 1) +-- out/compile -- +--- in.cue +{ + #Value: int + foo: 〈0;#Value〉 + foo: !=〈0;bar〉 + bar: 〈0;#Value〉 + bar: !=〈0;foo〉 + bar: 0 + foo: 1 +} diff --git a/internal/core/compile/testdata/sync/cycle/disjunction.txtar b/internal/core/compile/testdata/sync/cycle/disjunction.txtar new file mode 100644 index 000000000..55ab5b02f --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/disjunction.txtar @@ -0,0 +1,156 @@ +-- in.cue -- +// cycle is a structural cycle +cycle: a: cycle @test(err, code=structural_cycle, pos=[]) + +// reference to outside structural cycle +r1a: cycle | int @test(eq, int) +r1b: int | cycle @test(eq, int) + +r2a: cycle | 1 @test(eq, 1) +r2b: 1 | cycle @test(eq, 1) + +r3a: cycle | null @test(eq, null) +r3b: null | cycle @test(eq, null) + +r4a: cycle | {} @test(eq, {}) +r4b: {} | cycle @test(eq, {}) + +r5a: cycle | [] @test(eq, []) +r5b: [] | cycle @test(eq, []) + +// reference to ancestor node +s1a: { + x: s1a | int + @test(eq, {x: int}) +} +s1b: { + x: int | s1b + @test(eq, {x: int}) +} + +s2a: { + x: s2a | 1 + @test(eq, {x: 1}) +} +s2b: { + x: 1 | s2b + @test(eq, {x: 1}) +} + +s3a: { + x: s3a | null + @test(eq, {x: null}) +} +s3b: { + x: null | s3b + @test(eq, {x: null}) +} + +s4a: { + x: s4a | {} + @test(eq, {x: {}}) +} +s4b: { + x: {} | s4b + @test(eq, {x: {}}) +} + +s5a: { + x: s5a | [] + @test(eq, {x: []}) +} +s5b: { + x: [] | s5b + @test(eq, {x: []}) +} + +-- issue3042.cue -- +// Array element validation not being enforced for elements nested inside +// a struct: invalid values passed validation without error. +// https://cuelang.org/issue/3042 +issue3042: { + // Recursively, any field named "name" should begin with "foo". + // The data value below should then fail. + #foo: =~"^foo" + #nesting: string | {name?: #foo, [string]: #nesting} | [...#nesting] + + data: #nesting & { + secret: { + infra: [ + {name: "bar1"} + ] + } + } + @test(err, code=eval, + suberr=(code=eval, path=data, contains="conflicting values %s and %s (mismatched types %s and %s)", args=[{secret:{infra:[{name:"bar1"}]}}, [...#nesting], struct, list], pos=[4:57, 6:8, 6:19]), + suberr=(code=eval, path=data, contains="conflicting values %s and %s (mismatched types %s and %s)", args=[{secret:{infra:[{name:"bar1"}]}}, string, struct, string], pos=[4:12, 6:8, 6:19]), + ) +} +-- out/compile -- +--- in.cue +{ + cycle: { + a: 〈1;cycle〉 + } + r1a: (〈0;cycle〉|int) + r1b: (int|〈0;cycle〉) + r2a: (〈0;cycle〉|1) + r2b: (1|〈0;cycle〉) + r3a: (〈0;cycle〉|null) + r3b: (null|〈0;cycle〉) + r4a: (〈0;cycle〉|{}) + r4b: ({}|〈0;cycle〉) + r5a: (〈0;cycle〉|[]) + r5b: ([]|〈0;cycle〉) + s1a: { + x: (〈1;s1a〉|int) + } + s1b: { + x: (int|〈1;s1b〉) + } + s2a: { + x: (〈1;s2a〉|1) + } + s2b: { + x: (1|〈1;s2b〉) + } + s3a: { + x: (〈1;s3a〉|null) + } + s3b: { + x: (null|〈1;s3b〉) + } + s4a: { + x: (〈1;s4a〉|{}) + } + s4b: { + x: ({}|〈1;s4b〉) + } + s5a: { + x: (〈1;s5a〉|[]) + } + s5b: { + x: ([]|〈1;s5b〉) + } +} +--- issue3042.cue +{ + issue3042: { + #foo: =~"^foo" + #nesting: (string|{ + name?: 〈1;#foo〉 + [string]: 〈1;#nesting〉 + }|[ + ...〈1;#nesting〉, + ]) + data: (〈0;#nesting〉 & { + secret: { + infra: [ + { + name: "bar1" + }, + ] + } + }) + } +} diff --git a/internal/core/compile/testdata/sync/cycle/evaluate.txtar b/internal/core/compile/testdata/sync/cycle/evaluate.txtar new file mode 100644 index 000000000..7abc7c3ad --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/evaluate.txtar @@ -0,0 +1,301 @@ +-- in.cue -- +// All these cases whose name end with cycle should fail with a structural +// error. These are all uncommon code paths, triggered when container types +// are evalated within a nested expression such as as an argument to a +// function call. +// +// The builtins are typically used to trigger the uncommon path. The choice of +// builtin is irrelevant, as long as they don't finalize args before processing. + +import "list" + +// This is a resolvable reference cycle, were b is equated to c. +letCycleOK: t1: { + b: c + let X = b + c: X + @test(eq, {b: _, c: _}) +} + +// The let has structural cycle, but it is only used in a way that the +// structural cycle is avoided. +letCycleOK: t2: { + a: { + b: 1 + let X = a + c: X.b + } + @test(eq, {a: {b: 1, c: 1}}) +} + +// Ensure that the cycle exemption algorithm does not bypass actual structural +// cycles. +letCycleFail: t1: { + a: { + b: 1 + let X = a + c: X + } + @test(err, code=structural_cycle, path=a.c, contains="structural cycle", pos=[]) +} + +// Cycles should also be detected in evaluation paths that descend into +// recursion at non-field boundaries. +letCycleFail: t2: { + a: { + let X = a + if X == _|_ { } + x: y: "" + } + @test(eq, {a: {x: {y: ""}}}) + // TODO(eval): not sure if it really should fail here, so this may be okay. + @test(debug, """ + (struct){ + a: (struct){ + let X#4 = (_|_){ + // [structural_cycle] letCycleFail.t2.a.X: structural cycle + } + x: (struct){ + y: (string){ "" } + } + } + } + """) +} + +listCycleOK: { + a: b + b: and([c]) + c: a + @test(eq, {a: _, b: _, c: _}) +} + +disjunctionCycle: { + a: b + b: and(1 | c) + c: a + @test(err, code=eval, path=b, + hint="This probably should be a totally different error message.", + contains="cannot use %s (type %s) as %s in argument %d to %v", + args=[1, int, list, 1, and], pos=[2:9]) +} + +forCycle: { + #A: a: #B // TODO(errors): Correct error position, or at all. + #B: or([for x in #A { b: x }]) + @test(err, code=structural_cycle, path=#B.b, contains="structural cycle", pos=[]) +} + +letCycleWithAnd: { + a: d: b + b: and([for x in a let y = x { y }]) + c: a + @test(eq, {a: {d: {}}, b: {}, c: {d: {}}}) +} + +closeCycle: { + a: b + b: close({d: c}) + c: a + @test(err, code=structural_cycle, path=c, contains="structural cycle", pos=[]) +} + +structCycle: { + a: b + b: and([{d: c}]) + c: a + @test(err, code=structural_cycle, path=c, contains="structural cycle", pos=[]) +} + +embedCycle: { + a: b + b: close({c}) + c: a + @test(eq, {a: {}, b: {}, c: {}}) +} + +listAddCycle: { + a: b + b: list.Concat([[c], [c]]) + c: a + @test(err, code=structural_cycle, path=b, contains="error in call to %s", args=[list.Concat], pos=[2:5]) +} + +listMulCycle: { + a: b + b: list.Repeat([{a: b: c}], 3) + c: a + @test(err, code=structural_cycle, path=b, contains="error in call to %s", args=[list.Repeat], pos=[2:5]) +} + +// consult the correct closeness info in the face of it being passed down +// from parent. +closeFail: { + #T: [_]: _ + #T: close({"a": string}) + x: #T + x: b: "foo" + @test(err, code=eval, path=x.b, contains="field not allowed", pos=[1:6, 4:5]) +} + +printCycle: { + a: { + X: a + if X { + } + } + @test(err, code=structural_cycle, path=a.X, contains="structural cycle", pos=[]) +} +-- self.cue -- +issue3978: { + a: self={ + if self.missing != _|_ { + } + } + @test(eq, {a: {}}) +} +-- out/compile -- +--- in.cue +{ + letCycleOK: { + t1: { + b: 〈0;c〉 + let X#1 = 〈0;b〉 + c: 〈0;let X#1〉 + } + } + letCycleOK: { + t2: { + a: { + b: 1 + let X#2 = 〈1;a〉 + c: 〈0;let X#2〉.b + } + } + } + letCycleFail: { + t1: { + a: { + b: 1 + let X#3 = 〈1;a〉 + c: 〈0;let X#3〉 + } + } + } + letCycleFail: { + t2: { + a: { + let X#4 = 〈1;a〉 + if (〈0;let X#4〉 == _|_(explicit error (_|_ literal) in source)) {} + x: { + y: "" + } + } + } + } + listCycleOK: { + a: 〈0;b〉 + b: and([ + 〈1;c〉, + ]) + c: 〈0;a〉 + } + disjunctionCycle: { + a: 〈0;b〉 + b: and((1|〈0;c〉)) + c: 〈0;a〉 + } + forCycle: { + #A: { + a: 〈1;#B〉 + } + #B: or([ + for _, x in 〈1;#A〉 { + b: 〈1;x〉 + }, + ]) + } + letCycleWithAnd: { + a: { + d: 〈1;b〉 + } + b: and([ + for _, x in 〈1;a〉 let y = 〈0;x〉 { + 〈1;y〉 + }, + ]) + c: 〈0;a〉 + } + closeCycle: { + a: 〈0;b〉 + b: close({ + d: 〈1;c〉 + }) + c: 〈0;a〉 + } + structCycle: { + a: 〈0;b〉 + b: and([ + { + d: 〈2;c〉 + }, + ]) + c: 〈0;a〉 + } + embedCycle: { + a: 〈0;b〉 + b: close({ + 〈1;c〉 + }) + c: 〈0;a〉 + } + listAddCycle: { + a: 〈0;b〉 + b: 〈import;list〉.Concat([ + [ + 〈2;c〉, + ], + [ + 〈2;c〉, + ], + ]) + c: 〈0;a〉 + } + listMulCycle: { + a: 〈0;b〉 + b: 〈import;list〉.Repeat([ + { + a: { + b: 〈3;c〉 + } + }, + ], 3) + c: 〈0;a〉 + } + closeFail: { + #T: { + [_]: _ + } + #T: close({ + a: string + }) + x: 〈0;#T〉 + x: { + b: "foo" + } + } + printCycle: { + a: { + X: 〈1;a〉 + if 〈0;X〉 {} + } + } +} +--- self.cue +{ + issue3978: { + a: { + if (〈1〉.missing != _|_(explicit error (_|_ literal) in source)) {} + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/expression.txtar b/internal/core/compile/testdata/sync/cycle/expression.txtar new file mode 100644 index 000000000..ef740832a --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/expression.txtar @@ -0,0 +1,214 @@ +-- in.cue -- +t1: a: { + a1: a0 + 2 @test(eq, 7.0) + b1: a1 - 2 @test(eq, 5.0) + a0: X @test(eq, 5.0) + X: b1 @test(eq, 5.0) + X: 5.0 +} + +t1: b: { + X: 5.0 @test(eq, 5.0) + a1: a0 + 2 @test(eq, 7.0) + b1: a1 - 2 @test(eq, 5.0) + a0: X @test(eq, 5.0) + X: b1 + @test(eq, {X: 5.0, a1: 7.0, b1: 5.0, a0: 5.0}) +} + +// TODO: did we really mean to have 3 times c? +t1: c: { + a1: a0 + 2 @test(eq, 7.0) + b1: a1 - 2 @test(eq, 5.0) + X: 5.0 @test(eq, 5.0) + a0: X @test(eq, 5.0) + X: b1 +} + +t1: c: { + b1: a1 - 2 + a1: a0 + 2 + X: 5.0 + a0: X + X: b1 +} + +t1: c: { + b1: a1 - 2 + X: 5.0 + a1: a0 + 2 + a0: X + X: b1 + @test(eq, {a1: 7.0, b1: 5.0, X: 5.0, a0: 5.0}) +} + +t1total: { + for _, v in t1 {v} + @test(eq, {a1: 7.0, b1: 5.0, a0: 5.0, X: 5.0}) +} + +// Issue #622 +// `cue export` errors on a solvable mutual cycle: `X = b1 = b0/2 = Y/2 = a1/2 = a0 = X` +// with a concrete value `X: 5.0` should resolve, but instead reports a cycle error. +// https://cuelang.org/issue/622 +// +// TODO: are these meant to be permutations? If so use @test(permute) +t2: a: { + a0: X @test(eq, 5.0) + a1: a0 * 2 @test(eq, 10.0) + Y: a1 @test(eq, 10.0) + + b0: Y @test(eq, 10.0) + b1: b0 / 2 @test(eq, 5.0) + X: b1 @test(eq, 5.0) + + X: 5.0 + @test(eq, {a0: 5.0, a1: 10.0, Y: 10.0, b0: 10.0, b1: 5.0, X: 5.0}) +} + +t2: b: { + b0: Y @test(eq, 10.0) + b1: b0 / 2 @test(eq, 5.0) + X: b1 @test(eq, 5.0) + + a0: X @test(eq, 5.0) + a1: a0 * 2 @test(eq, 10.0) + Y: a1 @test(eq, 10.0) + + X: 5.0 + @test(eq, {b0: 10.0, b1: 5.0, X: 5.0, a0: 5.0, a1: 10.0, Y: 10.0}) +} + +t2: c: { + b0: Y @test(eq, 10.0) + b1: b0 / 2 @test(eq, 5.0) + X: b1 @test(eq, 5.0) + + X: 5.0 @test(eq, 5.0) + + a0: X @test(eq, 5.0) + a1: a0 * 2 @test(eq, 10.0) + Y: a1 @test(eq, 10.0) + @test(eq, {b0: 10.0, b1: 5.0, X: 5.0, a0: 5.0, a1: 10.0, Y: 10.0}) +} + +t2: d: { + b0: Y @test(eq, 10.0) + b1: b0 / 2 @test(eq, 5.0) + X: b1 @test(eq, 5.0) + + a0: X @test(eq, 5.0) + a1: a0 * 2 @test(eq, 10.0) + Y: a1 @test(eq, 10.0) + + X: 5.0 + @test(eq, {b0: 10.0, b1: 5.0, X: 5.0, a0: 5.0, a1: 10.0, Y: 10.0}) +} + +t2total: { + for _, v in t2 {v} + @test(eq, {a0: 5.0, a1: 10.0, Y: 10.0, b0: 10.0, b1: 5.0, X: 5.0}) +} +-- out/compile -- +--- in.cue +{ + t1: { + a: { + a1: (〈0;a0〉 + 2) + b1: (〈0;a1〉 - 2) + a0: 〈0;X〉 + X: 〈0;b1〉 + X: 5.0 + } + } + t1: { + b: { + X: 5.0 + a1: (〈0;a0〉 + 2) + b1: (〈0;a1〉 - 2) + a0: 〈0;X〉 + X: 〈0;b1〉 + } + } + t1: { + c: { + a1: (〈0;a0〉 + 2) + b1: (〈0;a1〉 - 2) + X: 5.0 + a0: 〈0;X〉 + X: 〈0;b1〉 + } + } + t1: { + c: { + b1: (〈0;a1〉 - 2) + a1: (〈0;a0〉 + 2) + X: 5.0 + a0: 〈0;X〉 + X: 〈0;b1〉 + } + } + t1: { + c: { + b1: (〈0;a1〉 - 2) + X: 5.0 + a1: (〈0;a0〉 + 2) + a0: 〈0;X〉 + X: 〈0;b1〉 + } + } + t1total: { + for _, v in 〈1;t1〉 { + 〈1;v〉 + } + } + t2: { + a: { + a0: 〈0;X〉 + a1: (〈0;a0〉 * 2) + Y: 〈0;a1〉 + b0: 〈0;Y〉 + b1: (〈0;b0〉 / 2) + X: 〈0;b1〉 + X: 5.0 + } + } + t2: { + b: { + b0: 〈0;Y〉 + b1: (〈0;b0〉 / 2) + X: 〈0;b1〉 + a0: 〈0;X〉 + a1: (〈0;a0〉 * 2) + Y: 〈0;a1〉 + X: 5.0 + } + } + t2: { + c: { + b0: 〈0;Y〉 + b1: (〈0;b0〉 / 2) + X: 〈0;b1〉 + X: 5.0 + a0: 〈0;X〉 + a1: (〈0;a0〉 * 2) + Y: 〈0;a1〉 + } + } + t2: { + d: { + b0: 〈0;Y〉 + b1: (〈0;b0〉 / 2) + X: 〈0;b1〉 + a0: 〈0;X〉 + a1: (〈0;a0〉 * 2) + Y: 〈0;a1〉 + X: 5.0 + } + } + t2total: { + for _, v in 〈1;t2〉 { + 〈1;v〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/freeze.txtar b/internal/core/compile/testdata/sync/cycle/freeze.txtar new file mode 100644 index 000000000..daa9fb157 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/freeze.txtar @@ -0,0 +1,252 @@ +// This files tests that values are properly "frozen" in case of mutual +// references. Non-structural cyclic references are okay, as long a property +// that is dependended upon in the cycle is not changed after the fact, +// that is, a value may not become more specific after it is used. +-- in.cue -- +freezing: t1: ok: { + #a: x: "a" + len(#a) // 1 + @test(eq, {1, #a: {x: "a"}}) +} + +-- comprehension.cue -- +// This should be an incomplete error, as z is inserted in x, over which the +// comprehension loops. Adding a field z to x would fix this. +// This test would fail in the old evaluator, depending on ordering. +comprehension: t1: _ +comprehension: t1: ok:{ + @test(permute, count=) + + x: y: {} + // order of comprehensions matter in old evaluator. + for _ in x { + if true { x: z: a: {} } + } + if true { + if true { x: z: a: {} } + } + @test(eq, {x: {y: {}, z: {a: {}}}}) +} + +comprehension: t2: err: { + a: { + x: 1 + for k, v in a { + (k+"q"): v // This increases the set of fields in a. + } + @test(err, code=eval, contains="adding field %v not allowed as field set was already referenced", args=[xq], pos=[3:13]) + } +} + +comprehension: t3: err: { + // mutual dependencies not okay in this case, as the set of fields grows. + a: x: 1 + b: y: 1 + a: { + for k, v in b { + (k+"q"): v + } + @test(err, code=eval, + suberr=(code=eval, contains="adding field %v not allowed as field set was already referenced", args=[yq], pos=[2:13]), + suberr=(code=eval, contains="adding field %v not allowed as field set was already referenced", args=[xq], pos=[2:13])) + } + b: { + for k, v in a { + (k): v + } + @test(eq, {y: 1, x: 1}) + } +} + +comprehension: t4: ok: { + // It is okay to make x more specific as long as no fields are added. + x: y: {} + for _ in x { + if true { x: y: a: {} } + } + @test(eq, {x: {y: {a: {}}}}) +} + +comprehension: moreSpecific: ok: { + a: { + x: int + for k, v in a { + (k): 1 + } + @test(eq, {x: 1}) + } +} + +comprehension: moreSpecific: err: { + a: { + x: {y: 1} + // len(v) should free the size of x. + for k, v in a if len(v) > 0 { + (k): {z: 1} + } + @test(err, code=eval, path=x, + contains="adding field %v not allowed as field set was already referenced", args=[z], pos=[4:9]) + } +} +-- issue3178.cue -- +// evalv3 regression: exporting via the Go API produced an error that evalv2 +// did not, for a case involving chained comprehensions. +// https://cuelang.org/issue/3178 +issue3178: { + // This should pass. Reasoning: + // - second comprehension runs + // - in order to satisfy, first comprehension must run + // - first comprehension runs and completes + input: [ "Value" ] + output: {...} + for name in input { + output: "\(name)": true + } + for name, v in output { + } + @test(eq, {input: ["Value"], output: {Value: true}}) +} +-- out/compile -- +--- comprehension.cue +{ + comprehension: { + t1: _ + } + comprehension: { + t1: { + ok: { + x: { + y: {} + } + for _, _ in 〈0;x〉 { + if true { + x: { + z: { + a: {} + } + } + } + } + if true { + if true { + x: { + z: { + a: {} + } + } + } + } + } + } + } + comprehension: { + t2: { + err: { + a: { + x: 1 + for k, v in 〈1;a〉 { + (〈1;k〉 + "q"): 〈1;v〉 + } + } + } + } + } + comprehension: { + t3: { + err: { + a: { + x: 1 + } + b: { + y: 1 + } + a: { + for k, v in 〈1;b〉 { + (〈1;k〉 + "q"): 〈1;v〉 + } + } + b: { + for k, v in 〈1;a〉 { + 〈1;k〉: 〈1;v〉 + } + } + } + } + } + comprehension: { + t4: { + ok: { + x: { + y: {} + } + for _, _ in 〈0;x〉 { + if true { + x: { + y: { + a: {} + } + } + } + } + } + } + } + comprehension: { + moreSpecific: { + ok: { + a: { + x: int + for k, v in 〈1;a〉 { + 〈1;k〉: 1 + } + } + } + } + } + comprehension: { + moreSpecific: { + err: { + a: { + x: { + y: 1 + } + for k, v in 〈1;a〉 if (len(〈0;v〉) > 0) { + 〈1;k〉: { + z: 1 + } + } + } + } + } + } +} +--- in.cue +{ + freezing: { + t1: { + ok: { + #a: { + x: "a" + } + len(〈0;#a〉) + } + } + } +} +--- issue3178.cue +{ + issue3178: { + input: [ + "Value", + ] + output: { + ... + } + for _, name in 〈0;input〉 { + output: { + "\(〈2;name〉)": true + } + } + for name, v in 〈0;output〉 {} + } +} diff --git a/internal/core/compile/testdata/sync/cycle/inline.txtar b/internal/core/compile/testdata/sync/cycle/inline.txtar new file mode 100644 index 000000000..ba40b7a1b --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/inline.txtar @@ -0,0 +1,462 @@ +-- x.cue -- +// variants of fib + +inline: small: { + f: { + n: int + out: (f & {"n": n - 1}).out @test(err, code=structural_cycle, contains="structural cycle", pos=[0:9]) + } +} + +inline: medium: { + f2: (f & {n: 2}).out @test(err, code=structural_cycle, contains="structural cycle", pos=[1:24]) + fRec: {nn: int, out: (f & {n: nn}).out} + @test(err, at=fRec.out, code=structural_cycle, contains="structural cycle", pos=[6:9]) + f: { + n: int + out: (fRec & {nn: n - 1}).out @test(err, code=structural_cycle, contains="structural cycle", pos=[0:9]) + } +} + +inline: patterns: { + f: n: (f & {n: {}}).n + f: n: {} @test(err, code=structural_cycle, contains="structural cycle", pos=[-1:9]) + [string]: {n: {}} + f: [string]: {} + f: {} +} + +inline: acrossFields: fail1: { + f: { + in: number + out: in + 1 + } + k00: 0 + k10: (f & {in: k00}).out + k20: (f & {in: k10}).out + k30: (f & {in: k20}).out + + // invalid recursion is here. + k10: (f & {in: k30}).out + @test(eq, { + f: { + in: number + out: _|_ @test(err, code=incomplete, contains="inline.acrossFields.fail1.f.out: non-concrete value number in operand to +", pos=[31:8, 30:8]) + } + k00: 0 + k10: _|_ @test(err, code=incomplete, contains="in: non-concrete value number in operand to +", pos=[31:8, 30:8, 36:17]) + k20: _|_ @test(err, code=incomplete, contains="in: non-concrete value number in operand to +", pos=[31:8, 30:8, 39:17]) + k30: _|_ @test(err, code=incomplete, contains="in: non-concrete value number in operand to +", pos=[31:8, 30:8, 35:17]) + }) +} + +// Issue #2163 +inline: acrossFields: ok1: { + f: { + in: number + out: in + } + k00: 0 + k10: (f & {in: k00}).out + k20: (f & {in: k10}).out + k30: (f & {in: k20}).out + + // TODO: what is correct behavior here. + // This is borderline okay. + k10: (f & {in: k30}).out + @test(eq, { + f: {in: number, out: number} + k00: 0 + k10: 0 + k20: 0 + k30: 0 + }, hint="might be okay to fail") +} +-- inlineexpand.cue -- +inlined: { + X: { + input: a: _ + output: input.a + } + root: a: (X & {input: root}).output + @test(eq, { + X: {input: {a: _}, output: _} + root: {a: _} + }) +} +expanded1: hasCycle: { + X: { + input: a: _ + output: input.a + } + root: { + a: _a.output + _a: X & {input: root} + } + @test(err, code=structural_cycle, at=root._a.input._a.input, contains="structural cycle", pos=[]) +} +expanded2: noCycle: { + X: { + input: a: _ + output: input.a + } + root: a: _a.output + _a: X & {input: root} + @test(eq, { + X: {input: {a: _}, output: _} + root: {a: _} + _a: {input: {a: _}, output: _} + }) +} +issue3731: reduced: { + #lookup: { + input: {...} + output: [ + for _, v in input if v.show != _|_ { v }, + ] + } + + root: { + self: show: true + others: (#lookup & {input: root}).output + } + @test(eq, { + #lookup: {input: {}, output: []} + root: { + self: {show: true} + others: [{show: true}] + } + }) +} +issue3731: expanded: { + #lookup: { + input: {...} + output: [ + for _, v in input if v.show != _|_ { v }, + ] + } + + root: { + self: show: true + others: _others.output + _others: #lookup & {input: root} + } + @test(err, code=structural_cycle, at=root._others.input._others.input, contains="structural cycle", pos=[]) +} +issue3731: full: { + #Workspace: { + workspaceA?: {} + workspaceB?: {} + } + + #AccountConfig: { + workspaces: #Workspace + siblings?: [...string] + } + + #AccountConfigSub1: { + #AccountConfig + workspaces: "workspaceA": {} + } + + #AccountConfigSub2: { + #AccountConfig + workspaces: "workspaceB": {} + } + + tree: env1: { + "region1": { + "env1-r1-account-sub1": #AccountConfigSub1 + "env1-r1-account-sub2-1": #AccountConfigSub2 + } + } + + #lookupSiblings: { + envtree: {...} + out: [ + for region, v in envtree + for account, config in v + if config.workspaces."workspaceB" != _|_ { account }, + ] + } + + tree: ENVTREE=env1: [_]: [_]: #AccountConfig & { + siblings: (#lookupSiblings & {envtree: ENVTREE}).out + } + @test(eq, { + #Workspace: {workspaceA?: {}, workspaceB?: {}} + #AccountConfig: { + workspaces: {workspaceA?: {}, workspaceB?: {}} + siblings?: [] + } + #AccountConfigSub1: { + workspaces: {workspaceA: {}, workspaceB?: {}} + siblings?: [] + } + #AccountConfigSub2: { + workspaces: {workspaceB: {}, workspaceA?: {}} + siblings?: [] + } + tree: { + env1: { + region1: { + "env1-r1-account-sub1": { + siblings: ["env1-r1-account-sub2-1"] + workspaces: {workspaceA: {}, workspaceB?: {}} + } + "env1-r1-account-sub2-1": { + siblings: ["env1-r1-account-sub2-1"] + workspaces: {workspaceB: {}, workspaceA?: {}} + } + } + } + } + #lookupSiblings: {envtree: {}, out: []} + }) +} +-- out/compile -- +--- inlineexpand.cue +{ + inlined: { + X: { + input: { + a: _ + } + output: 〈0;input〉.a + } + root: { + a: (〈1;X〉 & { + input: 〈2;root〉 + }).output + } + } + expanded1: { + hasCycle: { + X: { + input: { + a: _ + } + output: 〈0;input〉.a + } + root: { + a: 〈0;_a〉.output + _a: (〈1;X〉 & { + input: 〈2;root〉 + }) + } + } + } + expanded2: { + noCycle: { + X: { + input: { + a: _ + } + output: 〈0;input〉.a + } + root: { + a: 〈1;_a〉.output + } + _a: (〈0;X〉 & { + input: 〈1;root〉 + }) + } + } + issue3731: { + reduced: { + #lookup: { + input: { + ... + } + output: [ + for _, v in 〈1;input〉 if (〈0;v〉.show != _|_(explicit error (_|_ literal) in source)) { + 〈1;v〉 + }, + ] + } + root: { + self: { + show: true + } + others: (〈1;#lookup〉 & { + input: 〈2;root〉 + }).output + } + } + } + issue3731: { + expanded: { + #lookup: { + input: { + ... + } + output: [ + for _, v in 〈1;input〉 if (〈0;v〉.show != _|_(explicit error (_|_ literal) in source)) { + 〈1;v〉 + }, + ] + } + root: { + self: { + show: true + } + others: 〈0;_others〉.output + _others: (〈1;#lookup〉 & { + input: 〈2;root〉 + }) + } + } + } + issue3731: { + full: { + #Workspace: { + workspaceA?: {} + workspaceB?: {} + } + #AccountConfig: { + workspaces: 〈1;#Workspace〉 + siblings?: [ + ...string, + ] + } + #AccountConfigSub1: { + 〈1;#AccountConfig〉 + workspaces: { + workspaceA: {} + } + } + #AccountConfigSub2: { + 〈1;#AccountConfig〉 + workspaces: { + workspaceB: {} + } + } + tree: { + env1: { + region1: { + "env1-r1-account-sub1": 〈3;#AccountConfigSub1〉 + "env1-r1-account-sub2-1": 〈3;#AccountConfigSub2〉 + } + } + } + #lookupSiblings: { + envtree: { + ... + } + out: [ + for region, v in 〈1;envtree〉 for account, config in 〈0;v〉 if (〈0;config〉.workspaces.workspaceB != _|_(explicit error (_|_ literal) in source)) { + 〈1;account〉 + }, + ] + } + tree: { + env1: { + [_]: { + [_]: (〈3;#AccountConfig〉 & { + siblings: (〈4;#lookupSiblings〉 & { + envtree: 〈4;env1〉 + }).out + }) + } + } + } + } + } +} +--- x.cue +{ + inline: { + small: { + f: { + n: int + out: (〈1;f〉 & { + n: (〈1;n〉 - 1) + }).out + } + } + } + inline: { + medium: { + f2: (〈0;f〉 & { + n: 2 + }).out + fRec: { + nn: int + out: (〈1;f〉 & { + n: 〈1;nn〉 + }).out + } + f: { + n: int + out: (〈1;fRec〉 & { + nn: (〈1;n〉 - 1) + }).out + } + } + } + inline: { + patterns: { + f: { + n: (〈1;f〉 & { + n: {} + }).n + } + f: { + n: {} + } + [string]: { + n: {} + } + f: { + [string]: {} + } + f: {} + } + } + inline: { + acrossFields: { + fail1: { + f: { + in: number + out: (〈0;in〉 + 1) + } + k00: 0 + k10: (〈0;f〉 & { + in: 〈1;k00〉 + }).out + k20: (〈0;f〉 & { + in: 〈1;k10〉 + }).out + k30: (〈0;f〉 & { + in: 〈1;k20〉 + }).out + k10: (〈0;f〉 & { + in: 〈1;k30〉 + }).out + } + } + } + inline: { + acrossFields: { + ok1: { + f: { + in: number + out: 〈0;in〉 + } + k00: 0 + k10: (〈0;f〉 & { + in: 〈1;k00〉 + }).out + k20: (〈0;f〉 & { + in: 〈1;k10〉 + }).out + k30: (〈0;f〉 & { + in: 〈1;k20〉 + }).out + k10: (〈0;f〉 & { + in: 〈1;k30〉 + }).out + } + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/inline_non_recursive.txtar b/internal/core/compile/testdata/sync/cycle/inline_non_recursive.txtar new file mode 100644 index 000000000..b681e8e67 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/inline_non_recursive.txtar @@ -0,0 +1,341 @@ +-- in.cue -- +// All these should pass. These look like recursive inlined calls, but they are +// not. + +ok1: { + f: { + in: number + out: in + } + k00: 0 + k10: (f & {in: k00}).out + k20: (f & {in: k10}).out + k30: (f & {in: k20}).out + @test(eq, { + f: {in: number, out: number} + k00: 0 + k10: 0 + k20: 0 + k30: 0 + }) +} + +ok2: { + f: { + in: number + out: in + } + k00: 0 + k10: {(f & {in: k00}).out} + k20: {(f & {in: k10}).out} + k30: {(f & {in: k20}).out} + @test(eq, { + f: {in: number, out: number} + k00: 0 + k10: 0 + k20: 0 + k30: 0 + }) +} + +ok3: { + f: { + in: number + out: in + } + k00: 0 + k10: {close((f & {in: k00})).out} + k20: {close((f & {in: k10})).out} + k30: {close((f & {in: k20})).out} + @test(eq, { + f: {in: number, out: number} + k00: 0 + k10: 0 + k20: 0 + k30: 0 + }) +} + +ok4: { + f: { + in: number + out: in + } + k00: 0 + k10: {out: {(f & {in: k00}).out}}.out + k20: {out: {(f & {in: k10}).out}}.out + k30: {out: {(f & {in: k20}).out}}.out + @test(eq, { + f: {in: number, out: number} + k00: 0 + k10: 0 + k20: 0 + k30: 0 + }) +} + +// Issue #1708: nested indirect selectors on a definition instantiated more than +// twice cause a false structural cycle. Concrete conjuncts like `{in: kN}` are +// not recognized as cycle-breakers, so successive `(#add10 & {in: k}).out` +// chains are incorrectly treated as self-recursive. +// https://cuelang.org/issue/1708 +issue1708: { + #add10: { + in: number + a10: { i: in, o: i + 10 } + out: a10.o + } + k00: 0 + k10: (#add10 & {in: k00}).out + k20: (#add10 & {in: k10}).out + k30: (#add10 & {in: k20}).out + + // TODO(inline): the generation of this value is broken, had to hand-adjust. + // TODO(inline): file positions are absolute instead of relative to the definition. + @test(eq, { + #add10: { + in: number + a10: { + i: number + o: _|_ @test(err, code=incomplete, contains="non-concrete value number in operand to +", pos=[84:20, 83:7]) + } + out: _|_ @test(err) + } + k00: 0 + k10: 10 + k20: 20 + k30: _|_ @test(err, code=incomplete, contains="undefined field: out", pos=[88:28]) + }) +} +-- issue3182.cue -- +// evalv3 regression: references under projections (e.g. `{ a: x }.a`) were +// not resolved correctly, producing errors or wrong output that evalv2 handled. +// https://cuelang.org/issue/3182 +issue3182: { + first: t1: { + x: { a: x }.a + @test(eq, {x: _}) + } + first: t2: { + x: { a: b: x }.a + @test(err, code=structural_cycle) + } + second: { + { t: x }.t.y + x: y: x: y: a: 1 + @test(eq, {x: {y: {x: {y: {a: 1}}, a: 1}}, a: 1}) + } + third: { + { + p: { + x: p + y: 1 + } + }.p.x.y + @test(eq, 1) + } +} +-- select.cue -- +// The value of #Step should be consistent between these test cases. +select: direct: { + #Step: (#Job & {opt: _}).opt + #Job: matchN(1, [#NormalJob]) + // TODO(inline): broken generation: retains reference. + @test(eq, { + #Step: _ + #Job: matchN(1, [{req!: int, opt?: {run?: string}}]) + }) +} +select: indirect: { + #Step: #Job.opt + #Job: matchN(1, [#NormalJob]) & {opt: _} + @test(eq, {#Step: _, #Job: {_|_, opt: _}}) +} +#NormalJob: { + req!: int + opt?: run?: string +} +-- out/compile -- +--- in.cue +{ + ok1: { + f: { + in: number + out: 〈0;in〉 + } + k00: 0 + k10: (〈0;f〉 & { + in: 〈1;k00〉 + }).out + k20: (〈0;f〉 & { + in: 〈1;k10〉 + }).out + k30: (〈0;f〉 & { + in: 〈1;k20〉 + }).out + } + ok2: { + f: { + in: number + out: 〈0;in〉 + } + k00: 0 + k10: { + (〈1;f〉 & { + in: 〈2;k00〉 + }).out + } + k20: { + (〈1;f〉 & { + in: 〈2;k10〉 + }).out + } + k30: { + (〈1;f〉 & { + in: 〈2;k20〉 + }).out + } + } + ok3: { + f: { + in: number + out: 〈0;in〉 + } + k00: 0 + k10: { + close((〈1;f〉 & { + in: 〈2;k00〉 + })).out + } + k20: { + close((〈1;f〉 & { + in: 〈2;k10〉 + })).out + } + k30: { + close((〈1;f〉 & { + in: 〈2;k20〉 + })).out + } + } + ok4: { + f: { + in: number + out: 〈0;in〉 + } + k00: 0 + k10: { + out: { + (〈2;f〉 & { + in: 〈3;k00〉 + }).out + } + }.out + k20: { + out: { + (〈2;f〉 & { + in: 〈3;k10〉 + }).out + } + }.out + k30: { + out: { + (〈2;f〉 & { + in: 〈3;k20〉 + }).out + } + }.out + } + issue1708: { + #add10: { + in: number + a10: { + i: 〈1;in〉 + o: (〈0;i〉 + 10) + } + out: 〈0;a10〉.o + } + k00: 0 + k10: (〈0;#add10〉 & { + in: 〈1;k00〉 + }).out + k20: (〈0;#add10〉 & { + in: 〈1;k10〉 + }).out + k30: (〈0;#add10〉 & { + in: 〈1;k20〉 + }).out + } +} +--- issue3182.cue +{ + issue3182: { + first: { + t1: { + x: { + a: 〈1;x〉 + }.a + } + } + first: { + t2: { + x: { + a: { + b: 〈2;x〉 + } + }.a + } + } + second: { + { + t: 〈1;x〉 + }.t.y + x: { + y: { + x: { + y: { + a: 1 + } + } + } + } + } + third: { + { + p: { + x: 〈1;p〉 + y: 1 + } + }.p.x.y + } + } +} +--- select.cue +{ + select: { + direct: { + #Step: (〈0;#Job〉 & { + opt: _ + }).opt + #Job: matchN(1, [ + 〈3;#NormalJob〉, + ]) + } + } + select: { + indirect: { + #Step: 〈0;#Job〉.opt + #Job: (matchN(1, [ + 〈3;#NormalJob〉, + ]) & { + opt: _ + }) + } + } + #NormalJob: { + req!: int + opt?: { + run?: string + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue1960.txtar b/internal/core/compile/testdata/sync/cycle/issue1960.txtar new file mode 100644 index 000000000..413b5f3e5 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue1960.txtar @@ -0,0 +1,174 @@ +#inlinetest:exclude t2 contains an unreferenced-alias compile-time error, preventing +# full inline conversion. +# Tests let-alias cycles and comprehension cycles in deeply nested structs; t1 +# uses a let alias referencing an enclosing comprehension variable; t3 exercises +# recursive definitions with computed-field access through a let and comprehension. +-- issue1960.cue -- +// evalv3 regression: a spurious structural cycle error was reported for a +// pattern that had previously evaluated correctly, causing valid CUE to fail. +// https://cuelang.org/issue/1960 +t1: { + z: blah: s: [for z in z {}] + z: hello: { + for x in p {} + let q = z.blah + p: q.r // Incomplete error should not cause cycle. + p: t: 1 + } +} + +t2: { + z: blah: s: [for z in z {}] + z: hello: { + for x in p {} + let q = z.blah + p: t: 1 + } +} + +t3: { + #z: { + n: string + p: t: "e" + s: [...string] + _p: { + n: string + e: p: {} + } + r: (_p )[p.t] + for _, pl in r.p { + if pl.blah { + } + } + } + + #i: { + #z + t: "i" + r: e: {} + } + + #c: { + #z + t: "c" + n: string + } + + z: [N= =~"^b"]: #i & { + s: [ + for n, z in z + if z.t == "c" + if z.n == N {n}, + ] + } + + z: [N= =~"^h"]: #c & { + n: string + // Causes a structural cycle on its own, but not when referenced below. + let q = z[n] + p: q.r.e + } + + z: { + "blah": {} + "hello": n: "blah" + } +} +-- out/compile -- +t2.z.hello: unreferenced alias or let clause q: + ./issue1960.cue:18:3 +--- issue1960.cue +{ + t1: { + z: { + blah: { + s: [ + for _, z in 〈3;z〉 {}, + ] + } + } + z: { + hello: { + for _, x in 〈0;p〉 {} + let q#1 = 〈2;z〉.blah + p: 〈0;let q#1〉.r + p: { + t: 1 + } + } + } + } + t2: { + z: { + blah: { + s: [ + for _, z in 〈3;z〉 {}, + ] + } + } + z: { + hello: { + for _, x in 〈0;p〉 {} + let q#2 = 〈2;z〉.blah + p: { + t: 1 + } + } + } + } + t3: { + #z: { + n: string + p: { + t: "e" + } + s: [ + ...string, + ] + _p: { + n: string + e: { + p: {} + } + } + r: 〈0;_p〉[〈0;p〉.t] + for _, pl in 〈0;r〉.p { + if 〈1;pl〉.blah {} + } + } + #i: { + 〈1;#z〉 + t: "i" + r: { + e: {} + } + } + #c: { + 〈1;#z〉 + t: "c" + n: string + } + z: { + [=~"^b"]: (〈1;#i〉 & { + s: [ + for n, z in 〈3;z〉 if (〈0;z〉.t == "c") if (〈0;z〉.n == 〈3;-〉) { + 〈1;n〉 + }, + ] + }) + } + z: { + [=~"^h"]: (〈1;#c〉 & { + n: string + let q#3 = 〈2;z〉[〈0;n〉] + p: 〈0;let q#3〉.r.e + }) + } + z: { + blah: {} + hello: { + n: "blah" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue241.txtar b/internal/core/compile/testdata/sync/cycle/issue241.txtar new file mode 100644 index 000000000..c0941b73c --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue241.txtar @@ -0,0 +1,64 @@ +# `!=` applied to a disjunction before structural cycle is concrete: +# CUE incorrectly reports an empty disjunction error instead of handling +# the abstract `!=` constraint between fields sharing a disjunction type. +# https://cuelang.org/issue/241 +-- in.cue -- +#Value: 0 | 1 + +foo: #Value @test(err, code=cycle|incomplete, args=[bar], pos=[-2:13, 2:6, 3:6]) +foo: !=bar +bar: #Value @test(eq, 0 | 1) +bar: !=foo @test(err:todo, code=cycle|incomplete) + +#Value: 0 | 1 + +Foo: #Value @test(eq, 1) +Foo: !=Bar +Bar: #Value @test(eq, 0) +Bar: !=Foo +Bar: 0 + +cell: a: 0 | 1 +cell: a: !=cell.b +cell: b: 0 | 1 +cell: b: !=cell.a +cell: a: 0 @test(eq, 0) +cell: b: _ @test(eq, 1) + +a: cell.a @test(eq, 0) +b: cell.b @test(eq, 1) +-- out/compile -- +--- in.cue +{ + #Value: (0|1) + foo: 〈0;#Value〉 + foo: !=〈0;bar〉 + bar: 〈0;#Value〉 + bar: !=〈0;foo〉 + #Value: (0|1) + Foo: 〈0;#Value〉 + Foo: !=〈0;Bar〉 + Bar: 〈0;#Value〉 + Bar: !=〈0;Foo〉 + Bar: 0 + cell: { + a: (0|1) + } + cell: { + a: !=〈1;cell〉.b + } + cell: { + b: (0|1) + } + cell: { + b: !=〈1;cell〉.a + } + cell: { + a: 0 + } + cell: { + b: _ + } + a: 〈0;cell〉.a + b: 〈0;cell〉.b +} diff --git a/internal/core/compile/testdata/sync/cycle/issue242.txtar b/internal/core/compile/testdata/sync/cycle/issue242.txtar new file mode 100644 index 000000000..5a79f358b --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue242.txtar @@ -0,0 +1,296 @@ +# Stack overflow when multiple `!=` constraints are applied between fields +# in a structural cycle involving a disjunction (e.g. a grid where each cell +# must differ from its neighbors). +# https://cuelang.org/issue/242 +-- in.cue -- +#size: 2 +#CellValue: 0 | 1 | 2 | 3 +cell: "0": "0": #CellValue +cell: "0": "0": !=cell["0"]["1"] +cell: "0": "0": !=cell["1"]["0"] +cell: "0": "0": !=cell["1"]["1"] + +cell: "0": "1": #CellValue +cell: "0": "1": !=cell["0"]["0"] +cell: "0": "1": !=cell["1"]["0"] +cell: "0": "1": !=cell["1"]["1"] + +cell: "1": "0": #CellValue +cell: "1": "0": !=cell["0"]["0"] +cell: "1": "0": !=cell["0"]["1"] +cell: "1": "0": !=cell["1"]["1"] + +cell: "1": "1": #CellValue +cell: "1": "1": !=cell["0"]["0"] +cell: "1": "1": !=cell["0"]["1"] +cell: "1": "1": !=cell["1"]["0"] + +cell: "0": "0": 0 +cell: "0": "1": 1 +cell: "1": "0": 2 +cell: "1": "1": 3 +@test(eq, { + "0": {"0": 0, "1": 1} + "1": {"0": 2, "1": 3} +}, at=cell) + +cell2: a: 0 | 1 +cell2: a: !=cell2.b + +cell2: b: 0 | 1 +cell2: b: !=cell2.a + +cell2: a: _ +cell2: b: 1 +@test(eq, {a: 0, b: 1}, at=cell2) + +cell3: a: 0 | 1 +cell3: a: !=cell3.b + +cell3: b: 0 | 1 +cell3: b: !=cell3.a + +cell3: a: 0 +cell3: b: _ +@test(eq, {a: 0, b: 1}, at=cell3) + +cell4: a: 0 | 1 +cell4: a: !=cell4.b + +cell4: b: 0 | 1 +cell4: b: !=cell4.a + +cell4: b: _ +cell4: a: 0 + +cell5: b: 0 | 1 +cell5: b: !=cell5.a + +cell5: a: 0 | 1 +cell5: a: !=cell5.b + +cell5: b: _ +cell5: a: 0 + +a: #CellValue +a: !=b +a: !=c +a: !=d + +b: #CellValue +b: !=a +b: !=c +b: !=d + +c: #CellValue +c: !=a +c: !=b +c: !=d + +d: #CellValue +d: !=a +d: !=b +d: !=c + +a: 0 +b: 1 +c: 2 +d: 3 +-- out/compile -- +--- in.cue +{ + #size: 2 + #CellValue: (0|1|2|3) + cell: { + "0": { + "0": 〈2;#CellValue〉 + } + } + cell: { + "0": { + "0": !=〈2;cell〉["0"]["1"] + } + } + cell: { + "0": { + "0": !=〈2;cell〉["1"]["0"] + } + } + cell: { + "0": { + "0": !=〈2;cell〉["1"]["1"] + } + } + cell: { + "0": { + "1": 〈2;#CellValue〉 + } + } + cell: { + "0": { + "1": !=〈2;cell〉["0"]["0"] + } + } + cell: { + "0": { + "1": !=〈2;cell〉["1"]["0"] + } + } + cell: { + "0": { + "1": !=〈2;cell〉["1"]["1"] + } + } + cell: { + "1": { + "0": 〈2;#CellValue〉 + } + } + cell: { + "1": { + "0": !=〈2;cell〉["0"]["0"] + } + } + cell: { + "1": { + "0": !=〈2;cell〉["0"]["1"] + } + } + cell: { + "1": { + "0": !=〈2;cell〉["1"]["1"] + } + } + cell: { + "1": { + "1": 〈2;#CellValue〉 + } + } + cell: { + "1": { + "1": !=〈2;cell〉["0"]["0"] + } + } + cell: { + "1": { + "1": !=〈2;cell〉["0"]["1"] + } + } + cell: { + "1": { + "1": !=〈2;cell〉["1"]["0"] + } + } + cell: { + "0": { + "0": 0 + } + } + cell: { + "0": { + "1": 1 + } + } + cell: { + "1": { + "0": 2 + } + } + cell: { + "1": { + "1": 3 + } + } + cell2: { + a: (0|1) + } + cell2: { + a: !=〈1;cell2〉.b + } + cell2: { + b: (0|1) + } + cell2: { + b: !=〈1;cell2〉.a + } + cell2: { + a: _ + } + cell2: { + b: 1 + } + cell3: { + a: (0|1) + } + cell3: { + a: !=〈1;cell3〉.b + } + cell3: { + b: (0|1) + } + cell3: { + b: !=〈1;cell3〉.a + } + cell3: { + a: 0 + } + cell3: { + b: _ + } + cell4: { + a: (0|1) + } + cell4: { + a: !=〈1;cell4〉.b + } + cell4: { + b: (0|1) + } + cell4: { + b: !=〈1;cell4〉.a + } + cell4: { + b: _ + } + cell4: { + a: 0 + } + cell5: { + b: (0|1) + } + cell5: { + b: !=〈1;cell5〉.a + } + cell5: { + a: (0|1) + } + cell5: { + a: !=〈1;cell5〉.b + } + cell5: { + b: _ + } + cell5: { + a: 0 + } + a: 〈0;#CellValue〉 + a: !=〈0;b〉 + a: !=〈0;c〉 + a: !=〈0;d〉 + b: 〈0;#CellValue〉 + b: !=〈0;a〉 + b: !=〈0;c〉 + b: !=〈0;d〉 + c: 〈0;#CellValue〉 + c: !=〈0;a〉 + c: !=〈0;b〉 + c: !=〈0;d〉 + d: 〈0;#CellValue〉 + d: !=〈0;a〉 + d: !=〈0;b〉 + d: !=〈0;c〉 + a: 0 + b: 1 + c: 2 + d: 3 +} diff --git a/internal/core/compile/testdata/sync/cycle/issue2526.txtar b/internal/core/compile/testdata/sync/cycle/issue2526.txtar new file mode 100644 index 000000000..a2eb4ac79 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue2526.txtar @@ -0,0 +1,19 @@ +# The evaluator enters an infinite loop when processing a cycle involving +# struct embeddings, causing `cue eval` to hang indefinitely. +# https://cuelang.org/issue/2526 +-- in.cue -- +x +x: { + y + y: x +} +@test(err, code=structural_cycle, path=x.y, contains="structural cycle", pos=[]) +-- out/compile -- +--- in.cue +{ + 〈0;x〉 + x: { + 〈0;y〉 + y: 〈1;x〉 + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue306.txtar b/internal/core/compile/testdata/sync/cycle/issue306.txtar new file mode 100644 index 000000000..edd973df9 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue306.txtar @@ -0,0 +1,18 @@ +# CUE panics/crashes instead of reporting a clean error when evaluating +# values with cyclic field dependencies. +# https://cuelang.org/issue/306 +-- in.cue -- +a: 12 @test(eq, 12) +#Controller: settings: { + controller: #Controller +} @test(err, code=structural_cycle, path=controller, contains="structural cycle", pos=[]) +-- out/compile -- +--- in.cue +{ + a: 12 + #Controller: { + settings: { + controller: 〈2;#Controller〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue3118.txtar b/internal/core/compile/testdata/sync/cycle/issue3118.txtar new file mode 100644 index 000000000..8930de850 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue3118.txtar @@ -0,0 +1,73 @@ +# Cycle errors report no source position information, making it impossible +# to locate the offending code. +# https://cuelang.org/issue/3118 +-- in.cue -- +#TimeSpan: { + start: float + duration: float + end: float + + start: end - duration + duration: end - start + end: start + duration + + start: <=end +} + +examples: [string]: #TimeSpan + +examples: eg1: { + start: 10.0 + duration: 2.1 + @test(eq, {start: 10.0, duration: 2.1, end: 12.1}) +} + +examples: eg2: { + start: 10.0 + @test(eq, { + start: _|_ @test(err, code=incomplete, pos=[6:12, 4:12, 8:12]) + duration: _|_ @test(err, code=incomplete, pos=[7:12, 4:12, 8:12]) + end: _|_ @test(err, code=incomplete, pos=[7:12, 4:12, 8:12]) +}) +} + +examples: eg3: { + end: 10.0 + @test(eq, { + end: _|_ @test(err, code=incomplete, pos=[8:12, 2:12, 6:12, 10:9]) + start: _|_ @test(err, code=incomplete, pos=[7:12, 2:12, 6:12, 10:9]) + duration: _|_ @test(err, code=incomplete, pos=[7:12, 2:12, 6:12, 10:9]) +}) +} +-- out/compile -- +--- in.cue +{ + #TimeSpan: { + start: float + duration: float + end: float + start: (〈0;end〉 - 〈0;duration〉) + duration: (〈0;end〉 - 〈0;start〉) + end: (〈0;start〉 + 〈0;duration〉) + start: <=〈0;end〉 + } + examples: { + [string]: 〈1;#TimeSpan〉 + } + examples: { + eg1: { + start: 10.0 + duration: 2.1 + } + } + examples: { + eg2: { + start: 10.0 + } + } + examples: { + eg3: { + end: 10.0 + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue3527.txtar b/internal/core/compile/testdata/sync/cycle/issue3527.txtar new file mode 100644 index 000000000..de3f5aefd --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue3527.txtar @@ -0,0 +1,73 @@ +# evalv3 panics with nil pointer dereference on a reduced real-world CUE file +# involving `let` bindings and mutual references between definitions, whereas +# evalv2 handles it correctly. +# https://cuelang.org/issue/3527 +-- in.cue -- +package p + +_taxPayer: self: {} + +let sam = {taxPayer: _taxPayer} +assert: { + invoke: sam + invoke: _ + res: subject & {in: invoke} +} + +subject: { + in: #ReturnData + _computed: (#computeF1040 & {"in": in}) +} +#computeF1040: in: #ReturnData +#ReturnData: taxPayer?: #TaxPayer +#TaxPayer: self?: _ + +@test(eq, { + _taxPayer$p: {self: {}} + assert: { + invoke: {taxPayer: {self: {}}} + res: { + in: {taxPayer: {self: {}}} + _computed$p: {in: {taxPayer: {self: {}}}} + } + } + subject: { + in: {taxPayer?: {self?: _}} + _computed$p: {in: {taxPayer?: {self?: _}}} + } + #computeF1040: {in: {taxPayer?: {self?: _}}} + #ReturnData: {taxPayer?: {self?: _}} + #TaxPayer: {self?: _} +}) +-- out/compile -- +--- in.cue +{ + _taxPayer(:p): { + self: {} + } + let sam#1 = { + taxPayer: 〈1;_taxPayer(:p)〉 + } + assert: { + invoke: 〈1;let sam#1〉 + invoke: _ + res: (〈1;subject〉 & { + in: 〈1;invoke〉 + }) + } + subject: { + in: 〈1;#ReturnData〉 + _computed(:p): (〈1;#computeF1040〉 & { + in: 〈1;in〉 + }) + } + #computeF1040: { + in: 〈1;#ReturnData〉 + } + #ReturnData: { + taxPayer?: 〈1;#TaxPayer〉 + } + #TaxPayer: { + self?: _ + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue3570.txtar b/internal/core/compile/testdata/sync/cycle/issue3570.txtar new file mode 100644 index 000000000..93dd792d7 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue3570.txtar @@ -0,0 +1,16 @@ +# evalv2 panics in `DerefValue` when processing a specific CUE input +# discovered via oss-fuzz, reproducing on both v0.9.2 and v0.10.1. +# https://cuelang.org/issue/3570 +-- in.cue -- +foo: foo: 25 | 44 +foo +foo: foo @test(eq, {foo: _}) +-- out/compile -- +--- in.cue +{ + foo: { + foo: (25|44) + } + 〈0;foo〉 + foo: 〈0;foo〉 +} diff --git a/internal/core/compile/testdata/sync/cycle/issue3571.txtar b/internal/core/compile/testdata/sync/cycle/issue3571.txtar new file mode 100644 index 000000000..8d1a55634 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue3571.txtar @@ -0,0 +1,106 @@ +# evalv3 incorrectly reports a structural cycle error for a CUE definition that +# validates correctly under evalv2, representing a regression in cycle detection. +# https://cuelang.org/issue/3571 +-- in.cue -- +// These tests should NOT have structural cycles. +simplified: { + #T + in: _ + x: #T + x: x: #T + + #T: { + in: x + x: _ + } + + @test(eq, { + in: {x: {in: _, x: _}, in: {in: _, x: _}} + x: {x: {in: _, x: _}, in: {in: _, x: _}} + #T: {in: _, x: _} + }) +} + +issue3571: { + a: #T + a: in: f: true + a: #in: { + g: #T + g: #in: f: #T + g: #in: f: #in: x: true + f?: _ + } + + #T: { + in: #in + #in: _ + } + + @test(eq, { + a: { + in: { + f: true + g: { + #in: {f: {#in: {x: true}, in: {x: true}}} + in: {f: {#in: {x: true}, in: {x: true}}} + } + } + #in: { + g: { + #in: {f: {#in: {x: true}, in: {x: true}}} + in: {f: {#in: {x: true}, in: {x: true}}} + } + f?: _ + } + } + #T: {in: _, #in: _} + }) +} +-- out/compile -- +--- in.cue +{ + simplified: { + 〈0;#T〉 + in: _ + x: 〈0;#T〉 + x: { + x: 〈1;#T〉 + } + #T: { + in: 〈0;x〉 + x: _ + } + } + issue3571: { + a: 〈0;#T〉 + a: { + in: { + f: true + } + } + a: { + #in: { + g: 〈2;#T〉 + g: { + #in: { + f: 〈4;#T〉 + } + } + g: { + #in: { + f: { + #in: { + x: true + } + } + } + } + f?: _ + } + } + #T: { + in: 〈0;#in〉 + #in: _ + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue3827.txtar b/internal/core/compile/testdata/sync/cycle/issue3827.txtar new file mode 100644 index 000000000..73dc57233 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue3827.txtar @@ -0,0 +1,77 @@ +# evalv3 incorrectly produces a "field not allowed" error when unifying against +# a definition that succeeds without error under evalv2, regressing on a +# real-world GitHub Actions schema. +# https://cuelang.org/issue/3827 +-- in.cue -- +reduced: { + A: b: (A.c & {}).x + A: null | { c: x: 1 } + @test(eq, {A: {b: 1, c: {x: 1}}}) +} + +full: { + out: #Workflow.#Step & { + uses: "actions/upload-artifact@v3" + with: { + name: "foo" + path: "bar" + } + } + + Y=#Workflow: #Step: (Y.steps & {x: {}}).x + + #Workflow: null | { + steps: [string]: { + uses?: string + with?: [string]: string + } + } + @test(eq, { + out: { + uses: "actions/upload-artifact@v3" + with: {name: "foo", path: "bar"} + } + #Workflow: { + #Step: {uses?: string, with?: {}} + steps: {} + } + }) +} +-- out/compile -- +--- in.cue +{ + reduced: { + A: { + b: (〈1;A〉.c & {}).x + } + A: (null|{ + c: { + x: 1 + } + }) + } + full: { + out: (〈0;#Workflow〉.#Step & { + uses: "actions/upload-artifact@v3" + with: { + name: "foo" + path: "bar" + } + }) + #Workflow: { + #Step: (〈1;#Workflow〉.steps & { + x: {} + }).x + } + #Workflow: (null|{ + steps: { + [string]: { + uses?: string + with?: { + [string]: string + } + } + } + }) + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue4203.txtar b/internal/core/compile/testdata/sync/cycle/issue4203.txtar new file mode 100644 index 000000000..e021688ce --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue4203.txtar @@ -0,0 +1,91 @@ +# A CUE file using comprehensions and struct embeddings that exports +# successfully in v0.13.2 fails with "undefined field" in later versions. +# https://cuelang.org/issue/4203 +-- in.cue -- +import "strings" + +// Marking comprehension fields as optional for cycle detection +// should not prevent fixed fields from being resolved. +_listBuilder: { + kind: "kind1" + _deps: [...] + _kindJoin: { + _objs: [...] + _out: strings.Join([for d in _objs {d.kind}], ",") + } + _depKinds: {_kindJoin & {_objs: _deps}}._out + variable: "{" + _depKinds + "}" +} + +output: _ +if true { + _input: [{ + _listBuilder + _deps: [{_listBuilder}] + }] + + output: _input[0].variable +} +@test(eq, { + _listBuilder: { + kind: "kind1" + _deps: [] + _kindJoin: {_objs: [], _out: ""} + _depKinds: "" + variable: "{}" + } + output: "{kind1}" + _input: [{ + _deps: [{ + kind: "kind1" + _deps: [] + _kindJoin: {_objs: [], _out: ""} + _depKinds: "" + variable: "{}" + }] + kind: "kind1" + _kindJoin: {_objs: [], _out: ""} + _depKinds: "kind1" + variable: "{kind1}" + }] +}) +-- out/compile -- +--- in.cue +{ + _listBuilder: { + kind: "kind1" + _deps: [ + ..., + ] + _kindJoin: { + _objs: [ + ..., + ] + _out: 〈import;strings〉.Join([ + for _, d in 〈1;_objs〉 { + 〈1;d〉.kind + }, + ], ",") + } + _depKinds: { + (〈1;_kindJoin〉 & { + _objs: 〈2;_deps〉 + }) + }._out + variable: (("{" + 〈0;_depKinds〉) + "}") + } + output: _ + if true { + _input: [ + { + 〈3;_listBuilder〉 + _deps: [ + { + 〈5;_listBuilder〉 + }, + ] + }, + ] + output: 〈0;_input〉[0].variable + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue4210.txtar b/internal/core/compile/testdata/sync/cycle/issue4210.txtar new file mode 100644 index 000000000..050f6a635 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue4210.txtar @@ -0,0 +1,67 @@ +# CUE hangs indefinitely when a structural cycle reference is wrapped in braces +# before a field selector, e.g. `a: b: c: {a}.b`. Without braces (`a: b: c: +# a.b`) the cycle is correctly detected and reported as an error. The braces +# prevent cycle detection, causing CUE to loop forever instead of reporting an +# error. Affects all variants: `{a & _}.b`, `{a.b}.c`, nested structs, etc. +# https://cuelang.org/issue/4210 +-- in.cue -- +t1: { + a: b: c: {a}.b + @test(err, code=structural_cycle, contains="structural cycle", pos=[]) +} +t2: { + a: b: c: {a & _}.b + @test(err, code=structural_cycle, contains="structural cycle", pos=[]) +} +t3: { + a: b: c: d: {a.b}.c + @test(err, code=structural_cycle, contains="structural cycle", pos=[]) +} +t4: { + x: y: z: {a}.y + a: x + @test(err, code=structural_cycle, contains="structural cycle", pos=[]) +} +-- out/compile -- +--- in.cue +{ + t1: { + a: { + b: { + c: { + 〈3;a〉 + }.b + } + } + } + t2: { + a: { + b: { + c: { + (〈3;a〉 & _) + }.b + } + } + } + t3: { + a: { + b: { + c: { + d: { + 〈4;a〉.b + }.c + } + } + } + } + t4: { + x: { + y: { + z: { + 〈3;a〉 + }.y + } + } + a: 〈0;x〉 + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue4228.txtar b/internal/core/compile/testdata/sync/cycle/issue4228.txtar new file mode 100644 index 000000000..4ffbdc4b7 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue4228.txtar @@ -0,0 +1,197 @@ +# Test that cyclic error formatting doesn't cause stack overflow. +# The combination of error() with self interpolation and complex nested +# struct patterns can cause infinite recursion when formatting error messages. +# https://cuelang.org/issue/4228 +-- in.cue -- +package main + +_objectBase: self={ + name: string + k8s: metadata: name: self.name +} + +_namespacedResource: self={ + _objectBase + namespace: string + k8s: metadata: namespace: self.namespace +} + +// Key validation pattern with error() and self +_allValuesAreValidStructs: [_]: self={ + *{} | error("<- invalid \(self)") +} + +_setTypeMeta: self={ + #apiVersion!: string + #kind!: string + #template: k8s: { + apiVersion: self.#apiVersion + kind: self.#kind + } +} + +// Resource kinds pattern +_resourceKindsBase: { + _base!: _ + + [string]: { + _allValuesAreValidStructs + _setTypeMeta + #resourceSchema: _ + #template: { + _base + k8s: #resourceSchema + } + [_]: #template + } +} + +_namespacedResourceKinds: { + _resourceKindsBase + _base: _namespacedResource + [string]: [string]: namespace: string + + app: { + #apiVersion: "argoproj.io/v1alpha1" + #kind: "Application" + #resourceSchema: { + spec?: revisionHistoryLimit?: int + } + + #template: self={ + revisionHistoryLimit: *3 | int + k8s: spec: revisionHistoryLimit: self.revisionHistoryLimit + } + } +} + +// Usage +argocd: _namespacedResourceKinds & { + app: apps: {} +} @test(err, code=eval) + +-- export.cue -- +@experiment(aliasv2) + +package main + +import "encoding/yaml" + +let _globalScope = self + +#export: { + #entries: [...] + manifests: [ + for _entry in #entries + for _ns in _entry + for _kind, _objs in _ns + for _name, _obj in _objs { + _obj.k8s + }] + yamlStream: yaml.MarshalStream(manifests) +} + +#manifests: {#export, #entries: [_globalScope]}.yamlStream + +@test(err, code=eval) +-- out/compile -- +--- export.cue +{ + let _globalScope#1 = 〈1〉 + #export: { + #entries: [ + ..., + ] + manifests: [ + for _, _entry in 〈1;#entries〉 for _, _ns in 〈0;_entry(:main)〉 for _kind, _objs in 〈0;_ns(:main)〉 for _name, _obj in 〈0;_objs(:main)〉 { + 〈1;_obj(:main)〉.k8s + }, + ] + yamlStream: 〈import;"encoding/yaml"〉.MarshalStream(〈0;manifests〉) + } + #manifests: { + 〈1;#export〉 + #entries: [ + 〈2;let _globalScope#1〉, + ] + }.yamlStream +} +--- in.cue +{ + _objectBase(:main): { + name: string + k8s: { + metadata: { + name: 〈3〉.name + } + } + } + _namespacedResource(:main): { + 〈1;_objectBase(:main)〉 + namespace: string + k8s: { + metadata: { + namespace: 〈3〉.namespace + } + } + } + _allValuesAreValidStructs(:main): { + [_]: { + (*{}|error("<- invalid \(〈1〉)")) + } + } + _setTypeMeta(:main): { + #apiVersion!: string + #kind!: string + #template: { + k8s: { + apiVersion: 〈3〉.#apiVersion + kind: 〈3〉.#kind + } + } + } + _resourceKindsBase(:main): { + _base(:main)!: _ + [string]: { + 〈2;_allValuesAreValidStructs(:main)〉 + 〈2;_setTypeMeta(:main)〉 + #resourceSchema: _ + #template: { + 〈2;_base(:main)〉 + k8s: 〈1;#resourceSchema〉 + } + [_]: 〈0;#template〉 + } + } + _namespacedResourceKinds(:main): { + 〈1;_resourceKindsBase(:main)〉 + _base(:main): 〈1;_namespacedResource(:main)〉 + [string]: { + [string]: { + namespace: string + } + } + app: { + #apiVersion: "argoproj.io/v1alpha1" + #kind: "Application" + #resourceSchema: { + spec?: { + revisionHistoryLimit?: int + } + } + #template: { + revisionHistoryLimit: (*3|int) + k8s: { + spec: { + revisionHistoryLimit: 〈3〉.revisionHistoryLimit + } + } + } + } + } + argocd: (〈0;_namespacedResourceKinds(:main)〉 & { + app: { + apps: {} + } + }) +} diff --git a/internal/core/compile/testdata/sync/cycle/issue4230.txtar b/internal/core/compile/testdata/sync/cycle/issue4230.txtar new file mode 100644 index 000000000..b04c574ee --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue4230.txtar @@ -0,0 +1,48 @@ +# The new evaluator (v3) produces empty output for `or(["eu-west-1", "us-east-1"])` +# when used inside a self-referential struct, while the old evaluator produces the +# correct result. Replacing `or([...])` with a plain disjunction `"a" | "b"` works +# correctly. The root cause: calls with only literal arguments were incorrectly +# deferred when evaluated from within a cyclic context, resulting in empty output. +# https://cuelang.org/issue/4230 +-- in.cue -- +#transform: { + _input: {...} + _output: [ + if _input.app != _|_ { + _input.app.region + }, + ] +} + +x: X={ + regions: (#transform & {_input: X})._output + app: region: or(["west", "east"]) & "west" +} @test(eq, { + regions: ["west"] + app: {region: "west"} +}) +-- out/compile -- +--- in.cue +{ + #transform: { + _input: { + ... + } + _output: [ + if (〈1;_input〉.app != _|_(explicit error (_|_ literal) in source)) { + 〈2;_input〉.app.region + }, + ] + } + x: { + regions: (〈1;#transform〉 & { + _input: 〈2〉 + })._output + app: { + region: (or([ + "west", + "east", + ]) & "west") + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue4244.txtar b/internal/core/compile/testdata/sync/cycle/issue4244.txtar new file mode 100644 index 000000000..1e16239c3 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue4244.txtar @@ -0,0 +1,57 @@ +# A `let` binding that factors out a repeated expression changes the evaluation +# result unexpectedly compared to the inline form, indicating a bug in how +# `let`-bound values are resolved relative to their enclosing scope. +# https://cuelang.org/issue/4244 +-- in.cue -- +import "strings" + +#schema: { + let splits = strings.Split(id, "_never_") + let prefix = splits[0] + + #ID: =~"^\(prefix)$" @test(err, code=incomplete, contains="invalid interpolation", pos=[0:12, -2:22]) + #SubID: =~"^\(prefix):sub$" @test(err, code=incomplete, contains="invalid interpolation", pos=[0:12, -3:22]) + + id: #ID @test(err, code=incomplete, contains="invalid interpolation", pos=[-3:12, -5:22]) + subid: #SubID @test(err, code=incomplete, contains="invalid interpolation", pos=[-3:12, -6:22]) +} + +case1: #schema & { + id: "foo" + subid: "foo:sub" +} @test(eq, { + id: "foo" + subid: "foo:sub" + #ID: =~"^foo$" + #SubID: =~"^foo:sub$" +}) + +case2: #schema & { + subid: "foo:sub" + id: "foo" +} @test(eq, { + subid: "foo:sub" + id: "foo" + #ID: =~"^foo$" + #SubID: =~"^foo:sub$" +}) +-- out/compile -- +--- in.cue +{ + #schema: { + let splits#1 = 〈import;strings〉.Split(〈0;id〉, "_never_") + let prefix#2 = 〈0;let splits#1〉[0] + #ID: =~"^\(〈0;let prefix#2〉)$" + #SubID: =~"^\(〈0;let prefix#2〉):sub$" + id: 〈0;#ID〉 + subid: 〈0;#SubID〉 + } + case1: (〈0;#schema〉 & { + id: "foo" + subid: "foo:sub" + }) + case2: (〈0;#schema〉 & { + subid: "foo:sub" + id: "foo" + }) +} diff --git a/internal/core/compile/testdata/sync/cycle/issue4253.txtar b/internal/core/compile/testdata/sync/cycle/issue4253.txtar new file mode 100644 index 000000000..dd54161e8 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue4253.txtar @@ -0,0 +1,51 @@ +# Non-CallExpr conjuncts (=~, == _|_, interpolation) must not be deferred +# under a cyclic context; companion to issue4230.txtar which covers CallExpr. +# https://cuelang.org/issue/4253 +-- in.cue -- +@experiment(aliasv2) + +x: { + #tmpl: { + let _self = self + foo: 1 + k8s: foo: _self.foo + } + + #allowed: =~"^[a-z0-9]+$" + + [string]: { + [string]~(ID,_): { + #tmpl + if (#allowed & ID) == _|_ { + error("bad: \(ID)") + } + } + } + + gateway: whoami2: {} +} @test(eq, at=gateway.whoami2, {foo: 1, k8s: {foo: 1}}) +-- out/compile -- +--- in.cue +{ + x: { + #tmpl: { + let _self#1 = 〈1〉 + foo: 1 + k8s: { + foo: 〈1;let _self#1〉.foo + } + } + #allowed: =~"^[a-z0-9]+$" + [string]: { + [string]: { + 〈2;#tmpl〉 + if ((〈2;#allowed〉 & 〈1;-〉) == _|_(explicit error (_|_ literal) in source)) { + error("bad: \(〈2;-〉)") + } + } + } + gateway: { + whoami2: {} + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue429.txtar b/internal/core/compile/testdata/sync/cycle/issue429.txtar new file mode 100644 index 000000000..4ca318b3d --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue429.txtar @@ -0,0 +1,123 @@ +# `cue export` incorrectly rejects a `#Size` definition with interdependent +# bound constraints (`num: >res | *(1+res)`, `max: >=num | *num`) when a +# concrete value is provided, e.g. `a: #Size & { num: 5 }`. Expected output +# would be `{ res: 0, num: 5, max: 5 }` but instead CUE reports empty +# disjunction errors for both `num` and `max`. Works correctly in v0.2.1. +# TODO: a bound value resolving to a disjunction should probably be an error. +# In this case #Size.amx should resolve. +# https://cuelang.org/issue/429 +-- in.cue -- +// Range disjunction without cycle (checks only one-way). +#Size: { + res: uint | *0 + min: >res | *(1 + res) + max: >min | *min +} + +s0: #Size & {res: 1} @test(eq, { + res: 1 + min: *2 | >1 + max: *2 | >1 | >2 +}) + +// This discards the default for max. This is correct, but unfortunate. +// TODO: is there a tweak to the default mechanism possible that would fix that? +// Tread very carefully, though! Perhaps we could have a builtin that +// discards any default, so that we can at least manually override this +// behavior. +s1: #Size & {min: 5} @test(eq, { + min: 5 + res: *0 | >=0 & int + max: *5 | >5 +}) +s2: #Size & {max: 5} @test(eq, { + max: 5 + res: *0 | >=0 & int + min: *1 | >0 +}) +s3: #Size & { + min: 5 + max: 10 +} @test(eq, {min: 5, max: 10, res: *0 | >=0 & int}) +es3: #Size & { + min: 10 + max: 5 +} @test(err, code=eval, + suberr=(code=eval, path=max, contains="%d errors in empty disjunction:", args=[2], pos=[]), + suberr=(code=eval, path=max, contains="conflicting values %s and %s", args=[1, 5], pos=[-29:16, -28:15, 0:6, 2:7]), + suberr=(code=eval, path=max, contains="conflicting values %s and %s", args=[10, 5], pos=[-28:15, 0:6, 1:7, 2:7]), + suberr=(code=eval, path=max, contains="invalid value %v (out of bound %s)", args=[5, >10], pos=[-28:7, 2:7])) + +// Disjunctions with cycles +// TODO: improve error message here. Logic is correct, though. +#nonEmptyRange: { + min: *1 | int + min: min +} +r1: #nonEmptyRange & { + min: 3 +} @test(eq, { + min: _|_ @test(err, code=incomplete, contains="r1.min: non-concrete value max for bound < (and 2 more errors)", pos=[46:8]) + max: >3 +}) +r2: #nonEmptyRange & { + max: 5 +} @test(eq, {max: 5, min: *1 | <5 & int}) +r3: #nonEmptyRange & { + min: 3 + max: 6 +} @test(eq, {min: 3, max: 6}) + +er3: #nonEmptyRange & { + min: 5 + max: 5 +} @test(err, code=eval, + suberr=(code=eval, path=min, contains="conflicting values %s and %s", args=[1, 5], pos=[-18:8, 0:6, 1:7]), + suberr=(code=eval, path=min, contains="invalid value %v (out of bound %s)", args=[5, <5], pos=[-17:7, 1:7]), + suberr=(code=eval, path=min, contains="invalid value %v (out of bound %s)", args=[5, <5], pos=[-17:7, 1:7])) +-- out/compile -- +--- in.cue +{ + #Size: { + res: (&(int, >=0)|*0) + min: (>〈0;res〉|*(1 + 〈0;res〉)) + max: (>〈0;min〉|*〈0;min〉) + } + s0: (〈0;#Size〉 & { + res: 1 + }) + s1: (〈0;#Size〉 & { + min: 5 + }) + s2: (〈0;#Size〉 & { + max: 5 + }) + s3: (〈0;#Size〉 & { + min: 5 + max: 10 + }) + es3: (〈0;#Size〉 & { + min: 10 + max: 5 + }) + #nonEmptyRange: { + min: (*1|int) + min: <〈0;max〉 + max: >〈0;min〉 + } + r1: (〈0;#nonEmptyRange〉 & { + min: 3 + }) + r2: (〈0;#nonEmptyRange〉 & { + max: 5 + }) + r3: (〈0;#nonEmptyRange〉 & { + min: 3 + max: 6 + }) + er3: (〈0;#nonEmptyRange〉 & { + min: 5 + max: 5 + }) +} diff --git a/internal/core/compile/testdata/sync/cycle/issue494.txtar b/internal/core/compile/testdata/sync/cycle/issue494.txtar new file mode 100644 index 000000000..69132d1b1 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue494.txtar @@ -0,0 +1,110 @@ +# `a: [rn=string]: _Q[0:len(a[rn])]` silently produces wrong output: `a.ben` +# should be `[{pos: 0}]` (a one-element slice matching the concrete entry's +# length) but instead produces `[{}]` with `pos` missing and no error reported. +# The equivalent closed-type pattern `#d: [rn=string]: [...] & _Q[0:len(#d[rn])]` +# works correctly. The self-referential slice constraint is not being unified. +# https://cuelang.org/issue/494 +-- in.cue -- +_Q: [{pos: 0}, {pos: 1}] + +a: [rn=string]: _Q[0:len(a[rn])] +a: ben: [{}] @test(eq, [{pos: 0}]) + +b: [rn=string]: _Q[0:1] +b: ben: [{}] @test(eq, [{pos: 0}]) + +c: [rn=string]: [...{l: len(a[rn])}] +c: ben: [{}] @test(eq, [{l: 1}]) + +#d: [rn=string]: [...{pos: uint}] & _Q[0:len(#d[rn])] +#d: ben: [{}] @test(eq, [{pos: 0}]) + +d: #d @test(eq, {ben: [{pos: 0}]}) + +e: [rn=string]: _Q[0 : len(a[rn])+1] +e: ben: [{}, ...] @test(eq, [{pos: 0}, {pos: 1}]) + +f: [rn=string]: _Q[0 : len(a[rn])+1] +f: ben: [{}] @test(err, code=eval, contains="incompatible list lengths", pos=[]) + +g: [rn=string]: _Q[0:len(a[rn])] +g: ben: [{}, {}] @test(err, code=eval, contains="incompatible list lengths", pos=[]) +-- out/compile -- +--- in.cue +{ + _Q: [ + { + pos: 0 + }, + { + pos: 1 + }, + ] + a: { + [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] + } + a: { + ben: [ + {}, + ] + } + b: { + [string]: 〈1;_Q〉[0:1] + } + b: { + ben: [ + {}, + ] + } + c: { + [string]: [ + ...{ + l: len(〈3;a〉[〈2;-〉]) + }, + ] + } + c: { + ben: [ + {}, + ] + } + #d: { + [string]: ([ + ...{ + pos: &(int, >=0) + }, + ] & 〈1;_Q〉[0:len(〈1;#d〉[〈0;-〉])]) + } + #d: { + ben: [ + {}, + ] + } + d: 〈0;#d〉 + e: { + [string]: 〈1;_Q〉[0:(len(〈1;a〉[〈0;-〉]) + 1)] + } + e: { + ben: [ + {}, + ..., + ] + } + f: { + [string]: 〈1;_Q〉[0:(len(〈1;a〉[〈0;-〉]) + 1)] + } + f: { + ben: [ + {}, + ] + } + g: { + [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] + } + g: { + ben: [ + {}, + {}, + ] + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue502.txtar b/internal/core/compile/testdata/sync/cycle/issue502.txtar new file mode 100644 index 000000000..8776364d9 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue502.txtar @@ -0,0 +1,175 @@ +# A recursive configuration using `_link: #T` in a map's entry struct is +# incorrectly rejected as a structural cycle in v0.3.0+, but worked in v0.2.2. +# The user expects config values to propagate through linked chains (e.g. nested +# `mas: one: { mas: two: { ... } }`) but gets "structural cycle" errors for +# `#a.mas.one._link.mas.two.link` etc. Shallow nesting (one level) works fine. +# https://cuelang.org/issue/502 +-- in.cue -- +#T: { + config: _ + body: _ + mas: [string]: { + cfg: _ + _link: #T + link: _link & {config: cfg} + } +} + +#a: #T & { + config: a: int + body: config.a + mas: one: { + cfg: b: config.a + _link: { + config: b: int + body: config.b + mas: two: { + cfg: c: config.b + _link: { + config: c: int + body: config.c + } + } + } + } +} + +a: #a & {config: a: 34} @test(eq, { + config: {a: 34} + body: 34 + mas: one: { + cfg: {b: 34} + _link: { + config: {b: int} + body: int + mas: two: { + cfg: {c: int} + _link: {config: {c: int}, body: int, mas: {}} + link: {config: {c: int}, body: int, mas: {}} + } + } + link: { + config: {b: 34} + body: 34 + mas: two: { + cfg: {c: 34} + _link: {config: {c: int}, body: int, mas: {}} + link: {config: {c: 34}, body: 34, mas: {}} + } + } + } +}) +-- reduced.cue -- +reduced: t1: { + #T: x: y?: { + V: _ + z: #T & V & {} + } + a: #T + a: x: y: V: x: y: V: {} + + @test(eq, { + #T: x: y?: { + V: _ + z: x: y?: { + _|_ + V: _ + z: _|_ @test(err, code=structural_cycle, contains="reduced.t1.#T.x.y.z.x.y.z: structural cycle", pos=[]) + } + } + a: x: y: { + V: x: y: V: {} + z: x: y: { + V: {} + z: x: y?: { + _|_ + V: _ + z: _|_ @test(err, code=structural_cycle, contains="reduced.t1.a.x.y.z.x.y.z.x.y.z: structural cycle", pos=[]) + } + } + } + }) +} +-- out/compile -- +--- in.cue +{ + #T: { + config: _ + body: _ + mas: { + [string]: { + cfg: _ + _link: 〈3;#T〉 + link: (〈0;_link〉 & { + config: 〈1;cfg〉 + }) + } + } + } + #a: (〈0;#T〉 & { + config: { + a: int + } + body: 〈0;config〉.a + mas: { + one: { + cfg: { + b: 〈3;config〉.a + } + _link: { + config: { + b: int + } + body: 〈0;config〉.b + mas: { + two: { + cfg: { + c: 〈3;config〉.b + } + _link: { + config: { + c: int + } + body: 〈0;config〉.c + } + } + } + } + } + } + }) + a: (〈0;#a〉 & { + config: { + a: 34 + } + }) +} +--- reduced.cue +{ + reduced: { + t1: { + #T: { + x: { + y?: { + V: _ + z: ((〈3;#T〉 & 〈0;V〉) & {}) + } + } + } + a: 〈0;#T〉 + a: { + x: { + y: { + V: { + x: { + y: { + V: {} + } + } + } + } + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/issue990.txtar b/internal/core/compile/testdata/sync/cycle/issue990.txtar new file mode 100644 index 000000000..cf4934fc8 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/issue990.txtar @@ -0,0 +1,285 @@ +# CUE incorrectly reports a structural cycle error for a valid CUE expression +# that does not actually contain a cycle, producing a false positive. +# https://cuelang.org/issue/990 +-- in.cue -- +// A simple discriminated element +#AC: { + k: "simple" + d: #C +} + +// A recursive discriminated element +#AS: { + k: "complex" + d: #S +} + +#R: { + a: #AC | #AS +} + +// The structure of the recursive element +#S: { + n: string + r: [string]: #R +} + +// The structure of the simple element +#C: { + n: string +} + +#sub: { + $p=#p: #AS + dict: [string]: _ + + for rn, rd in $p.d.r if rd.a.k == "complex" { + let subs = #sub & {#p: rd.a} + for sn, sd in subs.dict { + dict: "\(rn)_\(sn)": sd + } + } + for rn, rd in $p.d.r if rd.a.k == "simple" { + dict: "\(rn)": rd + } +} + +// Data +_test: { + c1: #AC + c1: d: { + n: "c1" + } + + + s3: #AS + s3: d: { + n: "s3" + r: r1: a:c1 + } + + s2: #AS + s2: d: { + n: "s2" + r: { + r1: a: c1 + r2: a: s3 + } + } + + s1: #AS + s1: d: { + n: "s1" + r: { + r1: a: c1 + r2: a: s2 + } + } +} + +// Test + +out: #sub & {#p: _test.s1} + +// TODO(fmt): can we improve this? +@test(eq, { + #AC: {k: "simple", d: {n: string}} + #AS: {k: "complex", d: {n: string, r: {}}} + #R: { + a: {k: "simple", d: {n: string}} | {k: "complex", d: {n: string, r: {}}} + } + #S: {n: string, r: {}} + #C: {n: string} + #sub: { + #p: {k: "complex", d: {n: string, r: {}}} + dict: {} + } + _test: { + c1: {d: {n: "c1"}, k: "simple"} + s3: { + d: { + n: "s3" + r: {r1: {a: {d: {n: "c1"}, k: "simple"}}} + } + k: "complex" + } + s2: { + d: { + n: "s2" + r: { + r1: {a: {d: {n: "c1"}, k: "simple"}} + r2: { + a: { + d: { + n: "s3" + r: {r1: {a: {d: {n: "c1"}, k: "simple"}}} + } + k: "complex" + } + } + } + } + k: "complex" + } + s1: { + d: { + n: "s1" + r: { + r1: {a: {d: {n: "c1"}, k: "simple"}} + r2: { + a: { + d: { + n: "s2" + r: { + r1: {a: {d: {n: "c1"}, k: "simple"}} + r2: { + a: { + d: { + n: "s3" + r: {r1: {a: {d: {n: "c1"}, k: "simple"}}} + } + k: "complex" + } + } + } + } + k: "complex" + } + } + } + } + k: "complex" + } + } + out: { + #p: { + d: { + n: "s1" + r: { + r1: {a: {d: {n: "c1"}, k: "simple"}} + r2: { + a: { + d: { + n: "s2" + r: { + r1: {a: {d: {n: "c1"}, k: "simple"}} + r2: { + a: { + d: { + n: "s3" + r: {r1: {a: {d: {n: "c1"}, k: "simple"}}} + } + k: "complex" + } + } + } + } + k: "complex" + } + } + } + } + k: "complex" + } + dict: { + r1: {a: {d: {n: "c1"}, k: "simple"}} + r2_r1: {a: {d: {n: "c1"}, k: "simple"}} + r2_r2_r1: {a: {d: {n: "c1"}, k: "simple"}} + } + } +}) +-- out/compile -- +--- in.cue +{ + #AC: { + k: "simple" + d: 〈1;#C〉 + } + #AS: { + k: "complex" + d: 〈1;#S〉 + } + #R: { + a: (〈1;#AC〉|〈1;#AS〉) + } + #S: { + n: string + r: { + [string]: 〈2;#R〉 + } + } + #C: { + n: string + } + #sub: { + #p: 〈1;#AS〉 + dict: { + [string]: _ + } + for rn, rd in 〈0;#p〉.d.r if (〈0;rd〉.a.k == "complex") { + let subs#1multi = (〈3;#sub〉 & { + #p: 〈2;rd〉.a + }) + for sn, sd in 〈0;let subs#1〉.dict { + dict: { + "\(〈4;rn〉)_\(〈2;sn〉)": 〈2;sd〉 + } + } + } + for rn, rd in 〈0;#p〉.d.r if (〈0;rd〉.a.k == "simple") { + dict: { + "\(〈2;rn〉)": 〈2;rd〉 + } + } + } + _test: { + c1: 〈1;#AC〉 + c1: { + d: { + n: "c1" + } + } + s3: 〈1;#AS〉 + s3: { + d: { + n: "s3" + r: { + r1: { + a: 〈4;c1〉 + } + } + } + } + s2: 〈1;#AS〉 + s2: { + d: { + n: "s2" + r: { + r1: { + a: 〈4;c1〉 + } + r2: { + a: 〈4;s3〉 + } + } + } + } + s1: 〈1;#AS〉 + s1: { + d: { + n: "s1" + r: { + r1: { + a: 〈4;c1〉 + } + r2: { + a: 〈4;s2〉 + } + } + } + } + } + out: (〈0;#sub〉 & { + #p: 〈1;_test〉.s1 + }) +} diff --git a/internal/core/compile/testdata/sync/cycle/patterns.txtar b/internal/core/compile/testdata/sync/cycle/patterns.txtar new file mode 100644 index 000000000..1eaa3a300 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/patterns.txtar @@ -0,0 +1,61 @@ +// Lots of cycle-reference goodness. +# Tests that pattern constraints on cyclically-referenced fields do not +# cause infinite evaluation. Also tests issue3326 (cyclic pattern constraints). +-- in.cue -- +[!~"^[.]"]: c +a: b +b: [string]: int +c: a: int +[string]: c +a: b @test(eq, {a: int}) +b: [string]: int +c: a: int @test(eq, int) + +-- issue3326.cue -- +// https://cuelang.org/issue/3326 +issue3326: { + // This issue triggered a cyclic evaluation in pattern constraints. + // + // It seems like there is still an issue as the evaluation of `x` in + // `and` may trigger a cyclic evaluation of `and`. However, `and` only + // does a shallow evaluation, and inserting `x`'s conjuncts into itself + // is identified as idempotent and thus further evaluation is skipped. + _self: x: [...and(x)] + _self + x: [1] + @test(eq, {_self: {x: []}, x: [1], a: int}) +} +-- out/compile -- +--- in.cue +{ + [!~"^[.]"]: 〈0;c〉 + a: 〈0;b〉 + b: { + [string]: int + } + c: { + a: int + } + [string]: 〈0;c〉 + a: 〈0;b〉 + b: { + [string]: int + } + c: { + a: int + } +} +--- issue3326.cue +{ + issue3326: { + _self: { + x: [ + ...and(〈1;x〉), + ] + } + 〈0;_self〉 + x: [ + 1, + ] + } +} diff --git a/internal/core/compile/testdata/sync/cycle/self.txtar b/internal/core/compile/testdata/sync/cycle/self.txtar new file mode 100644 index 000000000..2d66eeaa3 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/self.txtar @@ -0,0 +1,846 @@ +-- in.cue -- +@experiment(aliasv2) + +import "list" + +expr: error1: { + a: 3 + a: a + 1 + @test(err, code=eval, path=a, contains="conflicting values %s and %s", args=[4, 3], pos=[1:5, 2:5]) +} +expr: error2: { + a: a + 1 + a: 3 + @test(err, code=eval, path=a, contains="conflicting values %s and %s", args=[4, 3], pos=[1:5, 2:5]) +} +listConcat: error1: { + a: ["1", "2"] + a: list.Concat([a, ["3"]]) + @test(err, code=structural_cycle, path=a, contains="error in call to %s", args=[list.Concat], pos=[2:5]) +} + +listConcat: error2: { + a: list.Concat([["3"], a]) + a: ["1", "2"] + @test(err, code=structural_cycle, path=a, contains="error in call to %s", args=[list.Concat], pos=[1:5]) +} + +selfEmbed: ok1: { + a: x + Y: x + x: {Y} + @test(eq, {a: {}, Y: {}, x: {}}) +} + +selfEmbed: ok2: { + Y: x.b + a: x + x: b: {Y} + @test(eq, {Y: {}, a: {b: {}}, x: {b: {}}}) +} + +selfEmbed: ok3: { + Y: x + a: x + x: {Y} + @test(eq, {Y: {}, a: {}, x: {}}) +} + +selfEmbed: ok4: { + a: x + x: {Y} + Y: x + @test(eq, {a: {}, x: {}, Y: {}}) +} + +selfEmbed: ok5: { + x: {Y} + a: x + Y: x + @test(eq, {x: {}, a: {}, Y: {}}) +} + +selfEmbed: ok6: { + x: b: {Y} + Y: x.b + a: x + @test(eq, {x: {b: {}}, Y: {}, a: {b: {}}}) +} + + +disjSelf: ok1: { + #A: string | #A + x: #A + @test(eq, {#A: string | _, x: string | _}) +} + +disjSelf: ok2: { + x: #A + #A: string | #A + @test(eq, {x: string | _, #A: string | _}) +} + +disjSelf: ok3: { + #A: #A | string + x: #A + @test(eq, {#A: _ | string, x: _ | string}) +} + +disjSelf: ok4: { + x: #A + #A: #A | string + @test(eq, {x: _ | string, #A: _ | string}) +} + +disjEmbed: ok1: { + #A: string | {#A} + x: #A + @test(eq, {#A: string | {}, x: string | {}}) +} + +disjEmbed: ok2: { + x: #A + #A: string | {#A} + @test(eq, {x: string | {}, #A: string | {}}) +} + +disjEmbed: ok3: { + #A: {#A} | string + x: #A + @test(eq, {#A: {} | string, x: {} | string}) +} + +disjEmbed: ok4: { + x: #A + #A: {#A} | string + @test(eq, {x: {} | string, #A: {} | string}) +} + +// x and #A should yield the same result. +disjList: _ +disjList: ok1: { + #A: string | [#A] + x: #A + + y: x + y: [[[[string]]]] + @test(eq, { + #A: string + x: string + y: [[[[string]]]] + }) +} + +disjList: ok2: { + x: #A + #A: string | [#A] + @test(eq, {x: string, #A: string}) +} + +disjList: ok3: { + #A: [#A] | string + x: #A + @test(eq, {#A: string, x: string}) +} + +disjList: ok4: { + x: #A + #A: [#A] | string + @test(eq, {x: string, #A: string}) +} + +-- old.cue -- +name: "foo" +dynamicSelf: ok1: { + X=(name): string | X + x: X + @test(eq, {x: string | _, foo: string | _}) +} + +dynamicSelf: ok2: { + x: X + X=(name): string | X + @test(eq, {x: string | _, foo: string | _}) +} + +dynamicSelf: ok3: { + X=(name): X | string + x: X + @test(eq, {x: _ | string, foo: _ | string}) +} + +dynamicSelf: ok4: { + x: X + X=(name): X | string + @test(eq, {x: _ | string, foo: _ | string}) +} + +dynamicEmbed: ok1: { + X=(name): string | {X} + x: X + @test(eq, {x: string | {}, foo: string | {}}) +} + +dynamicEmbed: ok2: { + x: X + X=(name): string | {X} + @test(eq, {x: string | {}, foo: string | {}}) +} + +dynamicEmbed: ok3: { + X=(name): {X} | string + x: X + @test(eq, {x: {} | string, foo: {} | string}) +} + +dynamicEmbed: ok4: { + x: X + X=(name): {X} | string + @test(eq, {x: {} | string, foo: {} | string}) +} + +dynamicList: _ +dynamicList: ok1: { + X=(name): string | [X] + x: X + + y: x + y: [[[[string]]]] + @test(eq, { + x: string + y: [[[[string]]]] + foo: string + }) +} + +dynamicList: ok2: { + x: X + X=(name): string | [X] + @test(eq, {x: string, foo: string}) +} + +dynamicList: ok3: { + X=(name): [X] | string + x: X + @test(eq, {x: string, foo: string}) +} + +dynamicList: ok4: { + x: X + X=(name): [X] | string + @test(eq, {x: string, foo: string}) +} + +dynamicPatternSelf: ok1: { + X=[string]: string | X + @test(eq, {}) +} +dynamicPatternSelf: ok2: { + X=[string]: X | string + @test(eq, {}) +} +dynamicPatternEmbed: ok1: { + X=[string]: string | {X} + @test(eq, {}) +} +dynamicPatternEmbed: ok2: { + X=[string]: {X} | string + @test(eq, {}) +} +dynamicPatternList: ok1: { + X=[string]: string | [X] + @test(eq, {}) +} +dynamicPatternList: ok2: { + X=[string]: [X] | string + @test(eq, {}) +} + +valueSelf: ok1: { + y: X={string | X} + x: y + @test(eq, {y: string | {}, x: string | {}}) +} + +valueSelf: ok2: { + x: y + y: X={string | X} + @test(eq, {x: string | {}, y: string | {}}) +} + +valueSelf: ok3: { + y: X={X | string} + x: y + @test(eq, {y: {} | string, x: {} | string}) +} + +valueSelf: ok4: { + x: y + y: X={X | string} + @test(eq, {x: {} | string, y: {} | string}) +} + +valueEmbed: ok1: { + y: X={string | {X}} + x: y + @test(eq, {y: string | {}, x: string | {}}) +} + +valueEmbed: ok2: { + x: y + y: X={string | {X}} + @test(eq, {x: string | {}, y: string | {}}) +} + +valueEmbed: ok3: { + y: X={{X} | string} + x: y + @test(eq, {y: {} | string, x: {} | string}) +} + +valueEmbed: ok4: { + x: y + y: X={{X} | string} + @test(eq, {x: {} | string, y: {} | string}) +} + +valueList: ok1: { + y: X={string | [X]} + x: y + @test(eq, {y: string, x: string}) +} + +valueList: ok2: { + x: y + y: X={string | [X]} + @test(eq, {x: string, y: string}) +} + +valueList: ok3: { + y: X={[X] | string} + x: y + @test(eq, {y: string, x: string}) +} + +valueList: ok4: { + x: y + y: X={[X] | string} + @test(eq, {x: string, y: string}) +} + +// Issue #1729 +issue1729: t1: { + #x: { #x | {} } + x: #x & {} + @test(eq, {#x: {}, x: {}}) +} + +issue1729: t2: { + x: #x & {} + #x: { #x | {} } + @test(eq, {x: {}, #x: {}}) +} + +-- selfnew.cue -- +@experiment(aliasv2) + +issue4125: t1_self: { + let Root = self + a: Root.a + @test(eq, {a: _}) +} +-- selfold.cue -- +issue4125: t2_alias: X={ + let Y = X + b: Y.b + @test(eq, {b: _}) +} + +-- out/compile -- +--- in.cue +{ + expr: { + error1: { + a: 3 + a: (〈0;a〉 + 1) + } + } + expr: { + error2: { + a: (〈0;a〉 + 1) + a: 3 + } + } + listConcat: { + error1: { + a: [ + "1", + "2", + ] + a: 〈import;list〉.Concat([ + 〈1;a〉, + [ + "3", + ], + ]) + } + } + listConcat: { + error2: { + a: 〈import;list〉.Concat([ + [ + "3", + ], + 〈1;a〉, + ]) + a: [ + "1", + "2", + ] + } + } + selfEmbed: { + ok1: { + a: 〈0;x〉 + Y: 〈0;x〉 + x: { + 〈1;Y〉 + } + } + } + selfEmbed: { + ok2: { + Y: 〈0;x〉.b + a: 〈0;x〉 + x: { + b: { + 〈2;Y〉 + } + } + } + } + selfEmbed: { + ok3: { + Y: 〈0;x〉 + a: 〈0;x〉 + x: { + 〈1;Y〉 + } + } + } + selfEmbed: { + ok4: { + a: 〈0;x〉 + x: { + 〈1;Y〉 + } + Y: 〈0;x〉 + } + } + selfEmbed: { + ok5: { + x: { + 〈1;Y〉 + } + a: 〈0;x〉 + Y: 〈0;x〉 + } + } + selfEmbed: { + ok6: { + x: { + b: { + 〈2;Y〉 + } + } + Y: 〈0;x〉.b + a: 〈0;x〉 + } + } + disjSelf: { + ok1: { + #A: (string|〈0;#A〉) + x: 〈0;#A〉 + } + } + disjSelf: { + ok2: { + x: 〈0;#A〉 + #A: (string|〈0;#A〉) + } + } + disjSelf: { + ok3: { + #A: (〈0;#A〉|string) + x: 〈0;#A〉 + } + } + disjSelf: { + ok4: { + x: 〈0;#A〉 + #A: (〈0;#A〉|string) + } + } + disjEmbed: { + ok1: { + #A: (string|{ + 〈1;#A〉 + }) + x: 〈0;#A〉 + } + } + disjEmbed: { + ok2: { + x: 〈0;#A〉 + #A: (string|{ + 〈1;#A〉 + }) + } + } + disjEmbed: { + ok3: { + #A: ({ + 〈1;#A〉 + }|string) + x: 〈0;#A〉 + } + } + disjEmbed: { + ok4: { + x: 〈0;#A〉 + #A: ({ + 〈1;#A〉 + }|string) + } + } + disjList: _ + disjList: { + ok1: { + #A: (string|[ + 〈1;#A〉, + ]) + x: 〈0;#A〉 + y: 〈0;x〉 + y: [ + [ + [ + [ + string, + ], + ], + ], + ] + } + } + disjList: { + ok2: { + x: 〈0;#A〉 + #A: (string|[ + 〈1;#A〉, + ]) + } + } + disjList: { + ok3: { + #A: ([ + 〈1;#A〉, + ]|string) + x: 〈0;#A〉 + } + } + disjList: { + ok4: { + x: 〈0;#A〉 + #A: ([ + 〈1;#A〉, + ]|string) + } + } +} +--- old.cue +{ + name: "foo" + dynamicSelf: { + ok1: { + 〈2;name〉: (string|〈0;(〈2;name〉)〉) + x: 〈0;(〈2;name〉)〉 + } + } + dynamicSelf: { + ok2: { + x: 〈0;(〈2;name〉)〉 + 〈2;name〉: (string|〈0;(〈2;name〉)〉) + } + } + dynamicSelf: { + ok3: { + 〈2;name〉: (〈0;(〈2;name〉)〉|string) + x: 〈0;(〈2;name〉)〉 + } + } + dynamicSelf: { + ok4: { + x: 〈0;(〈2;name〉)〉 + 〈2;name〉: (〈0;(〈2;name〉)〉|string) + } + } + dynamicEmbed: { + ok1: { + 〈2;name〉: (string|{ + 〈1;(〈2;name〉)〉 + }) + x: 〈0;(〈2;name〉)〉 + } + } + dynamicEmbed: { + ok2: { + x: 〈0;(〈2;name〉)〉 + 〈2;name〉: (string|{ + 〈1;(〈2;name〉)〉 + }) + } + } + dynamicEmbed: { + ok3: { + 〈2;name〉: ({ + 〈1;(〈2;name〉)〉 + }|string) + x: 〈0;(〈2;name〉)〉 + } + } + dynamicEmbed: { + ok4: { + x: 〈0;(〈2;name〉)〉 + 〈2;name〉: ({ + 〈1;(〈2;name〉)〉 + }|string) + } + } + dynamicList: _ + dynamicList: { + ok1: { + 〈2;name〉: (string|[ + 〈1;(〈2;name〉)〉, + ]) + x: 〈0;(〈2;name〉)〉 + y: 〈0;x〉 + y: [ + [ + [ + [ + string, + ], + ], + ], + ] + } + } + dynamicList: { + ok2: { + x: 〈0;(〈2;name〉)〉 + 〈2;name〉: (string|[ + 〈1;(〈2;name〉)〉, + ]) + } + } + dynamicList: { + ok3: { + 〈2;name〉: ([ + 〈1;(〈2;name〉)〉, + ]|string) + x: 〈0;(〈2;name〉)〉 + } + } + dynamicList: { + ok4: { + x: 〈0;(〈2;name〉)〉 + 〈2;name〉: ([ + 〈1;(〈2;name〉)〉, + ]|string) + } + } + dynamicPatternSelf: { + ok1: { + [string]: (string|〈0;(〈0;-〉)〉) + } + } + dynamicPatternSelf: { + ok2: { + [string]: (〈0;(〈0;-〉)〉|string) + } + } + dynamicPatternEmbed: { + ok1: { + [string]: (string|{ + 〈1;(〈0;-〉)〉 + }) + } + } + dynamicPatternEmbed: { + ok2: { + [string]: ({ + 〈1;(〈0;-〉)〉 + }|string) + } + } + dynamicPatternList: { + ok1: { + [string]: (string|[ + 〈1;(〈0;-〉)〉, + ]) + } + } + dynamicPatternList: { + ok2: { + [string]: ([ + 〈1;(〈0;-〉)〉, + ]|string) + } + } + valueSelf: { + ok1: { + y: { + (string|〈1〉) + } + x: 〈0;y〉 + } + } + valueSelf: { + ok2: { + x: 〈0;y〉 + y: { + (string|〈1〉) + } + } + } + valueSelf: { + ok3: { + y: { + (〈1〉|string) + } + x: 〈0;y〉 + } + } + valueSelf: { + ok4: { + x: 〈0;y〉 + y: { + (〈1〉|string) + } + } + } + valueEmbed: { + ok1: { + y: { + (string|{ + 〈2〉 + }) + } + x: 〈0;y〉 + } + } + valueEmbed: { + ok2: { + x: 〈0;y〉 + y: { + (string|{ + 〈2〉 + }) + } + } + } + valueEmbed: { + ok3: { + y: { + ({ + 〈2〉 + }|string) + } + x: 〈0;y〉 + } + } + valueEmbed: { + ok4: { + x: 〈0;y〉 + y: { + ({ + 〈2〉 + }|string) + } + } + } + valueList: { + ok1: { + y: { + (string|[ + 〈2〉, + ]) + } + x: 〈0;y〉 + } + } + valueList: { + ok2: { + x: 〈0;y〉 + y: { + (string|[ + 〈2〉, + ]) + } + } + } + valueList: { + ok3: { + y: { + ([ + 〈2〉, + ]|string) + } + x: 〈0;y〉 + } + } + valueList: { + ok4: { + x: 〈0;y〉 + y: { + ([ + 〈2〉, + ]|string) + } + } + } + issue1729: { + t1: { + #x: { + (〈1;#x〉|{}) + } + x: (〈0;#x〉 & {}) + } + } + issue1729: { + t2: { + x: (〈0;#x〉 & {}) + #x: { + (〈1;#x〉|{}) + } + } + } +} +--- selfnew.cue +{ + issue4125: { + t1_self: { + let Root#1 = 〈1〉 + a: 〈0;let Root#1〉.a + } + } +} +--- selfold.cue +{ + issue4125: { + t2_alias: { + let Y#2 = 〈1〉 + b: 〈0;let Y#2〉.b + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/structural.txtar b/internal/core/compile/testdata/sync/cycle/structural.txtar new file mode 100644 index 000000000..df812a883 --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/structural.txtar @@ -0,0 +1,1679 @@ +-- in.cue -- +import "list" + +a1: { + f: [f] + @test(err, code=structural_cycle, path=f.0, contains="structural cycle", pos=[]) +} + +a2: { + f: f + @test(eq, {f: _}) +} + +a3: { + f: {g: f} + @test(err, code=structural_cycle, path=f.g, contains="structural cycle", pos=[]) +} + +a4: { + a: [a | int] + @test(eq, {a: [int]}) +} + +a5: { + a: b: a | int + @test(eq, {a: {b: int}}) +} + +a6: { + a: a | int + @test(eq, {a: _ | int}) +} + +a7: { + a: c.x + b: { + x: c + y: "foo" + } + c: { + x: b.y + y: 3 + } + @test(eq, { + a: "foo" + b: {x: {x: "foo", y: 3}, y: "foo"} + c: {x: "foo", y: 3} + }) +} + +b1: { + b: a & [1] + a: [a | int] + @test(eq, {b: [1], a: [int]}) +} + +b2: { + a: [a | int] + b: a & [1] + @test(eq, {a: [int], b: [1]}) +} + +b3: { + x: a: [a | int] + b: x & {a: [1]} + @test(eq, {x: {a: [int]}, b: {a: [1]}}) +} + +b4: { + b: x.y & [1] + x: y: [y] + @test(err, code=eval, path=b.0, contains="conflicting values %s and %s (mismatched types %s and %s)", args=[1, [y], int, list], pos=[1:5, 1:12, 2:8, 2:9]) +} + +// Ensure that the cycle error is not blindly copied to a referring field, +// as the cycle may not persist. +b4: cond1: { + b: x.y & { _z: false, [1] } + x: y: { + _z: *true | bool + if _z { + [y] + } + } + @test(err, code=structural_cycle, path=x.y.0, contains="structural cycle", pos=[]) +} + +// This reports a structural cycle at b4.cond2.b, because the value it refers +// has a structural cycle. Technically, this is incorrect, as the cycle +// really only occurs in b4.cond2.x.y. But since structural cycles are +// permanent, the entire configuration is invalidated, so the spurious +// additional cycle is merely cosmetic. By most logical standards, one can prove +// any fact from a contradiction. So assuming that, this is not incorrect. +// TODO: fix this cosmetic blemish. +b4: cond2: { + x: y: { + _z: *true | bool + if _z { + [y] + } + } + b: x.y & { _z: false, [1] } + @test(err, code=structural_cycle, path=x.y.0, contains="structural cycle", pos=[]) +} + +b5: { + b: x.y & {a: [1]} + x: y: a: [a | int] + @test(eq, {b: {a: [1]}, x: {y: {a: [int]}}}) +} + +b6: { + b: x & {a: [1]} + x: a: [a] + @test(err, code=eval, path=b.a.0, contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[1, [1], int, list], pos=[1:5, 1:13, 1:14, 2:9]) +} + +b7: { + b: a & [[1]] + a: [a] + @test(err, code=eval, path=b.0.0, contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[1, [a], int, list], pos=[1:5, 1:11, 2:5, 2:6]) +} + +// Issue #555 +b8: { + x: a + a: f: b + b: a | string + @test(eq, { + x: {f: string} + a: {f: string} + b: string + }) +} + +// Issue #555 +b9: { + #a: string | #b | #ref + #b: { + c: [#a, #a, #a] + } + #ref: ref: string + x: #b | #ref + @test(eq, { + #a: string | {ref: string} + #b: { + c: [string | {ref: string}, + string | {ref: string}, + string | {ref: string}] + } + #ref: {ref: string} + x: {c: [string | {ref: string}, + string | {ref: string}, + string | {ref: string}]} | {ref: string} + }) +} + +// Issue #534 +// TODO: the resolution here is arguably incorrect: c should be +// d: string | { b: string } +// However, this is not the end of the world, as the disjunction is preserved +// under the hood and still unifies with extended structure. +b10: { + a: close({ + b: string | a | c + }) + c: close({ + d: string | a + }) + + d: d: b: string + @test(eq, { + a: {b: string | {d: string}} + c: { + d: string | {b: string | {b: string | {b: string}}} + } + d: {d: {b: string}} + }) +} + +// Issue #509 -- with comprehension +b11: { + #list: { + tail: #list | *null + if tail != null { + } + } + @test(eq, {#list: {tail: null}}) +} + +// Issue #509 -- with comprehension +b12: { + #list: { + V=value: int + T=tail: #list | *null + if T != null { + sum: V + T.sum + } + if T == null { + sum: V + } + } + + list1: #list + list1: { + value: 1 + tail: { + value: 2 + tail: { + value: 3 + tail: { + value: 4 + } + } + } + } + @test(eq, { + #list: {value: int, tail: null, sum: int} + list1: { + value: 1 + tail: { + value: 2 + tail: { + value: 3 + tail: { + value: 4 + tail: *null | {value: int, tail: null, sum: int} + sum: 4 + } + sum: 7 + } + sum: 9 + } + sum: 10 + } + }) +} + +// More trigger happy on stack overflows. +b12b: { + #list: { + tail: #list + + if tail != null { + sum: tail.sum + } + } @test(err, code=structural_cycle, path=tail, contains="structural cycle", pos=[]) + + list1: #list @test(err, code=structural_cycle, path=b12b.#list.tail, contains="structural cycle", pos=[]) + list1: { + tail: { + tail: { + } + } + } +} + +// Issue #587 +b13: { + root: a: [for x in root {x}] + @test(err, code=structural_cycle, path=root.a.0.0, contains="structural cycle", pos=[]) +} + +// Issue #587 +// TODO: this should probably be okay if we allow shallow evaluation of +// comprehension sources. See #1881. +b14: { + root: { + a: [...int] + + for x in a { + "\(x)": {} + } + + b: [for x in root {x}] + } + @test(err, code=structural_cycle, path=root.b.1.1, contains="structural cycle", pos=[]) +} + +// This is okay +// Issue #587 +b15: { + root: a: {for x in root {x}} + @test(eq, {root: {a: {}}}) +} + +// Issue #502 -- unused bulk constraints are not cyclic +p1: { + #T: { + a: [string]: link: #T + } + + a: #T & { + a: one: link: a: two: {} + } + @test(eq, { + #T: {a: {}} + a: { + a: { + one: {link: {a: {two: {link: {a: {}}}}}} + } + } + }) +} + +// Issue #502 -- but they are if it is invoked within the struct. +p2: { + #T: { + a: [string]: link: #T + a: b: {} + } + + a: #T & { + a: one: link: a: two: {} + } + @test(eq, {one: {link: {a: {two: {}}}}}, at=a.a) + @test(err, code=structural_cycle, path=#T.a.b.link, contains="structural cycle", pos=[]) +} + +// Issue #502 -- or added later. +p3: { + #S: #T: { + a: [string]: link: #T + } + + #U: { + #S + #T: a: b: {} + } @test(err, code=structural_cycle, path=#T.a.b.link, contains="structural cycle", pos=[]) + + a: #U.#T & { + a: one: link: a: two: {} + } @test(err, code=structural_cycle, path=p3.#U.#T.a.b.link, contains="structural cycle", pos=[]) +} + +// Issue #502 -- unused bulk constraints are not cyclic +p4: { + #T: { + a: [...{link: #T}] + } + + a: #T & { + a: [{link: a: [{}]}] + } + @test(eq, { + #T: {a: []} + a: {a: [{link: {a: [{link: {a: []}}]}}]} + }) +} + +// Issue #502 -- but they are if it is invoked within the struct. +p5: { + #T: { + a: [...{link: #T}] + a: [{}] + } + + a: #T & { + a: [{link: a: [{}]}] + } + @test(err, code=structural_cycle, path=#T.a.0.link, contains="structural cycle", pos=[]) + @test(eq, [{link: {a: [{}]}}], at=a.a) +} + +// Issue #502 -- or added later. +p6: { + #S: #T: { + a: [...{link: #T}] + } + + #U: { + #S + #T: a: [{}] + } @test(err, code=structural_cycle, path=#T.a.0.link, contains="structural cycle", pos=[]) + + a: #U.#T & { + a: [{link: a: [{}]}] + } @test(err, code=structural_cycle, path=p6.#U.#T.a.0.link, contains="structural cycle", pos=[]) +} + +c1: { + a: { + b: {} + c: a & b + } + @test(err, code=structural_cycle, path=a.c.c, contains="structural cycle", pos=[]) +} + +// indirection +d1: { + a: b: c: d: {h: int, t: r} + @test(err, at=a.b.c.d.t, code=structural_cycle, path=d1.r, contains="structural cycle", pos=[]) + + r: a.b @test(err, code=structural_cycle, contains="structural cycle", pos=[]) + + x: a.b.c + +} + +d2: { + x: a.b.c @test(shareID=X) + @test(shareID=X, at=a.b.c) + + r: a.b @test(shareID=R) + @test(shareID=R, at=a.b) + + a: b: c: d: {h: int, t: r} +} + +d3: { + config: { + a: b: c: indirect + indirect: [a.b, null][i] + i: int | *1 + } + x: config & {i: 0} + @test(err, at=x.indirect, code=structural_cycle, contains="structural cycle", pos=[]) + @test(err, at=x.a.b.c, code=structural_cycle, contains="structural cycle", pos=[]) + @test(eq, at=config, { + a: {b: {c: null}} + indirect: null + i: *1 | int + }) +} + +// Ensure that the cycles here fail early. +// TODO: they can still be shorter. +shortPathFail: _ + +shortPathFail: doubleRef: { + // Avoid this: the first #List reference is different from the second, so + // the second #List reference counts as a first occurrence, causing the + // result to be longer than perhaps expected. + a: #List + #List: Next: #List | *null + @test(eq, {a: {Next: null}, #List: {Next: null}}) +} + +shortPathFail: elipsis: { + // Avoid this: the elipsis causes `_` to be mixed in with the #Foo + // reference, causing the first cycle to be discounted. + t1: { + #Foo: ref: null | #Foo + #Foo: { ... } + @test(eq, {#Foo: {ref: null}}) + } + t2: { + Foo: ref: Foo + Foo: {...} + @test(err, code=structural_cycle, at=Foo.ref, contains="structural cycle", pos=[]) + } +} + +// Issue #2374: a pattern constraint with an alias referring back to itself +// (e.g., `r=[string]: {b: r}`) should be detected as a structural cycle, +// but the evaluator instead emitted output with a renamed alias. +// https://cuelang.org/issue/2374 +patternFail: issue2374: { + r=[string]: {b: r} + a: {r: 0} + @test(err, code=structural_cycle, at=a.b, contains="structural cycle", pos=[]) +} + +shortPathFail: comprehension: { + #list: { + tail: #list | *null + if tail != null { + } + } + @test(eq, {#list: {tail: null}}) +} + +withLetFail: { + schema: next: _schema_1 + let _schema_1 = schema + @test(err, code=structural_cycle, at=schema.next, contains="structural cycle", pos=[]) +} + +// Issue #3310: `list.Sum` called with a comprehension iterating over the +// enclosing struct causes a structural cycle because `total` is included in +// its own computation. The cycle error is correct; evalv2 incorrectly produced +// a wrong numeric result instead of erroring. +// https://cuelang.org/issue/3310 +fieldsSumInfinite: issue3310: { + cheeseburger: 3.00 + fries: 2.00 + sprite: 1.00 + + total: list.Sum([for _, v in issue3310 {v}]) + @test(err, code=structural_cycle, at=total, contains="error in call to %s", args=[list.Sum], pos=[5:9]) +} + +listOptOK: { + list: { + head: int + tail?: list + } + a: list & {head: 3, tail: head: 2} + @test(eq, { + list: { + head: int + tail?: _|_ @test(err, code=structural_cycle, contains="list.tail: structural cycle", pos=[]) + } + a: { + head: 3 + tail: { + head: 2 + tail?: { + head: int + tail?: _|_ @test(err, code=structural_cycle, contains="list.tail: structural cycle", pos=[]) + } + } + } + }) +} + +// The cyclic definitions below used to work OK on old versions of evalv2, +// and broke around the release of CUE v0.6.0. evalv3 fixes this again. +// It should succeed, given that the optional field breaks the cycle. +issue2545: { + #A: { + B?: #B + } + #B: { + A: #A + } + @test(err, code=structural_cycle, + hint="the comment says this should succeed since the optional field breaks the cycle, but it still errors in both v2 and v3") + @test(eq:todo, { + #A: {B?: _ @test(ignore)} + #B: {A: {B?: _|_}} + }) +} + +// combining structural with reference cycles +e1: { + a: a + a: c: a + + b: c: b + b: b + @test(err, code=structural_cycle, at=a.c, contains="structural cycle", pos=[]) + @test(err, code=structural_cycle, at=b.c, contains="structural cycle", pos=[]) +} + +e2: { + a: {a} + a: c: a + + b: c: b + b: {b} + @test(err, code=structural_cycle, at=a.c, contains="structural cycle", pos=[]) + @test(err, code=structural_cycle, at=b.c, contains="structural cycle", pos=[]) +} + +e3: { + a: [a] @test(err, code=eval, contains="conflicting values %s and %s (mismatched types %s and %s)", args=[[a], {c:a}, list, struct], pos=[0:5, 1:5]) + a: c: a @test(err, code=structural_cycle, contains="structural cycle", pos=[]) + + b: [b] @test(err, code=eval, contains="conflicting values %s and %s (mismatched types %s and %s)", args=[[b], {c:b}, list, struct], pos=[0:5, 1:5]) + b: c: b +} + +e4: { + a: [a | {}] + a: [[{c: 1}]] + + b: [[{c: 1}]] + b: [b | {}] + @test(err, code=eval, + suberr=(code=eval, path=a.0, contains="conflicting values %s and %s (mismatched types %s and %s)", args=[[{c:1}], {}, list, struct], pos=[1:10, 2:6]), + suberr=(code=eval, path=a.0.0, contains="conflicting values %s and %s (mismatched types %s and %s)", args=[{c:1}, [{c:1}], struct, list], pos=[1:6, 2:6, 2:7])) +} + +e5: { + a: c: a | int + a: a | int + + b: b | int + b: c: b | int + @test(eq, {a: {c: int}, b: {c: int}}) +} + +// validating values +nestedList: { + v1e: { + x: [x | int, 1] + y: x & [[[2], 1], 1] + @test(err, code=eval, + suberr=(code=eval, path=y.0, contains="conflicting values %s and %s (mismatched types %s and %s)", pos=[1:11, 2:6, 2:11]), + suberr=(code=eval, path=y.0.0, contains="%d errors in empty disjunction:", args=[2], pos=[]), + suberr=(code=eval, path=y.0.0, contains="conflicting values %s and %s (mismatched types %s and %s)", pos=[1:7, 1:11, 2:6, 2:12]), + suberr=(code=eval, path=y.0.0, contains="incompatible list lengths (%d and %d)", args=[1, 2], pos=[1:6])) + } + + v2e: { + y: x & [[[2], 1], 1] + x: [x | int, 1] + @test(err, code=eval, + suberr=(code=eval, path=y.0, contains="conflicting values %s and %s (mismatched types %s and %s)", pos=[1:6, 1:11, 2:11]), + suberr=(code=eval, path=y.0.0, contains="%d errors in empty disjunction:", args=[2], pos=[]), + suberr=(code=eval, path=y.0.0, contains="conflicting values %s and %s (mismatched types %s and %s)", pos=[1:6, 1:12, 2:7, 2:11]), + suberr=(code=eval, path=y.0.0, contains="incompatible list lengths (%d and %d)", args=[1, 2], pos=[2:6])) + } + + v1: { + x: [x | int, 1] + y: x & [[[2, 1], 1], 1] + @test(eq, {x: [int, 1], y: [[[2, 1], 1], 1]}) + } + + v2: { + y: x & [[[2, 1], 1], 1] + x: [x | int, 1] + @test(eq, {y: [[[2, 1], 1], 1], x: [int, 1]}) + } +} + +v3: { + list: { + head: int + tail: list | null + } + + myList: list + myList: { + head: 2 + tail: { + head: 3 + tail: { + head: 4 + } + } + } + @test(eq, { + list: {head: int, tail: null} + myList: { + head: 2 + tail: { + head: 3 + tail: { + head: 4 + tail: {head: int, tail: null} | null + } + } + } + }) +} + +v4: { + list: { + head: int + tail: list | 1 + } + + myList: list + myList: { + head: 2 + tail: head: 3 + } + @test(eq, { + list: {head: int, tail: 1} + myList: { + head: 2 + tail: { + head: 3 + tail: {head: int, tail: 1} | 1 + } + } + }) +} + +v5: { + list: { + head: int + tail: list | {} + } + + myList: list + myList: { + head: 2 + tail: head: 3 + } + @test(eq, { + list: {head: int, tail: {}} + myList: { + head: 2 + tail: {head: 3, tail: {head: int, tail: {}} | {}} | {head: 3} + } + }) +} + +// Example from "The Logic of Type Feature Structures" (Bob Carpenter)/ +z1: { + y: { + f: h: g + g: _ + } + x: { + f: _ + g: f + } + z: x & y + @test(err, code=structural_cycle, path=z.g, contains="structural cycle", pos=[]) +} + +// Cross references. Here there is no cycle, but the repeated instantiations +// of T will cause, in turn, cause repeated resolution of `x`. The algorithm +// should not identify these as cyclic references. Instead, it should be +// noted that the reference is each time referring to new content. +// Issue #754 +crossRefNoCycle: t1: { + T: { + x: _ + y: x + } + C: { x: T } & T + @test(eq, { + T: {x: _, y: _} + C: {x: {x: _, y: _}, y: {x: _, y: _}} + }) +} + +crossRefNoCycle: t2: { + T: { + x: _ + y: x + } + C: T & { x: T } + @test(eq, { + T: {x: _, y: _} + C: {x: {x: _, y: _}, y: {x: _, y: _}} + }) +} + +crossRefNoCycle: t3: { + T: { + x: _ + y: x + z: y + } + C: T & { x: T } + @test(eq, { + T: {x: _, y: _, z: _} + C: { + x: {x: _, y: _, z: _} + y: {x: _, y: _, z: _} + z: {x: _, y: _, z: _} + } + }) +} + +crossRefNoCycle: t4: { + T: { + x: _ + y: x + z: y + } + C: T & { x: T & { x: T } } + @test(eq, { + T: {x: _, y: _, z: _} + C: { + x: { + x: {x: _, y: _, z: _} + y: {x: _, y: _, z: _} + z: {x: _, y: _, z: _} + } + y: { + x: {x: _, y: _, z: _} + y: {x: _, y: _, z: _} + z: {x: _, y: _, z: _} + } + z: { + x: {x: _, y: _, z: _} + y: {x: _, y: _, z: _} + z: {x: _, y: _, z: _} + } + } + }) +} + +crossRefNoCycle: t5: { + T: X={ + y: X.x + } + C: T & { x: T } + @test(eq, { + T: { + y: _|_ @test(err, code=incomplete, contains="crossRefNoCycle.t5.T.y: undefined field: x", pos=[785:8]) + } + C: { + x: { + y: _|_ @test(err, code=incomplete, contains="crossRefNoCycle.t5.T.y: undefined field: x", pos=[785:8]) + } + y: { + y: _|_ @test(err, code=incomplete, contains="crossRefNoCycle.t5.T.y: undefined field: x", pos=[785:8]) + } + } + }) +} + +// Ensure these are NOT treated as structural errors. + +n1: { + a: b: int + @test(eq, {a: {b: int}}) +} +n2: { + n1 + a: n1 + @test(eq, {a: {b: int, a: {b: int}}}) +} +n3: { + n1 + @test(eq, {a: {b: int}}) +} +n4: { + n1 + x: { + n1 + y: { + n1 + z: int + } + } + @test(eq, { + x: {y: {z: int, a: {b: int}}, a: {b: int}} + a: {b: int} + }) +} +-- edge.cue -- +// TODO(eval): notice the difference, not a huge deal, but still. +resolveToAncestor: { + t1: X: { + a: b.a @test(eq, _) @test(err:todo, code=structural_cycle) + b: X @test(err, code=structural_cycle, contains="structural cycle", pos=[]) + } + t2: X: { + b: X @test(err, code=structural_cycle, contains="structural cycle", pos=[]) + a: b.a @test(err, code=structural_cycle, path=resolveToAncestor.t2.X.b, contains="structural cycle", pos=[]) + } +} +-- out/compile -- +--- edge.cue +{ + resolveToAncestor: { + t1: { + X: { + a: 〈0;b〉.a + b: 〈1;X〉 + } + } + t2: { + X: { + b: 〈1;X〉 + a: 〈0;b〉.a + } + } + } +} +--- in.cue +{ + a1: { + f: [ + 〈1;f〉, + ] + } + a2: { + f: 〈0;f〉 + } + a3: { + f: { + g: 〈1;f〉 + } + } + a4: { + a: [ + (〈1;a〉|int), + ] + } + a5: { + a: { + b: (〈1;a〉|int) + } + } + a6: { + a: (〈0;a〉|int) + } + a7: { + a: 〈0;c〉.x + b: { + x: 〈1;c〉 + y: "foo" + } + c: { + x: 〈1;b〉.y + y: 3 + } + } + b1: { + b: (〈0;a〉 & [ + 1, + ]) + a: [ + (〈1;a〉|int), + ] + } + b2: { + a: [ + (〈1;a〉|int), + ] + b: (〈0;a〉 & [ + 1, + ]) + } + b3: { + x: { + a: [ + (〈1;a〉|int), + ] + } + b: (〈0;x〉 & { + a: [ + 1, + ] + }) + } + b4: { + b: (〈0;x〉.y & [ + 1, + ]) + x: { + y: [ + 〈1;y〉, + ] + } + } + b4: { + cond1: { + b: (〈0;x〉.y & { + _z: false + [ + 1, + ] + }) + x: { + y: { + _z: (*true|bool) + if 〈0;_z〉 { + [ + 〈3;y〉, + ] + } + } + } + } + } + b4: { + cond2: { + x: { + y: { + _z: (*true|bool) + if 〈0;_z〉 { + [ + 〈3;y〉, + ] + } + } + } + b: (〈0;x〉.y & { + _z: false + [ + 1, + ] + }) + } + } + b5: { + b: (〈0;x〉.y & { + a: [ + 1, + ] + }) + x: { + y: { + a: [ + (〈1;a〉|int), + ] + } + } + } + b6: { + b: (〈0;x〉 & { + a: [ + 1, + ] + }) + x: { + a: [ + 〈1;a〉, + ] + } + } + b7: { + b: (〈0;a〉 & [ + [ + 1, + ], + ]) + a: [ + 〈1;a〉, + ] + } + b8: { + x: 〈0;a〉 + a: { + f: 〈1;b〉 + } + b: (〈0;a〉|string) + } + b9: { + #a: (string|〈0;#b〉|〈0;#ref〉) + #b: { + c: [ + 〈2;#a〉, + 〈2;#a〉, + 〈2;#a〉, + ] + } + #ref: { + ref: string + } + x: (〈0;#b〉|〈0;#ref〉) + } + b10: { + a: close({ + b: (string|〈1;a〉|〈1;c〉) + }) + c: close({ + d: (string|〈1;a〉) + }) + d: { + d: { + b: string + } + } + } + b11: { + #list: { + tail: (〈1;#list〉|*null) + if (〈0;tail〉 != null) {} + } + } + b12: { + #list: { + value: int + tail: (〈1;#list〉|*null) + if (〈0;tail〉 != null) { + sum: (〈1;value〉 + 〈1;tail〉.sum) + } + if (〈0;tail〉 == null) { + sum: 〈1;value〉 + } + } + list1: 〈0;#list〉 + list1: { + value: 1 + tail: { + value: 2 + tail: { + value: 3 + tail: { + value: 4 + } + } + } + } + } + b12b: { + #list: { + tail: 〈1;#list〉 + if (〈0;tail〉 != null) { + sum: 〈1;tail〉.sum + } + } + list1: 〈0;#list〉 + list1: { + tail: { + tail: {} + } + } + } + b13: { + root: { + a: [ + for _, x in 〈2;root〉 { + 〈1;x〉 + }, + ] + } + } + b14: { + root: { + a: [ + ...int, + ] + for _, x in 〈0;a〉 { + "\(〈1;x〉)": {} + } + b: [ + for _, x in 〈2;root〉 { + 〈1;x〉 + }, + ] + } + } + b15: { + root: { + a: { + for _, x in 〈2;root〉 { + 〈1;x〉 + } + } + } + } + p1: { + #T: { + a: { + [string]: { + link: 〈3;#T〉 + } + } + } + a: (〈0;#T〉 & { + a: { + one: { + link: { + a: { + two: {} + } + } + } + } + }) + } + p2: { + #T: { + a: { + [string]: { + link: 〈3;#T〉 + } + } + a: { + b: {} + } + } + a: (〈0;#T〉 & { + a: { + one: { + link: { + a: { + two: {} + } + } + } + } + }) + } + p3: { + #S: { + #T: { + a: { + [string]: { + link: 〈3;#T〉 + } + } + } + } + #U: { + 〈1;#S〉 + #T: { + a: { + b: {} + } + } + } + a: (〈0;#U〉.#T & { + a: { + one: { + link: { + a: { + two: {} + } + } + } + } + }) + } + p4: { + #T: { + a: [ + ...{ + link: 〈3;#T〉 + }, + ] + } + a: (〈0;#T〉 & { + a: [ + { + link: { + a: [ + {}, + ] + } + }, + ] + }) + } + p5: { + #T: { + a: [ + ...{ + link: 〈3;#T〉 + }, + ] + a: [ + {}, + ] + } + a: (〈0;#T〉 & { + a: [ + { + link: { + a: [ + {}, + ] + } + }, + ] + }) + } + p6: { + #S: { + #T: { + a: [ + ...{ + link: 〈3;#T〉 + }, + ] + } + } + #U: { + 〈1;#S〉 + #T: { + a: [ + {}, + ] + } + } + a: (〈0;#U〉.#T & { + a: [ + { + link: { + a: [ + {}, + ] + } + }, + ] + }) + } + c1: { + a: { + b: {} + c: (〈1;a〉 & 〈0;b〉) + } + } + d1: { + a: { + b: { + c: { + d: { + h: int + t: 〈4;r〉 + } + } + } + } + r: 〈0;a〉.b + x: 〈0;a〉.b.c + } + d2: { + x: 〈0;a〉.b.c + r: 〈0;a〉.b + a: { + b: { + c: { + d: { + h: int + t: 〈4;r〉 + } + } + } + } + } + d3: { + config: { + a: { + b: { + c: 〈2;indirect〉 + } + } + indirect: [ + 〈1;a〉.b, + null, + ][〈0;i〉] + i: (int|*1) + } + x: (〈0;config〉 & { + i: 0 + }) + } + shortPathFail: _ + shortPathFail: { + doubleRef: { + a: 〈0;#List〉 + #List: { + Next: (〈1;#List〉|*null) + } + } + } + shortPathFail: { + elipsis: { + t1: { + #Foo: { + ref: (null|〈1;#Foo〉) + } + #Foo: { + ... + } + } + t2: { + Foo: { + ref: 〈1;Foo〉 + } + Foo: { + ... + } + } + } + } + patternFail: { + issue2374: { + [string]: { + b: 〈1;(〈0;-〉)〉 + } + a: { + r: 0 + } + } + } + shortPathFail: { + comprehension: { + #list: { + tail: (〈1;#list〉|*null) + if (〈0;tail〉 != null) {} + } + } + } + withLetFail: { + schema: { + next: 〈1;let _schema_1#1〉 + } + let _schema_1#1 = 〈0;schema〉 + } + fieldsSumInfinite: { + issue3310: { + cheeseburger: 3.00 + fries: 2.00 + sprite: 1.00 + total: 〈import;list〉.Sum([ + for _, v in 〈2;issue3310〉 { + 〈1;v〉 + }, + ]) + } + } + listOptOK: { + list: { + head: int + tail?: 〈1;list〉 + } + a: (〈0;list〉 & { + head: 3 + tail: { + head: 2 + } + }) + } + issue2545: { + #A: { + B?: 〈1;#B〉 + } + #B: { + A: 〈1;#A〉 + } + } + e1: { + a: 〈0;a〉 + a: { + c: 〈1;a〉 + } + b: { + c: 〈1;b〉 + } + b: 〈0;b〉 + } + e2: { + a: { + 〈1;a〉 + } + a: { + c: 〈1;a〉 + } + b: { + c: 〈1;b〉 + } + b: { + 〈1;b〉 + } + } + e3: { + a: [ + 〈1;a〉, + ] + a: { + c: 〈1;a〉 + } + b: [ + 〈1;b〉, + ] + b: { + c: 〈1;b〉 + } + } + e4: { + a: [ + (〈1;a〉|{}), + ] + a: [ + [ + { + c: 1 + }, + ], + ] + b: [ + [ + { + c: 1 + }, + ], + ] + b: [ + (〈1;b〉|{}), + ] + } + e5: { + a: { + c: (〈1;a〉|int) + } + a: (〈0;a〉|int) + b: (〈0;b〉|int) + b: { + c: (〈1;b〉|int) + } + } + nestedList: { + v1e: { + x: [ + (〈1;x〉|int), + 1, + ] + y: (〈0;x〉 & [ + [ + [ + 2, + ], + 1, + ], + 1, + ]) + } + v2e: { + y: (〈0;x〉 & [ + [ + [ + 2, + ], + 1, + ], + 1, + ]) + x: [ + (〈1;x〉|int), + 1, + ] + } + v1: { + x: [ + (〈1;x〉|int), + 1, + ] + y: (〈0;x〉 & [ + [ + [ + 2, + 1, + ], + 1, + ], + 1, + ]) + } + v2: { + y: (〈0;x〉 & [ + [ + [ + 2, + 1, + ], + 1, + ], + 1, + ]) + x: [ + (〈1;x〉|int), + 1, + ] + } + } + v3: { + list: { + head: int + tail: (〈1;list〉|null) + } + myList: 〈0;list〉 + myList: { + head: 2 + tail: { + head: 3 + tail: { + head: 4 + } + } + } + } + v4: { + list: { + head: int + tail: (〈1;list〉|1) + } + myList: 〈0;list〉 + myList: { + head: 2 + tail: { + head: 3 + } + } + } + v5: { + list: { + head: int + tail: (〈1;list〉|{}) + } + myList: 〈0;list〉 + myList: { + head: 2 + tail: { + head: 3 + } + } + } + z1: { + y: { + f: { + h: 〈1;g〉 + } + g: _ + } + x: { + f: _ + g: 〈0;f〉 + } + z: (〈0;x〉 & 〈0;y〉) + } + crossRefNoCycle: { + t1: { + T: { + x: _ + y: 〈0;x〉 + } + C: ({ + x: 〈1;T〉 + } & 〈0;T〉) + } + } + crossRefNoCycle: { + t2: { + T: { + x: _ + y: 〈0;x〉 + } + C: (〈0;T〉 & { + x: 〈1;T〉 + }) + } + } + crossRefNoCycle: { + t3: { + T: { + x: _ + y: 〈0;x〉 + z: 〈0;y〉 + } + C: (〈0;T〉 & { + x: 〈1;T〉 + }) + } + } + crossRefNoCycle: { + t4: { + T: { + x: _ + y: 〈0;x〉 + z: 〈0;y〉 + } + C: (〈0;T〉 & { + x: (〈1;T〉 & { + x: 〈2;T〉 + }) + }) + } + } + crossRefNoCycle: { + t5: { + T: { + y: 〈1〉.x + } + C: (〈0;T〉 & { + x: 〈1;T〉 + }) + } + } + n1: { + a: { + b: int + } + } + n2: { + 〈1;n1〉 + a: 〈1;n1〉 + } + n3: { + 〈1;n1〉 + } + n4: { + 〈1;n1〉 + x: { + 〈2;n1〉 + y: { + 〈3;n1〉 + z: int + } + } + } +} diff --git a/internal/core/compile/testdata/sync/cycle/with_defaults.txtar b/internal/core/compile/testdata/sync/cycle/with_defaults.txtar new file mode 100644 index 000000000..4a344457b --- /dev/null +++ b/internal/core/compile/testdata/sync/cycle/with_defaults.txtar @@ -0,0 +1,36 @@ +# Tests cycle patterns involving default values and range constraints. +-- in.cue -- +range1: { + min: *1 | int + range: >min + range: 8 + @test(eq, {min: *1 | int, range: 8}) +} +range2: { + min: *1 | int + max: int & >min + @test(eq, {min: *1 | int, max: >1 & int}) +} +rg: range2 +rg: { + // min: 1 + max: 8 + @test(eq, {max: 8, min: *1 | int}) +} +-- out/compile -- +--- in.cue +{ + range1: { + min: (*1|int) + range: >〈0;min〉 + range: 8 + } + range2: { + min: (*1|int) + max: (int & >〈0;min〉) + } + rg: 〈0;range2〉 + rg: { + max: 8 + } +} diff --git a/internal/core/compile/testdata/sync/definitions/026_combined_definitions.txtar b/internal/core/compile/testdata/sync/definitions/026_combined_definitions.txtar new file mode 100644 index 000000000..35fa385fc --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/026_combined_definitions.txtar @@ -0,0 +1,76 @@ +#name: combined definitions +#evalPartial +-- in.cue -- +// Allow combining of structs within a definition +#D1: { + env: a: "A" + env: b: "B" + #def: {a: "A"} + #def: {b: "B"} +} +d1: #D1 & {env: c: "C" } @test(err, at=env.c, code=eval, contains="field not allowed", pos=[0:17]) +#D2: { + a: int +} +#D2: { + b: int +} @test(eq, {a: int, b: int}) +#D3: { + env: a: "A" +} +#D3: { + env: b: "B" +} @test(eq, { env: { a: "A", b: "B" } }) +#D4: { + env: #DC + env: b: int @test(err, code=eval, contains="field not allowed", pos=[0:7]) +} +#DC: {a: int} +-- out/compile -- +--- in.cue +{ + #D1: { + env: { + a: "A" + } + env: { + b: "B" + } + #def: { + a: "A" + } + #def: { + b: "B" + } + } + d1: (〈0;#D1〉 & { + env: { + c: "C" + } + }) + #D2: { + a: int + } + #D2: { + b: int + } + #D3: { + env: { + a: "A" + } + } + #D3: { + env: { + b: "B" + } + } + #D4: { + env: 〈1;#DC〉 + env: { + b: int + } + } + #DC: { + a: int + } +} diff --git a/internal/core/compile/testdata/sync/definitions/028_recursive_closing_starting_at_non-definition.txtar b/internal/core/compile/testdata/sync/definitions/028_recursive_closing_starting_at_non-definition.txtar new file mode 100644 index 000000000..ef6b30d5d --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/028_recursive_closing_starting_at_non-definition.txtar @@ -0,0 +1,36 @@ + +#name: recursive closing starting at non-definition +#evalPartial +-- in.cue -- +z: a: { + #B: { + c: d: 1 + c: f: 1 + } +} +A: z & {a: {#B: {c: e: 2}}} @test(eq, {a: #B: c: {e: 2, d: 1, f: 1}}) +-- out/compile -- +--- in.cue +{ + z: { + a: { + #B: { + c: { + d: 1 + } + c: { + f: 1 + } + } + } + } + A: (〈0;z〉 & { + a: { + #B: { + c: { + e: 2 + } + } + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/032_definitions_with_embedding.txtar b/internal/core/compile/testdata/sync/definitions/032_definitions_with_embedding.txtar new file mode 100644 index 000000000..6be6dfd0a --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/032_definitions_with_embedding.txtar @@ -0,0 +1,46 @@ +-- in.cue -- +#E: { + a: {b: int} +} + +#S: { + #E + a: {c: int} + b: 3 +} @test(eq, { + a: {b: int, c: int} + b: 3 +}) + +// adding a field to a nested struct that is closed. +#e1: #S & {a: d: 4} @test(err, at=a.d, code=eval, + contains="field not allowed", pos=[0:15]) + +// literal struct not closed until after unification. +#v1: #S & {a: c: 4} @test(eq, {a: {b: int, c: 4}, b: 3}) +-- out/compile -- +--- in.cue +{ + #E: { + a: { + b: int + } + } + #S: { + 〈1;#E〉 + a: { + c: int + } + b: 3 + } + #e1: (〈0;#S〉 & { + a: { + d: 4 + } + }) + #v1: (〈0;#S〉 & { + a: { + c: 4 + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/033_Issue_#153.txtar b/internal/core/compile/testdata/sync/definitions/033_Issue_#153.txtar new file mode 100644 index 000000000..21eb1a714 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/033_Issue_#153.txtar @@ -0,0 +1,57 @@ +# Tests that a comprehension-generated struct merged into a list element +# constrained by a closed definition correctly rejects fields not declared +# in the definition. Fields introduced via comprehension inside a list +# literal should still be subject to closedness checks. +# Issue: https://cuelang.org/issue/153 +-- in.cue -- +Foo: { + listOfCloseds: [...#Closed] +} + +#Closed: { + a: int | *0 +} + +Junk: { + b: 2 @test(eq, 2) +} + +Foo & { + listOfCloseds: [{ + for k, v in Junk { + "\(k)": v + } + }] +} +@test(eq, { + Foo: listOfCloseds: [] + #Closed: a: int | *0 + Junk: b: 2 + listOfCloseds: _|_ @test(err, at=0.b, code=eval, + hint="considerably more positions could be useful", + contains="field not allowed", pos=[16:4]) +}) +-- out/compile -- +--- in.cue +{ + Foo: { + listOfCloseds: [ + ...〈2;#Closed〉, + ] + } + #Closed: { + a: (int|*0) + } + Junk: { + b: 2 + } + (〈0;Foo〉 & { + listOfCloseds: [ + { + for k, v in 〈3;Junk〉 { + "\(〈1;k〉)": 〈1;v〉 + } + }, + ] + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/036_closing_with_failed_optional.txtar b/internal/core/compile/testdata/sync/definitions/036_closing_with_failed_optional.txtar new file mode 100644 index 000000000..1bf7ec5e2 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/036_closing_with_failed_optional.txtar @@ -0,0 +1,68 @@ +-- in.cue -- +#k1: {a: int, b?: int} & #A @test(eq, {a: int}) @test(closed) + +#k2: #A & {a: int, b?: int} @test(eq, {a: int}) @test(closed) + +o1: {a?: 3} & {a?: 4} @test(eq, {a?: _|_}) @test(closed=false) + +// Optional fields with error values can be eliminated when closing +#o2: {a?: 3} & {a?: 4} @test(eq, {}) @test(closed) + +#d1: {a?: 2, b: 4} | {a?: 3, c: 5} @test(closed) @test(eq, { + a?: 2 + b: 4 + } | { + a?: 3 + c: 5 + }) + +// Note: a? can be discarded safely. +v1: #d1 & {a?: 3, b: 4} @test(closed) @test(eq, {b: 4}) @test(debug, """ + (#struct){ + a?: (_|_){ + // [eval] v1.a: conflicting values 2 and 3: + // in.cue:10:11 + // in.cue:19:5 + // in.cue:19:16 + } + b: (int){ 4 } + } + """) + +#A: {a: int} +-- out/compile -- +--- in.cue +{ + #k1: ({ + a: int + b?: int + } & 〈0;#A〉) + #k2: (〈0;#A〉 & { + a: int + b?: int + }) + o1: ({ + a?: 3 + } & { + a?: 4 + }) + #o2: ({ + a?: 3 + } & { + a?: 4 + }) + #d1: ({ + a?: 2 + b: 4 + }|{ + a?: 3 + c: 5 + }) + v1: (〈0;#d1〉 & { + a?: 3 + b: 4 + }) + #A: { + a: int + } +} diff --git a/internal/core/compile/testdata/sync/definitions/036_optionals_in_open_structs.txtar b/internal/core/compile/testdata/sync/definitions/036_optionals_in_open_structs.txtar new file mode 100644 index 000000000..ad442fed1 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/036_optionals_in_open_structs.txtar @@ -0,0 +1,29 @@ +-- in.cue -- +A: { + [=~"^[a-s]*$"]: int +} +B: { + [=~"^[m-z]*$"]: int +} +#C: {A & B} +c: #C & {aaa: 3} @test(eq, { + [=~"^[a-s]*$"]: int + [=~"^[m-z]*$"]: int + aaa: 3 +}) +-- out/compile -- +--- in.cue +{ + A: { + [=~"^[a-s]*$"]: int + } + B: { + [=~"^[m-z]*$"]: int + } + #C: { + (〈1;A〉 & 〈1;B〉) + } + c: (〈0;#C〉 & { + aaa: 3 + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/037_closing_with_comprehensions.txtar b/internal/core/compile/testdata/sync/definitions/037_closing_with_comprehensions.txtar new file mode 100644 index 000000000..6c4d4c14c --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/037_closing_with_comprehensions.txtar @@ -0,0 +1,80 @@ +#name: closing with comprehensions +#evalPartial +-- in.cue -- +#A: {f1: int, f2: int} @test(eq, {f1: int, f2: int}) @test(closed) + +for k, v in {f3: int} { + a: #A & {"\(k)": v} +} +@test(err, at=a.f3, code=eval, contains="field not allowed", pos=[-2:11]) + +#B: { + for k, v in {f1: int} { + "\(k)": v + } +} @test(eq, { f1: int }) + +#C: { + f1: _ + for k, v in {f1: int} { + "\(k)": v + } +} @test(eq, { f1: int }) @test(closed) @test(allows=false, string) + +#D: { + for k, v in {f1: int} { + "\(k)": v + } + ... +} @test(eq, { f1: int }) @test(closed) @test(allows, string) + +#E: #A & { + for k, v in {f3: int} { + "\(k)": v + } +} @test(err, at=f3, code=eval, contains="field not allowed", pos=[2:3]) +-- out/compile -- +--- in.cue +{ + #A: { + f1: int + f2: int + } + for k, v in { + f3: int + } { + a: (〈2;#A〉 & { + "\(〈2;k〉)": 〈2;v〉 + }) + } + #B: { + for k, v in { + f1: int + } { + "\(〈1;k〉)": 〈1;v〉 + } + } + #C: { + f1: _ + for k, v in { + f1: int + } { + "\(〈1;k〉)": 〈1;v〉 + } + } + #D: { + for k, v in { + f1: int + } { + "\(〈1;k〉)": 〈1;v〉 + } + ... + } + #E: (〈0;#A〉 & { + for k, v in { + f3: int + } { + "\(〈1;k〉)": 〈1;v〉 + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/037_conjunction_of_optional_sets.txtar b/internal/core/compile/testdata/sync/definitions/037_conjunction_of_optional_sets.txtar new file mode 100644 index 000000000..0ab4749dc --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/037_conjunction_of_optional_sets.txtar @@ -0,0 +1,44 @@ +-- in.cue -- +#A: { + [=~"^[a-s]*$"]: int +} +#B: { + [=~"^[m-z]*$"]: int +} + +#C: #A & #B @test(allows, moo) @test(allows=false, QQQ) @test(eq, { + [=~"^[a-s]*$"]: int + [=~"^[m-z]*$"]: int +}) +c: #C +c: {aaa: 3 } @test(err, code=eval, at=aaa, + hint="positions missing", + contains="field not allowed", pos=[in.cue:2:2, 0:5]) + +#D: {#A & #B} +d: #D +d: {aaa: 3 } @test(err, code=eval, at=aaa, + hint="positions missing", + contains="field not allowed", pos=[in.cue:2:2, 0:5]) +-- out/compile -- +--- in.cue +{ + #A: { + [=~"^[a-s]*$"]: int + } + #B: { + [=~"^[m-z]*$"]: int + } + #C: (〈0;#A〉 & 〈0;#B〉) + c: 〈0;#C〉 + c: { + aaa: 3 + } + #D: { + (〈1;#A〉 & 〈1;#B〉) + } + d: 〈0;#D〉 + d: { + aaa: 3 + } +} diff --git a/internal/core/compile/testdata/sync/definitions/038_continue_recursive_closing_for_optionals.txtar b/internal/core/compile/testdata/sync/definitions/038_continue_recursive_closing_for_optionals.txtar new file mode 100644 index 000000000..0edaccd92 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/038_continue_recursive_closing_for_optionals.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +#S: { + [string]: {a: int} +} +a: #S & { + v: {b: int} +} @test(err, at=v.b, code=eval, contains="field not allowed", pos=[1:6]) +-- out/compile -- +--- in.cue +{ + #S: { + [string]: { + a: int + } + } + a: (〈0;#S〉 & { + v: { + b: int + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/039_augment_closed_optionals.txtar b/internal/core/compile/testdata/sync/definitions/039_augment_closed_optionals.txtar new file mode 100644 index 000000000..8cd25e05e --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/039_augment_closed_optionals.txtar @@ -0,0 +1,44 @@ +-- in.cue -- +#A: { + [=~"^[a-s]*$"]: int +} +#B: { + [=~"^[m-z]*?"]: int +} +#C: { + #A & #B + {[=~"^Q*$"]: int} +} @test(allows, moo) @test(allows, Qoo) @test(allows=false, string) +// TODO: What should this be? @test(allows=false, zoo) +c: #C & {QQ: 3} @test(eq, {QQ: 3}) +#D: { + #A + #B +} +d: #D & {aaa: 4} @test(eq, {aaa: 4}) +-- out/compile -- +--- in.cue +{ + #A: { + [=~"^[a-s]*$"]: int + } + #B: { + [=~"^[m-z]*?"]: int + } + #C: { + (〈1;#A〉 & 〈1;#B〉) + { + [=~"^Q*$"]: int + } + } + c: (〈0;#C〉 & { + QQ: 3 + }) + #D: { + 〈1;#A〉 + 〈1;#B〉 + } + d: (〈0;#D〉 & { + aaa: 4 + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/comprehensions.txtar b/internal/core/compile/testdata/sync/definitions/comprehensions.txtar new file mode 100644 index 000000000..1232b9b67 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/comprehensions.txtar @@ -0,0 +1,31 @@ +-- in.cue -- +// Closedness should not be silently swallowed when propagated through +// comprehensions; fields added via comprehensions should still be checked. +// https://cuelang.org/issue/595 +issue595: { + // NOTE: this should eval with an EVAL error, not + // an incomplete error. See Issue #595. + #cfgs: [{ + name: "foo" + }] + _name: #cfgs[0].name + for cfg in #cfgs { + files: cfg.nam + } + @test(err, code=eval, at=files, contains="undefined field: nam", pos=[8:14]) +} +-- out/compile -- +--- in.cue +{ + issue595: { + #cfgs: [ + { + name: "foo" + }, + ] + _name: 〈0;#cfgs〉[0].name + for _, cfg in 〈0;#cfgs〉 { + files: 〈1;cfg〉.nam + } + } +} diff --git a/internal/core/compile/testdata/sync/definitions/defembed.txtar b/internal/core/compile/testdata/sync/definitions/defembed.txtar new file mode 100644 index 000000000..02e5540b5 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/defembed.txtar @@ -0,0 +1,41 @@ +-- in.cue -- +a: { + #A +} + +a: c: 1 @test(err, code=eval, contains="field not allowed", pos=[0:4]) + +#A: b: 1 + +b: { + #A + leaf: "leaf value" + interpolation: "more \(leaf_ref)" + leaf_ref: leaf + + @test(eq, { + b: 1 + leaf: "leaf value" + interpolation: "more leaf value" + leaf_ref: "leaf value" + }) +} +-- out/compile -- +--- in.cue +{ + a: { + 〈1;#A〉 + } + a: { + c: 1 + } + #A: { + b: 1 + } + b: { + 〈1;#A〉 + leaf: "leaf value" + interpolation: "more \(〈0;leaf_ref〉)" + leaf_ref: 〈0;leaf〉 + } +} diff --git a/internal/core/compile/testdata/sync/definitions/dynamic.txtar b/internal/core/compile/testdata/sync/definitions/dynamic.txtar new file mode 100644 index 000000000..8dca6a3ae --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/dynamic.txtar @@ -0,0 +1,81 @@ +-- in.cue -- +#A: { + a: "foo" + "\(a)": 3 + + @test(eq, { + a: "foo" + foo: 3 + }) +} +#B: a: b: { + c: string + d: 2 +} @test(eq, { + c: string + d: 2 +}) + +#C: a: b: { + c: *"d" | string + (c): 2 +} @test(eq, { + c: *"d" | string + d: 2 +}) + +x: #B & #C @test(eq, { + a: b: { + c: *"d" | string + d: 2 + } +}) + +-- evalv3regress.cue -- +chained: x: { + // TODO: add this once the todo is fixed. + // @test(permute) + (a.b): "foo" + (x.hello): "true" + a: b: "hello" + + @test(eq, {a: b: "hello", hello: "foo"}, incorrect, hint="shouldn't foo be in here?") + @test(eq:todo, {a: b: "hello", hello: "foo", foo: "true"}) +} +-- out/compile -- +--- evalv3regress.cue +{ + chained: { + x: { + 〈0;a〉.b: "foo" + 〈1;x〉.hello: "true" + a: { + b: "hello" + } + } + } +} +--- in.cue +{ + #A: { + a: "foo" + "\(〈0;a〉)": 3 + } + #B: { + a: { + b: { + c: string + d: 2 + } + } + } + #C: { + a: { + b: { + c: (*"d"|string) + 〈0;c〉: 2 + } + } + } + x: (〈0;#B〉 & 〈0;#C〉) +} diff --git a/internal/core/compile/testdata/sync/definitions/embed.txtar b/internal/core/compile/testdata/sync/definitions/embed.txtar new file mode 100644 index 000000000..b26869efc --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/embed.txtar @@ -0,0 +1,164 @@ +-- in.cue -- +deployment: [string]: #Deployment + +deployment: foo: spec: replicas: 1 + +@test(eq, { + [string]: spec: replicas: int + foo: spec: replicas: 1 +}, at=deployment) + +#Deployment: { + #TypeMeta + + spec: #Spec +} + +#Spec: replicas: int + +#TypeMeta: {} + +recloseSimple: { + #foo: {} + a: {#foo} & {b: int} @test(err, at=b, code=eval, contains="field not allowed", pos=[0:15]) +} + +// Reclosing +reclose1: { + #D: { + x: int + y: int + } + #a: { + #D + b: { + c: int + } + } + + z: #a.b + z: d: 3 @test(err, code=eval, contains="field not allowed", pos=[0:5]) +} + +reclose2: { + #D: { + x: int + y: int + } + a: { + #D + b: {// keep open + c: int + } + } + + z: a.b @test(eq, { c: int, d: 3 }) + z: d: 3 +} + +reclose3: { + #Step: { + (#A | #B) + #Common + } + #Common: { + Name: string + } + #A: { + #Common + Something: int + } + #B: { + #Common + Else: int + } + x: #Step + x: #A & { + Name: "a" + Something: 4 + } @test(eq, {Name: "a", Something: 4}) +} +-- out/compile -- +--- in.cue +{ + deployment: { + [string]: 〈1;#Deployment〉 + } + deployment: { + foo: { + spec: { + replicas: 1 + } + } + } + #Deployment: { + 〈1;#TypeMeta〉 + spec: 〈1;#Spec〉 + } + #Spec: { + replicas: int + } + #TypeMeta: {} + recloseSimple: { + #foo: {} + a: ({ + 〈1;#foo〉 + } & { + b: int + }) + } + reclose1: { + #D: { + x: int + y: int + } + #a: { + 〈1;#D〉 + b: { + c: int + } + } + z: 〈0;#a〉.b + z: { + d: 3 + } + } + reclose2: { + #D: { + x: int + y: int + } + a: { + 〈1;#D〉 + b: { + c: int + } + } + z: 〈0;a〉.b + z: { + d: 3 + } + } + reclose3: { + #Step: { + (〈1;#A〉|〈1;#B〉) + 〈1;#Common〉 + } + #Common: { + Name: string + } + #A: { + 〈1;#Common〉 + Something: int + } + #B: { + 〈1;#Common〉 + Else: int + } + x: 〈0;#Step〉 + x: (〈0;#A〉 & { + Name: "a" + Something: 4 + }) + } +} diff --git a/internal/core/compile/testdata/sync/definitions/exclude.txtar b/internal/core/compile/testdata/sync/definitions/exclude.txtar new file mode 100644 index 000000000..bdead3fd9 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/exclude.txtar @@ -0,0 +1,197 @@ +-- in.cue -- +package p + +excludeLet: { + // Two lets with the same name should not unify and checked by definition. + #D: { let X = {}, #foo: X, f: _ } + a: #D + a: { let X = { a: 1 }, f: X } @test(debugCheck, """ + (#struct){ + let X#2 = (struct){ + a: (int){ 1 } + } + f: (#struct){ + a: (int){ 1 } + } + let X#1 = (#struct){ + } + #foo: (#struct){ + } + } + """) + + @test(eq, { + #D: { + #foo: {} + f: _ + } + a: { + #foo: {} + f: a: 1 + } + }) +} + +definition: { + // Check a definition only if it s contained withing a definition. + err1: { + #D: { #foo: a: int } + a: #D + a: { #foo: b: int @test(err, code=eval, contains="field not allowed", pos=[0:14]) } + } + ok1: { + #D: {} + a: #D + a: { #foo: b: int } + @test(eq, { + #D: {} + a: #foo: b: int + }) + } +} + +hidden: { + // Check a hidden field only if it s contained withing a definition. + err1: { + #D: { _foo: a: int } + a: #D + a: { _foo: b: int } @test(err, code=eval, at=_foo$p, contains="field not allowed", pos=[0:14]) + } + ok1: { + #D: {} + a: #D + a: { _foo: b: int } + } @test(eq, {#D: {}, a: {_foo$p: {b: int}}}) +} +-- regress.cue -- +package p + +import "encoding/json" + +definition: ok2: { + #Tree: { + #Leaf: leaf: string + #Branch: branch?: #Leaf + root: #Branch + } + out: json.Marshal(#Tree & {root: {}}) @test(eq, #"{"root":{}}"#) +} + +hidden: ok2: { + out: #Workflow & { + _hidden: #step & { + run: "foo bar" + } + } + #Workflow: { + } + #step: matchN(1, [{ + "run"!: _ + }]) + + @test(eq, { + out: _hidden$p: run: "foo bar" + #Workflow: {} + #step: matchN(1, [{ run!: _ }]) + }) +} +-- out/compile -- +--- in.cue +{ + excludeLet: { + #D: { + let X#1 = {} + #foo: 〈0;let X#1〉 + f: _ + } + a: 〈0;#D〉 + a: { + let X#2 = { + a: 1 + } + f: 〈0;let X#2〉 + } + } + definition: { + err1: { + #D: { + #foo: { + a: int + } + } + a: 〈0;#D〉 + a: { + #foo: { + b: int + } + } + } + ok1: { + #D: {} + a: 〈0;#D〉 + a: { + #foo: { + b: int + } + } + } + } + hidden: { + err1: { + #D: { + _foo(:p): { + a: int + } + } + a: 〈0;#D〉 + a: { + _foo(:p): { + b: int + } + } + } + ok1: { + #D: {} + a: 〈0;#D〉 + a: { + _foo(:p): { + b: int + } + } + } + } +} +--- regress.cue +{ + definition: { + ok2: { + #Tree: { + #Leaf: { + leaf: string + } + #Branch: { + branch?: 〈1;#Leaf〉 + } + root: 〈0;#Branch〉 + } + out: 〈import;"encoding/json"〉.Marshal((〈0;#Tree〉 & { + root: {} + })) + } + } + hidden: { + ok2: { + out: (〈0;#Workflow〉 & { + _hidden(:p): (〈1;#step〉 & { + run: "foo bar" + }) + }) + #Workflow: {} + #step: matchN(1, [ + { + run!: _ + }, + ]) + } + } +} diff --git a/internal/core/compile/testdata/sync/definitions/explicitopen.txtar b/internal/core/compile/testdata/sync/definitions/explicitopen.txtar new file mode 100644 index 000000000..089879954 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/explicitopen.txtar @@ -0,0 +1,785 @@ +# Tests the explicitopen experiment: allows using the spread operator (...) to +# explicitly open closed structs. NewClosed1: {#A} is closed; NewOpen1: {#A...} +# is open. The test covers interactions between old and new style closedness. +-- cue.mod/module.cue -- +module: "mod.test" + +language: version: "v0.15.0" + +-- old.cue -- +package foo + +@test(shareID=AOpen2, at=#A) +#A: a: 1 +Old1: { + { + #A + b: 1 + } +} + +#Old2: { + { + #A + b: 1 + } +} + +useNewClosed1: { + t1: err: NewClosed1 & {c: 3} @test(err, code=eval, contains="field not allowed", pos=[0:25]) + t2: ok: {NewClosed1, c: 3} @test(eq, { a: 1, c: 3 }) +} + +useNewClosed2: { + t1: err: #NewClosed2 & {c: 3} @test(err, code=eval, contains="field not allowed", pos=[0:26]) + t2: ok: {#NewClosed2, c: 3} @test(eq, { a: 1, b: 1, c: 3 }) +} + +useNewOpen1: { + t1: ok: NewOpen1 & {c: 3} @test(eq, { a: 1, b: 1, c: 3 }) + t2: ok: {NewOpen1, c: 3} @test(eq, { a: 1, b: 1, c: 3 }) +} + +useNewOpen2: { + t1: ok: NewOpen2 & {c: 3} @test(eq, { a: 1, c: 3 }) + t2: ok: {NewOpen2, c: 3} @test(eq, { a: 1, c: 3 }) +} + +combineold: { + // all {a: 1} + a0: ok: #A & NewClosed1 @test(eq, { a: 1 }) + a1: ok: {#A, NewClosed1} @test(eq, { a: 1 }) + + a2: ok: NewClosed1 & NewOpen2 @test(eq, { a: 1 }) + a3: ok: {NewClosed1, NewOpen2} @test(eq, { a: 1 }) + + // all {a: 1, b: 2} + b0: ok: Old1 & #NewClosed2 @test(eq, { a: 1, b: 1 }) + b1: ok: #Old2 & #NewClosed2 @test(eq, { a: 1, b: 1 }) + + c1: ok: {#NewClosed2, Old1} @test(eq, { a: 1, b: 1 }) + c2: ok: {#NewClosed2, #Old2} @test(eq, { a: 1, b: 1 }) + + // {a: 1} and {a: 1, b: 2} + e0: err: #A & Old1 @test(err, code=eval, contains="field not allowed", pos=[-47:3]) + e1: err: #A & #Old2 @test(err, code=eval, contains="field not allowed", pos=[-41:3]) + e2: err: #A & #NewClosed2 @test(err, code=eval, contains="field not allowed", pos=[new.cue:12:2]) + e3: err: #A & NewOpen1 @test(err, code=eval, contains="field not allowed", pos=[new.cue:17:2]) + + e4: ok: {#A, Old1} @test(eq, { a: 1, b: 1 }) + e5: ok: {#A, #Old2} @test(eq, { a: 1, b: 1 }) + e6: ok: {#A, #NewClosed2} @test(eq, { a: 1, b: 1 }) + e7: ok: {#A, NewOpen1} @test(eq, { a: 1, b: 1 }) + + f0: err: NewClosed1 & Old1 @test(err, code=eval, contains="field not allowed", pos=[-57:3]) + f1: err: NewClosed1 & #Old2 @test(err, code=eval, contains="field not allowed", pos=[-51:3]) + f2: err: NewClosed1 & #NewClosed2 @test(err, code=eval, contains="field not allowed", pos=[new.cue:12:2]) + f3: err: NewClosed1 & NewOpen1 @test(err, code=eval, contains="field not allowed", pos=[new.cue:17:2]) + + f4: ok: {NewClosed1, Old1} @test(eq, { a: 1, b: 1 }) + f5: ok: {NewClosed1, #Old2} @test(eq, { a: 1, b: 1 }) + f6: ok: {NewClosed1, NewClosed1} @test(eq, { a: 1 }) + f7: ok: {NewClosed1, #NewClosed2} @test(eq, { a: 1, b: 1 }) + f8: ok: {NewClosed1, NewOpen1} @test(eq, { a: 1, b: 1 }) +} + +-- new.cue -- +@experiment(explicitopen) + +package foo + +NewClosed1: { + @test(shareID=NC1) + #A +} + +#NewClosed2: { + #A... + b: 1 +} + +NewOpen1: { + #A... + b: 1 +} + +NewOpen2: #A... @test(shareID=AOpen2) + +useOld1: { + t1: err: Old1 & {c: 3} @test(err, code=eval, contains="field not allowed", pos=[0:19]) + t2: err: {Old1, c: 3} @test(err, code=eval, contains="field not allowed", pos=[0:18]) // TODO + t3: ok: {Old1..., c: 3} @test(eq, {a: 1, b: 1, c: 3}) +} + +useOld2: { + t1: err: #Old2 & {c: 3} @test(err, code=eval, contains="field not allowed", pos=[0:20]) + t2: err: {#Old2, c: 3} @test(err, code=eval, contains="field not allowed", pos=[0:19]) + t3: ok: {#Old2..., c: 3} @test(eq, {a: 1, b: 1, c: 3}) +} + +combinenew: { + // all {a: 1} + a0: ok: #A & NewClosed1 @test(eq, {a: 1}) + a1: ok: {#A, NewClosed1} @test(eq, {a: 1}) + + a2: ok: NewClosed1 & NewOpen2 @test(eq, {a: 1}) + a3: ok: {NewClosed1, NewOpen2} @test(eq, {a: 1}) + a4: ok: {NewClosed1..., NewOpen2} @test(eq, {a: 1}) + + a5: ok: NewOpen2 & NewClosed1 @test(eq, {a: 1}) + a6: ok: {NewOpen2, NewClosed1} @test(eq, {a: 1}) + a7: ok: {NewOpen2..., NewClosed1} @test(eq, {a: 1}) + + // all {a: 1, b: 2} + b0: ok: Old1 & #NewClosed2 @test(eq, {a: 1, b: 1}) + b1: ok: #Old2 & #NewClosed2 @test(eq, {a: 1, b: 1}) + b2: ok: #NewClosed2 & Old1 @test(eq, {a: 1, b: 1}) + b3: ok: #NewClosed2 & #Old2 @test(eq, {a: 1, b: 1}) + + c1: ok: {#NewClosed2, Old1} @test(eq, {a: 1, b: 1}) + c2: ok: {#NewClosed2, #Old2} @test(eq, {a: 1, b: 1}) + c3: ok: {Old1, #NewClosed2} @test(eq, {a: 1, b: 1}) + c4: ok: {#Old2, #NewClosed2} @test(eq, {a: 1, b: 1}) + + d0: ok: {#NewClosed2, Old1...} @test(eq, {a: 1, b: 1}) + d1: ok: {#NewClosed2, #Old2...} @test(eq, {a: 1, b: 1}) + d2: ok: {#NewClosed2..., Old1} @test(eq, {a: 1, b: 1}) + d3: ok: {#NewClosed2..., #Old2} @test(eq, {a: 1, b: 1}) + d4: ok: {#NewClosed2..., Old1...} @test(eq, {a: 1, b: 1}) + d5: ok: {#NewClosed2..., #Old2...} @test(eq, {a: 1, b: 1}) + + d6: ok: {Old1..., #NewClosed2} @test(eq, {a: 1, b: 1}) + d7: ok: {#Old2..., #NewClosed2} @test(eq, {a: 1, b: 1}) + d8: ok: {Old1, #NewClosed2...,} @test(eq, {a: 1, b: 1}) + d9: ok: {#Old2, #NewClosed2...,} @test(eq, {a: 1, b: 1}) + d10: ok: {Old1..., #NewClosed2...,} @test(eq, {a: 1, b: 1}) + d11: ok: {#Old2..., #NewClosed2...,} @test(eq, {a: 1, b: 1}) + + // {a: 1} and {a: 1, b: 2} + e0: err: #A & Old1 @test(err, code=eval, contains="field not allowed", pos=[old.cue:8:3]) + e1: err: #A & #Old2 @test(err, code=eval, contains="field not allowed", pos=[old.cue:15:3]) + e2: err: #A & #NewClosed2 @test(err, code=eval, contains="field not allowed", pos=[-63:2]) + e3: err: #A & NewOpen1 @test(err, code=eval, contains="field not allowed", pos=[-59:2]) + + e4: err: {#A, Old1} @test(err, code=eval, contains="field not allowed", pos=[old.cue:8:3]) + e5: err: {#A, #Old2} @test(err, code=eval, contains="field not allowed", pos=[old.cue:15:3]) + e6: err: {#A, #NewClosed2} @test(err, code=eval, contains="field not allowed", pos=[-68:2]) + e7: err: {#A, NewOpen1} @test(err, code=eval, contains="field not allowed", pos=[-64:2]) + + e8: ok: {#A..., Old1} @test(eq, {a: 1, b: 1}) + e9: ok: {#A..., #Old2} @test(eq, {a: 1, b: 1}) + e10: ok: {#A..., #NewClosed2} @test(eq, {a: 1, b: 1}) + e11: ok: {#A..., NewOpen1} @test(eq, {a: 1, b: 1}) + + f0: err: NewClosed1 & Old1 @test(err, code=eval, contains="field not allowed", pos=[old.cue:8:3]) + f1: err: NewClosed1 & #Old2 @test(err, code=eval, contains="field not allowed", pos=[old.cue:15:3]) + f2: err: NewClosed1 & #NewClosed2 @test(err, code=eval, contains="field not allowed", pos=[-78:2]) + f3: err: NewClosed1 & NewOpen1 @test(err, code=eval, contains="field not allowed", pos=[-74:2]) + f4: ok: NewClosed1 & NewClosed1 @test(eq, {a: 1}) @test(shareID=NC1) + + f5: err: {NewClosed1, Old1} @test(err, code=eval, contains="field not allowed", pos=[old.cue:8:3]) + f6: err: {NewClosed1, #Old2} @test(err, code=eval, contains="field not allowed", pos=[old.cue:15:3]) + f7: err: {NewClosed1, #NewClosed2} @test(err, code=eval, contains="field not allowed", pos=[-84:2]) + f8: err: {NewClosed1, NewOpen1} @test(err, code=eval, contains="field not allowed", pos=[-80:2]) + f9: ok: {NewClosed1, NewClosed1} @test(err) + + f9: ok: {NewClosed1..., Old1} @test(err, code=eval, contains="field not allowed", pos=[old.cue:8:3], hint="see todo") + f10: ok: {NewClosed1..., #Old2} @test(eq, {a: 1, b: 1}) + f11: ok: {NewClosed1..., NewClosed1} @test(eq, {a: 1}) + f12: ok: {NewClosed1..., #NewClosed2} @test(eq, {a: 1, b: 1}) + f13: ok: {NewClosed1..., NewOpen1} @test(eq, {a: 1, b: 1}) + + f14: err: Old1 & NewClosed1 @test(eq, {a: 1, b: 1}, hint="see todo") + f15: err: #Old2 & NewClosed1 @test(eq, {a: 1, b: 1}, hint="see todo") + f16: err: #NewClosed2 & NewClosed1 @test(err, code=eval, contains="field not allowed", pos=[-96:2]) + f17: err: NewOpen1 & NewClosed1 @test(err, code=eval, contains="field not allowed", pos=[-92:2]) + f18: ok: NewClosed1 & NewClosed1 @test(eq, {a: 1}) @test(shareID=NC1) +} +-- issues.cue -- +@experiment(explicitopen) +// explicitopen experiment: postfix `...` spread cannot directly combine with +// `&`; tests open-struct spread behavior and non-struct operand tolerance. +// https://cuelang.org/issue/4150 +issue4150: { + #Def: a: int + + x: #Def... & { + a: 42 + b: 42 + } @test(eq, {a: 42, b: 42}) @test(closed) + + foo: {a: int} + bar: {b: int} + y: foo... & bar... @test(eq, {a: int, b: int}) + + // NOTE: we allow this, even though it doesn't mean anything. The benefit + // of this is that code doesn't become brittle using the spread operator + // for references. Consider this example: + // + // #Def: a: int + // foo: 1 | #Def + // bar: foo... + // + // Not allowing ... on any expression would mean #foo... may or may not be + // erroneous, depending on the value foo is set to. + z: 1... @test(eq, 1) +} +-- out/compile -- +--- issues.cue +{ + issue4150: { + #Def: { + a: int + } + x: (〈0;#Def〉... & { + a: 42 + b: 42 + }) + foo: { + a: int + } + bar: { + b: int + } + y: (〈0;foo〉... & 〈0;bar〉...) + z: 1... + } +} +--- new.cue +{ + NewClosed1: { + 〈1;#A〉 + } + #NewClosed2: { + 〈1;#A〉... + b: 1 + } + NewOpen1: { + 〈1;#A〉... + b: 1 + } + NewOpen2: 〈0;#A〉... + useOld1: { + t1: { + err: (〈2;Old1〉 & { + c: 3 + }) + } + t2: { + err: { + 〈3;Old1〉 + c: 3 + } + } + t3: { + ok: { + 〈3;Old1〉... + c: 3 + } + } + } + useOld2: { + t1: { + err: (〈2;#Old2〉 & { + c: 3 + }) + } + t2: { + err: { + 〈3;#Old2〉 + c: 3 + } + } + t3: { + ok: { + 〈3;#Old2〉... + c: 3 + } + } + } + combinenew: { + a0: { + ok: (〈2;#A〉 & 〈2;NewClosed1〉) + } + a1: { + ok: { + 〈3;#A〉 + 〈3;NewClosed1〉 + } + } + a2: { + ok: (〈2;NewClosed1〉 & 〈2;NewOpen2〉) + } + a3: { + ok: { + 〈3;NewClosed1〉 + 〈3;NewOpen2〉 + } + } + a4: { + ok: { + 〈3;NewClosed1〉... + 〈3;NewOpen2〉 + } + } + a5: { + ok: (〈2;NewOpen2〉 & 〈2;NewClosed1〉) + } + a6: { + ok: { + 〈3;NewOpen2〉 + 〈3;NewClosed1〉 + } + } + a7: { + ok: { + 〈3;NewOpen2〉... + 〈3;NewClosed1〉 + } + } + b0: { + ok: (〈2;Old1〉 & 〈2;#NewClosed2〉) + } + b1: { + ok: (〈2;#Old2〉 & 〈2;#NewClosed2〉) + } + b2: { + ok: (〈2;#NewClosed2〉 & 〈2;Old1〉) + } + b3: { + ok: (〈2;#NewClosed2〉 & 〈2;#Old2〉) + } + c1: { + ok: { + 〈3;#NewClosed2〉 + 〈3;Old1〉 + } + } + c2: { + ok: { + 〈3;#NewClosed2〉 + 〈3;#Old2〉 + } + } + c3: { + ok: { + 〈3;Old1〉 + 〈3;#NewClosed2〉 + } + } + c4: { + ok: { + 〈3;#Old2〉 + 〈3;#NewClosed2〉 + } + } + d0: { + ok: { + 〈3;#NewClosed2〉 + 〈3;Old1〉... + } + } + d1: { + ok: { + 〈3;#NewClosed2〉 + 〈3;#Old2〉... + } + } + d2: { + ok: { + 〈3;#NewClosed2〉... + 〈3;Old1〉 + } + } + d3: { + ok: { + 〈3;#NewClosed2〉... + 〈3;#Old2〉 + } + } + d4: { + ok: { + 〈3;#NewClosed2〉... + 〈3;Old1〉... + } + } + d5: { + ok: { + 〈3;#NewClosed2〉... + 〈3;#Old2〉... + } + } + d6: { + ok: { + 〈3;Old1〉... + 〈3;#NewClosed2〉 + } + } + d7: { + ok: { + 〈3;#Old2〉... + 〈3;#NewClosed2〉 + } + } + d8: { + ok: { + 〈3;Old1〉 + 〈3;#NewClosed2〉... + } + } + d9: { + ok: { + 〈3;#Old2〉 + 〈3;#NewClosed2〉... + } + } + d10: { + ok: { + 〈3;Old1〉... + 〈3;#NewClosed2〉... + } + } + d11: { + ok: { + 〈3;#Old2〉... + 〈3;#NewClosed2〉... + } + } + e0: { + err: (〈2;#A〉 & 〈2;Old1〉) + } + e1: { + err: (〈2;#A〉 & 〈2;#Old2〉) + } + e2: { + err: (〈2;#A〉 & 〈2;#NewClosed2〉) + } + e3: { + err: (〈2;#A〉 & 〈2;NewOpen1〉) + } + e4: { + err: { + 〈3;#A〉 + 〈3;Old1〉 + } + } + e5: { + err: { + 〈3;#A〉 + 〈3;#Old2〉 + } + } + e6: { + err: { + 〈3;#A〉 + 〈3;#NewClosed2〉 + } + } + e7: { + err: { + 〈3;#A〉 + 〈3;NewOpen1〉 + } + } + e8: { + ok: { + 〈3;#A〉... + 〈3;Old1〉 + } + } + e9: { + ok: { + 〈3;#A〉... + 〈3;#Old2〉 + } + } + e10: { + ok: { + 〈3;#A〉... + 〈3;#NewClosed2〉 + } + } + e11: { + ok: { + 〈3;#A〉... + 〈3;NewOpen1〉 + } + } + f0: { + err: (〈2;NewClosed1〉 & 〈2;Old1〉) + } + f1: { + err: (〈2;NewClosed1〉 & 〈2;#Old2〉) + } + f2: { + err: (〈2;NewClosed1〉 & 〈2;#NewClosed2〉) + } + f3: { + err: (〈2;NewClosed1〉 & 〈2;NewOpen1〉) + } + f4: { + ok: (〈2;NewClosed1〉 & 〈2;NewClosed1〉) + } + f5: { + err: { + 〈3;NewClosed1〉 + 〈3;Old1〉 + } + } + f6: { + err: { + 〈3;NewClosed1〉 + 〈3;#Old2〉 + } + } + f7: { + err: { + 〈3;NewClosed1〉 + 〈3;#NewClosed2〉 + } + } + f8: { + err: { + 〈3;NewClosed1〉 + 〈3;NewOpen1〉 + } + } + f9: { + ok: { + 〈3;NewClosed1〉 + 〈3;NewClosed1〉 + } + } + f9: { + ok: { + 〈3;NewClosed1〉... + 〈3;Old1〉 + } + } + f10: { + ok: { + 〈3;NewClosed1〉... + 〈3;#Old2〉 + } + } + f11: { + ok: { + 〈3;NewClosed1〉... + 〈3;NewClosed1〉 + } + } + f12: { + ok: { + 〈3;NewClosed1〉... + 〈3;#NewClosed2〉 + } + } + f13: { + ok: { + 〈3;NewClosed1〉... + 〈3;NewOpen1〉 + } + } + f14: { + err: (〈2;Old1〉 & 〈2;NewClosed1〉) + } + f15: { + err: (〈2;#Old2〉 & 〈2;NewClosed1〉) + } + f16: { + err: (〈2;#NewClosed2〉 & 〈2;NewClosed1〉) + } + f17: { + err: (〈2;NewOpen1〉 & 〈2;NewClosed1〉) + } + f18: { + ok: (〈2;NewClosed1〉 & 〈2;NewClosed1〉) + } + } +} +--- old.cue +{ + #A: { + a: 1 + } + Old1: { + { + 〈2;#A〉 + b: 1 + } + } + #Old2: { + { + 〈2;#A〉 + b: 1 + } + } + useNewClosed1: { + t1: { + err: (〈2;NewClosed1〉 & { + c: 3 + }) + } + t2: { + ok: { + 〈3;NewClosed1〉 + c: 3 + } + } + } + useNewClosed2: { + t1: { + err: (〈2;#NewClosed2〉 & { + c: 3 + }) + } + t2: { + ok: { + 〈3;#NewClosed2〉 + c: 3 + } + } + } + useNewOpen1: { + t1: { + ok: (〈2;NewOpen1〉 & { + c: 3 + }) + } + t2: { + ok: { + 〈3;NewOpen1〉 + c: 3 + } + } + } + useNewOpen2: { + t1: { + ok: (〈2;NewOpen2〉 & { + c: 3 + }) + } + t2: { + ok: { + 〈3;NewOpen2〉 + c: 3 + } + } + } + combineold: { + a0: { + ok: (〈2;#A〉 & 〈2;NewClosed1〉) + } + a1: { + ok: { + 〈3;#A〉 + 〈3;NewClosed1〉 + } + } + a2: { + ok: (〈2;NewClosed1〉 & 〈2;NewOpen2〉) + } + a3: { + ok: { + 〈3;NewClosed1〉 + 〈3;NewOpen2〉 + } + } + b0: { + ok: (〈2;Old1〉 & 〈2;#NewClosed2〉) + } + b1: { + ok: (〈2;#Old2〉 & 〈2;#NewClosed2〉) + } + c1: { + ok: { + 〈3;#NewClosed2〉 + 〈3;Old1〉 + } + } + c2: { + ok: { + 〈3;#NewClosed2〉 + 〈3;#Old2〉 + } + } + e0: { + err: (〈2;#A〉 & 〈2;Old1〉) + } + e1: { + err: (〈2;#A〉 & 〈2;#Old2〉) + } + e2: { + err: (〈2;#A〉 & 〈2;#NewClosed2〉) + } + e3: { + err: (〈2;#A〉 & 〈2;NewOpen1〉) + } + e4: { + ok: { + 〈3;#A〉 + 〈3;Old1〉 + } + } + e5: { + ok: { + 〈3;#A〉 + 〈3;#Old2〉 + } + } + e6: { + ok: { + 〈3;#A〉 + 〈3;#NewClosed2〉 + } + } + e7: { + ok: { + 〈3;#A〉 + 〈3;NewOpen1〉 + } + } + f0: { + err: (〈2;NewClosed1〉 & 〈2;Old1〉) + } + f1: { + err: (〈2;NewClosed1〉 & 〈2;#Old2〉) + } + f2: { + err: (〈2;NewClosed1〉 & 〈2;#NewClosed2〉) + } + f3: { + err: (〈2;NewClosed1〉 & 〈2;NewOpen1〉) + } + f4: { + ok: { + 〈3;NewClosed1〉 + 〈3;Old1〉 + } + } + f5: { + ok: { + 〈3;NewClosed1〉 + 〈3;#Old2〉 + } + } + f6: { + ok: { + 〈3;NewClosed1〉 + 〈3;NewClosed1〉 + } + } + f7: { + ok: { + 〈3;NewClosed1〉 + 〈3;#NewClosed2〉 + } + } + f8: { + ok: { + 〈3;NewClosed1〉 + 〈3;NewOpen1〉 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/definitions/fields.txtar b/internal/core/compile/testdata/sync/definitions/fields.txtar new file mode 100644 index 000000000..3444974f2 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/fields.txtar @@ -0,0 +1,825 @@ +// Tests fields.go +-- in.cue -- +// TODO: reorganize ordered on what is tested by name. E.g. +// insertion: longPath: ok: p1: { +// a: .... @fail() +// } + +ok: t1: { + c: #R + c: [{b: int}] @test(allows=false, int) + #R: [...] @test(allows, int) + + @test(eq, { + c: [{b: int}] + #R: [] + }) +} + +ok: t2: { + #A: _ + l: #A + l: f: "hi" + + @test(eq, { + #A: _ + l: f: "hi" + }) +} + +ok: t3: { + #A: f: {...} + #A1: { #A } + s: [string]: #A1 + s: foo: f: d: foo: 1 + + @test(eq, { + #A: f: {} + #A1: f: {} + s: foo: f: d: foo: 1 + }) +} + +ok: t4: { + #T: { a: b: 1 } + W: { + {#T} + b: c: 2 + } + + @test(eq, { + #T: a: b: 1 + W: { + a: b: 1 + b: c: 2 + } + }) +} + +ok: t5: { + // TODO: move to err + #A: { + Common + _ + } + Common: { } + x: #A + x: c: int @test(err, code=eval, + hint="not sure if this is actually correct", + contains="field not allowed", pos=[0:5]) +} + +ok: t6: { + #A: { + Common + ... + } + Common: { } + x: #A @test(allows, string) + x: c: int + + @test(eq, { + #A: {} + Common: {} + x: c: int + }) +} + +ok: t7: { + a: {#A, #B} + #A: b: f: 1 + #B: b: g: 1 + + @test(eq, { + a: b: { + f: 1 + g: 1 + } + #A: b: f: 1 + #B: b: g: 1 + }) +} + +ok: t8: { + // TODO: this should pass + foo: #X @test(shareID=ok_t8_foox) + #X: { + @test(shareID=ok_t8_foox) + + a: b: c: C: 1 + for k, _ in a { + // dynamic field causes insertion one level higher. This causes + // b to be inserted in a, after it has been referenced. + a: (k): c: D: 2 + } + } + + @test(eq, { + foo: a: b: c: { + C: 1 + D: 2 + } + #X: a: b: c: { + C: 1 + D: 2 + } + }) +} + +ok: t9: { + c: #R + c: [{b: int}] + #R: [...] + + @test(eq, { + c: [{ + b: int + }] + #R: [] + }) +} + +ok: t10: { + #A: _ // top should allow everything + l: #A + l: f: "hi" + + @test(eq, { + #A: _ + l: f: "hi" + }) +} + +ok: t11: { + // indirections + #A: f: {...} + #A1: { #A } + s: [string]: #A1 + s: foo: f: d: foo: "bar" // should pass + + @test(eq, { + #A: f: {} + #A1: f: {} + s: foo: f: d: foo: "bar" + }) +} + +ok: t12: { + // nested embedding + #T: { a: b: 1 } + W: { + {#T} + b: c: 2 + } + + @test(eq, { + #T: { a: b: 1 } + W: { + a: b: 1 + b: c: 2 + } + }) +} + +ok: t13: { + // TODO: move to err + + // top DOES NOT open up + #A: { + Common + _ + } + Common: { } + x: #A + x: c: int @test(err, code=eval, contains="field not allowed", pos=[0:5]) + + @test(eq, { + #A: {} + Common: {} + x: c: _|_ + }) +} + +ok: t14: { + // ellipsis opens up + #A: { + Common + ... + } + Common: { } + x: #A + x: c: int + + @test(eq, { + #A: {} + Common: {} + x: c: int + }) +} + +// TODO: move this test to "ok": _ means any and implicitly defines all fields +// to be present as optional fields with _, recursively (as long as the type +// has not been picked to be non-struct). +// This was not observed in V2, but is now observed in V3. We should probably +// either allow for an error variant that only "allows" all fields but does not +// define them as optional top, or rethink the closedness model altogether. +err: t1: { + @test(permute, count=6) + #D: _ & {a: 2} + a: #D + a: disallowed: 1 @test(err, code=eval, contains="field not allowed", pos=[0:5]) +} + +err: t2: { + @test(permute) + #S: { { c: d: 1 } } + V: #S + V: { c: e: 1 @test(err, code=eval, contains="field not allowed", pos=[0:10]) } +} + +err: t3: { + @test(permute) + #D: {} + a: #D + a: c: "C" @test(err, code=eval, contains="field not allowed", pos=[0:5]) +} + +err: t4: { + @test(permute) + a: #A + #A: b: f: 1 + a: b: h: 1 @test(err, code=eval, contains="field not allowed", pos=[0:8]) +} + +err: t5: { + @test(permute) + // TODO: this should fail + a: {#A, #B} + #A: b: f: 1 + #B: b: g: 1 + b: a + b: b: h: 1 @test(err, code=eval, contains="field not allowed", pos=[0:8]) +} + +err: t6: { + @test(permute) + // TODO: this should fail + a: {#A, #B} + #A: b: c: d: e: f: 1 + #B: b: c: d: e: g: 1 + b: a + b: b: c: d: e: h: 1 @test(err, code=eval, contains="field not allowed", pos=[0:17]) +} + +// TODO: move this test to "ok": _ means any and implicitly defines all fields +// to be present as optional fields with _, recursively (as long as the type +// has not been picked to be non-struct). +// This was not observed in V2, but is now observed in V3. We should probably +// either allow for an error variant that only "allows" all fields but does not +// define them as optional top, or rethink the closedness model altogether. +err: t7: { + @test(permute) + #D: _ & {a: 2} + a: #D + a: b: 1 @test(err, code=eval, contains="field not allowed", pos=[0:5]) +} + +err: t8: { + @test(permute) + // nested embedding + #S: { { c: d: 1 } } + V: #S + V: { c: e: 1 @test(err, code=eval, contains="field not allowed", pos=[0:10]) } +} +-- validators.cue -- +import "struct" + +// Validators represent top, but in the case of some validators, we should not +// allow a struct to "close" it. Basically, we any validator that takes a +// schema as argument (is marked as NonConcrete) will open up the struct. +// +// TODO: we should aim to eliminate this discrepancy in the closedness redesign. +validator: open: { + #Schema: { + matchN(1, [#x]) + #x: trailingComma?: "all" + } + data: trailingComma: "all" + data: #Schema + + @test(eq, { + #Schema: { + matchN(1, [{trailingComma: "all"}]) + #x: trailingComma?: "all" + } + data: { + // TODO: why is the matchN dropped here? + trailingComma: "all" + #x: trailingComma?: "all" + } + }) +} + +validator: keepClosed: { + #X: { + struct.MaxFields(1) + a?: int + b?: int + } + x: #X + x: c: 1 @test(err, code=eval, contains="field not allowed", pos=[-5:3, 0:5]) +} +-- issue1830.cue -- +// Closedness was not applied when accessing optional fields through a selector; +// extra fields should still be rejected by the definition. +// https://cuelang.org/issue/1830 +issue1830: { + #x: { + y: { + z?: { + name: string + } + } + } + + egs: { + x1: (#x & {y: z: _}).y.z & { + name: "blah" + age1: 5 + } @test(closed) @test(eq, { name: "blah", age1: 5 }, incorrect) + x2: (#x.y & {z: _}).z & { + name: "blah" + age2: 5 + } @test(closed) @test(eq, { name: "blah", age2: 5 }, incorrect) + + @test(err:todo, at=x1.age1, code=eval, contains="field not allowed") + @test(err:todo, at=x2.age2, code=eval, contains="field not allowed") + } +} +-- issue3491.cue -- +// evalv3 regression: "field not allowed" when unifying a definition with an +// optional field against a value that adds a regular field of the same name. +// https://cuelang.org/issue/3491 +issue3491: { + #Schema: field?: {} + + a: #Schema & { + field: {} + } + + a: b + b: #Extra: {} + + @test(eq, { + #Schema: field?: {} + a: { + field: {} + #Extra: {} + } + b: #Extra: {} + }) +} +-- out/compile -- +--- in.cue +{ + ok: { + t1: { + c: 〈0;#R〉 + c: [ + { + b: int + }, + ] + #R: [ + ..., + ] + } + } + ok: { + t2: { + #A: _ + l: 〈0;#A〉 + l: { + f: "hi" + } + } + } + ok: { + t3: { + #A: { + f: { + ... + } + } + #A1: { + 〈1;#A〉 + } + s: { + [string]: 〈1;#A1〉 + } + s: { + foo: { + f: { + d: { + foo: 1 + } + } + } + } + } + } + ok: { + t4: { + #T: { + a: { + b: 1 + } + } + W: { + { + 〈2;#T〉 + } + b: { + c: 2 + } + } + } + } + ok: { + t5: { + #A: { + 〈1;Common〉 + _ + } + Common: {} + x: 〈0;#A〉 + x: { + c: int + } + } + } + ok: { + t6: { + #A: { + 〈1;Common〉 + ... + } + Common: {} + x: 〈0;#A〉 + x: { + c: int + } + } + } + ok: { + t7: { + a: { + 〈1;#A〉 + 〈1;#B〉 + } + #A: { + b: { + f: 1 + } + } + #B: { + b: { + g: 1 + } + } + } + } + ok: { + t8: { + foo: 〈0;#X〉 + #X: { + a: { + b: { + c: { + C: 1 + } + } + } + for k, _ in 〈0;a〉 { + a: { + 〈2;k〉: { + c: { + D: 2 + } + } + } + } + } + } + } + ok: { + t9: { + c: 〈0;#R〉 + c: [ + { + b: int + }, + ] + #R: [ + ..., + ] + } + } + ok: { + t10: { + #A: _ + l: 〈0;#A〉 + l: { + f: "hi" + } + } + } + ok: { + t11: { + #A: { + f: { + ... + } + } + #A1: { + 〈1;#A〉 + } + s: { + [string]: 〈1;#A1〉 + } + s: { + foo: { + f: { + d: { + foo: "bar" + } + } + } + } + } + } + ok: { + t12: { + #T: { + a: { + b: 1 + } + } + W: { + { + 〈2;#T〉 + } + b: { + c: 2 + } + } + } + } + ok: { + t13: { + #A: { + 〈1;Common〉 + _ + } + Common: {} + x: 〈0;#A〉 + x: { + c: int + } + } + } + ok: { + t14: { + #A: { + 〈1;Common〉 + ... + } + Common: {} + x: 〈0;#A〉 + x: { + c: int + } + } + } + err: { + t1: { + #D: (_ & { + a: 2 + }) + a: 〈0;#D〉 + a: { + disallowed: 1 + } + } + } + err: { + t2: { + #S: { + { + c: { + d: 1 + } + } + } + V: 〈0;#S〉 + V: { + c: { + e: 1 + } + } + } + } + err: { + t3: { + #D: {} + a: 〈0;#D〉 + a: { + c: "C" + } + } + } + err: { + t4: { + a: 〈0;#A〉 + #A: { + b: { + f: 1 + } + } + a: { + b: { + h: 1 + } + } + } + } + err: { + t5: { + a: { + 〈1;#A〉 + 〈1;#B〉 + } + #A: { + b: { + f: 1 + } + } + #B: { + b: { + g: 1 + } + } + b: 〈0;a〉 + b: { + b: { + h: 1 + } + } + } + } + err: { + t6: { + a: { + 〈1;#A〉 + 〈1;#B〉 + } + #A: { + b: { + c: { + d: { + e: { + f: 1 + } + } + } + } + } + #B: { + b: { + c: { + d: { + e: { + g: 1 + } + } + } + } + } + b: 〈0;a〉 + b: { + b: { + c: { + d: { + e: { + h: 1 + } + } + } + } + } + } + } + err: { + t7: { + #D: (_ & { + a: 2 + }) + a: 〈0;#D〉 + a: { + b: 1 + } + } + } + err: { + t8: { + #S: { + { + c: { + d: 1 + } + } + } + V: 〈0;#S〉 + V: { + c: { + e: 1 + } + } + } + } +} +--- issue1830.cue +{ + issue1830: { + #x: { + y: { + z?: { + name: string + } + } + } + egs: { + x1: ((〈1;#x〉 & { + y: { + z: _ + } + }).y.z & { + name: "blah" + age1: 5 + }) + x2: ((〈1;#x〉.y & { + z: _ + }).z & { + name: "blah" + age2: 5 + }) + } + } +} +--- issue3491.cue +{ + issue3491: { + #Schema: { + field?: {} + } + a: (〈0;#Schema〉 & { + field: {} + }) + a: 〈0;b〉 + b: { + #Extra: {} + } + } +} +--- validators.cue +{ + validator: { + open: { + #Schema: { + matchN(1, [ + 〈1;#x〉, + ]) + #x: { + trailingComma?: "all" + } + } + data: { + trailingComma: "all" + } + data: 〈0;#Schema〉 + } + } + validator: { + keepClosed: { + #X: { + 〈import;struct〉.MaxFields(1) + a?: int + b?: int + } + x: 〈0;#X〉 + x: { + c: 1 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/definitions/files.txtar b/internal/core/compile/testdata/sync/definitions/files.txtar new file mode 100644 index 000000000..549e10c43 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/files.txtar @@ -0,0 +1,59 @@ +// Treat fields of different files as belonging to the same struct. +// This means that a closed embedding in one file should not restrict the +// fields of another. +-- in.cue -- +package foo + +#theme: { + color: string + ctermbg: string +} +dark: #theme & { + color: "dark" + ctermbg: "239" +} @test(eq, {color: "dark", ctermbg: "239"}) + +light: #theme & { + color: "light" + ctermbg: "254" +} @test(eq, {color: "light", ctermbg: "254"}) + +#Config: { + console: dark | *light +} @test(eq, { + console: *{color: "light", ctermbg: "254"} | {color: "dark", ctermbg: "239"} +}) +-- box.cue -- +package foo + +#Config & { + console: dark +} + +@test(eq, {color: "dark", ctermbg: "239"}, at=console) + +-- out/compile -- +--- box.cue +{ + (〈0;#Config〉 & { + console: 〈1;dark〉 + }) +} +--- in.cue +{ + #theme: { + color: string + ctermbg: string + } + dark: (〈0;#theme〉 & { + color: "dark" + ctermbg: "239" + }) + light: (〈0;#theme〉 & { + color: "light" + ctermbg: "254" + }) + #Config: { + console: (〈1;dark〉|*〈1;light〉) + } +} diff --git a/internal/core/compile/testdata/sync/definitions/hidden.txtar b/internal/core/compile/testdata/sync/definitions/hidden.txtar new file mode 100644 index 000000000..dd8d9b241 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/hidden.txtar @@ -0,0 +1,73 @@ +exec cue eval ./pkg:foo +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- in.cue -- +package foo + +import "mod.test/pkg" + +#def: { + _name: d: int +} + +d: pkg.#D & {_name: d: int, _val: f: 4} + +// TODO: this should fail, as the _name restricting it is in this +// package. +e: pkg.#D & #def & { + // This should fail as c is disallowed by the _name defined + // in this package + _name: c: int + + // This should not fail, as this is a different _val + _val: g: int +} @test(err, code=eval, at=_name$foo.c, contains="field not allowed", pos=[3:9]) + +f: pkg.#D & {_val: f: 4} @test(debugCheck, """ + (#struct){ + _val(:foo): (struct){ + f: (int){ 4 } + } + _val(mod.test/pkg): (#struct){ + f: (int){ 3 } + } + } + """) + +g: f._val @test(eq, {f: 4}) +-- pkg/bar.cue -- +package pkg + +#D: {_val: f: 3} +-- out/compile -- +--- in.cue +{ + #def: { + _name(:foo): { + d: int + } + } + d: (〈import;"mod.test/pkg"〉.#D & { + _name(:foo): { + d: int + } + _val(:foo): { + f: 4 + } + }) + e: ((〈import;"mod.test/pkg"〉.#D & 〈0;#def〉) & { + _name(:foo): { + c: int + } + _val(:foo): { + g: int + } + }) + f: (〈import;"mod.test/pkg"〉.#D & { + _val(:foo): { + f: 4 + } + }) + g: 〈0;f〉._val(:foo) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue271.txtar b/internal/core/compile/testdata/sync/definitions/issue271.txtar new file mode 100644 index 000000000..a87b33597 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue271.txtar @@ -0,0 +1,27 @@ + +# Tests that a struct combining an open pattern constraint with close() correctly +# rejects fields not allowed by the close() constraint when unified with a value. +# https://cuelang.org/issue/271 +-- in.cue -- +#T: [_]: _ +#T: close({"a": string}) +x: #T +x: { + a: "hello" @test(eq, "hello") + b: "foo" @test(err, code=eval, contains="field not allowed", pos=[-5:5, 0:2]) +} +-- out/compile -- +--- in.cue +{ + #T: { + [_]: _ + } + #T: close({ + a: string + }) + x: 〈0;#T〉 + x: { + a: "hello" + b: "foo" + } +} diff --git a/internal/core/compile/testdata/sync/definitions/issue317.txtar b/internal/core/compile/testdata/sync/definitions/issue317.txtar new file mode 100644 index 000000000..51a853472 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue317.txtar @@ -0,0 +1,117 @@ + +# Allow otherField +# Tests that comprehension-based schemas and deployment configurations correctly +# allow fields defined through pattern constraints and let comprehensions. +# Issue: https://cuelang.org/issue/317 +-- in.cue -- +#T: { + #Schema: [_]: #D + concrete: #Schema +} +#D: { + fieldWithDefault: *0 | int + ... +} +s: #T & { + #Schema: { + foo: otherField: string + } + concrete: foo: otherField: "hello" +} @test(closed) @test(eq, { + #Schema: foo: { + fieldWithDefault: *0 | int + otherField: string + } + concrete: foo: { + fieldWithDefault: *0 | int + otherField: "hello" + } +}) +#Container: { + Env: [Name=string]: { + name: string + value: string + } +} +#Deployment: { + #Containers: [Name=string]: #Container + containers: [for c in #Containers {c}] // Problem is here. +} +Something: { + #Deployment + #Containers: { + // Does not allow entries other than value. Either add ... or embed + "a thing": Env: foobar: value: "foo" + } +} +x: Something & #Deployment @test(closed) @test(eq, { + #Containers: { + "a thing": Env: foobar: { + value: "foo" + name: string + } + } + containers: [{ + Env: foobar: { + name: string + value: "foo" + } + }] +}) +-- out/compile -- +--- in.cue +{ + #T: { + #Schema: { + [_]: 〈2;#D〉 + } + concrete: 〈0;#Schema〉 + } + #D: { + fieldWithDefault: (*0|int) + ... + } + s: (〈0;#T〉 & { + #Schema: { + foo: { + otherField: string + } + } + concrete: { + foo: { + otherField: "hello" + } + } + }) + #Container: { + Env: { + [string]: { + name: string + value: string + } + } + } + #Deployment: { + #Containers: { + [string]: 〈2;#Container〉 + } + containers: [ + for _, c in 〈1;#Containers〉 { + 〈1;c〉 + }, + ] + } + Something: { + 〈1;#Deployment〉 + #Containers: { + "a thing": { + Env: { + foobar: { + value: "foo" + } + } + } + } + } + x: (〈0;Something〉 & 〈0;#Deployment〉) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue320.txtar b/internal/core/compile/testdata/sync/definitions/issue320.txtar new file mode 100644 index 000000000..94a32c67f --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue320.txtar @@ -0,0 +1,34 @@ + +# Tests that "field not allowed" errors in closed structs include sufficient +# diagnostic information about the source of the restriction. +# https://cuelang.org/issue/320 +-- in.cue -- +#Foo: { + x: string + #More +} + +#More: [=~"^x-"]: _ + +foo: #Foo & { + x: "hello" + y: "goodbye" +} @test(err, at=y, code=eval, + hint="could use more positions, like in v2", + contains="field not allowed", + pos=[in.cue:10:2]) +-- out/compile -- +--- in.cue +{ + #Foo: { + x: string + 〈1;#More〉 + } + #More: { + [=~"^x-"]: _ + } + foo: (〈0;#Foo〉 & { + x: "hello" + y: "goodbye" + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue342.txtar b/internal/core/compile/testdata/sync/definitions/issue342.txtar new file mode 100644 index 000000000..d6b09d3e7 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue342.txtar @@ -0,0 +1,64 @@ +# Tests that Fill() followed by Validate(concrete) succeeds for complex disjunction +# definitions under dynamic (interpolated) keys, as it does for static keys. +# https://cuelang.org/issue/342 +-- in.cue -- +X: { + #Simple: { + ref: string + } @test(shareID=SIMPLE) + + #Complex: { + { + ref: string + } | { + local: string + } + } @test(eq, {ref: string} | {local: string}) @test(shareID=COMPLEX) + + + var: "bar" + + // Validate(concrete) after Fill() on Complex.ref from a "static" key will succeed + "test_1": #Complex @test(shareID=COMPLEX) @test(eq, { + ref: string + } | { + local: string + }) + + // Validate(concrete) after Fill() on "#Simple.ref" from a "dynamic" key will succeed + "test_2_\(var)": #Simple + @test(shareID=SIMPLE, at=test_2_bar) + @test(eq, at=test_2_bar, { ref: string }) + + // Validate(concrete) after Fill() on Complex.ref from a "dynamic" key will fail + "test_3_\(var)": #Complex + + test_3_bar: ref: "FOO" + @test(eq, at=test_3_bar, { ref: "FOO" }) +} + +Z: X.test_3_bar.ref @test(eq, "FOO") +-- out/compile -- +--- in.cue +{ + X: { + #Simple: { + ref: string + } + #Complex: { + ({ + ref: string + }|{ + local: string + }) + } + var: "bar" + test_1: 〈0;#Complex〉 + "test_2_\(〈0;var〉)": 〈0;#Simple〉 + "test_3_\(〈0;var〉)": 〈0;#Complex〉 + test_3_bar: { + ref: "FOO" + } + } + Z: 〈0;X〉.test_3_bar.ref +} diff --git a/internal/core/compile/testdata/sync/definitions/issue359.txtar b/internal/core/compile/testdata/sync/definitions/issue359.txtar new file mode 100644 index 000000000..98dce7df6 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue359.txtar @@ -0,0 +1,137 @@ +# Tests that inner structs within a definition template constraint are not +# incorrectly treated as closed when unified via a non-definition value. +# https://cuelang.org/issue/359 +-- in.cue -- +#simple: { + peso: *1 | int + edad: *2 | int +} + +// Second struct is not considered closed, as expected +good: #simple & { + peso: 4 +} @test(eq, {peso: 4, edad: *2 | int}) + +#complex: { + things: [string]: #simple +} + +// Still, no closedness issue in the second struct +#many: #complex & { + things: hola: peso: 2 + things: sol: peso: 3 +} @test(eq, { + things: { + hola: { + peso: 2 + edad: *2 | int + } + sol: { + peso: 3 + edad: *2 | int + } + } +}) + +// Inner struct in second struct IS considered closed: why? +bad: #many & { + things: hola: peso: 2 +} @test(eq, { + things: { + hola: { + peso: 2 + edad: *2 | int + } + sol: { + peso: 3 + edad: *2 | int + } + } +}) + +// non-definition equivalent +many: #complex & { + things: hola: peso: 2 + things: sol: peso: 3 +} @test(eq, { + things: { + hola: { + peso: 2 + edad: *2 | int + } + sol: { + peso: 3 + edad: *2 | int + } + } +}) + +// Now inner struct on second struct is NOT considered closed +notbad: many & { + things: hola: peso: 2 +} @test(eq, { + things: { + hola: { + peso: 2 + edad: *2 | int + } + sol: { + peso: 3 + edad: *2 | int + } + } +}) +-- out/compile -- +--- in.cue +{ + #simple: { + peso: (*1|int) + edad: (*2|int) + } + good: (〈0;#simple〉 & { + peso: 4 + }) + #complex: { + things: { + [string]: 〈2;#simple〉 + } + } + #many: (〈0;#complex〉 & { + things: { + hola: { + peso: 2 + } + } + things: { + sol: { + peso: 3 + } + } + }) + bad: (〈0;#many〉 & { + things: { + hola: { + peso: 2 + } + } + }) + many: (〈0;#complex〉 & { + things: { + hola: { + peso: 2 + } + } + things: { + sol: { + peso: 3 + } + } + }) + notbad: (〈0;many〉 & { + things: { + hola: { + peso: 2 + } + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue367.txtar b/internal/core/compile/testdata/sync/definitions/issue367.txtar new file mode 100644 index 000000000..6f870ee7c --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue367.txtar @@ -0,0 +1,35 @@ +-- in.cue -- +#def1: l1: ["l2"]: {l3: int, l4: 26} +#special1: #def1 & {l1: l2: l3: <100} @test(eq, { + l1: l2: { + l3: int & <100 + l4: 26 + } +}) +instance: #special1 & {l1: l2: l3: 34} @test(eq, {l1: {l2: {l3: 34, l4: 26}}}) +-- out/compile -- +--- in.cue +{ + #def1: { + l1: { + ["l2"]: { + l3: int + l4: 26 + } + } + } + #special1: (〈0;#def1〉 & { + l1: { + l2: { + l3: <100 + } + } + }) + instance: (〈0;#special1〉 & { + l1: { + l2: { + l3: 34 + } + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue370.txtar b/internal/core/compile/testdata/sync/definitions/issue370.txtar new file mode 100644 index 000000000..09e783f1a --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue370.txtar @@ -0,0 +1,41 @@ +# Tests that embedding a definition (#C1) inside another definition (#C2) and +# then unifying with a concrete struct correctly validates all fields. +# https://cuelang.org/issue/370 +-- x.cue -- +package x + +#C1: { + name: string +} + +#C2: { + #C1 + age: int +} + +c1: #C1 & { + name: "cueckoo" +} @test(eq, {name: "cueckoo"}) + +c2: #C2 & { + c1 + age: 5 +} @test(eq, {age: 5, name: "cueckoo"}) +-- out/compile -- +--- x.cue +{ + #C1: { + name: string + } + #C2: { + 〈1;#C1〉 + age: int + } + c1: (〈0;#C1〉 & { + name: "cueckoo" + }) + c2: (〈0;#C2〉 & { + 〈1;c1〉 + age: 5 + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue3834.txtar b/internal/core/compile/testdata/sync/definitions/issue3834.txtar new file mode 100644 index 000000000..06ec9472d --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue3834.txtar @@ -0,0 +1,270 @@ +# Tests that hidden fields with disjunctions (close({y!: z?: _}) | _) work +# correctly when exposed through embedding. The key behavior is that _a unifies +# with close({y!: ...}) correctly even when exposed via {X} or X. +# Issue: https://cuelang.org/issue/3834 +-- in.cue -- +// expose at top level +X: { + _a: foo: true + _a: _ | close({y!: z?: _}) + _b: _a & {y: {}} + concrete: _b.y + isTrue: concrete != _|_ @test(eq, true) +} +{X} + +@test(eq, { + X: { + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + isTrue: true + } + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + isTrue: true + + sub: _ @test(ignore) + full: _ @test(ignore) +}) + +sub: t1: { + X: { + _a: foo: true + _a: _ | close({y!: z?: _}) + _b: _a & {y: {}} + concrete: _b.y + } + {X} + + @test(eq, { + X: { + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + } + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + }) +} +sub: t2: { + X: { + _a: foo: true + _a: _ | close({y!: z?: _}) + _b: _a & {y: {}} + concrete: _b.y @test(eq, {}) + } + X + + @test(eq, { + X: { + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + } + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + }) +} +sub: t3: { + #X: { + _a: foo: true + _a: _ | close({y!: z?: _}) + _b: _a & {y: {}} + concrete: _b.y @test(eq, {}) + } + {#X} + + @test(eq, { + #X: { + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + } + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + }) +} +sub: t4: { + #X: { + _a: foo: true + _a: _ | close({y!: z?: _}) + _b: _a & {y: {}} + concrete: _b.y @test(eq, {}) + @test(debug, """ + (#struct){ + _a: (#struct){ + foo: (bool){ true } + } + _b: (#struct){ + y: (#struct){ + } + foo: (bool){ true } + } + concrete: (#struct){ + } + } + """) + } + #X + + @test(eq, { + #X: { + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + } + _a: {foo: true} + _b: {y: {}, foo: true} + concrete: {} + }) +} + +full: { + #Foo: { + _data: Foo: true + _data: _ | close({Extra!: optional?: _}) + + _dataWithExtra: _data & {Extra: {}} + + out: _dataWithExtra.Extra != _|_ @test(eq, true) + } + + {#Foo} + + @test(eq, { + #Foo: { + _data: {Foo: true} + _dataWithExtra: {Extra: {}, Foo: true} + out: true + } + _data: {Foo: true} + _dataWithExtra: {Extra: {}, Foo: true} + out: true + }) +} +-- out/compile -- +--- in.cue +{ + X: { + _a: { + foo: true + } + _a: (_|close({ + y!: { + z?: _ + } + })) + _b: (〈0;_a〉 & { + y: {} + }) + concrete: 〈0;_b〉.y + isTrue: (〈0;concrete〉 != _|_(explicit error (_|_ literal) in source)) + } + { + 〈1;X〉 + } + sub: { + t1: { + X: { + _a: { + foo: true + } + _a: (_|close({ + y!: { + z?: _ + } + })) + _b: (〈0;_a〉 & { + y: {} + }) + concrete: 〈0;_b〉.y + } + { + 〈1;X〉 + } + } + } + sub: { + t2: { + X: { + _a: { + foo: true + } + _a: (_|close({ + y!: { + z?: _ + } + })) + _b: (〈0;_a〉 & { + y: {} + }) + concrete: 〈0;_b〉.y + } + 〈0;X〉 + } + } + sub: { + t3: { + #X: { + _a: { + foo: true + } + _a: (_|close({ + y!: { + z?: _ + } + })) + _b: (〈0;_a〉 & { + y: {} + }) + concrete: 〈0;_b〉.y + } + { + 〈1;#X〉 + } + } + } + sub: { + t4: { + #X: { + _a: { + foo: true + } + _a: (_|close({ + y!: { + z?: _ + } + })) + _b: (〈0;_a〉 & { + y: {} + }) + concrete: 〈0;_b〉.y + } + 〈0;#X〉 + } + } + full: { + #Foo: { + _data: { + Foo: true + } + _data: (_|close({ + Extra!: { + optional?: _ + } + })) + _dataWithExtra: (〈0;_data〉 & { + Extra: {} + }) + out: (〈0;_dataWithExtra〉.Extra != _|_(explicit error (_|_ literal) in source)) + } + { + 〈1;#Foo〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/definitions/issue3851.txtar b/internal/core/compile/testdata/sync/definitions/issue3851.txtar new file mode 100644 index 000000000..a0e0f71c6 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue3851.txtar @@ -0,0 +1,44 @@ +# Tests that a nested optional field structure combined with let bindings and +# disjunctions (#Output: null | #App) evaluates correctly without false errors. +# https://cuelang.org/issue/3851 +-- in.cue -- +#App: { + name?: string + sub1?: sub2?: null | _ +} +#Output: null | #App @test(eq, null | {name?: string, sub1?: {sub2?: null | _}}) +out: #Output & { + name: "foo" + sub1: sub2: {} | _ + sub1: sub2: { + sub3: { + let _let = "bar" + foo: _let + } + } +} @test(eq, {name: "foo", sub1: {sub2: {sub3: {foo: "bar"}}}}) +-- out/compile -- +--- in.cue +{ + #App: { + name?: string + sub1?: { + sub2?: (null|_) + } + } + #Output: (null|〈0;#App〉) + out: (〈0;#Output〉 & { + name: "foo" + sub1: { + sub2: ({}|_) + } + sub1: { + sub2: { + sub3: { + let _let#1 = "bar" + foo: 〈0;let _let#1〉 + } + } + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue4000.txtar b/internal/core/compile/testdata/sync/definitions/issue4000.txtar new file mode 100644 index 000000000..193369e69 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue4000.txtar @@ -0,0 +1,127 @@ +# Tests that list.Sort with complex type definitions involving defaults works. +# Issue: https://cuelang.org/issue/4000 +-- in.cue -- +import "list" + +items: list.Sort(#List.items, { + x: {} + y: {} + less: x.kind < y.kind +}) @test(eq, [{ + spec: [{rules: [{expr: "x"}]}] + kind: *"default" | string + + @test(shareID=L0) + },{ + spec: [{rules: [{expr: "y"}]}] + kind: *"default" | string + + @test(shareID=L1) + }] +) + +#List: items: list.Concat(_items) + +_items: [#VMRuleList] + +// This is an alternative way of writing sharing. +@test(shareID=L0, at=items.0) +@test(shareID=L1, at=items.1) +@test(shareID=L0, at=#VMRuleList.0) +@test(shareID=L1, at=#VMRuleList.1) + +#VMRuleList: [...null | #VMRule] & [{ + spec: [{ + rules: [{expr: "x"}] + }] +}, { + spec: [{ + rules: [{expr: "y"}] + }] +}] @test(eq, [{ + @test(shareID=L0) + + kind: *"default" | string + spec: [{ + rules: [{ + expr: "x" + }] + }] +}, { + @test(shareID=L1) + + kind: *"default" | string + spec: [{ + rules: [{ + expr: "y" + }] + }] +}]) + +#RuleGroup: rules: [...#Rule] + +#Rule: expr: string @test(eq, string) + +#VMRule: { + #TypeMeta + spec: [...#RuleGroup] +} +#TypeMeta: kind: string | *"default" +-- out/compile -- +--- in.cue +{ + items: 〈import;list〉.Sort(〈0;#List〉.items, { + x: {} + y: {} + less: (〈0;x〉.kind < 〈0;y〉.kind) + }) + #List: { + items: 〈import;list〉.Concat(〈1;_items〉) + } + _items: [ + 〈1;#VMRuleList〉, + ] + #VMRuleList: ([ + ...(null|〈1;#VMRule〉), + ] & [ + { + spec: [ + { + rules: [ + { + expr: "x" + }, + ] + }, + ] + }, + { + spec: [ + { + rules: [ + { + expr: "y" + }, + ] + }, + ] + }, + ]) + #RuleGroup: { + rules: [ + ...〈2;#Rule〉, + ] + } + #Rule: { + expr: string + } + #VMRule: { + 〈1;#TypeMeta〉 + spec: [ + ...〈2;#RuleGroup〉, + ] + } + #TypeMeta: { + kind: (string|*"default") + } +} diff --git a/internal/core/compile/testdata/sync/definitions/issue419.txtar b/internal/core/compile/testdata/sync/definitions/issue419.txtar new file mode 100644 index 000000000..7ab628bc4 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue419.txtar @@ -0,0 +1,45 @@ +# Tests that a list constrained with [...#X] where #X is a disjunction of +# definitions correctly accepts values matching either branch of the disjunction. +# https://cuelang.org/issue/419 +-- in.cue -- +#A: { + a: string +} + +#B: { + b: string +} + +#X: #A | #B + +l: [...#X] + +l: [ + {b: "bar"}, +] + +@test(eq, { + #A: {a: string} + #B: {b: string} + #X: {a: string} | {b: string} + l: [{ b: "bar" }] +}) +-- out/compile -- +--- in.cue +{ + #A: { + a: string + } + #B: { + b: string + } + #X: (〈0;#A〉|〈0;#B〉) + l: [ + ...〈1;#X〉, + ] + l: [ + { + b: "bar" + }, + ] +} diff --git a/internal/core/compile/testdata/sync/definitions/issue471.txtar b/internal/core/compile/testdata/sync/definitions/issue471.txtar new file mode 100644 index 000000000..39cb9ae4c --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue471.txtar @@ -0,0 +1,56 @@ +# Tests that unifying a disjunction of definitions with an additional constraint +# (#a: (#c | #d) & {name: string}) does not incorrectly reject fields from either branch. +# https://cuelang.org/issue/471 +-- in.cue -- +package x + +#a: (#c | #d) & { + name: string +} + +#a1: #c & { + name: string +} + +#a2: #d & { + name: string +} + +#c: { + name: string + age: int +} + +#d: { + name: string + address: string +} + +@test(eq, { + #a: {name: string, age: int} | {name: string, address: string} + #a1: {name: string, age: int} + #a2: {name: string, address: string} + #c: {name: string, age: int} + #d: {name: string, address: string} +}) +-- out/compile -- +--- in.cue +{ + #a: ((〈0;#c〉|〈0;#d〉) & { + name: string + }) + #a1: (〈0;#c〉 & { + name: string + }) + #a2: (〈0;#d〉 & { + name: string + }) + #c: { + name: string + age: int + } + #d: { + name: string + address: string + } +} diff --git a/internal/core/compile/testdata/sync/definitions/issue483.txtar b/internal/core/compile/testdata/sync/definitions/issue483.txtar new file mode 100644 index 000000000..42a4c1b4e --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue483.txtar @@ -0,0 +1,40 @@ +# Tests that optional nested fields within a definition unified with an open struct +# (#Root: {...}) correctly accept concrete values without "field not allowed" errors. +# https://cuelang.org/issue/483 +-- in.cue -- +out: { + instance +} @test(eq, {alpha: bravo: charlie: true}) + +instance: #Type & { + alpha: bravo: charlie: true +} @test(eq, {alpha: bravo: charlie: true}) + +#Type: #Root & { + alpha?: bravo?: charlie?: bool +} +#Root: {...} +-- out/compile -- +--- in.cue +{ + out: { + 〈1;instance〉 + } + instance: (〈0;#Type〉 & { + alpha: { + bravo: { + charlie: true + } + } + }) + #Type: (〈0;#Root〉 & { + alpha?: { + bravo?: { + charlie?: bool + } + } + }) + #Root: { + ... + } +} diff --git a/internal/core/compile/testdata/sync/definitions/issue491.txtar b/internal/core/compile/testdata/sync/definitions/issue491.txtar new file mode 100644 index 000000000..c30a512f7 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue491.txtar @@ -0,0 +1,78 @@ +# Tests that a definition used as a list element type correctly propagates default +# values and does not incorrectly reject fields like Pattern when unified. +# https://cuelang.org/issue/491 +-- in.cue -- +package x + +#Prestep: { + Args: *null | _ +} + +#PrestepNewUser: #Prestep & { + Args: #NewUser +} + +#NewUser: { + Repos: [...#Repo] +} + +#Repo: { + Var: string + Pattern: *"*" | string +} + +x: [...#Repo] +x: [{ + Var: "REPO1" +}] @test(eq, [{Var: "REPO1", Pattern: *"*" | string}]) + +y: #Repo & { + Var: "REPO1" +} @test(eq, {Var: "REPO1", Pattern: *"*" | string}) + +z: #PrestepNewUser & { + Args: { + Repos: [{ + Var: "REPO1" + }] + } +} @test(eq, {Args: {Repos: [{Var: "REPO1", Pattern: *"*" | string}]}}) +-- out/compile -- +--- in.cue +{ + #Prestep: { + Args: (*null|_) + } + #PrestepNewUser: (〈0;#Prestep〉 & { + Args: 〈1;#NewUser〉 + }) + #NewUser: { + Repos: [ + ...〈2;#Repo〉, + ] + } + #Repo: { + Var: string + Pattern: (*"*"|string) + } + x: [ + ...〈1;#Repo〉, + ] + x: [ + { + Var: "REPO1" + }, + ] + y: (〈0;#Repo〉 & { + Var: "REPO1" + }) + z: (〈0;#PrestepNewUser〉 & { + Args: { + Repos: [ + { + Var: "REPO1" + }, + ] + } + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue493.txtar b/internal/core/compile/testdata/sync/definitions/issue493.txtar new file mode 100644 index 000000000..2f22748ef --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue493.txtar @@ -0,0 +1,31 @@ +# Tests that a disjunction of identical definitions (#Both: #App | #Atom where +# both alias the same type) correctly unifies with an additional constraint. +# https://cuelang.org/issue/493 +-- in.cue -- +#Artifact: { + body: _ + other: [string]: int +} @test(shareID=appAtom) + +#App: #Artifact @test(shareID=appAtom) +#Atom: #Artifact @test(shareID=appAtom) + +#Both: #App | #Atom + +t1: #Both & {body: 3} @test(eq, {body: 3, other: {}}) +-- out/compile -- +--- in.cue +{ + #Artifact: { + body: _ + other: { + [string]: int + } + } + #App: 〈0;#Artifact〉 + #Atom: 〈0;#Artifact〉 + #Both: (〈0;#App〉|〈0;#Atom〉) + t1: (〈0;#Both〉 & { + body: 3 + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue496.txtar b/internal/core/compile/testdata/sync/definitions/issue496.txtar new file mode 100644 index 000000000..307a2c519 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue496.txtar @@ -0,0 +1,24 @@ +# Tests that hidden fields within a definition unified with #A: _ are correctly +# handled and do not cause spurious "field not allowed" errors. +# https://cuelang.org/issue/496 +-- in.cue -- +#A: _ + +#N: #A & { + _E: { + name: "hello" + } +} @test(shareID=lN) + +l: #N @test(shareID=lN) +-- out/compile -- +--- in.cue +{ + #A: _ + #N: (〈0;#A〉 & { + _E: { + name: "hello" + } + }) + l: 〈0;#N〉 +} diff --git a/internal/core/compile/testdata/sync/definitions/issue497.txtar b/internal/core/compile/testdata/sync/definitions/issue497.txtar new file mode 100644 index 000000000..08336fdf2 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue497.txtar @@ -0,0 +1,26 @@ +# Tests that nested fields within a definition unified with #A: _ are accepted +# and do not produce spurious "field not allowed" errors on the nested structure. +# https://cuelang.org/issue/497 +-- in.cue -- +#A: _ + +#N: #A & { + f: j: { + n: "hi" + } +} @test(shareID=lN) @test(eq, {f: {j: {n: "hi"}}}) + +l: #N @test(shareID=lN) +-- out/compile -- +--- in.cue +{ + #A: _ + #N: (〈0;#A〉 & { + f: { + j: { + n: "hi" + } + } + }) + l: 〈0;#N〉 +} diff --git a/internal/core/compile/testdata/sync/definitions/issue533.txtar b/internal/core/compile/testdata/sync/definitions/issue533.txtar new file mode 100644 index 000000000..64523bee1 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue533.txtar @@ -0,0 +1,41 @@ +# Tests that hidden definitions (_#x) enforce closedness the same way regular +# definitions (#x) do, rejecting extra fields not declared in the definition. +# https://cuelang.org/issue/533 +-- in.cue -- +package x + +#x: { + Name: string +} + +_#x: { + Name: string +} + +x1: #x & { + Name: "hello" + Age: 50 +} @test(err, code=eval, at=Age, contains="field not allowed", pos=[2:2]) + +x2: _#x & { + Name: "hello" + Age: 50 +} @test(err, code=eval, at=Age, contains="field not allowed", pos=[2:2]) +-- out/compile -- +--- in.cue +{ + #x: { + Name: string + } + _#x(:x): { + Name: string + } + x1: (〈0;#x〉 & { + Name: "hello" + Age: 50 + }) + x2: (〈0;_#x(:x)〉 & { + Name: "hello" + Age: 50 + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/issue539.txtar b/internal/core/compile/testdata/sync/definitions/issue539.txtar new file mode 100644 index 000000000..0dd6b797e --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/issue539.txtar @@ -0,0 +1,34 @@ +# Tests that combining a definition with open spread (`...`) and a non-definition +# struct preserves the expected fields including hidden definitions and defaults. +# Issue: https://cuelang.org/issue/539 +-- in.cue -- +#Schema: { + ... +} + +Component: { + hostname: string | *"localhost" + + _#foo: { + hello: "world" + } +} + +hello: #Schema & Component @test(closed) @test(eq, { + hostname: *"localhost" | string + _#foo: {hello: "world"} +}) +-- out/compile -- +--- in.cue +{ + #Schema: { + ... + } + Component: { + hostname: (string|*"localhost") + _#foo: { + hello: "world" + } + } + hello: (〈0;#Schema〉 & 〈0;Component〉) +} diff --git a/internal/core/compile/testdata/sync/definitions/list.txtar b/internal/core/compile/testdata/sync/definitions/list.txtar new file mode 100644 index 000000000..55ac34c5b --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/list.txtar @@ -0,0 +1,25 @@ +-- in.cue -- +c: #R & { + w: [{}, {b: int}] +} @test(eq, {w: [{}, {b: int}]}) +#R: { + w: [{}, ...] +} +-- out/compile -- +--- in.cue +{ + c: (〈0;#R〉 & { + w: [ + {}, + { + b: int + }, + ] + }) + #R: { + w: [ + {}, + ..., + ] + } +} diff --git a/internal/core/compile/testdata/sync/definitions/root1.txtar b/internal/core/compile/testdata/sync/definitions/root1.txtar new file mode 100644 index 000000000..72e79b3c4 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root1.txtar @@ -0,0 +1,20 @@ +-- in.cue -- +// Test embedding at root of file +root1: 1 +#Root1: x: {} +#Root1 & { } + +@test(eq, { + root1: 1 + #Root1: x: {} + x: {} +}) +-- out/compile -- +--- in.cue +{ + root1: 1 + #Root1: { + x: {} + } + (〈0;#Root1〉 & {}) +} diff --git a/internal/core/compile/testdata/sync/definitions/root2.txtar b/internal/core/compile/testdata/sync/definitions/root2.txtar new file mode 100644 index 000000000..d8d389ed4 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root2.txtar @@ -0,0 +1,16 @@ +-- in.cue -- +root2: 1 +#Root2: {} +#Root2 + +@test(eq, { + root2: 1 + #Root2: {} +}) +-- out/compile -- +--- in.cue +{ + root2: 1 + #Root2: {} + 〈0;#Root2〉 +} diff --git a/internal/core/compile/testdata/sync/definitions/root3.txtar b/internal/core/compile/testdata/sync/definitions/root3.txtar new file mode 100644 index 000000000..c98a89292 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root3.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +x: _ +#D: b: x +#D & { b: _ } + +@test(eq, { + x: _ + #D: b: _ + b: _ +}) +-- out/compile -- +--- in.cue +{ + x: _ + #D: { + b: 〈1;x〉 + } + (〈0;#D〉 & { + b: _ + }) +} diff --git a/internal/core/compile/testdata/sync/definitions/root4.txtar b/internal/core/compile/testdata/sync/definitions/root4.txtar new file mode 100644 index 000000000..f9a03d22a --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root4.txtar @@ -0,0 +1,33 @@ +-- in.cue -- +#schema: a!: bool +_hidden & #schema // must fail here, but not elsewhere +_hidden: { + "a": true, + notAllowed: true +} +allowed: true + +@test(eq, { + a: true + #schema: a!: bool + _hidden: { + a: true + notAllowed: true + } + allowed: true + notAllowed: _|_ +}) +@test(err, code=eval, contains="field not allowed", pos=[in.cue:5:2]) +-- out/compile -- +--- in.cue +{ + #schema: { + a!: bool + } + (〈0;_hidden〉 & 〈0;#schema〉) + _hidden: { + a: true + notAllowed: true + } + allowed: true +} diff --git a/internal/core/compile/testdata/sync/definitions/root5.txtar b/internal/core/compile/testdata/sync/definitions/root5.txtar new file mode 100644 index 000000000..700f85573 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root5.txtar @@ -0,0 +1,89 @@ +-- in.cue -- +_schema // embed schema through indirections +_schema: #Schema @test(shareID=topSchema) +#Schema: { + @test(shareID=topSchema) + a?: b?: string +} +a: b: "foo" +c: "foo" + + +x: { + _schema // embed schema through indirections + _schema: #Schema @test(shareID=xSchema) + #Schema: { + @test(shareID=xSchema) + a?: b?: string + } + a: b: "foo" + c: "foo" +} + +@test(eq, { + a: b: "foo" + _schema: a?: b?: string + #Schema: a?: b?: string + c: "foo" + x: { + a: b: "foo" + _schema: a?: b?: string + #Schema: a?: b?: string + c: "foo" + } +}) +// TODO(inline): fix sharing detection across hidden fields. +@test(debug, """ + (#struct){ + _schema: ~(#Schema) + #Schema: (#struct){ + a?: (#struct){ + b?: (string){ string } + } + } + a: (#struct){ + b: (string){ "foo" } + } + c: (string){ "foo" } + x: (#struct){ + _schema: ~(x.#Schema) + #Schema: (#struct){ + a?: (#struct){ + b?: (string){ string } + } + } + a: (#struct){ + b: (string){ "foo" } + } + c: (string){ "foo" } + } + } + """) +-- out/compile -- +--- in.cue +{ + 〈0;_schema〉 + _schema: 〈0;#Schema〉 + #Schema: { + a?: { + b?: string + } + } + a: { + b: "foo" + } + c: "foo" + x: { + 〈0;_schema〉 + _schema: 〈0;#Schema〉 + #Schema: { + a?: { + b?: string + } + } + a: { + b: "foo" + } + c: "foo" + } +} diff --git a/internal/core/compile/testdata/sync/definitions/root6.txtar b/internal/core/compile/testdata/sync/definitions/root6.txtar new file mode 100644 index 000000000..6279bd9b2 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root6.txtar @@ -0,0 +1,49 @@ +-- in.cue -- +c: "foo" +a: b: int +#Schema +#Schema: close({ a: b: int}) @test(closed) + +x: { + c: "foo" + a: b: int + #Schema + #Schema: close({ a: b: int}) +} @test(closed) + +@test(eq, { + a: b: int + c: "foo" + #Schema: { a: b: int } + x: { + a: b: int + c: "foo" + #Schema: a: b: int + } +}) +-- out/compile -- +--- in.cue +{ + c: "foo" + a: { + b: int + } + 〈0;#Schema〉 + #Schema: close({ + a: { + b: int + } + }) + x: { + c: "foo" + a: { + b: int + } + 〈0;#Schema〉 + #Schema: close({ + a: { + b: int + } + }) + } +} diff --git a/internal/core/compile/testdata/sync/definitions/root7.txtar b/internal/core/compile/testdata/sync/definitions/root7.txtar new file mode 100644 index 000000000..dae529416 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root7.txtar @@ -0,0 +1,19 @@ +-- in.cue -- +root: input: #deps: root: {} +{root.input.#deps} + +@test(eq, { root: input: #deps: root: {} }) +-- out/compile -- +--- in.cue +{ + root: { + input: { + #deps: { + root: {} + } + } + } + { + 〈1;root〉.input.#deps + } +} diff --git a/internal/core/compile/testdata/sync/definitions/root8.txtar b/internal/core/compile/testdata/sync/definitions/root8.txtar new file mode 100644 index 000000000..87358ab09 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/root8.txtar @@ -0,0 +1,44 @@ +-- in.cue -- +root: input: foo: { + metadata: name: *"foo" | string + id: "id-\(metadata.name)" + #deps: [string]: _ + #deps: root: {} + spec: replicas: 1 +} +{root.input.foo.#deps} + +@test(eq, { + root: input: foo: { + metadata: name: *"foo" | string + id: "id-foo" + #deps: root: {} + spec: replicas: 1 + } +}) +-- out/compile -- +--- in.cue +{ + root: { + input: { + foo: { + metadata: { + name: (*"foo"|string) + } + id: "id-\(〈0;metadata〉.name)" + #deps: { + [string]: _ + } + #deps: { + root: {} + } + spec: { + replicas: 1 + } + } + } + } + { + 〈1;root〉.input.foo.#deps + } +} diff --git a/internal/core/compile/testdata/sync/definitions/typocheck.txtar b/internal/core/compile/testdata/sync/definitions/typocheck.txtar new file mode 100644 index 000000000..11c7c8269 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/typocheck.txtar @@ -0,0 +1,2096 @@ +-- in.cue -- +embed: simple: { + #A: b: 1 + a: { #A } + a: err: 1 @test(err, code=eval, contains="field not allowed", pos=[0:5]) +} +embed: andInStruct: { + #Foo: a: int + a: { #Foo & { err: 2 } } + + @test(err, at=a.err, code=eval, contains="field not allowed", pos=[2:16]) +} +embed: embedDefWithEmbedding: { + #Foo: {{a: int}} + a: { #Foo & { err: 2 } } // not allowed + + @test(err, at=a.err, code=eval, contains="field not allowed", pos=[2:16]) +} +embed: embedComprehension: { + #Foo: {if true {a: int}} + a: { #Foo & { err: 2 } } // not allowed + + @test(err, at=a.err, code=eval, contains="field not allowed", pos=[2:16]) +} +embed: fieldWithAnd: { + #A: {} + { a: #A & {err: 3 } } + + @test(err, at=a.err, code=eval, contains="field not allowed", pos=[2:13]) +} +embed: embedAndRecursive: { + #A: a: int + B: x: #A + B & { x: err: 2 } + + @test(err, at=x.err, code=eval, contains="field not allowed", pos=[3:11]) +} +embed: andEmbed: { + #A: b: int + #B: b: int + #D: {#A & #B} + d: #D & {err: 3} + + @test(err, at=d.err, code=eval, contains="field not allowed", pos=[4:11]) +} +and: transitive: ok: { + Z: {a: string} @test(shareID:todo=Z) + #Y: Z @test(shareID:todo=Z) + #X: #Y & Z + out: #X & { + a: "foo" + } + + @test(eq, { + Z: {a: string} + #Y: {a: string} + #X: {a: string} + out: {a: "foo"} + }) +} +and: transitive: err: { + Z: a: string + #Y: Z + #X: #Y & Z + out: #X & { + err: "foo" + } @test(err, at=err, code=eval, contains="field not allowed", pos=[1:3]) +} +and: transitiveWithEmbed: ok: { + Z: a: string + #X: #Y & Z + #Y: {Z} + out: #X & { + a: "foo" + } + + @test(eq, { + Z: {a: string} + #X: {a: string} + #Y: {a: string} + out: {a: "foo"} + }) +} +and: transitiveWithEmbed: err: { + Z: a: string + #X: #Y & Z + #Y: {Z} + out: #X & { + err: "foo" + } + + @test(err, at=out.err, code=eval, contains="field not allowed", pos=[5:3]) +} +embed: nonDef: t1: { + X: a: string + #Y: #Z & X + #Z: { + X + b?: string + } + + @test(eq, { + X: {a: string} + #Y: {b?: string, a: string} + #Z: {b?: string, a: string} + }) +} +embed: defAndHidden: full: { + _stepCommon: Name: string + #Step: #Command & _stepCommon + #Command: { + _stepCommon + Path?: string + } + out: #Step & { + Name: "foo" + } + + @test(eq, { + _stepCommon: {Name: string} + #Step: {Path?: string, Name: string} + #Command: {Path?: string, Name: string} + out: {Name: "foo", Path?: string} + }) +} +embed: withIndirect: { + A: #B + #B: b: int + A & { err: 2 } // not allowed + + @test(err, at=err, code=eval, contains="field not allowed", pos=[3:8]) +} +-- validators.cue -- +import ( + "struct" + "list" +) + +embed: normalValidator: { + #X: { + struct.MaxFields(1) + a?: int + b?: int + } + x: #X + x: err: 1 @test(err, code=eval, contains="field not allowed", pos=[-5:3, 0:5]) +} +embed: openValidator: t1: { + #X: { + matchN(0, []) + a?: int + b?: int + } + x: #X + x: err: 1 + + @test(eq, { + #X: {matchN(0, []), a?: int, b?: int} + x: {err: 1, a?: int, b?: int} + }) +} +embed: openValidator: t2: { + Y: matchN(1, [X]) + X: b?: Y + a: X + a: b: 1 @test(err, suberr=(code=eval, contains="conflicting values"), + suberr=(code=eval, contains="does not satisfy matchN", pos=[-3:5, -3:12, -2:9, 0:8]), + ) +} +disjunction: withErr: t1: { + params: {} + out: #Schema1 & { + b1: b2: b3: params.mayExistLater + } + #Schema1: b1?: null | #Schema2 + #Schema2: b2?: null | {b3?: string} + + @test(eq, { + params: {} + out: {b1: {b2: {b3: _}}} + #Schema1: {b1?: null | {b2?: null | {b3?: string}}} + #Schema2: {b2?: null | {b3?: string}} + }) +} +embed: nestedValidator: { + #types: z?: list.UniqueItems + x: y: z: [1] + x: { + #def + y?: #types + } + #def: {} + + @test(eq, { + #types: _ @test(ignore) + x: {y: {z: [1]}} + #def: {} + }) +} +-- inline.cue -- +embedInline: { + #Schema: { + a: "hello" + // do not close outer struct of 'b', as inlined value is not a schema. + b: { {x: c: "foo"}.x } + b: { + c: string + d: "never printed" + } + } + out: #Schema & __no_sharing + + @test(eq, { + #Schema: {a: "hello", b: {c: "foo", d: "never printed"}} + out: {a: "hello", b: {c: "foo", d: "never printed"}} + }) +} +// evalv3 "field not allowed" regression involving embeddings and selectors; +// accessing a field via selector on an embedded definition should stay open. +// https://cuelang.org/issue/3853 +issue3853: { + #Schema: { + a: "hello" + // do not close outer struct of 'b', as inlined value is not a schema. + b: { {x: c: "foo"}.x } + b: { + c: string + d: "never printed" + } + } + out: {x: (#Schema & {}).a}.x + + @test(eq, { + #Schema: {a: "hello", b: {c: "foo", d: "never printed"}} + out: "hello" + }) +} +-- disjunction.cue -- +import "list" + +// evalv3 regression: closedness errors no longer reported when default values +// are present; disallowed fields in a default disjunct should still be caught. +// https://cuelang.org/issue/3947 +issue3947: full: { + #Schema: allowed?: string + _defaults: disallowed: _ | *"default value" + out: #Schema & _defaults @test(err, code=eval, at=disallowed, contains="field not allowed", pos=[-1:13]) +} +// evalv3 regression: #oneOf pattern disjunction; unifying a closed definition +// disjunction with a default string field caused incorrect field-not-allowed errors. +// https://cuelang.org/issue/3957 +issue3957: reduced: { + c: a: "bar" + c: #B & {a: string | *"foo"} + #B: b?: string + + @test(err, at=c.a, code=eval, contains="field not allowed", pos=[1:5, 2:11]) +} +issue3957: full: { + #oneof: {a: string} | {b?: [...string]} + c: #oneof & {a: string | *"foo"} + c: a: "bar" + + @test(eq, { + #oneof: {a: string} | {b?: []} + c: {a: "bar"} + }) +} +issue3957: derived: t1: { + #Schema: { + in: string | [...string] + out: list.FlattenN([in], 1) + } + x: #Schema & {in: "foo"} + + @test(eq, { + #Schema: {in: string | [], out: [string | []]} + x: {in: "foo", out: ["foo"]} + }) +} +issue3957: derived: t2: { + #Schema: { + in: string | [...string] + let _flat = list.FlattenN([in], 1) + out: _flat + } + out: #Schema & {in: "foo"} + + @test(eq, { + #Schema: {in: string | [], out: [string | []]} + out: {in: "foo", out: ["foo"]} + }) +} +-- issue3833.cue -- +// evalv3 "field not allowed" regression with embeddings; combining a definition +// that has an open field with another definition via embedding should be allowed. +// https://cuelang.org/issue/3833 +issue3833: ok: { + out: { #A & { a: #B } } + #A: { + a: {b: string, ...} + ... + } + #C: c: string + #B: { + #C & {c: "foo"} + b: "foo" + } + + @test(eq, { + out: {a: {b: "foo", c: "foo"}} + #A: {a: {b: string}} + #C: {c: string} + #B: {c: "foo", b: "foo"} + }) +} +issue3833: evalv2Issue:{ + out: { #A & { a: #B } } + #A: { + a: b: string + ... + } + #C: c: string + #B: { + #C & {c: "foo"} + b: "foo" + } + + @test(err, at=out.a.c, code=eval, + contains="field not allowed", pos=[6:6, 8:9], + hint="key positions are missing", + ) +} +-- issue3837.cue -- +// evalv3 regression with embeddings, disjunctions, and extra fields; a struct +// that embeds a definition and adds extra fields should not cause spurious errors. +// https://cuelang.org/issue/3837 +issue3837: reduced: { + A: { + #Embed + extra: "foo" + } + out: {{ x: A & __no_sharing }} + #Embed: {} + + @test(eq, { + A: {extra: "foo"} + out: {x: {extra: "foo"}} + #Embed: {} + }) +} +issue3837: full: { + #Embed: {} + #A: { + #Embed + extra: "foo" + } + #B: (#C | {}) + #C: bar: string + out: #B & { + bar: "baz" + { + #def: (#A & __no_sharing) + } + } + + @test(eq, { + #Embed: {} + #A: {extra: "foo"} + #B: {bar: string} | {} + #C: {bar: string} + out: {bar: "baz", #def: {extra: "foo"}} + }) +} +-- issue3832.cue -- +// evalv3 "field not allowed" regression with a disjunction and a let field; +// a let binding inside a disjunct should not cause closedness errors. +// https://cuelang.org/issue/3832 +issue3832: { + _person: self: firstName: "Sam" + + #T: { + _subject: { + in: _ + out: { + let self = in.self + outFirstName: self.firstName + } + } + _assert: pass: _ + _assert: { + check!: _ + pass: "never" + } | { + invoke!: _ + // TODO: here, the let from _subject.out gets converted to a + // permanent error,instead of incomplete. + pass: (_subject & {in: invoke}).out + } + results: _assert.pass + } + #T & { + _assert: invoke: _person + } + + @test(eq, { + _person: {self: {firstName: "Sam"}} + #T: _ @test(ignore) + _assert: { + invoke: {self: {firstName: "Sam"}} + pass: {outFirstName: "Sam"} + } + _subject: _ @test(ignore) + results: {outFirstName: "Sam"} + }) +} +-- issue3839.cue -- +// evalv3 closedness regression with embeddings and definitions; embedding a +// definition with an ellipsis inside a non-definition should remain open. +// https://cuelang.org/issue/3839 +issue3839: reduced: { + x: { A & __no_sharing } + x: y: 1 + #B: { + // Note: true with both old semantics and explicitopen + @test(closed) + @test(allows=false, string) + } + A: { + #B + ... + + // Note: true with both old semantics and explicitopen + @test(closed) + @test(allows, string) + } + + @test(eq, {x: {y: 1}, #B: {}, A: {}}) +} +issue3839: full: { + _globals: glb: globalField: "" + + #GlobalContext: globalField: string + #Context: { + glb: #GlobalContext + out: glb + } + out: { + ingress: { + #Ingress & { + #def: (#Context & _globals).out + } + } + + ingress?: { + foo: 1234 + bar: "http" + } + } + #Embed: #def: {...} + + #Ingress: { + #Embed + ... + } + + @test(eq, { + _globals: {glb: {globalField: ""}} + #GlobalContext: {globalField: string} + #Context: {glb: {globalField: string}, out: {globalField: string}} + out: {ingress: {#def: {globalField: ""}, foo: 1234, bar: "http"}} + #Embed: {#def: {}} + #Ingress: {#def: {}} + }) +} +-- chaineddef.cue -- +// evalv3 "field not allowed" regression when embedding a chain of definitions; +// chained optional-field definitions embedded in a struct should not be enforced. +// https://cuelang.org/issue/3920 +// chained definitions should be handled correctly within embeddings. +issue3920: { + out: { + #A + a: b: "out" // do not enforce #B + } + #A: a?: #B + #B: c?: string + + @test(eq, { + out: {a: {b: "out", c?: string}} + #A: {a?: {c?: string}} + #B: {c?: string} + }) +} +onlyCloseDirectStruct: { + #foo: {} + x: {y: {{a: #foo}}} + x: y: b: 1 + + @test(eq, {#foo: {}, x: {y: {a: {}, b: 1}}}) +} +closeInEmbed: { + x: {close({{["d"]: f: int}})} + x: d: e: 1 + + @test(eq, {x: {d: {e: 1, f: int}}}) +} +-- embedelim.cue -- +// evalv3 "field not allowed" regression with nested definitions; eliminating +// an embedded top value from a definition should not incorrectly close the struct. +// https://cuelang.org/issue/3921 +issue3921: top: { + #A: #B + #A: b: string + #B: _ + a: {#A & {}} + + @test(eq, {#A: {b: string}, #B: _, a: {b: string}}) +} +issue3921: hidden: { + #A: #B + #A: _hidden: b: string + #B: {} + a: { #A & { _hidden: {} }} + + @test(eq, { + #A: {_hidden: {b: string}} + #B: {} + a: {_hidden: {b: string}} + }) +} +issue3921: full: { + out: #templateList & #defineMap + #templateList: { + #stepMap: [string]: _ + stepList: [for c in #stepMap {c}] + } + #defineMap: { + #stepMap: foo: #Step & { + image: "bar" + #config: {} + } + stepList: _ + } + #Step: #StepInner & { + image: string + #config: version: string + } + #StepInner: image: string + + @test(eq, { + out: { + #stepMap: {foo: { + image: "bar" + #config: {version: string} + }} + stepList: [{ + image: "bar" + #config: {version: string} + }] + } + #templateList: {#stepMap: {}, stepList: []} + #defineMap: { + #stepMap: {foo: { + image: "bar" + #config: {version: string}} + } + stepList: _ + } + #Step: { + image: string + #config: {version: string} + } + #StepInner: {image: string} + }) +} +-- issue3843.cue -- +// evalv3 "field not allowed" regression when a definition is reused at +// multiple levels and pattern constraints are unified more than once. +// https://cuelang.org/issue/3843 +// Pattern is unified twice. Ensure that deduping is handled correctly. +dedupPattern: t1: p1: { + A: { + #Z: [string]: _ + x: #Z + x: y: z: 1 + } + B: A & __no_sharing + out: A.#Z & B.x + + @test(eq, { + A: {#Z: {}, x: {y: {z: 1}}} + B: {#Z: {}, x: {y: {z: 1}}} + out: {y: {z: 1}} + }) +} +dedupPattern: t1: p2: { + A: { + #Z: [string]: _ + x: #Z + x: y: z: 1 + } + B: A & __no_sharing + out: B.x & A.#Z + + @test(eq, { + A: {#Z: {}, x: {y: {z: 1}}} + B: {#Z: {}, x: {y: {z: 1}}} + out: {y: {z: 1}} + }) +} +-- issue3858.cue -- +// evalv3 "field not allowed" regression with embeddings where a definition +// with an embedded field reference was incorrectly rejected. +// https://cuelang.org/issue/3858 +orig: t1: { + #Image: embed: image: "foo:v1" + #JobConfig: { + image: #Image + job: #Job & { + image.embed + } + } + #Job: { + image: string + vcs: "git" + args: [...string] + env: [string]: string + } + + #Output: { + _in: _ + out: (_in & {}) + } + #Output & { + _in: (#JobConfig & {}).job + } + + @test(eq, { + #Image: {embed: {image: "foo:v1"}} + #JobConfig: { + image: {embed: {image: "foo:v1"}} + job: {image: "foo:v1", vcs: "git", args: [], env: {}} + } + #Job: {image: string, vcs: "git", args: [], env: {}} + #Output: {_in: _, out: {}} + _in: {image: "foo:v1", vcs: "git", args: [], env: {}} + out: {image: "foo:v1", vcs: "git", args: [], env: {}} + }) +} +reduced: t1: { + Y: { + a: e: "foo" + b: X & { a } + } + X: { + e: string + f: 1 // fails in `out` + } + #Z: { + _in: _ + out: _in & __no_sharing + } + #Z & { + _in: Y + } + + @test(eq, { + Y: {a: {e: "foo"}, b: {e: "foo", f: 1}} + X: {e: string, f: 1} + #Z: {_in: _, out: _} + _in: {a: {e: "foo"}, b: {e: "foo", f: 1}} + out: {a: {e: "foo"}, b: {e: "foo", f: 1}} + }) +} +orig: t2: { + #JobConfig: { + image: spec: image: "someimage" + job: #Job & { + image.spec + } + } + #Job: { + image: string + env: "FOO" + } + #Output: { + in: _ + out: (in & {}).input + } + out: #Output & { + in: input: (#JobConfig & {}).job + } + + @test(eq, { + #JobConfig: { + image: {spec: {image: "someimage"}} + job: {image: "someimage", env: "FOO"} + } + #Job: {image: string, env: "FOO"} + #Output: { + in: _ + out: _ @test(ignore) + } + out: { + in: {input: {image: "someimage", env: "FOO"}} + out: {image: "someimage", env: "FOO"} + } + }) +} +reduced: t2: { + Y: { + a: e: "foo" + b: X & { a } + } + X: { + e: string + f: 1 // fails + } + #Z: { + _in: _ + out: _in + } + #Z & { _in: Y } + + @test(eq, { + Y: {a: {e: "foo"}, b: {e: "foo", f: 1}} + X: {e: string, f: 1} + #Z: {_in: _, out: _} + _in: {a: {e: "foo"}, b: {e: "foo", f: 1}} + out: {a: {e: "foo"}, b: {e: "foo", f: 1}} + }) +} +-- issue3934.cue -- +// evalv3 "field not allowed" regression with disjunctions and a comprehension; +// a false-branch comprehension inside a disjunct should not trigger closedness errors. +// https://cuelang.org/issue/3934 +issue3934: { + out: #Foo & { + foo: { + if false { + extra: nested: 123 + } + } + } + #Foo: foo?: null | #Bar | *{bar: 3} + #Bar: { + bar?: int + extra?: null | {...} + } + + @test(eq, { + out: {foo: *{bar: 3} | {extra?: null | {}, bar?: int} | null} + #Foo: {foo?: *{bar: 3} | {bar?: int, extra?: null | {}} | null} + #Bar: {bar?: int, extra?: null | {}} + }) +} +-- large.cue -- +full: { + #Resource: { + someMsg: string + obs: {} | *{missing: true} + + let pickMsg = [ + if obs.missing {msg: "\(someMsg)"}, + {msg: "bar"}, + ][0] + patches: [{ + op: "add" + path: "/metadata" + value: pickMsg.msg + }] + } + + #Patches: [string]: _ + #JSONPatch: { + namespace?: string + patch: [...#JSONOp] + output: #Patches & {(namespace): patch} + } + #JSONOp: { + op: "add" + path: string + value: _ + } | { + op: "remove" + path: string + } + + #Main: { + NS=namespace: string + + output: jsonPatch.output + + let jsonPatch = #JSONPatch & { + let base = #Resource & {} + let withMsg = base & {someMsg: "foo"} + + namespace: NS + + patch: withMsg.patches + } + } + out: (#Main & {namespace: "ns1"}).output + + @test(eq, { + #Resource: _ @test(ignore) + #Patches: _ @test(ignore) + #JSONPatch: _ @test(ignore) + #JSONOp: _ @test(ignore) + #Main: _ @test(ignore) + out: {ns1: [{op: "add", path: "/metadata", value: "foo"}]} + }) +} +-- ellipsis.cue -- +nestedEllipsis: minimal: { + out: #Schema & { extra: "foo" } + #Schema: { + #meta + ... + } + #meta: {} + + @test(eq, {out: {extra: "foo"}, #Schema: {}, #meta: {}}) +} +nestedEllipsis: nestedWithPatterns: { + out: #Schema & { + objs: obj1: extra: "foo" + } + #Schema: { + [_]: [_]: { + #meta + ... + } + #meta: name?: int + objs?: _ + } + + @test(eq, { + out: { + objs: {obj1: {extra: "foo", name?: int}} + #meta: {name?: int} + } + #Schema: {#meta: {name?: int}, objs?: {}} + }) +} +// evalv3 "field not allowed" regression with ellipses since v0.13.0; embedding +// a schema with `...` alongside additional fields should not close the struct. +// https://cuelang.org/issue/4015 +issue4015: reduced: { + #X: { ... } + out: { + // Embedded schema allows `a: _`. Adding `a` below should not change that. + #X + a: b: string + } @test(allows, string) @test(closed) + out: { + a: { + c: "h" + b: "x" + } + } + + @test(eq, {#X: {}, out: {a: {b: "x", c: "h"}}}) +} +issue4015: nested: { + #X: { foo: {...} } + out: { + #X + foo: {a: b: string} @test(allows, string) @test(closed) + } + out: { + foo: a: { + c: "h" + b: "x" + } + } + + @test(eq, {#X: {foo: {}}, out: {foo: {a: {b: "x", c: "h"}}}}) +} +issue4015: full: { + #Schema: { + cfg: { + foo: { + enabled: bool | *false + fooField: string + } + bar: barField: string + } + capacity: int | *3 + } + + #MoreCapacity: { + capacity: 30 + ... + } + + out: #Schema + out: { + #MoreCapacity + cfg: foo: enabled: true + } + out: { + cfg: { + foo: fooField: "h" + bar: barField: "x" + } + + // This one is rather confusing, but true. Note that this should no + // longer hold if this is converted to the explicitopen semantics, in + // which case #Schema applies "monotonically" limiting to its fields. + @test(allows, string) + @test(allows:todo=false, string, hint="for explicit open") + @test(closed) + } + + @test(eq, { + #Schema: { + cfg: { + foo: {enabled: *false | bool, fooField: string} + bar: {barField: string} + } + capacity: *3 | int + } + #MoreCapacity: {capacity: 30} + out: { + cfg: {foo: {enabled: true, fooField: "h"}, bar: {barField: "x"}} + capacity: 30 + } + }) +} +-- issue3964.cue -- +// evalv3 closedness regression since v0.13.1; a definition that embeds another +// definition containing a disjunction should correctly allow matching fields. +// https://cuelang.org/issue/3964 +issue3964: reduced: { + #Output: { #Embedded } + #Embedded: { + name: string + #Unused | #Used + } + #Unused: {} + #Used: {} + + @test(eq, { + #Output: {name: string} + #Embedded: {name: string} + #Unused: {} + #Used: {} + }) +} +issue3964: full: { + out: #Output & { + name: "oauth2" + used: "bar" + } + #Output: { #Embedded } + #Embedded: { + name: string + #Unused | #Used + } + #Unused: unused: string + #Used: used: string + + @test(eq, { + out: {name: "oauth2", used: "bar"} + #Output: {name: string, unused: string} | {name: string, used: string} + #Embedded: {name: string, unused: string} | {name: string, used: string} + #Unused: {unused: string} + #Used: {used: string} + }) +} +-- cycle.cue -- +// evalv3 stack overflow due to latest closedness changes; mutually recursive +// definitions that embed each other caused infinite recursion during evaluation. +// https://cuelang.org/issue/4006 +issue4006: { + #A: { + #B + fieldA: string + } + #B: { #A } + #C: #A & {} + out: #C & #B + + @test(eq, { + #A: {fieldA: string} + #B: {fieldA: string} + #C: {fieldA: string} + out: {fieldA: string} + }) +} +-- out/compile -- +--- chaineddef.cue +{ + issue3920: { + out: { + 〈1;#A〉 + a: { + b: "out" + } + } + #A: { + a?: 〈1;#B〉 + } + #B: { + c?: string + } + } + onlyCloseDirectStruct: { + #foo: {} + x: { + y: { + { + a: 〈3;#foo〉 + } + } + } + x: { + y: { + b: 1 + } + } + } + closeInEmbed: { + x: { + close({ + { + ["d"]: { + f: int + } + } + }) + } + x: { + d: { + e: 1 + } + } + } +} +--- cycle.cue +{ + issue4006: { + #A: { + 〈1;#B〉 + fieldA: string + } + #B: { + 〈1;#A〉 + } + #C: (〈0;#A〉 & {}) + out: (〈0;#C〉 & 〈0;#B〉) + } +} +--- disjunction.cue +{ + issue3947: { + full: { + #Schema: { + allowed?: string + } + _defaults: { + disallowed: (_|*"default value") + } + out: (〈0;#Schema〉 & 〈0;_defaults〉) + } + } + issue3957: { + reduced: { + c: { + a: "bar" + } + c: (〈0;#B〉 & { + a: (string|*"foo") + }) + #B: { + b?: string + } + } + } + issue3957: { + full: { + #oneof: ({ + a: string + }|{ + b?: [ + ...string, + ] + }) + c: (〈0;#oneof〉 & { + a: (string|*"foo") + }) + c: { + a: "bar" + } + } + } + issue3957: { + derived: { + t1: { + #Schema: { + in: (string|[ + ...string, + ]) + out: 〈import;list〉.FlattenN([ + 〈1;in〉, + ], 1) + } + x: (〈0;#Schema〉 & { + in: "foo" + }) + } + } + } + issue3957: { + derived: { + t2: { + #Schema: { + in: (string|[ + ...string, + ]) + let _flat#1 = 〈import;list〉.FlattenN([ + 〈1;in〉, + ], 1) + out: 〈0;let _flat#1〉 + } + out: (〈0;#Schema〉 & { + in: "foo" + }) + } + } + } +} +--- ellipsis.cue +{ + nestedEllipsis: { + minimal: { + out: (〈0;#Schema〉 & { + extra: "foo" + }) + #Schema: { + 〈1;#meta〉 + ... + } + #meta: {} + } + } + nestedEllipsis: { + nestedWithPatterns: { + out: (〈0;#Schema〉 & { + objs: { + obj1: { + extra: "foo" + } + } + }) + #Schema: { + [_]: { + [_]: { + 〈2;#meta〉 + ... + } + } + #meta: { + name?: int + } + objs?: _ + } + } + } + issue4015: { + reduced: { + #X: { + ... + } + out: { + 〈1;#X〉 + a: { + b: string + } + } + out: { + a: { + c: "h" + b: "x" + } + } + } + } + issue4015: { + nested: { + #X: { + foo: { + ... + } + } + out: { + 〈1;#X〉 + foo: { + a: { + b: string + } + } + } + out: { + foo: { + a: { + c: "h" + b: "x" + } + } + } + } + } + issue4015: { + full: { + #Schema: { + cfg: { + foo: { + enabled: (bool|*false) + fooField: string + } + bar: { + barField: string + } + } + capacity: (int|*3) + } + #MoreCapacity: { + capacity: 30 + ... + } + out: 〈0;#Schema〉 + out: { + 〈1;#MoreCapacity〉 + cfg: { + foo: { + enabled: true + } + } + } + out: { + cfg: { + foo: { + fooField: "h" + } + bar: { + barField: "x" + } + } + } + } + } +} +--- embedelim.cue +{ + issue3921: { + top: { + #A: 〈0;#B〉 + #A: { + b: string + } + #B: _ + a: { + (〈1;#A〉 & {}) + } + } + } + issue3921: { + hidden: { + #A: 〈0;#B〉 + #A: { + _hidden: { + b: string + } + } + #B: {} + a: { + (〈1;#A〉 & { + _hidden: {} + }) + } + } + } + issue3921: { + full: { + out: (〈0;#templateList〉 & 〈0;#defineMap〉) + #templateList: { + #stepMap: { + [string]: _ + } + stepList: [ + for _, c in 〈1;#stepMap〉 { + 〈1;c〉 + }, + ] + } + #defineMap: { + #stepMap: { + foo: (〈2;#Step〉 & { + image: "bar" + #config: {} + }) + } + stepList: _ + } + #Step: (〈0;#StepInner〉 & { + image: string + #config: { + version: string + } + }) + #StepInner: { + image: string + } + } + } +} +--- in.cue +{ + embed: { + simple: { + #A: { + b: 1 + } + a: { + 〈1;#A〉 + } + a: { + err: 1 + } + } + } + embed: { + andInStruct: { + #Foo: { + a: int + } + a: { + (〈1;#Foo〉 & { + err: 2 + }) + } + } + } + embed: { + embedDefWithEmbedding: { + #Foo: { + { + a: int + } + } + a: { + (〈1;#Foo〉 & { + err: 2 + }) + } + } + } + embed: { + embedComprehension: { + #Foo: { + if true { + a: int + } + } + a: { + (〈1;#Foo〉 & { + err: 2 + }) + } + } + } + embed: { + fieldWithAnd: { + #A: {} + { + a: (〈1;#A〉 & { + err: 3 + }) + } + } + } + embed: { + embedAndRecursive: { + #A: { + a: int + } + B: { + x: 〈1;#A〉 + } + (〈0;B〉 & { + x: { + err: 2 + } + }) + } + } + embed: { + andEmbed: { + #A: { + b: int + } + #B: { + b: int + } + #D: { + (〈1;#A〉 & 〈1;#B〉) + } + d: (〈0;#D〉 & { + err: 3 + }) + } + } + and: { + transitive: { + ok: { + Z: { + a: string + } + #Y: 〈0;Z〉 + #X: (〈0;#Y〉 & 〈0;Z〉) + out: (〈0;#X〉 & { + a: "foo" + }) + } + } + } + and: { + transitive: { + err: { + Z: { + a: string + } + #Y: 〈0;Z〉 + #X: (〈0;#Y〉 & 〈0;Z〉) + out: (〈0;#X〉 & { + err: "foo" + }) + } + } + } + and: { + transitiveWithEmbed: { + ok: { + Z: { + a: string + } + #X: (〈0;#Y〉 & 〈0;Z〉) + #Y: { + 〈1;Z〉 + } + out: (〈0;#X〉 & { + a: "foo" + }) + } + } + } + and: { + transitiveWithEmbed: { + err: { + Z: { + a: string + } + #X: (〈0;#Y〉 & 〈0;Z〉) + #Y: { + 〈1;Z〉 + } + out: (〈0;#X〉 & { + err: "foo" + }) + } + } + } + embed: { + nonDef: { + t1: { + X: { + a: string + } + #Y: (〈0;#Z〉 & 〈0;X〉) + #Z: { + 〈1;X〉 + b?: string + } + } + } + } + embed: { + defAndHidden: { + full: { + _stepCommon: { + Name: string + } + #Step: (〈0;#Command〉 & 〈0;_stepCommon〉) + #Command: { + 〈1;_stepCommon〉 + Path?: string + } + out: (〈0;#Step〉 & { + Name: "foo" + }) + } + } + } + embed: { + withIndirect: { + A: 〈0;#B〉 + #B: { + b: int + } + (〈0;A〉 & { + err: 2 + }) + } + } +} +--- inline.cue +{ + embedInline: { + #Schema: { + a: "hello" + b: { + { + x: { + c: "foo" + } + }.x + } + b: { + c: string + d: "never printed" + } + } + out: (〈0;#Schema〉 & _|_(no sharing)) + } + issue3853: { + #Schema: { + a: "hello" + b: { + { + x: { + c: "foo" + } + }.x + } + b: { + c: string + d: "never printed" + } + } + out: { + x: (〈1;#Schema〉 & {}).a + }.x + } +} +--- issue3832.cue +{ + issue3832: { + _person: { + self: { + firstName: "Sam" + } + } + #T: { + _subject: { + in: _ + out: { + let self#2 = 〈1;in〉.self + outFirstName: 〈0;let self#2〉.firstName + } + } + _assert: { + pass: _ + } + _assert: ({ + check!: _ + pass: "never" + }|{ + invoke!: _ + pass: (〈1;_subject〉 & { + in: 〈1;invoke〉 + }).out + }) + results: 〈0;_assert〉.pass + } + (〈0;#T〉 & { + _assert: { + invoke: 〈2;_person〉 + } + }) + } +} +--- issue3833.cue +{ + issue3833: { + ok: { + out: { + (〈1;#A〉 & { + a: 〈2;#B〉 + }) + } + #A: { + a: { + b: string + ... + } + ... + } + #C: { + c: string + } + #B: { + (〈1;#C〉 & { + c: "foo" + }) + b: "foo" + } + } + } + issue3833: { + evalv2Issue: { + out: { + (〈1;#A〉 & { + a: 〈2;#B〉 + }) + } + #A: { + a: { + b: string + } + ... + } + #C: { + c: string + } + #B: { + (〈1;#C〉 & { + c: "foo" + }) + b: "foo" + } + } + } +} +--- issue3837.cue +{ + issue3837: { + reduced: { + A: { + 〈1;#Embed〉 + extra: "foo" + } + out: { + { + x: (〈2;A〉 & _|_(no sharing)) + } + } + #Embed: {} + } + } + issue3837: { + full: { + #Embed: {} + #A: { + 〈1;#Embed〉 + extra: "foo" + } + #B: (〈0;#C〉|{}) + #C: { + bar: string + } + out: (〈0;#B〉 & { + bar: "baz" + { + #def: (〈2;#A〉 & _|_(no sharing)) + } + }) + } + } +} +--- issue3839.cue +{ + issue3839: { + reduced: { + x: { + (〈1;A〉 & _|_(no sharing)) + } + x: { + y: 1 + } + #B: {} + A: { + 〈1;#B〉 + ... + } + } + } + issue3839: { + full: { + _globals: { + glb: { + globalField: "" + } + } + #GlobalContext: { + globalField: string + } + #Context: { + glb: 〈1;#GlobalContext〉 + out: 〈0;glb〉 + } + out: { + ingress: { + (〈2;#Ingress〉 & { + #def: (〈3;#Context〉 & 〈3;_globals〉).out + }) + } + ingress?: { + foo: 1234 + bar: "http" + } + } + #Embed: { + #def: { + ... + } + } + #Ingress: { + 〈1;#Embed〉 + ... + } + } + } +} +--- issue3843.cue +{ + dedupPattern: { + t1: { + p1: { + A: { + #Z: { + [string]: _ + } + x: 〈0;#Z〉 + x: { + y: { + z: 1 + } + } + } + B: (〈0;A〉 & _|_(no sharing)) + out: (〈0;A〉.#Z & 〈0;B〉.x) + } + } + } + dedupPattern: { + t1: { + p2: { + A: { + #Z: { + [string]: _ + } + x: 〈0;#Z〉 + x: { + y: { + z: 1 + } + } + } + B: (〈0;A〉 & _|_(no sharing)) + out: (〈0;B〉.x & 〈0;A〉.#Z) + } + } + } +} +--- issue3858.cue +{ + orig: { + t1: { + #Image: { + embed: { + image: "foo:v1" + } + } + #JobConfig: { + image: 〈1;#Image〉 + job: (〈1;#Job〉 & { + 〈1;image〉.embed + }) + } + #Job: { + image: string + vcs: "git" + args: [ + ...string, + ] + env: { + [string]: string + } + } + #Output: { + _in: _ + out: (〈0;_in〉 & {}) + } + (〈0;#Output〉 & { + _in: (〈1;#JobConfig〉 & {}).job + }) + } + } + reduced: { + t1: { + Y: { + a: { + e: "foo" + } + b: (〈1;X〉 & { + 〈1;a〉 + }) + } + X: { + e: string + f: 1 + } + #Z: { + _in: _ + out: (〈0;_in〉 & _|_(no sharing)) + } + (〈0;#Z〉 & { + _in: 〈1;Y〉 + }) + } + } + orig: { + t2: { + #JobConfig: { + image: { + spec: { + image: "someimage" + } + } + job: (〈1;#Job〉 & { + 〈1;image〉.spec + }) + } + #Job: { + image: string + env: "FOO" + } + #Output: { + in: _ + out: (〈0;in〉 & {}).input + } + out: (〈0;#Output〉 & { + in: { + input: (〈2;#JobConfig〉 & {}).job + } + }) + } + } + reduced: { + t2: { + Y: { + a: { + e: "foo" + } + b: (〈1;X〉 & { + 〈1;a〉 + }) + } + X: { + e: string + f: 1 + } + #Z: { + _in: _ + out: 〈0;_in〉 + } + (〈0;#Z〉 & { + _in: 〈1;Y〉 + }) + } + } +} +--- issue3934.cue +{ + issue3934: { + out: (〈0;#Foo〉 & { + foo: { + if false { + extra: { + nested: 123 + } + } + } + }) + #Foo: { + foo?: (null|〈1;#Bar〉|*{ + bar: 3 + }) + } + #Bar: { + bar?: int + extra?: (null|{ + ... + }) + } + } +} +--- issue3964.cue +{ + issue3964: { + reduced: { + #Output: { + 〈1;#Embedded〉 + } + #Embedded: { + name: string + (〈1;#Unused〉|〈1;#Used〉) + } + #Unused: {} + #Used: {} + } + } + issue3964: { + full: { + out: (〈0;#Output〉 & { + name: "oauth2" + used: "bar" + }) + #Output: { + 〈1;#Embedded〉 + } + #Embedded: { + name: string + (〈1;#Unused〉|〈1;#Used〉) + } + #Unused: { + unused: string + } + #Used: { + used: string + } + } + } +} +--- large.cue +{ + full: { + #Resource: { + someMsg: string + obs: ({}|*{ + missing: true + }) + let pickMsg#3 = [ + if 〈1;obs〉.missing { + msg: "\(〈2;someMsg〉)" + }, + { + msg: "bar" + }, + ][0] + patches: [ + { + op: "add" + path: "/metadata" + value: 〈2;let pickMsg#3〉.msg + }, + ] + } + #Patches: { + [string]: _ + } + #JSONPatch: { + namespace?: string + patch: [ + ...〈2;#JSONOp〉, + ] + output: (〈1;#Patches〉 & { + 〈1;namespace〉: 〈1;patch〉 + }) + } + #JSONOp: ({ + op: "add" + path: string + value: _ + }|{ + op: "remove" + path: string + }) + #Main: { + namespace: string + output: 〈0;let jsonPatch#4〉.output + let jsonPatch#4 = (〈1;#JSONPatch〉 & { + let base#7 = (〈2;#Resource〉 & {}) + let withMsg#8 = (〈0;let base#7〉 & { + someMsg: "foo" + }) + namespace: 〈1;namespace〉 + patch: 〈0;let withMsg#8〉.patches + }) + } + out: (〈0;#Main〉 & { + namespace: "ns1" + }).output + } +} +--- validators.cue +{ + embed: { + normalValidator: { + #X: { + 〈import;struct〉.MaxFields(1) + a?: int + b?: int + } + x: 〈0;#X〉 + x: { + err: 1 + } + } + } + embed: { + openValidator: { + t1: { + #X: { + matchN(0, []) + a?: int + b?: int + } + x: 〈0;#X〉 + x: { + err: 1 + } + } + } + } + embed: { + openValidator: { + t2: { + Y: matchN(1, [ + 〈1;X〉, + ]) + X: { + b?: 〈1;Y〉 + } + a: 〈0;X〉 + a: { + b: 1 + } + } + } + } + disjunction: { + withErr: { + t1: { + params: {} + out: (〈0;#Schema1〉 & { + b1: { + b2: { + b3: 〈3;params〉.mayExistLater + } + } + }) + #Schema1: { + b1?: (null|〈1;#Schema2〉) + } + #Schema2: { + b2?: (null|{ + b3?: string + }) + } + } + } + } + embed: { + nestedValidator: { + #types: { + z?: 〈import;list〉.UniqueItems + } + x: { + y: { + z: [ + 1, + ] + } + } + x: { + 〈1;#def〉 + y?: 〈1;#types〉 + } + #def: {} + } + } +} diff --git a/internal/core/compile/testdata/sync/definitions/visibility.txtar b/internal/core/compile/testdata/sync/definitions/visibility.txtar new file mode 100644 index 000000000..d40cb6f44 --- /dev/null +++ b/internal/core/compile/testdata/sync/definitions/visibility.txtar @@ -0,0 +1,28 @@ +-- in.cue -- +#foo: { + name: string +} +foo: #foo & { + // These should all be allowed. + _name: "foo" + _#name: "bar" + + #name: "baz" +} @test(closed) @test(eq, { + _name: "foo" + _#name: "bar" + #name: "baz" + name: string +}) +-- out/compile -- +--- in.cue +{ + #foo: { + name: string + } + foo: (〈0;#foo〉 & { + _name: "foo" + _#name: "bar" + #name: "baz" + }) +} diff --git a/internal/core/compile/testdata/sync/disjunctions/019_ips.txtar b/internal/core/compile/testdata/sync/disjunctions/019_ips.txtar new file mode 100644 index 000000000..169e898b5 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/019_ips.txtar @@ -0,0 +1,67 @@ +#name: ips +#evalFull +-- in.cue -- +import "list" + +IP: list.Repeat([uint8], 4) + +Private: + *[ 192, 168, uint8, uint8] | + [ 10, uint8, uint8, uint8] | + [ 172, >=16 & <=32, uint8, uint8] + +Inst: Private & [ _, 10, ...] + +MyIP: Inst & [_, _, 10, 10] @test(eq, [10, 10, 10, 10]) +@test(eq, { + IP: [ + >=0 & <=255 & int, + >=0 & <=255 & int, + >=0 & <=255 & int, + >=0 & <=255 & int + ] + Private: *[192, 168, >=0 & <=255 & int, >=0 & <=255 & int] | + [10, >=0 & <=255 & int, >=0 & <=255 & int, >=0 & <=255 & int] | + [172, >=16 & <=32, >=0 & <=255 & int, >=0 & <=255 & int] + Inst: [ + 10, + 10, + >=0 & <=255 & int, + >=0 & <=255 & int + ] + MyIP: [10, 10, 10, 10] +}) +-- out/compile -- +--- in.cue +{ + IP: 〈import;list〉.Repeat([ + &(int, >=0, <=255), + ], 4) + Private: (*[ + 192, + 168, + &(int, >=0, <=255), + &(int, >=0, <=255), + ]|[ + 10, + &(int, >=0, <=255), + &(int, >=0, <=255), + &(int, >=0, <=255), + ]|[ + 172, + (>=16 & <=32), + &(int, >=0, <=255), + &(int, >=0, <=255), + ]) + Inst: (〈0;Private〉 & [ + _, + 10, + ..., + ]) + MyIP: (〈0;Inst〉 & [ + _, + _, + 10, + 10, + ]) +} diff --git a/internal/core/compile/testdata/sync/disjunctions/confluence.txtar b/internal/core/compile/testdata/sync/disjunctions/confluence.txtar new file mode 100644 index 000000000..0efe67814 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/confluence.txtar @@ -0,0 +1,53 @@ +-- in.cue -- +import ( + "net" + "strings" +) +// evalv3 regression: disjunctions with conditionals depending on the +// disjunction's own value were left unresolved. +// https://cuelang.org/issue/3993 +issue3993: reduced: { + x: net.IPv4 | =~"fail" + x: { if net.IPv4(x) {=~"^10\\." } } + x: "10.10.10.10" + @test(eq, {x: "10.10.10.10"}) +} + +issue3993: full: { + addr!: string & (net.IPv4 | net.IPv6) + if net.IPv4(addr) { + addr: strings.HasPrefix("10.") + } + if net.IPv6(addr) { + addr: strings.HasPrefix("2a02:") + } + addr: "10.10.10.10" + @test(eq, {addr: "10.10.10.10"}) +} +-- out/compile -- +--- in.cue +{ + issue3993: { + reduced: { + x: (〈import;net〉.IPv4|=~"fail") + x: { + if 〈import;net〉.IPv4(〈1;x〉) { + =~"^10\\." + } + } + x: "10.10.10.10" + } + } + issue3993: { + full: { + addr!: (string & (〈import;net〉.IPv4|〈import;net〉.IPv6)) + if 〈import;net〉.IPv4(〈0;addr〉) { + addr: 〈import;strings〉.HasPrefix("10.") + } + if 〈import;net〉.IPv6(〈0;addr〉) { + addr: 〈import;strings〉.HasPrefix("2a02:") + } + addr: "10.10.10.10" + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/crossembed.txtar b/internal/core/compile/testdata/sync/disjunctions/crossembed.txtar new file mode 100644 index 000000000..ed805e24a --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/crossembed.txtar @@ -0,0 +1,38 @@ +# Cross-package embedded disjunction of definitions should correctly +# eliminate branches when unified with a concrete field. +# From issue #4197. +-- cue.mod/module.cue -- +module: "foo.test/main" +language: version: "v0.14.0" +-- in.cue -- +package main + +import "foo.test/main/imported" + +out: imported +out: either: foo: "world" + +@test(eq, { + out: { + either: {foo: "world"} + #Foo: {foo: _} + #Bar: {bar: _} + } +}) +-- imported/imported.cue -- +package imported + +#Foo: foo: _ +#Bar: bar: _ + +{either: #Foo | #Bar} +-- out/compile -- +--- in.cue +{ + out: 〈import;"foo.test/main/imported"〉 + out: { + either: { + foo: "world" + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/defaults.txtar b/internal/core/compile/testdata/sync/disjunctions/defaults.txtar new file mode 100644 index 000000000..1d051d1e9 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/defaults.txtar @@ -0,0 +1,60 @@ +-- in.cue -- +passToSingleValue: p1: _ | *((_ | *"x") & "y") @test(eq, *"y" | _) +passToSingleValue: p2: _ | *((*"x" | _) & "y") @test(eq, *"y" | _) +passToSingleValue: p3: *((_ | *"x") & "y") | _ @test(eq, *"y" | _) +passToSingleValue: p4: *((*"x" | _) & "y") | _ @test(eq, *"y" | _) + +// eval: "incomplete value" regression with defaults involving multiple +// definitions; default values that depend on other fields should resolve. +// https://cuelang.org/issue/3779 +issue3779: { + out: #Foo & { + fieldFoo: "foo" + } + #Foo: #Bar & { + fieldFoo: string | *"foo-default" + } + #Bar: { + fieldFoo: _ + fieldBar: string | *fieldFoo + } + @test(eq, { + out: { + fieldFoo: "foo" + fieldBar: *"foo" | string + } + #Foo: { + fieldFoo: *"foo-default" | string + fieldBar: *"foo-default" | string + } + #Bar: {fieldFoo: _, fieldBar: *_ | string} + }) +} +-- out/compile -- +--- in.cue +{ + passToSingleValue: { + p1: (_|*((_|*"x") & "y")) + } + passToSingleValue: { + p2: (_|*((*"x"|_) & "y")) + } + passToSingleValue: { + p3: (*((_|*"x") & "y")|_) + } + passToSingleValue: { + p4: (*((*"x"|_) & "y")|_) + } + issue3779: { + out: (〈0;#Foo〉 & { + fieldFoo: "foo" + }) + #Foo: (〈0;#Bar〉 & { + fieldFoo: (string|*"foo-default") + }) + #Bar: { + fieldFoo: _ + fieldBar: (string|*〈0;fieldFoo〉) + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/defembed.txtar b/internal/core/compile/testdata/sync/disjunctions/defembed.txtar new file mode 100644 index 000000000..589f7355e --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/defembed.txtar @@ -0,0 +1,98 @@ +Interaction between defaults, embedding and disjunctions. + +// TODO: at the moment, using a default will select it. +-- in.cue -- +x: { + // All of these resolve to *2 | 3 + m1: (1 | (*2 | 3)) & (>=2 & <=3) + m2: (1 | (*2 | 3)) & (2 | 3) + m3: (*1 | *(*2 | 3)) & (2 | 3) + @test(eq, {m1: *2 | 3, m2: *2 | 3, m3: *2 | 3}) +} +y1: x & { + {m4: x.m1 + x.m2 + x.m3} +} @test(eq, { + m4: 6 + m1: *2 | 3 + m2: *2 | 3 + m3: *2 | 3 +}) +y2: { + x + {m4: y2.m1 + y2.m2 + y2.m3} + @test(eq, { + m4: 6 + m1: *2 | 3 + m2: *2 | 3 + m3: *2 | 3 + }) +} +Y=y3: { + x + {m4: Y.m1 + Y.m2 + Y.m3} +} +@test(eq, { + m4: 6 + m1: *2 | 3 + m2: *2 | 3 + m3: *2 | 3 +}, at=y3) + +y4: x & { + {m4: y4.m1 + y4.m2 + y4.m3} +} @test(eq, { + m4: 6 + m1: *2 | 3 + m2: *2 | 3 + m3: *2 | 3 +}) + +// Second disjunct in embedding is not possible because of previous declaration +// of `b`, so it should be resolved to {a: 1}. +z: { + b: (*"a" | "b") | "c" + {a: b} | {b: int} + @test(eq, { + b: *"a" | "b" | "c" + a: *"a" | "b" | "c" + }) +} +-- out/compile -- +--- in.cue +{ + x: { + m1: ((1|(*2|3)) & (>=2 & <=3)) + m2: ((1|(*2|3)) & (2|3)) + m3: ((*1|*(*2|3)) & (2|3)) + } + y1: (〈0;x〉 & { + { + m4: ((〈2;x〉.m1 + 〈2;x〉.m2) + 〈2;x〉.m3) + } + }) + y2: { + 〈1;x〉 + { + m4: ((〈2;y2〉.m1 + 〈2;y2〉.m2) + 〈2;y2〉.m3) + } + } + y3: { + 〈1;x〉 + { + m4: ((〈2;y3〉.m1 + 〈2;y3〉.m2) + 〈2;y3〉.m3) + } + } + y4: (〈0;x〉 & { + { + m4: ((〈2;y4〉.m1 + 〈2;y4〉.m2) + 〈2;y4〉.m3) + } + }) + z: { + b: ((*"a"|"b")|"c") + ({ + a: 〈1;b〉 + }|{ + b: int + }) + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/discriminator.txtar b/internal/core/compile/testdata/sync/disjunctions/discriminator.txtar new file mode 100644 index 000000000..f4b78bc19 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/discriminator.txtar @@ -0,0 +1,234 @@ +-- in.cue -- +// Important that the test cases below fail with more than just +// an incomplete error, as we want to track the quality of errors. + +// Disjunctions where multiple (or zero) disjuncts match by kind, +// so we cannot discriminate. +noKind: { + manyWithStructEmbed: { + #Def: {<10, _hidden: "field"} | >200 | string + + // The data is an int, but the struct embeds a matching scalar kind too. + out: #Def & 123 @test(err, + suberr=(code=eval, contains="conflicting values", args=[123, string]), + suberr=(code=eval, contains="invalid value", args=[123, <10]), + suberr=(code=eval, contains="invalid value", args=[123, >200]), + pos=[]) + } + manyStructsEmpty: { + #Def: {f1!: int} | {f2!: int} | string + + // The data is a struct, which matches multiple disjunct struct kinds. + out: #Def & {} @test(eq, {f1!: int} | {f2!: int}) + } + manyScalars: { + #Def: 1 | 2 | 3 + + // The data is an int, which matches all of the disjunct kinds. + out: #Def & 123 @test(err, + suberr=(code=eval, contains="conflicting values", args=[1, 123], pos=[-3:9, 0:8, 0:15]), + suberr=(code=eval, contains="conflicting values", args=[2, 123], pos=[-3:13, 0:8, 0:15]), + suberr=(code=eval, contains="conflicting values", args=[3, 123], pos=[-3:17, 0:8, 0:15])) + } + zeroScalars: { + #Def: int | string | null + + // The data is a bool, which matches none of the disjunct scalar kinds. + out: #Def & true @test(err, + suberr=(code=eval, contains="conflicting values", args=[true, int]), + suberr=(code=eval, contains="conflicting values", args=[true, null]), + suberr=(code=eval, contains="conflicting values", args=[true, string]), + pos=[]) + } +} + +// Disjunctions where just one disjunct matches by kind, +// so we can discriminate. +byKind: { + nullableStructRegular: { + #Def1: {f1: null | #Def2} + #Def2: {f2: null | #Def3} + #Def3: {f3: null | int} + + // The data is a struct, not a null. + out: #Def1 & {f1: f2: f3: "not an int"} @test(err, code=eval, + contains="6 errors in empty disjunction", + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:15, 0:8, 0:21]), + suberr=(code=eval, contains="4 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:22, -4:15, 0:8, 0:25]), + suberr=(code=eval, contains="2 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=["not an int", int], pos=[-5:22, -4:22, -3:22, 0:8, 0:29]), + suberr=(code=eval, contains="conflicting values", args=["not an int", null], pos=[-5:22, -4:22, -3:15, 0:8, 0:29]), + pos=[]) + } + + nullableStructRequired: { + #Def1: {f1!: null | #Def2} + #Def2: {f2!: null | #Def3} + #Def3: {f3!: null | int} + + // The data is a struct, not a null. + out: #Def1 & {f1: f2: f3: "not an int"} @test(err, code=eval, + contains="6 errors in empty disjunction", + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:16, 0:8, 0:21]), + suberr=(code=eval, contains="4 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:23, -4:16, 0:8, 0:25]), + suberr=(code=eval, contains="2 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=["not an int", int], pos=[-5:23, -4:23, -3:23, 0:8, 0:29]), + suberr=(code=eval, contains="conflicting values", args=["not an int", null], pos=[-5:23, -4:23, -3:16, 0:8, 0:29]), + pos=[]) + } + + nullableStructOptional: { + #Def1: {f1?: null | #Def2} + #Def2: {f2?: null | #Def3} + #Def3: {f3?: null | int} + + // The data is a struct, not a null. + out: #Def1 & {f1: f2: f3: "not an int"} @test(err, code=eval, + contains="6 errors in empty disjunction", + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:16, 0:8, 0:21]), + suberr=(code=eval, contains="4 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:23, -4:16, 0:8, 0:25]), + suberr=(code=eval, contains="2 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=["not an int", int], pos=[-5:23, -4:23, -3:23, 0:8, 0:29]), + suberr=(code=eval, contains="conflicting values", args=["not an int", null], pos=[-5:23, -4:23, -3:16, 0:8, 0:29]), + pos=[]) + } + + nullableList: { + #Def1: [...null | #Def2] + #Def2: [...null | #Def3] + #Def3: [...null | int] + + // The data is a list, not a null. + out: #Def1 & [[["not an int"]]] @test(err, code=eval, + contains="6 errors in empty disjunction", + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:14, 0:8, 0:17]), + suberr=(code=eval, contains="4 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=[null], pos=[-5:21, -4:14, 0:8, 0:18]), + suberr=(code=eval, contains="2 errors in empty disjunction"), + suberr=(code=eval, contains="conflicting values", args=["not an int", int], pos=[-5:21, -4:21, -3:21, 0:8, 0:19]), + suberr=(code=eval, contains="conflicting values", args=["not an int", null], pos=[-5:21, -4:21, -3:14, 0:8, 0:19]), + pos=[]) + } + + scalarConstraints: { + #Def: >10 | "" | null | false + + // The data is an integer, not any other scalar type. + out: #Def & 5 @test(err, + suberr=(code=eval, contains="conflicting values", args=[5, ""]), + suberr=(code=eval, contains="conflicting values", args=[5, false]), + suberr=(code=eval, contains="conflicting values", args=[5, null]), + suberr=(code=eval, contains="invalid value", args=[5, >10]), + pos=[]) + } +} +-- out/compile -- +--- in.cue +{ + noKind: { + manyWithStructEmbed: { + #Def: ({ + <10 + _hidden: "field" + }|>200|string) + out: (〈0;#Def〉 & 123) + } + manyStructsEmpty: { + #Def: ({ + f1!: int + }|{ + f2!: int + }|string) + out: (〈0;#Def〉 & {}) + } + manyScalars: { + #Def: (1|2|3) + out: (〈0;#Def〉 & 123) + } + zeroScalars: { + #Def: (int|string|null) + out: (〈0;#Def〉 & true) + } + } + byKind: { + nullableStructRegular: { + #Def1: { + f1: (null|〈1;#Def2〉) + } + #Def2: { + f2: (null|〈1;#Def3〉) + } + #Def3: { + f3: (null|int) + } + out: (〈0;#Def1〉 & { + f1: { + f2: { + f3: "not an int" + } + } + }) + } + nullableStructRequired: { + #Def1: { + f1!: (null|〈1;#Def2〉) + } + #Def2: { + f2!: (null|〈1;#Def3〉) + } + #Def3: { + f3!: (null|int) + } + out: (〈0;#Def1〉 & { + f1: { + f2: { + f3: "not an int" + } + } + }) + } + nullableStructOptional: { + #Def1: { + f1?: (null|〈1;#Def2〉) + } + #Def2: { + f2?: (null|〈1;#Def3〉) + } + #Def3: { + f3?: (null|int) + } + out: (〈0;#Def1〉 & { + f1: { + f2: { + f3: "not an int" + } + } + }) + } + nullableList: { + #Def1: [ + ...(null|〈1;#Def2〉), + ] + #Def2: [ + ...(null|〈1;#Def3〉), + ] + #Def3: [ + ...(null|int), + ] + out: (〈0;#Def1〉 & [ + [ + [ + "not an int", + ], + ], + ]) + } + scalarConstraints: { + #Def: (>10|""|null|false) + out: (〈0;#Def〉 & 5) + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/edge.txtar b/internal/core/compile/testdata/sync/disjunctions/edge.txtar new file mode 100644 index 000000000..e3d974a04 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/edge.txtar @@ -0,0 +1,319 @@ +# This file mostly contains edge cases of disjunction semantics. +# We should ensure that all these cases can be derived from thee spec. +# +# Many of these cases were discovered as part of the development of the new +# evaluator that started at v0.7 and do not pass for that version. +-- in.cue -- +cyclicalInsertInDisjunction: { + // We do not allow lookups across unresolved disjunctions. As such, the + // references across disjunctions are not allowed to disambiguate a + // disjunction. + // + // Algorithmically, the distinction between allowing this or not is + // achieved by allowing dereferencing of the node in which a disjunction + // occurs to the disjunct under evaluation. Effectively this is what the + // v0.6 evaluator does. + + ok1: { + // In this case, unifying the comprehension into the processing of the + // disjunctions would _not_ case the reference to cross disjunction + // boundaries. + c: {d: e, e: _} + c: {d: 1, e: 2} | {d : 2, e: 2} + @test(eq, {c: {d: 2, e: 2}}) + } + maybe1: { + // In this case, the reference c.e crosses a disjunction boundary. + // However, since the reference starts from within a disjunction, this + // could be allowed, if we define it to be. + c: d: c.e + c: {d: 1, e: 2} | {d : 2, e: 2} + @test(eq, {c: {d: 2, e: 2}}) + } + err1: { + // This should be an error: to resolve x in c.d, we need to first + // resolve x to a concrete value. As `x` is defined outside the + // disjunction, and the disjunction cannot be resolved without it, `x` + // cannot be evaluated to a concrete value, resulting in an error. + @test(permute, count=6) + x: c.e + c: d: x + c: {d: 1, e: 2} | {d : 2, e: 2} + @test(eq, {x: 2, c: {d: 2, e: 2}}) + } + err2: { + // This is a more obviously erroneous variant of err1. The div in x + // requires a concrete value for c.e. However, the disjunction can only + // be disambiguated as a result of computing x. This means c.e cannot + // be concrete at the time of evaluation. + // NOTE: not so obvious. It clearly works, and arguably it should. + @test(permute, count=6) + x: div(c.e, 2) + c: d: x + c: {d: 1, e: 2} | {d : 2, e: 3} + @test(eq, {x: 1, c: {d: 1, e: 2}}) + } + err3: { + // Here it is clear that d will not disambiguate the disjunction at c. + // So c.e. cannot be resolved. + @test(permute, count=6) + x: c.e @test(err, code=incomplete, contains="unresolved disjunction", pos=[0:6]) + c: d: 1 | 2 | x + c: {d: 1, e: 2} | {d : 2, e: 3} + @test(eq, { + x: _|_ @test(err, code=incomplete, contains="unresolved disjunction", pos=[54:6]) + c: {d: 1, e: 2} | {d: 2, e: 3} + }) + } + @test(eq, { + ok1: {c: {d: 2, e: 2}} + maybe1: {c: {d: 2, e: 2}} + err1: {x: 2, c: {d: 2, e: 2}} + err2: {x: 1, c: {d: 1, e: 2}} + err3: { + x: _|_ @test(err, code=incomplete, contains="unresolved disjunction {d:1,e:2} | {d:2,e:3} (type struct)", pos=[54:6]) + c: {d: 1, e: 2} | {d: 2, e: 3} + } + }) +} + +preseveBottomSemantics: ok: { + // `a: a`, which just says that `a` is `a`, is logically equivalent to + // `a: _`. Consequently, the disjunction `a: a | X` is equivalent to + // `a: _ | X`. As we do not simplify disjunctions, the result is `a: _ | X`. + // However, we could consider simplifying in this case to `a: _` if we can + // come up with a good general mechanism for subsumption. + #x: { #x | {} } + @test(eq, {#x: {}}) +} + +eliminateOpenVariant: ok: { + // We have two structs in the disjunction that are identical in every way + // except openness. TODO: should we disambiguate those? + c: {a: 1} | #b + #b: {a: 1} + @test(eq, {c: {a: 1} | {a: 1}, #b: {a: 1}}) +} + +cyclicSelfElimination: ok: { + // This should resolve to {y: 1} (works for new evaluator) + y: 1 | {y: 1} + y + @test(eq, {y: 1}) +} + +// Value aliases must resolve to the specific disjunct arm's value, +// not the original unresolved disjunction. +issue4251_notC: { + #NotC: x={ + string + _must: true & x != "c" @test(err, code=incomplete, contains="non-concrete value string in operand to !=", pos=[0:17, -2:11, -1:3]) + } + @test(err, at=#NotC._must, =incomplete, contains="non-concrete value string in operand to !=", pos=[3:17, 1:11, 2:3]) + + a: #NotC + a: "a" | "b" + a: "a" @test(eq, {"a", _must: true}) +} +issue4251_notB: { + #NotB: x={ + string + _must: true & x != "b" @test(err, code=incomplete, contains="non-concrete value string in operand to !=", pos=[0:17, -2:11, -1:3]) + } + @test(err, at=#NotB._must, code=incomplete, contains="non-concrete value string in operand to !=", pos=[3:17, 1:11, 2:3]) + a: #NotB + a: "a" | "b" + a: "a" @test(eq, {"a", _must: true}) +} +issue4251_notB_reversed: { + #NotB: x={ + string + _must: true & x != "b" @test(err, code=incomplete, contains="non-concrete value string in operand to !=", pos=[0:17, -2:11, -1:3]) + } + @test(err, at=#NotB._must, code=incomplete, contains="non-concrete value string in operand to !=", pos=[3:17, 1:11, 2:3]) + a: #NotB + a: "b" | "a" + a: "a" @test(eq, {"a", _must: true}) +} +-- panic.cue -- +// This used to cause a panic with evalv3. +panic1: { + #TypeFoo: { + name: "foo" + // Make foo_field here optional and master panics too! + foo_field: string + } + #TypeBar: { + #TypeBar2 + bar_field?: string + } + + #TypeBar2: name: "bar" + + objs: obj1: { + type: #TypeFoo | #TypeBar + type: *objs["missing"] | #TypeFoo | #TypeBar + } @test(eq, { + type: {name: "foo", foo_field: string} | {bar_field?: string, name: "bar"} + }) + + out: #TypeFoo | #TypeBar + out: objs["obj1"].type + @test(eq, { + #TypeFoo: {name: "foo", foo_field: string} + #TypeBar: {bar_field?: string, name: "bar"} + #TypeBar2: {name: "bar"} + objs: { + obj1: { + type: {name: "foo", foo_field: string} | {bar_field?: string, name: "bar"} + } + } + out: {name: "foo", foo_field: string} | {bar_field?: string, name: "bar"} + }) +} +-- out/compile -- +--- in.cue +{ + cyclicalInsertInDisjunction: { + ok1: { + c: { + d: 〈0;e〉 + e: _ + } + c: ({ + d: 1 + e: 2 + }|{ + d: 2 + e: 2 + }) + } + maybe1: { + c: { + d: 〈1;c〉.e + } + c: ({ + d: 1 + e: 2 + }|{ + d: 2 + e: 2 + }) + } + err1: { + x: 〈0;c〉.e + c: { + d: 〈1;x〉 + } + c: ({ + d: 1 + e: 2 + }|{ + d: 2 + e: 2 + }) + } + err2: { + x: div(〈0;c〉.e, 2) + c: { + d: 〈1;x〉 + } + c: ({ + d: 1 + e: 2 + }|{ + d: 2 + e: 3 + }) + } + err3: { + x: 〈0;c〉.e + c: { + d: (1|2|〈1;x〉) + } + c: ({ + d: 1 + e: 2 + }|{ + d: 2 + e: 3 + }) + } + } + preseveBottomSemantics: { + ok: { + #x: { + (〈1;#x〉|{}) + } + } + } + eliminateOpenVariant: { + ok: { + c: ({ + a: 1 + }|〈0;#b〉) + #b: { + a: 1 + } + } + } + cyclicSelfElimination: { + ok: { + y: (1|{ + y: 1 + }) + 〈0;y〉 + } + } + issue4251_notC: { + #NotC: { + string + _must: (true & (〈1〉 != "c")) + } + a: 〈0;#NotC〉 + a: ("a"|"b") + a: "a" + } + issue4251_notB: { + #NotB: { + string + _must: (true & (〈1〉 != "b")) + } + a: 〈0;#NotB〉 + a: ("a"|"b") + a: "a" + } + issue4251_notB_reversed: { + #NotB: { + string + _must: (true & (〈1〉 != "b")) + } + a: 〈0;#NotB〉 + a: ("b"|"a") + a: "a" + } +} +--- panic.cue +{ + panic1: { + #TypeFoo: { + name: "foo" + foo_field: string + } + #TypeBar: { + 〈1;#TypeBar2〉 + bar_field?: string + } + #TypeBar2: { + name: "bar" + } + objs: { + obj1: { + type: (〈2;#TypeFoo〉|〈2;#TypeBar〉) + type: (*〈2;objs〉["missing"]|〈2;#TypeFoo〉|〈2;#TypeBar〉) + } + } + out: (〈0;#TypeFoo〉|〈0;#TypeBar〉) + out: 〈0;objs〉["obj1"].type + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/elimination.txtar b/internal/core/compile/testdata/sync/disjunctions/elimination.txtar new file mode 100644 index 000000000..51fe5cf20 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/elimination.txtar @@ -0,0 +1,2480 @@ +// Ensure that disjunction elimination is not done prematurely. + +// Issue #651 +-- in.cue -- +import "struct" + +// Closedness checks should not be triggered too early, or with an improper +// subset of StructInfos. Blindly finalizing partial disjuncts will end up +// doing a closedness check with not all embeddings present, which can lead to +// a field being rejected prematurely. +// +// It should be recursively disabled. +disambiguateClosed: { + b: #Def & a + a: #Def + #Def: {{x: true} | {y: true}} + @test(eq, { + b: {x: true} | {y: true} + a: {x: true} | {y: true} + #Def: {x: true} | {y: true} + }) +} + +// Checks should never be disabled for field matching. +alwaysCheckMatchers1: { + b: {[=~"^xxxx$"]: int} | null + b: {c: string} | null + b: c: "yyyyy" + @test(eq, {b: {c: "yyyyy"}}) +} + +alwaysCheckPatterns2: { + a: #X + a: b + + b: #X + b: c: "yyyyy" + + #X: string | { + c: string + {[=~"^xxxx$"]: int} + } + @test(eq, { + a: {c: "yyyyy"} + b: {c: "yyyyy"} + #X: string | {c: string} + }) +} + +nestedNonMonotonic: resolved: n1: { + x: {a: struct.MinFields(2)} | null + x: {a: c: 1} | null + x: {a: d: 1} | null + @test(eq, {x: {a: {c: 1, d: 1}} | null}) +} + +nestedNonMonotonic: resolved: n2: { + x: {a: b: struct.MinFields(2)} | null + x: {a: b: c: 1} | null + x: {a: b: d: 1} | null + @test(eq, {x: {a: {b: {c: 1, d: 1}}} | null}) +} + +nestedNonMonotonic: eliminated: n1: p1: { + x: {a: struct.MaxFields(1)} | null + x: {a: c: 1} | null + x: {a: d: 1} | null + @test(eq, {x: null}) +} + +nestedNonMonotonic: eliminated: n1: p2: { + x: {a: c: 1} | null + x: {a: struct.MaxFields(1)} | null + x: {a: d: 1} | null + @test(eq, {x: null}) +} + +nestedNonMonotonic: eliminated: n1: p2: { + x: {a: c: 1} | null + x: {a: d: 1} | null + x: {a: struct.MaxFields(1)} | null + // TODO: Should be p3, fix. +} + +nestedNonMonotonic: eliminated: n2: p1: { + x: {a: b: struct.MaxFields(1)} | null + x: {a: b: c: 1} | null + x: {a: b: d: 1} | null + @test(eq, {x: null}) +} + +nestedNonMonotonic: eliminated: n2: p2: { + x: {a: b: c: 1} | null + x: {a: b: struct.MaxFields(1)} | null + x: {a: b: d: 1} | null + @test(eq, {x: null}) +} + +nestedNonMonotonic: eliminated: n2: p2: { + x: {a: b: c: 1} | null + x: {a: b: d: 1} | null + x: {a: b: struct.MaxFields(1)} | null + // TODO: should be p3 +} + +// TODO: should be incomplete. +nestedNonMonotonic: incomplete: a: n1: p1: { + x: {a: struct.MinFields(2)} | null + x: {a: c: 1} | null + @test(eq, {x: null}) + @test(eq:todo, {x: {a: {c: 1} & struct.MinFields(2)} | null}) +} + +// TODO: should be incomplete. +nestedNonMonotonic: incomplete: a: n1: p2: { + x: {a: c: 1} | null + x: {a: struct.MinFields(2)} | null + @test(eq, {x: null}) + @test(eq:todo, {x: {a: {c: 1} & struct.MinFields(2)} | null}) +} + +nestedNonMonotonic: incomplete: a: n2: p1: { + x: {a: b: struct.MinFields(2)} | null + x: {a: b: c: 1} | null + @test(eq, {x: {a: {b: {c: 1}}} | null}) +} + +nestedNonMonotonic: incomplete: a: n2: p2: { + x: {a: b: c: 1} | null + x: {a: b: struct.MinFields(2)} | null + @test(eq, {x: {a: {b: {c: 1}}} | null}) +} + +nestedNonMonotonic: incomplete: b: n1: p1: { + x: {a: struct.MinFields(3)} | null + x: {a: c: 1} | null + x: {a: d: 1} | null + @test(eq, {x: null}) +} + +nestedNonMonotonic: incomplete: b: n1: p2: { + x: {a: c: 1} | null + x: {a: struct.MinFields(3)} | null + x: {a: d: 1} | null + @test(eq, {x: null}) +} + +nestedNonMonotonic: incomplete: b: n1: p3: { + x: {a: c: 1} | null + x: {a: d: 1} | null + x: {a: struct.MinFields(3)} | null + @test(eq, {x: null}) +} + +nestedNonMonotonic: incomplete: b: n2: p1: { + x: {a: b: struct.MinFields(3)} | null + x: {a: b: c: 1} | null + x: {a: b: d: 1} | null + @test(eq, {x: {a: {b: {c: 1, d: 1}}} | null}) +} + +nestedNonMonotonic: incomplete: b: n2: p1: { + x: {a: b: c: 1} | null + x: {a: b: struct.MinFields(3)} | null + x: {a: b: d: 1} | null + @test(eq) // TODO: rename to p2 +} + +nestedNonMonotonic: incomplete: b: n2: p1: { + x: {a: b: c: 1} | null + x: {a: b: d: 1} | null + x: {a: b: struct.MinFields(3)} | null + @test(eq, {x: {a: {b: {c: 1, d: 1}}} | null}) // TODO: rename to p3 +} + +preserveClosedness: small: p1: { + #A: #B & {a: string} + #B: { + *{} | {a: string} + *{} | {b: int} + } + @test(eq, { + #A: *{a: string} | {a: string, b: int} + #B: *{} | {b: int} | {a: string} | {a: string, b: int} + }) +} + +preserveClosedness: small: p2: { + #A: #B & {a: string} + #B: { + {a: string} | *{} + *{} | {b: int} + } + @test(eq, { + #A: *{a: string} | {a: string, b: int} + #B: *{} | {a: string, b: int} | {a: string} | {b: int} + }) +} + +preserveClosedness: medium: p1: { + #A: #B & {a: string} + #B: { + *{} | {a: string} | {b: string} + *{} | {c: int} | {d: string} + } + @test(eq, { + #A: *{a: string} | {a: string, c: int} | {a: string, d: string} + #B: *{} | {c: int} | {d: string} | {a: string} | {a: string, c: int} | {a: string, d: string} | {b: string} | {b: string, c: int} | {b: string, d: string} + }) +} + +preserveClosedness: medium: p2: { + #A: #B & {a: string} + #B: { + {a: string} | *{} | {b: string} + *{} | {c: int} | {d: string} + } + @test(eq, { + #A: *{a: string} | {a: string, c: int} | {a: string, d: string} + #B: *{} | {a: string, c: int} | {a: string, d: string} | {a: string} | {c: int} | {d: string} | {b: string} | {b: string, c: int} | {b: string, d: string} + }) +} + +preserveClosedness: medium: p3: { + #A: #B & {a: string} + #B: { + {a: string} | {b: string} | *{} + *{} | {c: int} | {d: string} + } + @test(eq, { + #A: *{a: string} | {a: string, c: int} | {a: string, d: string} + #B: *{} | {a: string, c: int} | {a: string, d: string} | {b: string} | {b: string, c: int} | {b: string, d: string} | {a: string} | {c: int} | {d: string} + }) +} + +// If an error occurred in the last disjunction, it may sometimes be propagated +// to parent nodes. This, in turn, could lead to references to such field +// to fail with that error. +noChildError: _ +noChildError: issue1608: { + myValue: #type & {fieldName: "some string"} + #type: fieldName: #subtype + + #subtype: string | {foo: string} | {bar: #subtype} + @test(eq, { + myValue: {fieldName: "some string"} + #type: {fieldName: string | {foo: string}} + #subtype: string | {foo: string} + }) +} + +noChildError: t1: { + #D: {b: string} | {c: #D } + o: #D & {b: "test"} + @test(eq, {#D: {b: string}, o: {b: "test"}}) +} + +noChildError: t2: { + o: #D & {b: "test"} + #D: {b: string} | {c: #D } + @test(eq, {o: {b: "test"}, #D: {b: string}}) +} + +noChildError: t3: { + #D: {a: null} | {b: string} | {c: #D } + o: #D & {b: "test"} + @test(eq, { + #D: {a: null} | {b: string} + o: {b: "test"} + }) +} + +noChildError: t4: { + o: #D & {b: "test"} + #D: {a: null} | {b: string} | {c: #D } + @test(eq, { + o: {b: "test"} + #D: {a: null} | {b: string} + }) +} + + +issue1924: t1: { + m: a: 2 + x: *[m.b] | 2 + @test(eq, {m: {a: 2}, x: 2}) +} +issue1924: t2: { + m: a: 2 + x: *{v: m.b} | 3 + @test(eq, {m: {a: 2}, x: 3}) +} +issue1924: t3: { + m: a: 2 + x: *m.b | 1 + @test(eq, {m: {a: 2}, x: 1}) +} + +// should eliminate erroneous comprehension and pass +issue1838: t1: { + p?: [] + a: [for k in p {k}] | null + @test(eq, {p?: [], a: null}) +} +issue1838: t2: { + p?: [] + a: null | [for k in p {k}] + @test(eq, {p?: [], a: null}) +} + +noHang: { + // This should terminate. + #T: ["a", #T] | ["d", ...#T] + + x: #T + + #X: x + #X: #T + @test(eq, {#T: ["d"], x: ["d"], #X: ["d"]}) +} + +issue1940: { + #T: ["a", #T] | ["b", #T] | ["c", #T] | ["d", [...#T]] + + #A: type: #T + + #B: [string]: #A + + #C: #B & { + x: #A + } + @test(eq, { + #T: ["d", []] + #A: {type: ["d", []]} + #B: {} + #C: {x: {type: ["d", []]}} + }) +} + +-- issue2209full.cue -- +// Evaluator 0.5 regression where disjunctions combined with comprehensions +// produced incorrect results or spurious errors. +// https://cuelang.org/issue/2209 +// TODO: fix + +issue2209: simplified: t1: { + #SpecFoo: foo: min: 1 + #SpecBar: bar: min: 1 + spec: bar: {} + spec: #SpecFoo | #SpecBar + out: { + {nullFoo: null} | {nullBar: null} + {minFoo: int} | {minBar: int} + if X.bar != _|_ { + minBar: X.bar.min + } + X: spec + } + @test(eq, { + #SpecFoo: {foo: {min: 1}} + #SpecBar: {bar: {min: 1}} + spec: {bar: {min: 1}} + out: { + minBar: 1 + X: {bar: {min: 1}} + nullFoo: null + minFoo: int + } | { + minBar: 1 + X: {bar: {min: 1}} + nullFoo: null + } | { + minBar: 1 + X: {bar: {min: 1}} + nullBar: null, + minFoo: int + } | { + minBar: 1 + X: {bar: {min: 1}} + nullBar: null + } + }) +} + +issue2209: simplified: t2: { + #SpecFoo: foo: {} + #SpecBar: bar: x: 1 + spec: bar: {} + spec: *#SpecFoo | #SpecBar + if spec.bar != _|_ { + BAZ: spec.bar.x + } + {f1: int} | {b2: int} + {f2: int} | {b2: int} + @test(eq, { + #SpecFoo: {foo: {}} + #SpecBar: {bar: {x: 1}} + spec: {bar: {x: 1}} + BAZ: 1 + f1: int + f2: int + } | { + #SpecFoo: {foo: {}} + #SpecBar: {bar: {x: 1}} + spec: {bar: {x: 1}} + BAZ: 1 + f1: int + b2: int + } | { + #SpecFoo: {foo: {}} + #SpecBar: {bar: {x: 1}} + spec: {bar: {x: 1}} + BAZ: 1 + b2: int + f2: int + } | { + #SpecFoo: {foo: {}} + #SpecBar: {bar: {x: 1}} + spec: {bar: {x: 1}} + BAZ: 1 + b2: int + }) +} + +// This test fails for 0.4 and 0.5. +issue2209: simplified: t3: { + #A: v: 1 + {f1: int} | {b2: int} + {f2: int} | {b2: int} + BAZ: S.y + S: *#A | #B + #B: {x: 1, y: 1} + S: x: 1 + @test(eq, { + #A: {v: 1} + BAZ: 1 + S: {x: 1, y: 1} + #B: {x: 1, y: 1} + f1: int + f2: int + } | { + #A: {v: 1} + BAZ: 1 + S: {x: 1, y: 1} + #B: {x: 1, y: 1} + f1: int + b2: int + } | { + #A: {v: 1} + BAZ: 1 + S: {x: 1, y: 1} + #B: {x: 1, y: 1} + b2: int + f2: int + } | { + #A: {v: 1} + BAZ: 1 + S: {x: 1, y: 1} + #B: {x: 1, y: 1} + b2: int + }) +} + +issue2209: full: { + Foo: #Abstract & {spec: foo: {}} + @test(shareID=FooSpec, at=Foo.spec) + @test(shareID=FooSpec, at=Foo.resource._X.spec) + @test(eq, at=Foo, { + spec: {foo: {min: *10 | int, max: *20 | int}} + resource: { + _X: spec: {foo: {min: *10 | int, max: *20 | int}} + spec: *{ + minFoo: *10 | int + maxFoo: *20 | int + minBar?: null + maxBar?: null + hoge?: null | bool + fuga?: null + } | { + minFoo: *10 | int + maxFoo: *20 | int + minBar?: null + maxBar?: null + hoge?: null + fuga?: null | bool + } + } + }) + + Bar: #Abstract & {spec: bar: {}} + @test(shareID=BarSpec, at=Bar.spec) + @test(shareID=BarSpec, at=Bar.resource._X.spec) + + #Abstract: X={ + spec: _#Spec + + resource: _Thing & {_X: spec: X.spec} + } + + _#Spec: *_#SpecFoo | _#SpecBar + + _#SpecFoo: { + foo: { + min: int | *10 + max: int | *20 + } + } + + _#SpecBar: { + bar: { + min: int | *30 + max: int | *40 + } + } + + _Thing: #Constrained & { + _X: _ + + spec: { + if _X.spec.foo != _|_ { + minFoo: _X.spec.foo.min + maxFoo: _X.spec.foo.max + } + + if _X.spec.bar != _|_ { + minBar: _X.spec.bar.min + maxBar: _X.spec.bar.max + } + } + } + + #Constrained: #Base & { + spec: { + minFoo: int | *10 + maxFoo: int | *20 + minBar?: null + maxBar?: null + } | { + minBar: int | *30 + maxBar: int | *40 + minFoo?: null + maxFoo?: null + } + + spec: *{ + fuga?: null + } | { + hoge?: null + } + } + + #Base: { + spec: { + minFoo?: null | int + maxFoo?: null | int + minBar?: null | int + maxBar?: null | int + + hoge?: null | bool + fuga?: null | bool + } + } + + @test(eq, at=Bar, { + spec: {bar: {min: *30 | int, max: *40 | int}} + resource: { + _X: spec: {bar: {min: *30 | int, max: *40 | int}} + spec: *{ + minFoo?: null + maxFoo?: null + minBar: *30 | int + maxBar: *40 | int + hoge?: null | bool + fuga?: null + } | { + minFoo?: null + maxFoo?: null + minBar: *30 | int + maxBar: *40 | int + hoge?: null + fuga?: null | bool + } + } + }) + // #Abstract: { + // spec: *{ + // foo: {min: *10 | int, max: *20 | int} + // } | { + // bar: {min: *30 | int, max: *40 | int} + // } + // resource: { + // _X: { + // spec: *{ + // foo: {min: *10 | int, max: *20 | int} + // } | { + // bar: {min: *30 | int, max: *40 | int} + // } + // } + // spec: *{ + // minFoo: *10 | int + // maxFoo: *20 | int + // minBar?: null + // maxBar?: null + // hoge?: null | bool + // fuga?: null + // } | { + // minFoo: *10 | int + // maxFoo: *20 | int + // minBar?: null + // maxBar?: null + // hoge?: null + // fuga?: null | bool + // } + // } + // } + // _#Spec: *{ + // foo: {min: *10 | int, max: *20 | int} + // } | { + // bar: {min: *30 | int, max: *40 | int} + // } + // _#SpecFoo: {foo: {min: *10 | int, max: *20 | int}} + // _#SpecBar: {bar: {min: *30 | int, max: *40 | int}} + // _Thing: { + // _X: _ + // spec: *{ + // minFoo: *10 | int + // maxFoo: *20 | int + // minBar?: null + // maxBar?: null + // hoge?: null | bool + // fuga?: null + // } | *{ + // minFoo?: null + // maxFoo?: null + // minBar: *30 | int + // maxBar: *40 | int + // hoge?: null | bool + // fuga?: null + // } | { + // minFoo: *10 | int + // maxFoo: *20 | int + // minBar?: null + // maxBar?: null + // hoge?: null + // fuga?: null | bool + // } | { + // minFoo?: null + // maxFoo?: null + // minBar: *30 | int + // maxBar: *40 | int + // hoge?: null + // fuga?: null | bool} + // } + // #Constrained: { + // spec: *{minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null | bool, fuga?: null} | *{minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null | bool, fuga?: null + // } | { + // minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null, fuga?: null | bool + // } | { + // minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null, fuga?: null | bool} + // } + // #Base: { + // spec: { + // minFoo?: null | int + // maxFoo?: null | int + // minBar?: null | int + // maxBar?: null | int + // hoge?: null | bool + // fuga?: null | bool + // } + // } + // }) +} + + +-- issue2246.cue -- +// Evaluator regression where repeated use of an embedded disjunction resulted +// in spurious "field not allowed" errors. +// https://cuelang.org/issue/2246 +issue2246: simplified: { + #FormFoo: fooID: string + #FormBar: barID: string + #Form: { #FormFoo | #FormBar } + + data: {fooID: "123"} + out1: #Form & data + out2: #Form & out1 + @test(eq, { + #FormFoo: {fooID: string} + #FormBar: {barID: string} + #Form: {fooID: string} | {barID: string} + data: {fooID: "123"} + out1: {fooID: "123"} + out2: {fooID: "123"} + }) +} +issue2246: full: { + data: forms: [{ + fooID: "00-0000001" + }] + + form1040: (#compute & {in: data}).out + + #K1: { + #_base: common: 3 + #FormFoo: { + #_base + fooID: string + } + #FormBar: { + #_base + barID: string + } + #Form: { + #FormFoo | #FormBar + } + } + + #Input: { + forms: [...#K1.#Form] + } + + #summarizeReturn: { + in: #Input + out: [for k in in.forms { k.common }] + } + + #compute: { + in: #Input + out: (#summarizeReturn & {"in": in}).out + } + @test(eq, { + data: {forms: [{ + fooID: "00-0000001" + }]} + form1040: [3] + #K1: { + #_base: {common: 3} + #FormFoo: {fooID: string, common: 3} + #FormBar: {barID: string, common: 3} + #Form: {fooID: string, common: 3} | {barID: string, common: 3} + } + #Input: {forms: []} + #summarizeReturn: {in: {forms: []}, out: []} + #compute: {in: {forms: []}, out: []} + }) +} + +-- issue2263.cue -- +// Disjunction regression in v0.5.0-beta.5 where multiple embedded disjunctions +// in a definition were not evaluated correctly. +// https://cuelang.org/issue/2263 +issue2263: simplified: { + metrics: #Metric + #Metric: { + #IDSource | {} + #TargetAverage | {} + } + + metrics: { + id: "foo" + avg: 60 + } + + #IDSource: id: string + #TargetAverage: avg: number + @test(eq, { + metrics: {id: "foo", avg: 60} + #Metric: {id: string, avg: number} | {id: string} | {avg: number} | {} + #IDSource: {id: string} + #TargetAverage: {avg: number} + }) +} +issue2263: full: { + metrics: [...#Metric] + + metrics: [{ + id: "foo" + avg: 60 + }, { + id: "bar" + value: 80 + }, { + uri: "baz" + avg: 70 + }, { + uri: "qux" + value: 90 + }] + + #Metric: { + #Source + #Target + } + + #Source: + #IDSource | + #URISource + + #Target: + #TargetAverage | + #TargetValue + + #IDSource: { + id: string + } + + #URISource: { + uri: string + } + + #TargetAverage: { + avg: number + } + + #TargetValue: { + value: number + } + @test(eq, { + metrics: [{ + avg: 60 + id: "foo" + }, { + id: "bar" + value: 80 + }, { + avg: 70 + uri: "baz" + }, { + uri: "qux" + value: 90 + }] + #Metric: {id: string, avg: number} | {id: string, value: number} | {uri: string, avg: number} | {uri: string, value: number} + #Source: {id: string} | {uri: string} + #Target: {avg: number} | {value: number} + #IDSource: {id: string} + #URISource: {uri: string} + #TargetAverage: {avg: number} + #TargetValue: {value: number} + }) +} +-- issue1417.cue -- +// Regression where disjuncts sometimes behaved like conjuncts, causing +// incorrect unification of disjunction members. +// https://cuelang.org/issue/1417 +issue1417: { + #ID: !~"^a" | =~"^ab$" | =~"^aB$" + #ID: =~"^a" | !~"[A-Z]" + ids: [...#ID] & ["xyz", "ab", "aB"] + @test(eq, { + #ID: !~"^a" & =~"^a" | !~"^a" & !~"[A-Z]" | =~"^ab$" & =~"^a" | =~"^ab$" & !~"[A-Z]" | =~"^aB$" & =~"^a" | =~"^aB$" & !~"[A-Z]" + ids: ["xyz", "ab", "aB"] + }) +} +-- issue3149.cue -- +// Evaluator regression where unifying disjunctions incorrectly failed to +// validate a fixed value that satisfied the constraint. +// https://cuelang.org/issue/3149 +issue3149: { + #valid: { + name!: ( (=~"^Foo") | "an exception") & ( (=~"Foo$") | "an exception") + } + list: [...#valid] + list: [ + {name: "FooBarFoo"}, + {name: "FooBazFoo"}, + {name: "FooQuuxFoo"}, + {name: "an exception"}, + ] + @test(eq, { + #valid: { + name!: =~"^Foo" & =~"Foo$" | "an exception" + } + list: [{ + name: "FooBarFoo" + }, { + name: "FooBazFoo" + }, { + name: "FooQuuxFoo" + }, { + name: "an exception" + }] + }) +} +-- issue770.cue -- +// Default value resolution issue where chained pattern constraints with default +// disjunctions did not propagate defaults correctly. +// https://cuelang.org/issue/770 +issue770: { + #A: { + v: "a" | "b" | "c" + } + h: [string]: #A + h: a: { + v: *"a" | string + } + h: [=~"^b"]: { + v: *h.a.v | string + } + h: [=~"^c"]: { + v: *h.b.v | string + } + h: b: _ + h: boo: _ + h: c: _ + h: coo: _ + @test(eq, { + #A: {v: "a" | "b" | "c"} + h: { + a: {v: *"a" | "b" | "c"} + b: {v: *"a" | "b" | "c"} + boo: {v: *"a" | "b" | "c"} + c: {v: *"a" | "b" | "c"} + coo: {v: *"a" | "b" | "c"} + } + }) +} +-- issue3528.cue -- +// evalv3 "incDependent: already closed" panic with repeated disjunctions +// and definitions in workflow container schemas. +// https://cuelang.org/issue/3528 +issue3528: original: { + workflows: [...#Workflow] + workflows: [test] + + test: #Workflow & {} + + #Workflow: { + container: [string]: string | #container + #container: string | {volumes?: [...string]} + } + @test(eq, { + workflows: [ + {container: {}, #container: string | {volumes?: []}}, + ] + test: { + container: {} + #container: string | {volumes?: []} + } + #Workflow: { + container: {} + #container: string | {volumes?: []} + } + }) +} +issue3528: reduced: { + a?: #A + a: #A & {} + #A: { + A: [string]: 1 | #a + #a: 2 | {v: 1} + } + @test(eq, { + a: {A: {}, #a: 2 | {v: 1}} + #A: {A: {}, #a: 2 | {v: 1}} + }) +} +issue3528: counter: { + @test(eq, {}) +} +issue3528: nested: t1: { + {v: 1} | (2 | 3) + {v: 1} | (2 | 3) + {v: 1} | (2 | 3) + {v: 1} | (2 | 3) + @test(eq, {v: 1} | { + 2 + @test(eq) + } | { + 3 + @test(eq) + }) +} +issue3528: nested: t2: { + {v: 1} | 2 + {v: 1} | (2 | 3) + {v: 1} | 2 + {v: 1} | 2 + @test(eq, {v: 1} | { + 2 + @test(eq) + }) +} +-- issue3784.cue -- +// evalv3 regressions with "conflicting values" and "field not allowed" errors +// when evaluating schemas similar to the GitHub Terraform provider schema. +// https://cuelang.org/issue/3784 +issue3784: reduced: { + #Schema: a: { + kind: "A" + b: c?: string + b: {} + } | { + kind: "B" + } + + out: #Schema + out: a: { + kind: "A" + b: c: "x" + } + @test(eq, { + #Schema: { + a: {kind: "A", b: {c?: string}} | {kind: "B"} + } + out: {a: {kind: "A", b: {c: "x"}}} + }) +} +issue3784: full: { + #Schema: { + pages?: { + build_type?: "legacy" | "workflow" + source?: { + branch?: string + path?: string + } + cname?: string + } + pages?: { + build_type!: "legacy" + source!: { + branch!: _ + } + } | close({ + build_type!: "workflow" + cname?: _ + }) + } + out: #Schema & { + pages: { + cname: "foo.com" + build_type: "legacy" + source: { + branch: "main" + path: "/" + } + } + } + @test(eq, { + #Schema: { + pages?: {build_type!: "legacy", source!: {branch!: string, path?: string}, cname?: string} | {build_type!: "workflow", source?: {branch?: string, path?: string}, cname?: string} + } + out: { + pages: { + cname: "foo.com" + build_type: "legacy" + source: {branch: "main", path: "/"} + } + } + }) +} +issue3784: variant1: { + #Schema: { + pages: { + build_type?: "legacy" | "workflow" + source: { + branch?: string + path?: string + } + cname?: string + } + pages?: { + build_type!: "legacy" + source!: { + branch!: _ + } + } | close({ + build_type!: "workflow" + cname?: _ + }) + } + @test(eq, { + #Schema: { + pages: { + build_type!: "legacy" + source: {branch!: string, path?: string} + cname?: string + } + } + }) +} +issue3784: variant2: { + #Schema: { + build_type!: "legacy" + source!: { + branch!: _ + } + } | close({ + build_type!: "workflow" + cname?: _ + }) + a: #Schema + a: { + build_type?: "legacy" | "workflow" + source: { + branch?: string + path?: string + } + cname?: string + } + @test(eq, { + #Schema: {build_type!: "legacy", source!: {branch!: _}} | {build_type!: "workflow", cname?: _} + a: { + build_type!: "legacy" + source: { + branch!: string + path?: _|_ @test(err, code=eval, contains="issue3784.variant2.a.source.path: field not allowed", pos=[113:4]) + } + cname?: _|_ @test(err, code=eval, contains="issue3784.variant2.a.cname: field not allowed", pos=[115:3]) + } + }) +} +-- issue3958.cue -- +// evalv3 regression where unifying an odd number of default disjunctions no +// longer produced an error as expected. +// https://cuelang.org/issue/3958 +issue3958: t1: { + #schema: int | *1 + #schema: int | *3 + + test1: #schema & {int | *2} + test2: #schema & {int | *4} + @test(eq, { + #schema: int | 3 | 1 + test1: int | 3 | 1 | 2 + test2: int | 3 | 1 | 4 + }) +} +issue3958: t2: { + a: (int | *4) & (int | *1) & (int | *3) & (int | *8) + b: (int | *4) & (int | *1) & (int | *3) + @test(eq, { + a: int | 8 | 3 | 1 | 4 + b: int | 3 | 1 | 4 + }) +} +-- issue2685.cue -- +// Nested definition with a default value incorrectly took the default value +// even when a concrete value was provided via unification. +// https://cuelang.org/issue/2685 +issue2685: { + #Foo: { + bar: int + opt?: int + } | *{ + opt: int + } + + foo: #Foo + foo: bar: 0 + + { + foo: #Foo + } + @test(eq, { + #Foo: *{opt: int} | {bar: int, opt?: int} + foo: {bar: 0, opt?: int} + }) +} +-- out/compile -- +--- in.cue +{ + disambiguateClosed: { + b: (〈0;#Def〉 & 〈0;a〉) + a: 〈0;#Def〉 + #Def: { + ({ + x: true + }|{ + y: true + }) + } + } + alwaysCheckMatchers1: { + b: ({ + [=~"^xxxx$"]: int + }|null) + b: ({ + c: string + }|null) + b: { + c: "yyyyy" + } + } + alwaysCheckPatterns2: { + a: 〈0;#X〉 + a: 〈0;b〉 + b: 〈0;#X〉 + b: { + c: "yyyyy" + } + #X: (string|{ + c: string + { + [=~"^xxxx$"]: int + } + }) + } + nestedNonMonotonic: { + resolved: { + n1: { + x: ({ + a: 〈import;struct〉.MinFields(2) + }|null) + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: { + d: 1 + } + }|null) + } + } + } + nestedNonMonotonic: { + resolved: { + n2: { + x: ({ + a: { + b: 〈import;struct〉.MinFields(2) + } + }|null) + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: { + d: 1 + } + } + }|null) + } + } + } + nestedNonMonotonic: { + eliminated: { + n1: { + p1: { + x: ({ + a: 〈import;struct〉.MaxFields(1) + }|null) + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: { + d: 1 + } + }|null) + } + } + } + } + nestedNonMonotonic: { + eliminated: { + n1: { + p2: { + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: 〈import;struct〉.MaxFields(1) + }|null) + x: ({ + a: { + d: 1 + } + }|null) + } + } + } + } + nestedNonMonotonic: { + eliminated: { + n1: { + p2: { + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: { + d: 1 + } + }|null) + x: ({ + a: 〈import;struct〉.MaxFields(1) + }|null) + } + } + } + } + nestedNonMonotonic: { + eliminated: { + n2: { + p1: { + x: ({ + a: { + b: 〈import;struct〉.MaxFields(1) + } + }|null) + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: { + d: 1 + } + } + }|null) + } + } + } + } + nestedNonMonotonic: { + eliminated: { + n2: { + p2: { + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: 〈import;struct〉.MaxFields(1) + } + }|null) + x: ({ + a: { + b: { + d: 1 + } + } + }|null) + } + } + } + } + nestedNonMonotonic: { + eliminated: { + n2: { + p2: { + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: { + d: 1 + } + } + }|null) + x: ({ + a: { + b: 〈import;struct〉.MaxFields(1) + } + }|null) + } + } + } + } + nestedNonMonotonic: { + incomplete: { + a: { + n1: { + p1: { + x: ({ + a: 〈import;struct〉.MinFields(2) + }|null) + x: ({ + a: { + c: 1 + } + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + a: { + n1: { + p2: { + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: 〈import;struct〉.MinFields(2) + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + a: { + n2: { + p1: { + x: ({ + a: { + b: 〈import;struct〉.MinFields(2) + } + }|null) + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + a: { + n2: { + p2: { + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: 〈import;struct〉.MinFields(2) + } + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + b: { + n1: { + p1: { + x: ({ + a: 〈import;struct〉.MinFields(3) + }|null) + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: { + d: 1 + } + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + b: { + n1: { + p2: { + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: 〈import;struct〉.MinFields(3) + }|null) + x: ({ + a: { + d: 1 + } + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + b: { + n1: { + p3: { + x: ({ + a: { + c: 1 + } + }|null) + x: ({ + a: { + d: 1 + } + }|null) + x: ({ + a: 〈import;struct〉.MinFields(3) + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + b: { + n2: { + p1: { + x: ({ + a: { + b: 〈import;struct〉.MinFields(3) + } + }|null) + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: { + d: 1 + } + } + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + b: { + n2: { + p1: { + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: 〈import;struct〉.MinFields(3) + } + }|null) + x: ({ + a: { + b: { + d: 1 + } + } + }|null) + } + } + } + } + } + nestedNonMonotonic: { + incomplete: { + b: { + n2: { + p1: { + x: ({ + a: { + b: { + c: 1 + } + } + }|null) + x: ({ + a: { + b: { + d: 1 + } + } + }|null) + x: ({ + a: { + b: 〈import;struct〉.MinFields(3) + } + }|null) + } + } + } + } + } + preserveClosedness: { + small: { + p1: { + #A: (〈0;#B〉 & { + a: string + }) + #B: { + (*{}|{ + a: string + }) + (*{}|{ + b: int + }) + } + } + } + } + preserveClosedness: { + small: { + p2: { + #A: (〈0;#B〉 & { + a: string + }) + #B: { + ({ + a: string + }|*{}) + (*{}|{ + b: int + }) + } + } + } + } + preserveClosedness: { + medium: { + p1: { + #A: (〈0;#B〉 & { + a: string + }) + #B: { + (*{}|{ + a: string + }|{ + b: string + }) + (*{}|{ + c: int + }|{ + d: string + }) + } + } + } + } + preserveClosedness: { + medium: { + p2: { + #A: (〈0;#B〉 & { + a: string + }) + #B: { + ({ + a: string + }|*{}|{ + b: string + }) + (*{}|{ + c: int + }|{ + d: string + }) + } + } + } + } + preserveClosedness: { + medium: { + p3: { + #A: (〈0;#B〉 & { + a: string + }) + #B: { + ({ + a: string + }|{ + b: string + }|*{}) + (*{}|{ + c: int + }|{ + d: string + }) + } + } + } + } + noChildError: _ + noChildError: { + issue1608: { + myValue: (〈0;#type〉 & { + fieldName: "some string" + }) + #type: { + fieldName: 〈1;#subtype〉 + } + #subtype: (string|{ + foo: string + }|{ + bar: 〈1;#subtype〉 + }) + } + } + noChildError: { + t1: { + #D: ({ + b: string + }|{ + c: 〈1;#D〉 + }) + o: (〈0;#D〉 & { + b: "test" + }) + } + } + noChildError: { + t2: { + o: (〈0;#D〉 & { + b: "test" + }) + #D: ({ + b: string + }|{ + c: 〈1;#D〉 + }) + } + } + noChildError: { + t3: { + #D: ({ + a: null + }|{ + b: string + }|{ + c: 〈1;#D〉 + }) + o: (〈0;#D〉 & { + b: "test" + }) + } + } + noChildError: { + t4: { + o: (〈0;#D〉 & { + b: "test" + }) + #D: ({ + a: null + }|{ + b: string + }|{ + c: 〈1;#D〉 + }) + } + } + issue1924: { + t1: { + m: { + a: 2 + } + x: (*[ + 〈1;m〉.b, + ]|2) + } + } + issue1924: { + t2: { + m: { + a: 2 + } + x: (*{ + v: 〈1;m〉.b + }|3) + } + } + issue1924: { + t3: { + m: { + a: 2 + } + x: (*〈0;m〉.b|1) + } + } + issue1838: { + t1: { + p?: [] + a: ([ + for _, k in 〈1;p〉 { + 〈1;k〉 + }, + ]|null) + } + } + issue1838: { + t2: { + p?: [] + a: (null|[ + for _, k in 〈1;p〉 { + 〈1;k〉 + }, + ]) + } + } + noHang: { + #T: ([ + "a", + 〈1;#T〉, + ]|[ + "d", + ...〈1;#T〉, + ]) + x: 〈0;#T〉 + #X: 〈0;x〉 + #X: 〈0;#T〉 + } + issue1940: { + #T: ([ + "a", + 〈1;#T〉, + ]|[ + "b", + 〈1;#T〉, + ]|[ + "c", + 〈1;#T〉, + ]|[ + "d", + [ + ...〈2;#T〉, + ], + ]) + #A: { + type: 〈1;#T〉 + } + #B: { + [string]: 〈1;#A〉 + } + #C: (〈0;#B〉 & { + x: 〈1;#A〉 + }) + } +} +--- issue1417.cue +{ + issue1417: { + #ID: (!~"^a"|=~"^ab$"|=~"^aB$") + #ID: (=~"^a"|!~"[A-Z]") + ids: ([ + ...〈1;#ID〉, + ] & [ + "xyz", + "ab", + "aB", + ]) + } +} +--- issue2209full.cue +{ + issue2209: { + simplified: { + t1: { + #SpecFoo: { + foo: { + min: 1 + } + } + #SpecBar: { + bar: { + min: 1 + } + } + spec: { + bar: {} + } + spec: (〈0;#SpecFoo〉|〈0;#SpecBar〉) + out: { + ({ + nullFoo: null + }|{ + nullBar: null + }) + ({ + minFoo: int + }|{ + minBar: int + }) + if (〈0;X〉.bar != _|_(explicit error (_|_ literal) in source)) { + minBar: 〈1;X〉.bar.min + } + X: 〈1;spec〉 + } + } + } + } + issue2209: { + simplified: { + t2: { + #SpecFoo: { + foo: {} + } + #SpecBar: { + bar: { + x: 1 + } + } + spec: { + bar: {} + } + spec: (*〈0;#SpecFoo〉|〈0;#SpecBar〉) + if (〈0;spec〉.bar != _|_(explicit error (_|_ literal) in source)) { + BAZ: 〈1;spec〉.bar.x + } + ({ + f1: int + }|{ + b2: int + }) + ({ + f2: int + }|{ + b2: int + }) + } + } + } + issue2209: { + simplified: { + t3: { + #A: { + v: 1 + } + ({ + f1: int + }|{ + b2: int + }) + ({ + f2: int + }|{ + b2: int + }) + BAZ: 〈0;S〉.y + S: (*〈0;#A〉|〈0;#B〉) + #B: { + x: 1 + y: 1 + } + S: { + x: 1 + } + } + } + } + issue2209: { + full: { + Foo: (〈0;#Abstract〉 & { + spec: { + foo: {} + } + }) + Bar: (〈0;#Abstract〉 & { + spec: { + bar: {} + } + }) + #Abstract: { + spec: 〈1;_#Spec〉 + resource: (〈1;_Thing〉 & { + _X: { + spec: 〈3〉.spec + } + }) + } + _#Spec: (*〈0;_#SpecFoo〉|〈0;_#SpecBar〉) + _#SpecFoo: { + foo: { + min: (int|*10) + max: (int|*20) + } + } + _#SpecBar: { + bar: { + min: (int|*30) + max: (int|*40) + } + } + _Thing: (〈0;#Constrained〉 & { + _X: _ + spec: { + if (〈1;_X〉.spec.foo != _|_(explicit error (_|_ literal) in source)) { + minFoo: 〈2;_X〉.spec.foo.min + maxFoo: 〈2;_X〉.spec.foo.max + } + if (〈1;_X〉.spec.bar != _|_(explicit error (_|_ literal) in source)) { + minBar: 〈2;_X〉.spec.bar.min + maxBar: 〈2;_X〉.spec.bar.max + } + } + }) + #Constrained: (〈0;#Base〉 & { + spec: ({ + minFoo: (int|*10) + maxFoo: (int|*20) + minBar?: null + maxBar?: null + }|{ + minBar: (int|*30) + maxBar: (int|*40) + minFoo?: null + maxFoo?: null + }) + spec: (*{ + fuga?: null + }|{ + hoge?: null + }) + }) + #Base: { + spec: { + minFoo?: (null|int) + maxFoo?: (null|int) + minBar?: (null|int) + maxBar?: (null|int) + hoge?: (null|bool) + fuga?: (null|bool) + } + } + } + } +} +--- issue2246.cue +{ + issue2246: { + simplified: { + #FormFoo: { + fooID: string + } + #FormBar: { + barID: string + } + #Form: { + (〈1;#FormFoo〉|〈1;#FormBar〉) + } + data: { + fooID: "123" + } + out1: (〈0;#Form〉 & 〈0;data〉) + out2: (〈0;#Form〉 & 〈0;out1〉) + } + } + issue2246: { + full: { + data: { + forms: [ + { + fooID: "00-0000001" + }, + ] + } + form1040: (〈0;#compute〉 & { + in: 〈1;data〉 + }).out + #K1: { + #_base: { + common: 3 + } + #FormFoo: { + 〈1;#_base〉 + fooID: string + } + #FormBar: { + 〈1;#_base〉 + barID: string + } + #Form: { + (〈1;#FormFoo〉|〈1;#FormBar〉) + } + } + #Input: { + forms: [ + ...〈2;#K1〉.#Form, + ] + } + #summarizeReturn: { + in: 〈1;#Input〉 + out: [ + for _, k in 〈1;in〉.forms { + 〈1;k〉.common + }, + ] + } + #compute: { + in: 〈1;#Input〉 + out: (〈1;#summarizeReturn〉 & { + in: 〈1;in〉 + }).out + } + } + } +} +--- issue2263.cue +{ + issue2263: { + simplified: { + metrics: 〈0;#Metric〉 + #Metric: { + (〈1;#IDSource〉|{}) + (〈1;#TargetAverage〉|{}) + } + metrics: { + id: "foo" + avg: 60 + } + #IDSource: { + id: string + } + #TargetAverage: { + avg: number + } + } + } + issue2263: { + full: { + metrics: [ + ...〈1;#Metric〉, + ] + metrics: [ + { + id: "foo" + avg: 60 + }, + { + id: "bar" + value: 80 + }, + { + uri: "baz" + avg: 70 + }, + { + uri: "qux" + value: 90 + }, + ] + #Metric: { + 〈1;#Source〉 + 〈1;#Target〉 + } + #Source: (〈0;#IDSource〉|〈0;#URISource〉) + #Target: (〈0;#TargetAverage〉|〈0;#TargetValue〉) + #IDSource: { + id: string + } + #URISource: { + uri: string + } + #TargetAverage: { + avg: number + } + #TargetValue: { + value: number + } + } + } +} +--- issue2685.cue +{ + issue2685: { + #Foo: ({ + bar: int + opt?: int + }|*{ + opt: int + }) + foo: 〈0;#Foo〉 + foo: { + bar: 0 + } + { + foo: 〈1;#Foo〉 + } + } +} +--- issue3149.cue +{ + issue3149: { + #valid: { + name!: ((=~"^Foo"|"an exception") & (=~"Foo$"|"an exception")) + } + list: [ + ...〈1;#valid〉, + ] + list: [ + { + name: "FooBarFoo" + }, + { + name: "FooBazFoo" + }, + { + name: "FooQuuxFoo" + }, + { + name: "an exception" + }, + ] + } +} +--- issue3528.cue +{ + issue3528: { + original: { + workflows: [ + ...〈1;#Workflow〉, + ] + workflows: [ + 〈1;test〉, + ] + test: (〈0;#Workflow〉 & {}) + #Workflow: { + container: { + [string]: (string|〈1;#container〉) + } + #container: (string|{ + volumes?: [ + ...string, + ] + }) + } + } + } + issue3528: { + reduced: { + a?: 〈0;#A〉 + a: (〈0;#A〉 & {}) + #A: { + A: { + [string]: (1|〈1;#a〉) + } + #a: (2|{ + v: 1 + }) + } + } + } + issue3528: { + counter: {} + } + issue3528: { + nested: { + t1: { + ({ + v: 1 + }|(2|3)) + ({ + v: 1 + }|(2|3)) + ({ + v: 1 + }|(2|3)) + ({ + v: 1 + }|(2|3)) + } + } + } + issue3528: { + nested: { + t2: { + ({ + v: 1 + }|2) + ({ + v: 1 + }|(2|3)) + ({ + v: 1 + }|2) + ({ + v: 1 + }|2) + } + } + } +} +--- issue3784.cue +{ + issue3784: { + reduced: { + #Schema: { + a: ({ + kind: "A" + b: { + c?: string + } + b: {} + }|{ + kind: "B" + }) + } + out: 〈0;#Schema〉 + out: { + a: { + kind: "A" + b: { + c: "x" + } + } + } + } + } + issue3784: { + full: { + #Schema: { + pages?: { + build_type?: ("legacy"|"workflow") + source?: { + branch?: string + path?: string + } + cname?: string + } + pages?: ({ + build_type!: "legacy" + source!: { + branch!: _ + } + }|close({ + build_type!: "workflow" + cname?: _ + })) + } + out: (〈0;#Schema〉 & { + pages: { + cname: "foo.com" + build_type: "legacy" + source: { + branch: "main" + path: "/" + } + } + }) + } + } + issue3784: { + variant1: { + #Schema: { + pages: { + build_type?: ("legacy"|"workflow") + source: { + branch?: string + path?: string + } + cname?: string + } + pages?: ({ + build_type!: "legacy" + source!: { + branch!: _ + } + }|close({ + build_type!: "workflow" + cname?: _ + })) + } + } + } + issue3784: { + variant2: { + #Schema: ({ + build_type!: "legacy" + source!: { + branch!: _ + } + }|close({ + build_type!: "workflow" + cname?: _ + })) + a: 〈0;#Schema〉 + a: { + build_type?: ("legacy"|"workflow") + source: { + branch?: string + path?: string + } + cname?: string + } + } + } +} +--- issue3958.cue +{ + issue3958: { + t1: { + #schema: (int|*1) + #schema: (int|*3) + test1: (〈0;#schema〉 & { + (int|*2) + }) + test2: (〈0;#schema〉 & { + (int|*4) + }) + } + } + issue3958: { + t2: { + a: ((((int|*4) & (int|*1)) & (int|*3)) & (int|*8)) + b: (((int|*4) & (int|*1)) & (int|*3)) + } + } +} +--- issue770.cue +{ + issue770: { + #A: { + v: ("a"|"b"|"c") + } + h: { + [string]: 〈1;#A〉 + } + h: { + a: { + v: (*"a"|string) + } + } + h: { + [=~"^b"]: { + v: (*〈2;h〉.a.v|string) + } + } + h: { + [=~"^c"]: { + v: (*〈2;h〉.b.v|string) + } + } + h: { + b: _ + } + h: { + boo: _ + } + h: { + c: _ + } + h: { + coo: _ + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/embed.txtar b/internal/core/compile/testdata/sync/disjunctions/embed.txtar new file mode 100644 index 000000000..47ef1f420 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/embed.txtar @@ -0,0 +1,223 @@ +-- in.cue -- +// Given the existence of this field, embedDefault is a struct. This +// means that embedding this conjunction into `embedDefault` itself should +// make it resolve to `{a: 2}`. + +default: { + y: *1 | {a: 2} + y + @test(eq, {y: *1 | {a: 2}, a: 2}) +} + +unambiguous: { + y: 1 | {a: 2} + y + @test(eq, {y: 1 | {a: 2}, a: 2}) +} + +forDefault: { + y: *1 | {a: 2} + for x in [1] {y} + @test(eq, {y: *1 | {a: 2}, a: 2}) +} + +// Carry over default to first disjunct. +openDefault: { + #y: *1 | {a: 2} + #y + @test(eq, *{1, #y: *1 | {a: 2}} | {#y: *1 | {a: 2}, a: 2}) +} + +openAmbiguous: { + #y: 1 | {a: 2} + #y + @test(eq, {1, #y: 1 | {a: 2}} | {#y: 1 | {a: 2}, a: 2}) +} + +forceStruct: { + #y: 1 | {a: 2} + #y + {} + @test(eq, {#y: 1 | {a: 2}, a: 2}) +} + +defaultsMulti: { + a: { + #def: { + *{} | {a: string} | {b: string} + *{} | {c: string} | {d: string} + } + + a: #def & {a: "foo"} + } + + b: { + #def: { + *{} | {a: string} | {b: string} + *{} | {c: string} | {d: string} + *{} | {d: string} | {e: string} + } + + a: #def & {a: "foo", e: "bar"} + } + @test(eq, { + a: { + #def: *{} | {c: string} | {d: string} | {a: string} | {a: string, c: string} | {a: string, d: string} | {b: string} | {b: string, c: string} | {b: string, d: string} + a: *{a: "foo"} | {a: "foo", c: string} | {a: "foo", d: string} + } + b: { + #def: *{} | {d: string} | {e: string} | {c: string} | {c: string, d: string} | {c: string, e: string} | {d: string, e: string} | {a: string} | {a: string, d: string} | {a: string, e: string} | {a: string, c: string} | {a: string, c: string, d: string} | {a: string, c: string, e: string} | {a: string, d: string, e: string} | {b: string} | {b: string, d: string} | {b: string, e: string} | {b: string, c: string} | {b: string, c: string, d: string} | {b: string, c: string, e: string} | {b: string, d: string, e: string} + a: *{a: "foo", e: "bar"} | {a: "foo", e: "bar", c: string} | {a: "foo", e: "bar", d: string} + } + }) +} + +nested: { + a: 1 | 2 | *( + (3 | 4 | *( 5 | 6 | *7)) & ( 3 | 4 | ( *7 | 8 ))) + @test(eq, {a: *7 | 2 | 3 | 4 | 1}) +} +-- issue3415.cue -- +// evalv3: calculated embedded scalars with a default value disagree with v2 +// when co-located with a hidden field; embedded scalar addition should work. +// https://cuelang.org/issue/3415 +issue3415: full: { + A: #A & { + i: { + _a + _b + _a: 1 + _b: 10 + } + } + #A: { + i: *0 | number + } + @test(eq, { + A: {i: {11, _a: 1, _b: 10}} + #A: {i: *0 | number} + }) +} +issue3415: reduced: { + a: { + 1 + #b + #b: 10 + } + a: *0 | number + @test(eq, {a: {11, #b: 10}}) +} +-- out/compile -- +--- in.cue +{ + default: { + y: (*1|{ + a: 2 + }) + 〈0;y〉 + } + unambiguous: { + y: (1|{ + a: 2 + }) + 〈0;y〉 + } + forDefault: { + y: (*1|{ + a: 2 + }) + for _, x in [ + 1, + ] { + 〈2;y〉 + } + } + openDefault: { + #y: (*1|{ + a: 2 + }) + 〈0;#y〉 + } + openAmbiguous: { + #y: (1|{ + a: 2 + }) + 〈0;#y〉 + } + forceStruct: { + #y: (1|{ + a: 2 + }) + 〈0;#y〉 + {} + } + defaultsMulti: { + a: { + #def: { + (*{}|{ + a: string + }|{ + b: string + }) + (*{}|{ + c: string + }|{ + d: string + }) + } + a: (〈0;#def〉 & { + a: "foo" + }) + } + b: { + #def: { + (*{}|{ + a: string + }|{ + b: string + }) + (*{}|{ + c: string + }|{ + d: string + }) + (*{}|{ + d: string + }|{ + e: string + }) + } + a: (〈0;#def〉 & { + a: "foo" + e: "bar" + }) + } + } + nested: { + a: (1|2|*((3|4|*(5|6|*7)) & (3|4|(*7|8)))) + } +} +--- issue3415.cue +{ + issue3415: { + full: { + A: (〈0;#A〉 & { + i: { + (〈0;_a〉 + 〈0;_b〉) + _a: 1 + _b: 10 + } + }) + #A: { + i: (*0|number) + } + } + } + issue3415: { + reduced: { + a: { + (1 + 〈0;#b〉) + #b: 10 + } + a: (*0|number) + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/errors.txtar b/internal/core/compile/testdata/sync/disjunctions/errors.txtar new file mode 100644 index 000000000..611c219d2 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/errors.txtar @@ -0,0 +1,479 @@ +-- in.cue -- +// cmd/cue: misleading "field not allowed" error when a type clash occurs inside +// a disjunction; the actual conflict should be reported instead. +// https://cuelang.org/issue/570 +issue570: { + results: #DecodeOutput + results: result: "hello" + + #Output: { + result: _ + } | { + error: string + } + + #DecodeOutput: #Output & { + result?: [... string] + ... + } + @test(err, code=eval, at=results.result, contains="conflicting values", args=["hello", [...string]], pos=[1:11, 2:19, 11:12]) +} + +// Clarify when an error resulted from a failed disjunction; error messages +// should indicate which disjunct failed rather than showing a generic error. +// https://cuelang.org/issue/516 +issue516: { + #Def: { + match: metrics: string: {} + } | {} + + x: #Def + x: match: metrics: "foo": {} + @test(err, code=eval, at=x, contains="2 errors in empty disjunction", pos=[]) +} + +// issue #465 +explicitDefaultError: { + a: string | *_|_ + + if a != "" { + } + @test(err, code=incomplete, contains="non-concrete value string in operand to !=", pos=[3:5, 1:5]) +} + +// evaluator: export as YAML vs JSON emits different templated data when +// pattern constraints with defaults produce different disjunction results. +// https://cuelang.org/issue/2916 +issue2916: { + b: _ + [_]: c: uint | *1 + [string]: c: >=3 | *3 + @test(eq, {b: {c: *3 | >=3 & int}}) +} +// evaluator: inconsistent export output for different formats based on which +// default is selected when multiple defaults are unified. +// https://cuelang.org/issue/3157 +issue3157: { + foo: *42 | _ + foo: *43 | bool + @test(eq, {foo: *43 | bool}) +} +-- issue3581.cue -- +// evalv3: tools/flow unexpected error when a flow task result field is used as +// a list item; string interpolation in a list element caused a spurious error. +// https://cuelang.org/issue/3581 +issue3581: reduced: { + list: [...] | *[] + list: ["\(c)" ] @test(err, code=incomplete, contains="2 errors in empty disjunction", + suberr=(code=incomplete, contains="incompatible list lengths", args=[0, 1], pos=[-1:17]), + suberr=(code=incomplete, contains="invalid interpolation: non-concrete value", pos=[0:9]), + ) + c: _ + @test(eq, {list: _|_, c: _}) +} +-- issue3576.cue -- +// evalv3: disjunct of definitions with identical optional fields results in +// incomplete evaluation; the resolved disjunct should be fully evaluated. +// https://cuelang.org/issue/3576 +issue3576: reduced: { + #A: a!: string + #B: { + if false { + dummy: {} + } + } + foo: #B | #A + foo: a: "1" + @test(eq, { + #A: {a!: string} + #B: {} + foo: {a: "1"} + }) +} +issue3576: full: { + #Run: { + run!: string + options?: #Option | [#Option, ...] + if options != _|_ { + optionsValue: options + } + } + + #Copy: { + copy!: string + options?: #Option | [#Option, ...] + if options != _|_ { + optionsValue: options + } + } + + #Option: {} + + foo: #Run | #Copy + foo: run: "make" + @test(eq, { + #Run: {run!: string, options?: {} | [{}]} + #Copy: {copy!: string, options?: {} | [{}]} + #Option: {} + foo: {run: "make", options?: {} | [{}]} + }) +} +-- issue3599.cue -- +// evalv3: "explicit error in source" regression when using bottom (_|_) in +// repeating disjunctions; errors in optional/let fields should be ignored. +// https://cuelang.org/issue/3599 +// Ignore errors for irrelevant fields like let and optional fields. +issue3599: full: { + #Action: { + action: { + read!: string + write?: _|_ + } | { + write!: string + read?: _|_ + } + } + + #Minio: { + container: #Action & { + action: { + read!: string + write?: _|_ + } | { + write!: string + read?: _|_ + } + } + doWrite: bool | *true + container: action: defaultAction + defaultAction: { + if doWrite { write: "somefile.txt" } + if !doWrite { read: "somefile.txt" } + } + } + @test(skip, hint="somehow this test doesn't work. Fix it.") + @test(eq:todo, { + #Action: { + action: {read!: string, write?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[])} | {write!: string, read?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[])} + } + #Minio: { + container: { + action: { + write: "somefile.txt" + read?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source (and 1 more errors)", pos=[23:13]) + } + } + doWrite: *true | bool + defaultAction: {write: "somefile.txt"} + } + }) +} +issue3599: reduced: p1: { + { a?: 1&2 } | { a: string, b?: 1&2 } + { } | { } + @test(eq, {a?: _|_ @test(err, code=eval, contains="conflicting values", args=[2, 1], pos=[49:25, 50:2, 50:9, 50:11])} | {a: string, b?: _|_ @test(err, code=eval, contains="conflicting values", args=[2, 1], pos=[49:25, 50:2, 50:35, 50:37])}) +} +issue3599: reduced: p2: { + { } | { } + { a?: 1&2 } | { a: string, b?: 1&2 } + @test(eq, {a?: _|_ @test(err, code=eval, contains="conflicting values", args=[2, 1], pos=[54:25, 56:2, 56:9, 56:11])} | {a: string, b?: _|_ @test(err, code=eval, contains="conflicting values", args=[2, 1], pos=[54:25, 56:2, 56:35, 56:37])}) +} +issue3599: let: { + { } | { a: B | 1, let B = 1&2 } + { } | { } + @test(eq, {} | {a: 1}) +} +-- optionalerror.cue -- +// evalv3 closedness regression with disjunctions and ellipses; a definition +// using _|_ in an optional field inside a disjunction caused spurious errors. +// https://cuelang.org/issue/4022 +issue4022: reduced: { + #NonNamespaced: metadata: namespace?: _|_ + #NullOrNonNamespaced: int | #NonNamespaced + out: #NullOrNonNamespaced + out: #NonNamespaced + out: metadata: {} + @test(eq, { + #NonNamespaced: { + metadata: { + namespace?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[5:40]) + } + } + #NullOrNonNamespaced: int | {metadata: { + namespace?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[5:40]) + }} + out: { + metadata: { + namespace?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[5:40]) + } + } + }) +} +issue4022: full: { + #NonNamespaced: { + metadata: { + name!: string + namespace?: _|_ + ... + } + ... + } + + #NullOrNonNamespaced: null | #NonNamespaced + + out: #NullOrNonNamespaced + out: #NonNamespaced + out: { + metadata: name: "foo" + apiVersion: "v1" + } + @test(eq, { + #NonNamespaced: { + metadata: { + name!: string + namespace?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[30:16]) + } + } + #NullOrNonNamespaced: null | {metadata: { + name!: string + namespace?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[30:16]) + }} + out: { + metadata: { + name: "foo" + namespace?: _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[30:16]) + } + apiVersion: "v1" + } + }) +} +-- out/compile -- +--- in.cue +{ + issue570: { + results: 〈0;#DecodeOutput〉 + results: { + result: "hello" + } + #Output: ({ + result: _ + }|{ + error: string + }) + #DecodeOutput: (〈0;#Output〉 & { + result?: [ + ...string, + ] + ... + }) + } + issue516: { + #Def: ({ + match: { + metrics: { + string: {} + } + } + }|{}) + x: 〈0;#Def〉 + x: { + match: { + metrics: { + foo: {} + } + } + } + } + explicitDefaultError: { + a: (string|*_|_(explicit error (_|_ literal) in source)) + if (〈0;a〉 != "") {} + } + issue2916: { + b: _ + [_]: { + c: (&(int, >=0)|*1) + } + [string]: { + c: (>=3|*3) + } + } + issue3157: { + foo: (*42|_) + foo: (*43|bool) + } +} +--- issue3576.cue +{ + issue3576: { + reduced: { + #A: { + a!: string + } + #B: { + if false { + dummy: {} + } + } + foo: (〈0;#B〉|〈0;#A〉) + foo: { + a: "1" + } + } + } + issue3576: { + full: { + #Run: { + run!: string + options?: (〈1;#Option〉|[ + 〈2;#Option〉, + ..., + ]) + if (〈0;options〉 != _|_(explicit error (_|_ literal) in source)) { + optionsValue: 〈1;options〉 + } + } + #Copy: { + copy!: string + options?: (〈1;#Option〉|[ + 〈2;#Option〉, + ..., + ]) + if (〈0;options〉 != _|_(explicit error (_|_ literal) in source)) { + optionsValue: 〈1;options〉 + } + } + #Option: {} + foo: (〈0;#Run〉|〈0;#Copy〉) + foo: { + run: "make" + } + } + } +} +--- issue3581.cue +{ + issue3581: { + reduced: { + list: ([ + ..., + ]|*[]) + list: [ + "\(〈1;c〉)", + ] + c: _ + } + } +} +--- issue3599.cue +{ + issue3599: { + full: { + #Action: { + action: ({ + read!: string + write?: _|_(explicit error (_|_ literal) in source) + }|{ + write!: string + read?: _|_(explicit error (_|_ literal) in source) + }) + } + #Minio: { + container: (〈1;#Action〉 & { + action: ({ + read!: string + write?: _|_(explicit error (_|_ literal) in source) + }|{ + write!: string + read?: _|_(explicit error (_|_ literal) in source) + }) + }) + doWrite: (bool|*true) + container: { + action: 〈1;defaultAction〉 + } + defaultAction: { + if 〈1;doWrite〉 { + write: "somefile.txt" + } + if !〈1;doWrite〉 { + read: "somefile.txt" + } + } + } + } + } + issue3599: { + reduced: { + p1: { + ({ + a?: (1 & 2) + }|{ + a: string + b?: (1 & 2) + }) + ({}|{}) + } + } + } + issue3599: { + reduced: { + p2: { + ({}|{}) + ({ + a?: (1 & 2) + }|{ + a: string + b?: (1 & 2) + }) + } + } + } + issue3599: { + let: { + ({}|{ + a: (〈0;let B#1〉|1) + let B#1 = (1 & 2) + }) + ({}|{}) + } + } +} +--- optionalerror.cue +{ + issue4022: { + reduced: { + #NonNamespaced: { + metadata: { + namespace?: _|_(explicit error (_|_ literal) in source) + } + } + #NullOrNonNamespaced: (int|〈0;#NonNamespaced〉) + out: 〈0;#NullOrNonNamespaced〉 + out: 〈0;#NonNamespaced〉 + out: { + metadata: {} + } + } + } + issue4022: { + full: { + #NonNamespaced: { + metadata: { + name!: string + namespace?: _|_(explicit error (_|_ literal) in source) + ... + } + ... + } + #NullOrNonNamespaced: (null|〈0;#NonNamespaced〉) + out: 〈0;#NullOrNonNamespaced〉 + out: 〈0;#NonNamespaced〉 + out: { + metadata: { + name: "foo" + } + apiVersion: "v1" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/incomplete.txtar b/internal/core/compile/testdata/sync/disjunctions/incomplete.txtar new file mode 100644 index 000000000..fbd76e5b8 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/incomplete.txtar @@ -0,0 +1,176 @@ +-- in.cue -- +import "encoding/yaml" + +// Defaults don't resolve struct values; a default that selects a missing +// field in a struct should fall back to the other disjunct. +// https://cuelang.org/issue/700 +issue700: { + a: y: "y" + test1: *a.x | 1 + test2: *a.y | 1 + @test(eq, {a: {y: "y"}, test1: 1, test2: *"y" | 1}) +} + +lookup: { + x: { + name: "Hello" + } + y: x.a @test(err, code=incomplete, contains="undefined field: a", pos=[0:14]) + ok1: *x.a | x @test(eq, {name: "Hello"}) + ok2: x | *x.a @test(eq, {name: "Hello"}) + ok3: x.a | *x @test(eq, {name: "Hello"}) + ok4: *x | x.a @test(eq, {name: "Hello"}) + ok5: x | x.a @test(eq) + ok5: x.a | x @test(eq, {name: "Hello"}) + allFail1: x.a | x.b @test(err, code=incomplete, contains="2 errors in empty disjunction", + suberr=(code=incomplete, contains="undefined field: a", pos=[0:14]), + suberr=(code=incomplete, contains="undefined field: b", pos=[0:20]), + ) + allFail2: x.a | x.b @test(err, code=incomplete, contains="2 errors in empty disjunction", + suberr=(code=incomplete, contains="undefined field: a", pos=[0:14]), + suberr=(code=incomplete, contains="undefined field: b", pos=[0:20]), + ) +} + +func: { + s: string + ok1: yaml.MarshalStream(s) | yaml.Marshal(s) @test(err, code=incomplete, + contains="2 errors in empty disjunction", + suberr=(code=incomplete, contains="non-concrete argument 0", pos=[0:7]), + suberr=(code=incomplete, contains="non-concrete argument 0", pos=[0:31]), + ) +} + +// Default mark on interpolated string; a concrete override should suppress +// a default interpolation regardless of whether it is left or right in the disjunction. +// https://cuelang.org/issue/782 +issue782: { + a: { + inner: string + interpolation: *"\(inner)" | string + interpolation: "override" + @test(eq, { + inner: string + interpolation: "override" + }) + } + b: { + inner: string + interpolation: string | *"\(inner)" + interpolation: "override" + @test(eq, { + inner: string + interpolation: "override" + }) + } + c: { + inner: string + interpolation: "\(inner)" | string + interpolation: "override" + @test(eq, { + inner: string + interpolation: "override" + }) + } + d: { + inner: string + interpolation: string | "\(inner)" + interpolation: "override" + @test(eq, { + inner: string + interpolation: "override" + }) + } +} +-- issue3680.cue -- +// evalv3: "unexpected uninitialized node" regression with bottom optional fields; +// optional fields set to _|_ in a disjunct should not cause a crash. +// https://cuelang.org/issue/3680 +issue3680: t1: { + {} | { + a?: _|_ + b?: _|_ + } + {} | {} + @test(eq, {} | {a?: _|_, b?: _|_}) +} +issue3680: t2: { + x: {} | { + a?: _|_ + b?: _|_ + } + x: {} | {} + @test(eq, {x: {} | {a?: _|_, b?: _|_}}) +} +-- out/compile -- +--- in.cue +{ + issue700: { + a: { + y: "y" + } + test1: (*〈0;a〉.x|1) + test2: (*〈0;a〉.y|1) + } + lookup: { + x: { + name: "Hello" + } + y: 〈0;x〉.a + ok1: (*〈0;x〉.a|〈0;x〉) + ok2: (〈0;x〉|*〈0;x〉.a) + ok3: (〈0;x〉.a|*〈0;x〉) + ok4: (*〈0;x〉|〈0;x〉.a) + ok5: (〈0;x〉|〈0;x〉.a) + ok5: (〈0;x〉.a|〈0;x〉) + allFail1: (〈0;x〉.a|〈0;x〉.b) + allFail2: (〈0;x〉.a|〈0;x〉.b) + } + func: { + s: string + ok1: (〈import;"encoding/yaml"〉.MarshalStream(〈0;s〉)|〈import;"encoding/yaml"〉.Marshal(〈0;s〉)) + } + issue782: { + a: { + inner: string + interpolation: (*"\(〈0;inner〉)"|string) + interpolation: "override" + } + b: { + inner: string + interpolation: (string|*"\(〈0;inner〉)") + interpolation: "override" + } + c: { + inner: string + interpolation: ("\(〈0;inner〉)"|string) + interpolation: "override" + } + d: { + inner: string + interpolation: (string|"\(〈0;inner〉)") + interpolation: "override" + } + } +} +--- issue3680.cue +{ + issue3680: { + t1: { + ({}|{ + a?: _|_(explicit error (_|_ literal) in source) + b?: _|_(explicit error (_|_ literal) in source) + }) + ({}|{}) + } + } + issue3680: { + t2: { + x: ({}|{ + a?: _|_(explicit error (_|_ literal) in source) + b?: _|_(explicit error (_|_ literal) in source) + }) + x: ({}|{}) + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/issue2209.txtar b/internal/core/compile/testdata/sync/disjunctions/issue2209.txtar new file mode 100644 index 000000000..99eb02808 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/issue2209.txtar @@ -0,0 +1,297 @@ +# Tests that complex configurations with disjunctions and comprehensions evaluate +# correctly. A regression in v0.5.0 caused "empty disjunction" errors for code +# involving nested definitions with spec disjunctions and if-guard comprehensions. +# https://cuelang.org/issue/2209 +-- input.cue -- +full: { + Foo: #Abstract & {spec: foo: {}} + Bar: #Abstract & {spec: bar: {}} + + #Abstract: X={ + spec: _#Spec + + resource: _Thing & {_X: spec: X.spec} + } + + _#Spec: *_#SpecFoo | _#SpecBar + + _#SpecFoo: { + foo: { + min: int | *10 + max: int | *20 + } + } + + _#SpecBar: { + bar: { + min: int | *30 + max: int | *40 + } + } + + _Thing: #Constrained & { + _X: _ + + spec: { + if _X.spec.foo != _|_ { + minFoo: _X.spec.foo.min + maxFoo: _X.spec.foo.max + } + + if _X.spec.bar != _|_ { + minBar: _X.spec.bar.min + maxBar: _X.spec.bar.max + } + } + } + + #Constrained: #Base & { + spec: { + minFoo: int | *10 + maxFoo: int | *20 + minBar?: null + maxBar?: null + } | { + minBar: int | *30 + maxBar: int | *40 + minFoo?: null + maxFoo?: null + } + + spec: *{ + fuga?: null + } | { + hoge?: null + } + } + + #Base: { + spec: { + minFoo?: null | int + maxFoo?: null | int + minBar?: null | int + maxBar?: null | int + + hoge?: null | bool + fuga?: null | bool + } + } + @test(eq, { + Foo: { + spec: {foo: {min: *10 | int, max: *20 | int}} + resource: { + _X: { + spec: {foo: {min: *10 | int, max: *20 | int}} + } + spec: *{minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null | bool, fuga?: null} | {minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null, fuga?: null | bool} + } + } + Bar: { + spec: {bar: {min: *30 | int, max: *40 | int}} + resource: { + _X: { + spec: {bar: {min: *30 | int, max: *40 | int}} + } + spec: *{minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null | bool, fuga?: null} | {minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null, fuga?: null | bool} + } + } + #Abstract: { + spec: *{foo: {min: *10 | int, max: *20 | int}} | {bar: {min: *30 | int, max: *40 | int}} + resource: { + _X: { + spec: *{foo: {min: *10 | int, max: *20 | int}} | {bar: {min: *30 | int, max: *40 | int}} + } + spec: *{minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null | bool, fuga?: null} | {minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null, fuga?: null | bool} + } + } + _#Spec: *{foo: {min: *10 | int, max: *20 | int}} | {bar: {min: *30 | int, max: *40 | int}} + _#SpecFoo: {foo: {min: *10 | int, max: *20 | int}} + _#SpecBar: {bar: {min: *30 | int, max: *40 | int}} + _Thing: { + _X: _ + spec: *{minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null | bool, fuga?: null} | *{minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null | bool, fuga?: null} | {minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null, fuga?: null | bool} | {minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null, fuga?: null | bool} + } + #Constrained: { + spec: *{minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null | bool, fuga?: null} | *{minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null | bool, fuga?: null} | {minFoo: *10 | int, maxFoo: *20 | int, minBar?: null, maxBar?: null, hoge?: null, fuga?: null | bool} | {minFoo?: null, maxFoo?: null, minBar: *30 | int, maxBar: *40 | int, hoge?: null, fuga?: null | bool} + } + #Base: { + spec: { + minFoo?: null | int + maxFoo?: null | int + minBar?: null | int + maxBar?: null | int + hoge?: null | bool + fuga?: null | bool + } + } + }) +} + +reduced: { + Foo: #Obj & {spec: foo: {}} + Bar: #Obj & {spec: bar: {}} + + #Obj: X={ + spec: *#SpecFoo | #SpecBar + + out: #Out & { + _Xspec: X.spec + if _Xspec.foo != _|_ { + minFoo: _Xspec.foo.min + } + if _Xspec.bar != _|_ { + minBar: _Xspec.bar.min + } + } + } + + #SpecFoo: foo: min: int | *10 + #SpecBar: bar: min: int | *20 + + #Out: { + {minFoo: int} | {minBar: int} + + *{nullFoo: null} | {nullBar: null} + } + @test(eq, { + Foo: { + spec: {foo: {min: *10 | int}} + out: *{_Xspec: {foo: {min: *10 | int}}, minFoo: *10 | int, nullFoo: null} | {_Xspec: {foo: {min: *10 | int}}, minFoo: *10 | int, nullBar: null} + } + Bar: { + spec: {bar: {min: *20 | int}} + out: *{_Xspec: {bar: {min: *20 | int}}, minBar: *20 | int, nullFoo: null} | {_Xspec: {bar: {min: *20 | int}}, minBar: *20 | int, nullBar: null} + } + #Obj: { + spec: *{foo: {min: *10 | int}} | {bar: {min: *20 | int}} + out: *{_Xspec: *{foo: {min: *10 | int}} | {bar: {min: *20 | int}}, minFoo: *10 | int, nullFoo: null} | {_Xspec: *{foo: {min: *10 | int}} | {bar: {min: *20 | int}}, minFoo: *10 | int, nullBar: null} + } + #SpecFoo: {foo: {min: *10 | int}} + #SpecBar: {bar: {min: *20 | int}} + #Out: *{minFoo: int, nullFoo: null} | *{minBar: int, nullFoo: null} | {minFoo: int, nullBar: null} | {minBar: int, nullBar: null} + }) +} +-- out/compile -- +--- input.cue +{ + full: { + Foo: (〈0;#Abstract〉 & { + spec: { + foo: {} + } + }) + Bar: (〈0;#Abstract〉 & { + spec: { + bar: {} + } + }) + #Abstract: { + spec: 〈1;_#Spec〉 + resource: (〈1;_Thing〉 & { + _X: { + spec: 〈3〉.spec + } + }) + } + _#Spec: (*〈0;_#SpecFoo〉|〈0;_#SpecBar〉) + _#SpecFoo: { + foo: { + min: (int|*10) + max: (int|*20) + } + } + _#SpecBar: { + bar: { + min: (int|*30) + max: (int|*40) + } + } + _Thing: (〈0;#Constrained〉 & { + _X: _ + spec: { + if (〈1;_X〉.spec.foo != _|_(explicit error (_|_ literal) in source)) { + minFoo: 〈2;_X〉.spec.foo.min + maxFoo: 〈2;_X〉.spec.foo.max + } + if (〈1;_X〉.spec.bar != _|_(explicit error (_|_ literal) in source)) { + minBar: 〈2;_X〉.spec.bar.min + maxBar: 〈2;_X〉.spec.bar.max + } + } + }) + #Constrained: (〈0;#Base〉 & { + spec: ({ + minFoo: (int|*10) + maxFoo: (int|*20) + minBar?: null + maxBar?: null + }|{ + minBar: (int|*30) + maxBar: (int|*40) + minFoo?: null + maxFoo?: null + }) + spec: (*{ + fuga?: null + }|{ + hoge?: null + }) + }) + #Base: { + spec: { + minFoo?: (null|int) + maxFoo?: (null|int) + minBar?: (null|int) + maxBar?: (null|int) + hoge?: (null|bool) + fuga?: (null|bool) + } + } + } + reduced: { + Foo: (〈0;#Obj〉 & { + spec: { + foo: {} + } + }) + Bar: (〈0;#Obj〉 & { + spec: { + bar: {} + } + }) + #Obj: { + spec: (*〈1;#SpecFoo〉|〈1;#SpecBar〉) + out: (〈1;#Out〉 & { + _Xspec: 〈2〉.spec + if (〈0;_Xspec〉.foo != _|_(explicit error (_|_ literal) in source)) { + minFoo: 〈1;_Xspec〉.foo.min + } + if (〈0;_Xspec〉.bar != _|_(explicit error (_|_ literal) in source)) { + minBar: 〈1;_Xspec〉.bar.min + } + }) + } + #SpecFoo: { + foo: { + min: (int|*10) + } + } + #SpecBar: { + bar: { + min: (int|*20) + } + } + #Out: { + ({ + minFoo: int + }|{ + minBar: int + }) + (*{ + nullFoo: null + }|{ + nullBar: null + }) + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/issue3850.txtar b/internal/core/compile/testdata/sync/disjunctions/issue3850.txtar new file mode 100644 index 000000000..99880363f --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/issue3850.txtar @@ -0,0 +1,192 @@ +# Tests that struct fields referencing hidden variables inside disjunctions +# evaluate correctly. A regression in evalv3 caused incomplete fields and +# panics when combining disjunctions with hidden-field lookups and definitions. +# https://cuelang.org/issue/3850 +-- issue3850.cue -- +issue3850: full: { + global: glb1: glb2: "123" + out: {foo?: _} | {} + out: {foo?: _} | {} + out: #WithFoo + + #WithFoo: { + _global: global + foo: _global.glb1.glb2 + } + @test(eq, { + global: {glb1: {glb2: "123"}} + out: { + _global: {glb1: {glb2: "123"}} + foo: "123" + } + #WithFoo: { + _global: {glb1: {glb2: "123"}} + foo: "123" + } + }) +} +issue3850: incomplete: { + global: glb1: glb2: "123" + out: {foo?: _} | {} + out: {foo?: _} | {} + out: #WithFoo + + #WithFoo: { + _global: global + foo: _global.glb1.glb2 + ... + } + @test(eq, { + global: {glb1: {glb2: "123"}} + out: { + _global: {glb1: {glb2: "123"}} + foo: "123" + } + #WithFoo: { + _global: {glb1: {glb2: "123"}} + foo: "123" + } + }) +} +issue3850: p2p: { + out: *{} | _ + out: *{} | _ + out: { + reg: #def + #def: foo: _global + @test(eq, { + reg: {foo: "global value"} + #def: {foo: "global value"} + }) + } + + _global: "global value" +} +-- issue3875.cue -- +issue3875: full: { + _global: name: "foo" + + out: desc: { + _hidden: _global.name + name: _hidden + } + out: #Schema | "never" + + #Schema: desc: {...} + @test(eq, { + _global: {name: "foo"} + out: {desc: {_hidden: "foo", name: "foo"}} + #Schema: {desc: {}} + }) +} +issue3875: reduced: { + global: a: "foo" + + out: desc: { + a: b + b: global.a + } + out: S | null + + S: {} + @test(eq, { + global: {a: "foo"} + out: {desc: {a: "foo", b: "foo"}} + S: {} + }) +} +-- out/compile -- +--- issue3850.cue +{ + issue3850: { + full: { + global: { + glb1: { + glb2: "123" + } + } + out: ({ + foo?: _ + }|{}) + out: ({ + foo?: _ + }|{}) + out: 〈0;#WithFoo〉 + #WithFoo: { + _global: 〈1;global〉 + foo: 〈0;_global〉.glb1.glb2 + } + } + } + issue3850: { + incomplete: { + global: { + glb1: { + glb2: "123" + } + } + out: ({ + foo?: _ + }|{}) + out: ({ + foo?: _ + }|{}) + out: 〈0;#WithFoo〉 + #WithFoo: { + _global: 〈1;global〉 + foo: 〈0;_global〉.glb1.glb2 + ... + } + } + } + issue3850: { + p2p: { + out: (*{}|_) + out: (*{}|_) + out: { + reg: 〈0;#def〉 + #def: { + foo: 〈2;_global〉 + } + } + _global: "global value" + } + } +} +--- issue3875.cue +{ + issue3875: { + full: { + _global: { + name: "foo" + } + out: { + desc: { + _hidden: 〈2;_global〉.name + name: 〈0;_hidden〉 + } + } + out: (〈0;#Schema〉|"never") + #Schema: { + desc: { + ... + } + } + } + } + issue3875: { + reduced: { + global: { + a: "foo" + } + out: { + desc: { + a: 〈0;b〉 + b: 〈2;global〉.a + } + } + out: (〈0;S〉|null) + S: {} + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/issue3857.txtar b/internal/core/compile/testdata/sync/disjunctions/issue3857.txtar new file mode 100644 index 000000000..80355d4b4 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/issue3857.txtar @@ -0,0 +1,175 @@ +# Tests that disjunctions combined with comprehensions and pattern constraints +# do not cause panics in the v3 evaluator. The issue reported crashes in +# Vertex.DerefValue and Environment.up for code that worked correctly in evalv2. +# https://cuelang.org/issue/3857 +-- in.cue -- +reduced: t1: { + S: { if true { a: U } } + x: S + x: { + ["a"]: b: 1 | T + d: b: x.a + } + T: 1 + U: b: 1 | 1 + @test(eq, { + S: {a: {b: 1}} + x: {d: {b: {b: 1}}, a: {b: 1}} + T: 1 + U: {b: 1} + }) +} +// issue3851: evalv3 incorrectly rejects a let field nested under multiple +// disjunctions with "field not allowed", a regression not present in evalv2. +// https://cuelang.org/issue/3851 +issue3851: t1: { + #Top: _ + #Config: { + disj: _ | *"default" + shared: _ + } + + #Schema: { + [string]: #Config + if true { + one: shared: "foo" + } + } + + out: #Schema + out: { + ["one"]: disj: _ | #Top + two: shared: out.one.shared + } + @test(eq, { + #Top: _ + #Config: {disj: *"default" | _, shared: _} + #Schema: { + one: {shared: "foo", disj: *"default" | _} + } + out: { + two: {shared: "foo", disj: *"default" | _} + one: {shared: "foo", disj: *"default" | _} + } + }) +} +issue3851: t2: { + #Top: _ + #Config: { + disj: _ | *{} + shared: _ + } + + #Env: { + conf: [string]: #Config + if true { + conf: one: shared: "foo" + } + } + + env1: #Env + + [string]: { + conf: ["one"]: disj: {} | #Top + conf: two: shared: conf.one.shared + } + @test(eq, { + #Top: _ + #Config: {disj: *{} | _, shared: _} + #Env: { + conf: {one: {shared: "foo", disj: *{} | _}} + } + env1: { + conf: { + two: {shared: "foo", disj: *{} | _} + one: {shared: "foo", disj: *{} | _} + } + } + }) +} +-- out/compile -- +--- in.cue +{ + reduced: { + t1: { + S: { + if true { + a: 〈2;U〉 + } + } + x: 〈0;S〉 + x: { + ["a"]: { + b: (1|〈2;T〉) + } + d: { + b: 〈2;x〉.a + } + } + T: 1 + U: { + b: (1|1) + } + } + } + issue3851: { + t1: { + #Top: _ + #Config: { + disj: (_|*"default") + shared: _ + } + #Schema: { + [string]: 〈1;#Config〉 + if true { + one: { + shared: "foo" + } + } + } + out: 〈0;#Schema〉 + out: { + ["one"]: { + disj: (_|〈2;#Top〉) + } + two: { + shared: 〈2;out〉.one.shared + } + } + } + } + issue3851: { + t2: { + #Top: _ + #Config: { + disj: (_|*{}) + shared: _ + } + #Env: { + conf: { + [string]: 〈2;#Config〉 + } + if true { + conf: { + one: { + shared: "foo" + } + } + } + } + env1: 〈0;#Env〉 + [string]: { + conf: { + ["one"]: { + disj: ({}|〈3;#Top〉) + } + } + conf: { + two: { + shared: 〈2;conf〉.one.shared + } + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/issue4339.txtar b/internal/core/compile/testdata/sync/disjunctions/issue4339.txtar new file mode 100644 index 000000000..2adf815eb --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/issue4339.txtar @@ -0,0 +1,30 @@ +# Tests that a default disjunct which embeds a struct referencing a sibling +# field, combined with an if-comprehension gated on a default boolean, does +# not panic. See: https://cuelang.org/issue/4339 +-- in.cue -- +_withExtra: extra: out.one + +out: { + *_withExtra | {} + + one: 1 + + enable: *true | false + if enable {} +} @test(eq, + // TODO: we should be able to use @test(final) here, avoiding the defaults. + *{one: 1, enable: *true | false, extra: 1} | {one: 1, enable: *true | false}, +) +-- out/compile -- +--- in.cue +{ + _withExtra: { + extra: 〈1;out〉.one + } + out: { + (*〈1;_withExtra〉|{}) + one: 1 + enable: (*true|false) + if 〈0;enable〉 {} + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/nested.txtar b/internal/core/compile/testdata/sync/disjunctions/nested.txtar new file mode 100644 index 000000000..f4b86dcdf --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/nested.txtar @@ -0,0 +1,156 @@ +-- issue3635.cue -- +import "list" +// evalv3: `incDependent: already closed` panic with a builtin and a disjunction; +// using list.Concat to satisfy a disjunction of map or list should not crash. +// https://cuelang.org/issue/3635 +issue3635: case1: { + Run: { + env: *{[string]: string} | [...string] + } + + command: Run & { + env: list.Concat([["foo"], ["bar"]]) + } + @test(eq, { + Run: {env: *{} | []} + command: {env: ["foo", "bar"]} + }) +} + +issue3635: case2: { + out: [...#Schema] + out: [#Schema & { + name: "x" + }] + + #Schema: { + name?: string + container?: [string]: string | #container + + #container: string | { + env?: #env + } + + #env: [string]: bool | string + } + @test(eq, { + out: [{ + name: "x" + container?: {} + #container: string | {env?: {}} + #env: [string]: bool | string + }] + #Schema: { + name?: string + container?: {} + #container: string | {env?: {}} + #env: [string]: bool | string + + } + }) +} + +issue3635: reduced: { + out: {X} & X + X: { + b: int | c + c: int | { e: d } + } + d: 1 + @test(eq, { + out: {b: int | {e: 1}, c: int | {e: 1}} + X: {b: int | {e: 1}, c: int | {e: 1}} + d: 1 + }) +} + +issue3635: reduced_noshare: { + out: {X} & X + X: { + b: int | c + c: int | { e: d & __no_sharing } + } + d: 1 + @test(eq, { + out: {b: int | {e: 1}, c: int | {e: 1}} + X: {b: int | {e: 1}, c: int | {e: 1}} + d: 1 + }) +} +-- out/compile -- +--- issue3635.cue +{ + issue3635: { + case1: { + Run: { + env: (*{ + [string]: string + }|[ + ...string, + ]) + } + command: (〈0;Run〉 & { + env: 〈import;list〉.Concat([ + [ + "foo", + ], + [ + "bar", + ], + ]) + }) + } + } + issue3635: { + case2: { + out: [ + ...〈1;#Schema〉, + ] + out: [ + (〈1;#Schema〉 & { + name: "x" + }), + ] + #Schema: { + name?: string + container?: { + [string]: (string|〈1;#container〉) + } + #container: (string|{ + env?: 〈1;#env〉 + }) + #env: { + [string]: (bool|string) + } + } + } + } + issue3635: { + reduced: { + out: ({ + 〈1;X〉 + } & 〈0;X〉) + X: { + b: (int|〈0;c〉) + c: (int|{ + e: 〈2;d〉 + }) + } + d: 1 + } + } + issue3635: { + reduced_noshare: { + out: ({ + 〈1;X〉 + } & 〈0;X〉) + X: { + b: (int|〈0;c〉) + c: (int|{ + e: (〈2;d〉 & _|_(no sharing)) + }) + } + d: 1 + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/operands.txtar b/internal/core/compile/testdata/sync/disjunctions/operands.txtar new file mode 100644 index 000000000..328ef78fa --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/operands.txtar @@ -0,0 +1,83 @@ +# This file tests disjunctions used as operands. +-- in.cue -- +list: *[1] | [2] @test(eq, *[1] | [2]) +condition: *true | false @test(eq, *true | false) +num: *1 | 2 @test(eq, *1 | 2) +object: *{a: 1} | {a: 2} @test(eq, *{a: 1} | {a: 2}) + +forLoop: [ + for e in list { + "count: \(e)" + }, +] @test(eq, ["count: 1"]) + +conditional: { + if condition { + a: 3 + } + if num < 5 { + b: 3 + } + @test(eq, {a: 3, b: 3}) +} + +selector: { + a: object.a + @test(eq, {a: 1}) +} + +index: { + a: list[0] + @test(eq, {a: 1}) +} + +binOp: { + a: num + 4 + @test(eq, {a: 5}) +} + +unaryOp: { + a: -num + @test(eq, {a: -1}) +} +-- out/compile -- +--- in.cue +{ + list: (*[ + 1, + ]|[ + 2, + ]) + condition: (*true|false) + num: (*1|2) + object: (*{ + a: 1 + }|{ + a: 2 + }) + forLoop: [ + for _, e in 〈1;list〉 { + "count: \(〈1;e〉)" + }, + ] + conditional: { + if 〈1;condition〉 { + a: 3 + } + if (〈1;num〉 < 5) { + b: 3 + } + } + selector: { + a: 〈1;object〉.a + } + index: { + a: 〈1;list〉[0] + } + binOp: { + a: (〈1;num〉 + 4) + } + unaryOp: { + a: -〈1;num〉 + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/propagate_err.txtar b/internal/core/compile/testdata/sync/disjunctions/propagate_err.txtar new file mode 100644 index 000000000..0d27c0c49 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/propagate_err.txtar @@ -0,0 +1,77 @@ +// Issue 4055: crash variant +// Issue 4056 +-- issue4056.cue -- +import "strings" + +// cmd/cue: "unresolved disjunction" when error() disjuncts are added inside +// a conditional that depends on the same field; the concrete value should win. +// https://cuelang.org/issue/4056 +issue4056: full: { + a: "foo-bar" + a: _ | error("error message 1") + if strings.HasPrefix(a, "foo") { + a: _ | error("error message 2") + } + @test(eq, {a: "foo-bar"}) +} +issue4056: reduced: { + a: "x" + a: _ | error("a") + if len(a) > 0 { + a: _ | error("b") + } + @test(eq, {a: "x"}) +} +variant: { + a: "x" + a: string | int + if len(a) > 0 { + a: _ + } + @test(eq, {a: "x"}) +} +-- pending.cue -- +// Be sure to emit errors for uncompleted pending arcs. +err: { + A: "forty two" + if A < 100 {B: true} + @test(err, code=eval, contains="invalid operands", pos=[2:5, 1:5, 2:9]) +} +-- out/compile -- +--- issue4056.cue +{ + issue4056: { + full: { + a: "foo-bar" + a: (_|error("error message 1")) + if 〈import;strings〉.HasPrefix(〈0;a〉, "foo") { + a: (_|error("error message 2")) + } + } + } + issue4056: { + reduced: { + a: "x" + a: (_|error("a")) + if (len(〈0;a〉) > 0) { + a: (_|error("b")) + } + } + } + variant: { + a: "x" + a: (string|int) + if (len(〈0;a〉) > 0) { + a: _ + } + } +} +--- pending.cue +{ + err: { + A: "forty two" + if (〈0;A〉 < 100) { + B: true + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/resolve.txtar b/internal/core/compile/testdata/sync/disjunctions/resolve.txtar new file mode 100644 index 000000000..ef8186ceb --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/resolve.txtar @@ -0,0 +1,48 @@ +// Ensure that references are resolved on the boundaries of disjunctions. +-- in.cue -- +resolveAcrossDisjunct: t1: { + {} | { #B: 1} // d resolves to 1 in the second case. + {d: #B} | {} + #B: int + @test(eq, {#B: int, d: int} | {#B: int} | {#B: 1, d: 1} | {#B: 1}) +} +resolveAcrossDisjunct: nested: { + {} | { a: b: #B: 1} // d resolves to 1 in the second case. + {d: a.b.#B} | {} + a: b: #B: int + @test(eq, {a: {b: {#B: int}}, d: int} | {a: {b: {#B: int}}} | {a: {b: {#B: 1}}, d: 1} | {a: {b: {#B: 1}}}) +} +-- out/compile -- +--- in.cue +{ + resolveAcrossDisjunct: { + t1: { + ({}|{ + #B: 1 + }) + ({ + d: 〈1;#B〉 + }|{}) + #B: int + } + } + resolveAcrossDisjunct: { + nested: { + ({}|{ + a: { + b: { + #B: 1 + } + } + }) + ({ + d: 〈1;a〉.b.#B + }|{}) + a: { + b: { + #B: int + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/disjunctions/specdeviation.txtar b/internal/core/compile/testdata/sync/disjunctions/specdeviation.txtar new file mode 100644 index 000000000..b62282631 --- /dev/null +++ b/internal/core/compile/testdata/sync/disjunctions/specdeviation.txtar @@ -0,0 +1,127 @@ +It turns out the semantics of the spec is somewhat awkward, +though theoretically nicer. It seems like we do need to change +the definition somewhat to make it less awkward, or at least +come up with a good workaround before adopting the spec. + +We have introduce a small hack to mimic the old behavior for scalar +values. + +Note that the value of p below is now 2 (default), but should +be the non-concrete 2 | int. + +Proof: + p: *((*1 | int) & 2) | int // substitution of both P conjuncts in p + p: *(*_|_ | 2) | int // U1: distribute conjuncts + p: *_|_ | 2 | int // M2: remove mark + p: 2 | int // value after removing default. +-- in.cue -- +Q: *1 | int @test(eq, *1 | int) +q: *Q | int @test(eq, *1 | int) // 1 as expected + +P: *1 | int +P: 2 +p: *P | int @test(eq, *2 | int) // now 2, but should be (2 | int), according to the spec: + +// Here the inner default may not be used as it is masked by the outer default. +r: (*3 | (*1 | 2)) & (1 | 2) @test(eq, 1 | 2) + +// Here the inner default is used, as there are no defaults marked in the +// outer disjunction. +s: (3 | (*1 | 2)) & (1 | 2) @test(eq, *1 | 2) + +s1: #Size & {min: 5} @test(eq, { + min: 5 + max: *5 | >5 + res: *0 | >=0 & int +}) + +#Size: { + max: >min | *min + res: uint | *0 + min: >res | *(1 + res) + @test(eq, { + max: *1 | >0 | >1 + res: *0 | >=0 & int + min: *1 | >0 + }) +} + +staged: { + c: ("a" | "b") & (*(*"a" | string) | string) + d: (*(*"a" | string) | string) & ("a" | "b") + @test(eq, {c: *"a" | *"b", d: *"a" | "b"}) +} + +issue763a: { + #A: { + v: "a" | "b" | "c" // change to string to fix + } + + h: [string]: #A + + h: [=~"^b"]: #A & { + v: *h.a.v | string + } + + h: a: { + v: *"a" | string + } + + h: baa: _ + h: boo: _ + @test(eq, { + #A: {v: "a" | "b" | "c"} + h: { + a: {v: *"a" | "b" | "c"} + baa: {v: *"a" | "b" | "c"} + boo: {v: *"a" | "b" | "c"} + } + }) +} +-- out/compile -- +--- in.cue +{ + Q: (*1|int) + q: (*〈0;Q〉|int) + P: (*1|int) + P: 2 + p: (*〈0;P〉|int) + r: ((*3|(*1|2)) & (1|2)) + s: ((3|(*1|2)) & (1|2)) + s1: (〈0;#Size〉 & { + min: 5 + }) + #Size: { + max: (>〈0;min〉|*〈0;min〉) + res: (&(int, >=0)|*0) + min: (>〈0;res〉|*(1 + 〈0;res〉)) + } + staged: { + c: (("a"|"b") & (*(*"a"|string)|string)) + d: ((*(*"a"|string)|string) & ("a"|"b")) + } + issue763a: { + #A: { + v: ("a"|"b"|"c") + } + h: { + [string]: 〈1;#A〉 + } + h: { + [=~"^b"]: (〈1;#A〉 & { + v: (*〈2;h〉.a.v|string) + }) + } + h: { + a: { + v: (*"a"|string) + } + } + h: { + baa: _ + } + h: { + boo: _ + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/basictypes.txtar b/internal/core/compile/testdata/sync/eval/basictypes.txtar new file mode 100644 index 000000000..fe025e1ca --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/basictypes.txtar @@ -0,0 +1,78 @@ +#inlinetest:exclude skip: compile errors. TODO: investigates +-- cue.mod/module.cue -- +module: "test.com" +language: version: "v0.15.0" +-- in.cue -- +top: { + a: {_} + b: _ +} + +scalar: { + a: {string} + b: string + c: {{{number}}} + d: number +} + +// StructCmp works with accepted experiment status +comparison: { + basicEquality: t: 42 == 42 + typeComparison: err: string == number // error for non-concrete + structEquality: t: {name: "test"} == {name: "test"} + nestedComparison: t: {data: {value: 1}} == {data: {value: 1}} +} +-- out/compile -- +comparison.typeComparison.err: invalid operand string ('==' requires concrete value): + ./in.cue:16:23 +comparison.typeComparison.err: invalid operand number ('==' requires concrete value): + ./in.cue:16:33 +--- in.cue +{ + top: { + a: { + _ + } + b: _ + } + scalar: { + a: { + string + } + b: string + c: { + { + { + number + } + } + } + d: number + } + comparison: { + basicEquality: { + t: (42 == 42) + } + typeComparison: { + err: (string == number) + } + structEquality: { + t: ({ + name: "test" + } == { + name: "test" + }) + } + nestedComparison: { + t: ({ + data: { + value: 1 + } + } == { + data: { + value: 1 + } + }) + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/bounds.txtar b/internal/core/compile/testdata/sync/eval/bounds.txtar new file mode 100644 index 000000000..fcf97e3f9 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/bounds.txtar @@ -0,0 +1,614 @@ +// Tests bound expression evaluation and simplification including binary bound +// simplification (incompatible bounds), simplifyExpr with non-concrete bound +// arguments, and struct equality bounds (== / !=). Also covers issue 4142 +// (struct equality in definitions) and issue 4251 (SimplifyBounds panic on == +// bounds combined with other bound types). +-- cue.mod/module.cue -- +module: "x.test" +language: version: "v0.14.0" +-- in.cue -- +x0: 5 @test(eq, 5) +x1: b5 & 30 @test(eq, 30) + +b0: 0 @test(eq, >0 & <5) +b1: b0 & int @test(eq, >0 & <5 & int) +b2: int & <5.5 @test(eq, <5.5 & int) +b3: <10 & <=5 @test(eq, <=5) +b4: >=20 & >20 @test(eq, >20) +b5: >=21 & >20 @test(eq, >=21) +b6: int & >5 & <=6 @test(eq, >5 & <=6 & int) + +simplifyExpr: { + // TODO: fill out later. + less1: <(<3) @test(err, code=incomplete, contains="non-concrete value <3", pos=[0:11]) + less2: <(<=3) @test(err, code=incomplete, contains="non-concrete value <=3", pos=[0:11]) + less3: <=(<3) @test(err, code=incomplete, contains="non-concrete value <3", pos=[0:12]) + less4: <=(<=3) @test(err, code=incomplete, contains="non-concrete value <=3", pos=[0:12]) + less5: <(!=3) @test(err, code=incomplete, contains="non-concrete value !=3", pos=[0:11]) + less6: <=(!=3) @test(err, code=incomplete, contains="non-concrete value !=3", pos=[0:12]) + + gtr1: >(>3) @test(err, code=incomplete, contains="non-concrete value >3", pos=[0:10]) + gtr2: >(>=3) @test(err, code=incomplete, contains="non-concrete value >=3", pos=[0:10]) + gtr3: >=(>3) @test(err, code=incomplete, contains="non-concrete value >3", pos=[0:11]) + gtr4: >=(>=3) @test(err, code=incomplete, contains="non-concrete value >=3", pos=[0:11]) + gtr5: >(!=3) @test(err, code=incomplete, contains="non-concrete value !=3", pos=[0:10]) + gtr6: >=(!=3) @test(err, code=incomplete, contains="non-concrete value !=3", pos=[0:11]) + + lg1: <(>3) @test(err, code=incomplete, contains="non-concrete value >3", pos=[0:9]) + lg2: <(>=3) @test(err, code=incomplete, contains="non-concrete value >=3", pos=[0:9]) + lg3: <=(>3) @test(err, code=incomplete, contains="non-concrete value >3", pos=[0:10]) + lg4: <=(>=3) @test(err, code=incomplete, contains="non-concrete value >=3", pos=[0:10]) + + gl1: >(<3) @test(err, code=incomplete, contains="non-concrete value <3", pos=[0:9]) + gl2: >(<=3) @test(err, code=incomplete, contains="non-concrete value <=3", pos=[0:9]) + gl3: >=(<3) @test(err, code=incomplete, contains="non-concrete value <3", pos=[0:10]) + gl4: >=(<=3) @test(err, code=incomplete, contains="non-concrete value <=3", pos=[0:10]) + + ne1: !=(!=3) @test(err, code=incomplete, contains="non-concrete value !=3", pos=[0:10]) + ne2: !=(<3) @test(err, code=incomplete, contains="non-concrete value <3", pos=[0:10]) + ne3: !=(<=3) @test(err, code=incomplete, contains="non-concrete value <=3", pos=[0:10]) + ne4: !=(>3) @test(err, code=incomplete, contains="non-concrete value >3", pos=[0:10]) + ne5: !=(>=3) @test(err, code=incomplete, contains="non-concrete value >=3", pos=[0:10]) + + s: string + n: number + i: int + f: float + b: bytes + basic1: <(i) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[i, <], pos=[0:12]) + basic2: >(n) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[n, >], pos=[0:12]) + basic3: >=(s) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[s, >=], pos=[0:13]) + basic4: <=(f) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[f, <=], pos=[0:13]) + basic5: <=(b) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[b, <=], pos=[0:13]) + + // Do NOT interpret this the same as `!= type`. + bne1: !=(s) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[s, !=], pos=[0:11]) + bne2: !=(n) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[n, !=], pos=[0:11]) + bne3: !=(n) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[n, !=], pos=[0:11]) + bne4: !=(i) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[i, !=], pos=[0:11]) + bne5: !=(b) @test(err, code=incomplete, contains="non-concrete value %s for bound %s", args=[b, !=], pos=[0:11]) + + e1: <(=~"foo") @test(err, code=incomplete, contains="non-concrete value =~", pos=[0:8]) + e2: >(null) @test(err, code=eval, contains="cannot use null for bound", pos=[0:8]) +} +-- binarystring.cue -- +simplifyBinary: strings: { + err1: { + p1: <"a" & >"b" @test(err, code=eval, contains="incompatible string bounds", pos=[0:16, 0:9]) + p2: >"b" & <"a" @test(err, code=eval, contains="incompatible string bounds", pos=[0:16, 0:9]) + } + err2: { + p1: >"b" & <="a" @test(err, code=eval, contains="incompatible string bounds", pos=[0:16, 0:9]) + p2: <="a" & >"b" @test(err, code=eval, contains="incompatible string bounds", pos=[0:17, 0:9]) + } + err3: { + p1: >="b" & <"b" @test(err, code=eval, contains="incompatible string bounds", pos=[0:17, 0:9]) + p2: <"b" & >="b" @test(err, code=eval, contains="incompatible string bounds", pos=[0:16, 0:9]) + p3: >"b" & <="b" @test(err, code=eval, contains="incompatible string bounds", pos=[0:16, 0:9]) + p4: <="b" & >"b" @test(err, code=eval, contains="incompatible string bounds", pos=[0:17, 0:9]) + } + ok1: { + p1: >"a" & <"b" @test(eq, >"a" & <"b") + p2: <"b" & >"a" @test(eq, >"a" & <"b") + } + ok2: { + p1: >"a" & <="b" @test(eq, >"a" & <="b") + p2: <="b" & >"a" @test(eq, >"a" & <="b") + p3: >="a" & <"b" @test(eq, >="a" & <"b") + p4: <"b" & >="a" @test(eq, >="a" & <"b") + } + ok3: { + p1: >="b" & <="c" @test(eq, >="b" & <="c") + p2: <="c" & >="b" @test(eq, >="b" & <="c") + } + ok4: { + p1: >="b" & <="b" @test(eq, >="b" & <="b") + } +} +simplifyBinary: byte: { + err1: { + p1: <'a' & >'b' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:16, 0:9]) + p2: >'b' & <'a' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:16, 0:9]) + } + err2: { + p1: >'b' & <='a' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:16, 0:9]) + p2: <='a' & >'b' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:17, 0:9]) + } + err3: { + p1: >='b' & <'b' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:17, 0:9]) + p2: <'b' & >='b' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:16, 0:9]) + p3: >'b' & <='b' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:16, 0:9]) + p4: <='b' & >'b' @test(err, code=eval, contains="incompatible bytes bounds", pos=[0:17, 0:9]) + } + ok1: { + p1: >'a' & <'b' @test(eq, >'a' & <'b') + p2: <'b' & >'a' @test(eq, >'a' & <'b') + } + ok2: { + p1: >'a' & <='b' @test(eq, >'a' & <='b') + p2: <='b' & >'a' @test(eq, >'a' & <='b') + p3: >='a' & <'b' @test(eq, >='a' & <'b') + p4: <'b' & >='a' @test(eq, >='a' & <'b') + } + ok3: { + p1: >='b' & <='c' @test(eq, >='b' & <='c') + p2: <='c' & >='b' @test(eq, >='b' & <='c') + } + ok4: { + p1: >='b' & <='b' @test(eq, >='b' & <='b') + } +} +-- binary.cue -- +simplifyBinary: float: { + err1: { + p1: <1 & >2 @test(err, code=eval, contains="incompatible number bounds", pos=[0:14, 0:9]) + p2: >2 & <1 @test(err, code=eval, contains="incompatible number bounds", pos=[0:14, 0:9]) + } + err2: { + p1: >2 & <=1 @test(err, code=eval, contains="incompatible number bounds", pos=[0:14, 0:9]) + p2: <=1 & >2 @test(err, code=eval, contains="incompatible number bounds", pos=[0:15, 0:9]) + } + err3: { + p1: >=2 & <2 @test(err, code=eval, contains="incompatible number bounds", pos=[0:15, 0:9]) + p2: <2 & >=2 @test(err, code=eval, contains="incompatible number bounds", pos=[0:14, 0:9]) + p3: >2 & <=2 @test(err, code=eval, contains="incompatible number bounds", pos=[0:14, 0:9]) + p4: <=2 & >2 @test(err, code=eval, contains="incompatible number bounds", pos=[0:15, 0:9]) + } + ok1: { + p1: >1 & <2 @test(eq, >1 & <2) + p2: <2 & >1 @test(eq, >1 & <2) + } + ok2: { + p1: >=2 & <=2 @test(eq, >=2 & <=2) + p2: <=2 & >=2 @test(eq, >=2 & <=2) + } +} + +simplifyBinary: integer: { + [_]: [_]: int + err1: { + p1: <1 & >2 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:14, 0:9]) + p2: >2 & <1 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:14, 0:9]) + } + err2: { + p1: >2 & <=1 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:14, 0:9]) + p2: <=1 & >2 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:15, 0:9]) + } + err3: { + p1: >=2 & <2 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:15, 0:9]) + p2: <2 & >=2 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:14, 0:9]) + p3: >2 & <=2 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:14, 0:9]) + p4: <=2 & >2 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:15, 0:9]) + } + err4: { + p1: >1 & <2 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:14, 0:9]) + p2: <2 & >1 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:14, 0:9]) + } + ok1: { + p1: >=2 & <=3 @test(eq, >=2 & <=3 & int) + p2: <=3 & >=2 @test(eq, >=2 & <=3 & int) + } + ok2: { + p1: >=2 & <=2 @test(eq, >=2 & <=2 & int) + p2: <=2 & >=2 @test(eq, >=2 & <=2 & int) + } + ok3: { + p1: >=2 & <3 @test(eq, >=2 & <3 & int) + p2: >2 & <=3 @test(eq, >2 & <=3 & int) + p3: <3 & >=2 @test(eq, >=2 & <3 & int) + p4: <=3 & >2 @test(eq, >2 & <=3 & int) + } +} +-- equals.cue -- +@experiment(structcmp) + +equalScalar: { + ok1: ==1 @test(eq, 1) + ok1: 1 + + ok2: [1, 2] + ok2: ==[1, 2] @test(eq, [1, 2]) + + err1: ==1 + err1: 2 @test(err, code=eval, contains="out of bound ==1", pos=[-1:8, 0:8]) + + err2: [1, 2] + err2: !=[1, 2] @test(err, code=eval, contains="out of bound !=", pos=[0:8, -1:8]) +} +equalStruct: { + ok1: =={} @test(eq, {}) + ok1: {} + + ok2: {a: 1, b: 2} + ok2: =={a: 1, b: 2} @test(eq, {a: 1, b: 2}) + + err1: =={} + err1: {a: 1, b: 2} @test(err, code=eval, contains="out of bound ==", pos=[-1:8, 0:8]) + + err2: {a: 1, b: 2} + err2: !={a: 1, b: 2} @test(err, code=eval, contains="out of bound !=", pos=[0:8, -1:8]) +} +nonConcrete: { + ok0: =="foo" @test(eq, =="foo") + + _int: int + + iErr1: ==_int @test(err, code=incomplete, contains="non-concrete value", pos=[0:11]) + + iErr2: !=_int @test(err, code=incomplete, contains="non-concrete value", pos=[0:11]) + + iErr3: ==_int + iErr3: == 1 @test(err, code=incomplete, contains="non-concrete value", pos=[-1:11]) + + ok4: ==1 + ok4: _int @test(eq, ==1 & int) // v3: ==1 & int is not an error + + eErr5: =="foo" + eErr5: _int @test(err, code=eval, contains="conflicting values", pos=[-13:8, -1:9, 0:9]) + + eErr6: ==_int + eErr6: "foo" @test(err, code=incomplete|eval, + hint="incompatible types, so this SHOULD be a permanent error", + contains="non-concrete value", pos=[-1:11]) @test(err:todo, code=eval) +} +-- issue4142.cue -- +@experiment(structcmp) + +inDefinitions: ok1: { + #X: =={ name: "X" } + x: #X & { name: "X" } + @test(eq, {#X: {=={ name: "X" }}, x: {name: "X"}}) +} +inDefinitions: ok2: { + x: #X & { name: "Y" } + #X: !={ name: "X" } + @test(eq, {x: {name: "Y"}, #X: {!={name: "X"}}}) +} +inDefinitions: err1: { + #X: =={ name: "X" } + x: #X & { name: "Y" } + @test(err, code=eval, at=x, contains="out of bound ==", pos=[1:6, 2:5]) +} +inDefinitions: err2: { + #X: !={ name: "X" } + x: #X & { name: "X" } + @test(err, code=eval, at=x, contains="out of bound !=", pos=[1:6, 2:5]) +} +-- issue4251-panic.cue -- +@experiment(structcmp) + +// SimplifyBounds should handle EqualOp bounds +// without panicking, including in combination +// with other bound types. +// Regression: SimplifyBounds panicked on == bounds combined with other bound types. +// https://cuelang.org/issue/4251 +issue4251: ok: { + a: !="c" & =="a" & "a" @test(eq, "a") + b: =="b" & !="c" & "b" @test(eq, "b") + c: =="x" & >="a" & "x" @test(eq, "x") + d: <="z" & =="y" & "y" @test(eq, "y") +} +issue4251: fail: { + b: =="b" & !="b" & "b" @test(err, code=eval, contains="out of bound !=", pos=[0:13, 0:5, 0:21]) +} +-- out/compile -- +--- binary.cue +{ + simplifyBinary: { + float: { + err1: { + p1: (<1 & >2) + p2: (>2 & <1) + } + err2: { + p1: (>2 & <=1) + p2: (<=1 & >2) + } + err3: { + p1: (>=2 & <2) + p2: (<2 & >=2) + p3: (>2 & <=2) + p4: (<=2 & >2) + } + ok1: { + p1: (>1 & <2) + p2: (<2 & >1) + } + ok2: { + p1: (>=2 & <=2) + p2: (<=2 & >=2) + } + } + } + simplifyBinary: { + integer: { + [_]: { + [_]: int + } + err1: { + p1: (<1 & >2) + p2: (>2 & <1) + } + err2: { + p1: (>2 & <=1) + p2: (<=1 & >2) + } + err3: { + p1: (>=2 & <2) + p2: (<2 & >=2) + p3: (>2 & <=2) + p4: (<=2 & >2) + } + err4: { + p1: (>1 & <2) + p2: (<2 & >1) + } + ok1: { + p1: (>=2 & <=3) + p2: (<=3 & >=2) + } + ok2: { + p1: (>=2 & <=2) + p2: (<=2 & >=2) + } + ok3: { + p1: (>=2 & <3) + p2: (>2 & <=3) + p3: (<3 & >=2) + p4: (<=3 & >2) + } + } + } +} +--- binarystring.cue +{ + simplifyBinary: { + strings: { + err1: { + p1: (<"a" & >"b") + p2: (>"b" & <"a") + } + err2: { + p1: (>"b" & <="a") + p2: (<="a" & >"b") + } + err3: { + p1: (>="b" & <"b") + p2: (<"b" & >="b") + p3: (>"b" & <="b") + p4: (<="b" & >"b") + } + ok1: { + p1: (>"a" & <"b") + p2: (<"b" & >"a") + } + ok2: { + p1: (>"a" & <="b") + p2: (<="b" & >"a") + p3: (>="a" & <"b") + p4: (<"b" & >="a") + } + ok3: { + p1: (>="b" & <="c") + p2: (<="c" & >="b") + } + ok4: { + p1: (>="b" & <="b") + } + } + } + simplifyBinary: { + byte: { + err1: { + p1: (<'a' & >'b') + p2: (>'b' & <'a') + } + err2: { + p1: (>'b' & <='a') + p2: (<='a' & >'b') + } + err3: { + p1: (>='b' & <'b') + p2: (<'b' & >='b') + p3: (>'b' & <='b') + p4: (<='b' & >'b') + } + ok1: { + p1: (>'a' & <'b') + p2: (<'b' & >'a') + } + ok2: { + p1: (>'a' & <='b') + p2: (<='b' & >'a') + p3: (>='a' & <'b') + p4: (<'b' & >='a') + } + ok3: { + p1: (>='b' & <='c') + p2: (<='c' & >='b') + } + ok4: { + p1: (>='b' & <='b') + } + } + } +} +--- equals.cue +{ + equalScalar: { + ok1: ==1 + ok1: 1 + ok2: [ + 1, + 2, + ] + ok2: ==[ + 1, + 2, + ] + err1: ==1 + err1: 2 + err2: [ + 1, + 2, + ] + err2: !=[ + 1, + 2, + ] + } + equalStruct: { + ok1: =={} + ok1: {} + ok2: { + a: 1 + b: 2 + } + ok2: =={ + a: 1 + b: 2 + } + err1: =={} + err1: { + a: 1 + b: 2 + } + err2: { + a: 1 + b: 2 + } + err2: !={ + a: 1 + b: 2 + } + } + nonConcrete: { + ok0: =="foo" + _int: int + iErr1: ==〈0;_int〉 + iErr2: !=〈0;_int〉 + iErr3: ==〈0;_int〉 + iErr3: ==1 + ok4: ==1 + ok4: 〈0;_int〉 + eErr5: =="foo" + eErr5: 〈0;_int〉 + eErr6: ==〈0;_int〉 + eErr6: "foo" + } +} +--- in.cue +{ + x0: 5 + x1: (〈0;b5〉 & 30) + b0: (<〈0;x0〉 & >0) + b1: (〈0;b0〉 & int) + b2: (int & <5.5) + b3: (<10 & <=5) + b4: (>=20 & >20) + b5: (>=21 & >20) + b6: ((int & >5) & <=6) + simplifyExpr: { + less1: <<3 + less2: <<=3 + less3: <=<3 + less4: <=<=3 + less5: >3 + gtr2: >>=3 + gtr3: >=>3 + gtr4: >=>=3 + gtr5: >!=3 + gtr6: >=!=3 + lg1: <>3 + lg2: <>=3 + lg3: <=>3 + lg4: <=>=3 + gl1: ><3 + gl2: ><=3 + gl3: >=<3 + gl4: >=<=3 + ne1: !=!=3 + ne2: !=<3 + ne3: !=<=3 + ne4: !=>3 + ne5: !=>=3 + s: string + n: number + i: int + f: float + b: bytes + basic1: <〈0;i〉 + basic2: >〈0;n〉 + basic3: >=〈0;s〉 + basic4: <=〈0;f〉 + basic5: <=〈0;b〉 + bne1: !=〈0;s〉 + bne2: !=〈0;n〉 + bne3: !=〈0;n〉 + bne4: !=〈0;i〉 + bne5: !=〈0;b〉 + e1: <=~"foo" + e2: >null + } +} +--- issue4142.cue +{ + inDefinitions: { + ok1: { + #X: =={ + name: "X" + } + x: (〈0;#X〉 & { + name: "X" + }) + } + } + inDefinitions: { + ok2: { + x: (〈0;#X〉 & { + name: "Y" + }) + #X: !={ + name: "X" + } + } + } + inDefinitions: { + err1: { + #X: =={ + name: "X" + } + x: (〈0;#X〉 & { + name: "Y" + }) + } + } + inDefinitions: { + err2: { + #X: !={ + name: "X" + } + x: (〈0;#X〉 & { + name: "X" + }) + } + } +} +--- issue4251-panic.cue +{ + issue4251: { + ok: { + a: ((!="c" & =="a") & "a") + b: ((=="b" & !="c") & "b") + c: ((=="x" & >="a") & "x") + d: ((<="z" & =="y") & "y") + } + } + issue4251: { + fail: { + b: ((=="b" & !="b") & "b") + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/bulk.txtar b/internal/core/compile/testdata/sync/eval/bulk.txtar new file mode 100644 index 000000000..35e7b17ae --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/bulk.txtar @@ -0,0 +1,493 @@ +// Tests bulk pattern constraints including pattern cycles, multiple pattern +// constraints, and field-not-allowed errors from pattern constraint closedness. +// Also covers regressions: issue 2109 (pattern cycle detection), issue 3638 +// (closedness/default markers erased in multiple contexts), and issue 3670 +// (int pattern incorrectly allowing non-int fields). +-- in.cue -- +a: { + foo: a: 1 + [X = =~"foo"]: { + b: 1 + name: X + } + + @test(eq, { + [=~"foo"]: { b: 1, name: string } + foo: {a: 1, b: 1, name: "foo"} + }) + @test(allows, foo) + @test(allows, foobar) + @test(allows, string) + // TODO(eval): struct isn't closed, so this should be true. + @test(allows:todo=false, bar) +} +d: a & { + "foobar": { + c: 2 + } +} @test(eq, { + foobar: {c: 2, b: 1, name: "foobar"} + foo: {a: 1, b: 1, name: "foo"} +}) + +t1: { + #a: { + [>"e" & <"z"]: int + } + // TODO(inline): support allow on fields. + b: #a & {f: 4} @test(eq, {f: 4}) @test(allows, f) @test(allows=false, a) @test(allows=false, string) + c: #a & {z: 4} @test(err, code=eval, at=z, contains="field not allowed", pos=[0:11]) +} + +t2: { + #a: { + ["x" | "y"]: int + } + // TODO(inline): support allow on fields. + b: #a & {x: 4} @test(eq, {x: 4}) @test(allows, x) @test(allows=false, z) @test(allows=false, string) + c: #a & {z: 4} @test(err, code=eval, at=z, contains="field not allowed", pos=[0:11]) +} + +-- issue2109.cue -- +// Detect cycle: +// The pattern constraint of FlagsURLS is applied to countries (because +// FlagsURLs is embedded. But the pattern constraint itself refers to +// countries. So countries -> or(countries) -> countries. +// +// Theoretically, or(countries) can be resolved without a cycle. And then we +// could see it does not apply to countries. For now we stick with this +// approach understanding that it is easier to relax later. +patternCycle: issue2109: p1: { + // TODO(inline: permute doesn't permute embeddings, so the permute count + // here is 2, not 6. Fix this. + countries: ["US", "GB", "AU"] + FlagsURLs: {[or(countries)]: string} + FlagsURLs + @test(eq, { + countries: ["US", "GB", "AU"] + FlagsURLs: {} + }) +} +patternCycle: issue2109: p2: { + FlagsURLs: {[or(countries)]: string} + FlagsURLs + countries: ["US", "GB", "AU"] + @test(eq, { + FlagsURLs: {} + countries: ["US", "GB", "AU"] + }) +} +patternCycle: issue2109: p3: { + FlagsURLs + FlagsURLs: {[or(countries)]: string} + countries: ["US", "GB", "AU"] + @test(eq, { + FlagsURLs: {} + countries: ["US", "GB", "AU"] + }) +} + +patternCycle: t1: p1: { + countries: "US" | "GB" | "AU" + FlagsURLs: {[countries]: string} + FlagsURLs + @test(eq, { + countries: "US" | "GB" | "AU" + FlagsURLs: {} + }) +} +patternCycle: t1: p2: { + FlagsURLs + countries: "US" | "GB" | "AU" + FlagsURLs: {[countries]: string} + @test(eq, { + countries: "US" | "GB" | "AU" + FlagsURLs: {} + }) +} +patternCycle: t1: p3: { + FlagsURLs + FlagsURLs: {[countries]: string} + countries: "US" | "GB" | "AU" + @test(eq, { + FlagsURLs: {} + countries: "US" | "GB" | "AU" + }) +} + +-- intpattern.cue -- +// evalv3 regression: a pattern constraint definition with int key incorrectly +// allowed a non-matching (non-int) field. +// https://cuelang.org/issue/3670 +issue3670: { + #X: [int]: string + a: #X + a: "not_int": "c" @test(err, code=eval, contains="field not allowed", pos=[0:5]) +} +dual: { + _ + // As long as it is undecided whether this is a struct or list, this should + // not be a conflict. Note that the spec does not allow int patterns, but + // both v2 and v3 allow it, and we soon will, so it seems gratuitous to + // break it now. + [string]: _ + [int]: _ + + @test(eq, {_, [int]: _, [string]: _}) + + // TODO: test allows once we know what it means in this case. +} +-- multi.cue -- +// evalv3 regression: closedness values and default markers were incorrectly +// erased, causing order-dependent "incomplete value" errors. +// https://cuelang.org/issue/3638 +// Ensure that if the same pattern is added multiple times in different +// contexts, it is added to all contexts to preserve closedness information. +issue3638: full: { + routes: default: {} + routes: [string]: spec: [{ + + refs: [{"default"}] + }] + #Fields: { + input: _ + output: [for x in input { x }] @test(err, code=incomplete, contains="cannot range over input (incomplete type _)", pos=[0:21]) + ... + } + #Kubernetes: { + #Fields & { + Routes: route: [_]: spec!: HTTPROUTESPEC.#x + } + #Fields // Commenting out this line also fixes evalv3. + Routes: _ + input: res1: Routes + } + let HTTPROUTESPEC = { + #x: [...{ + refs: [...{string}] + }] | *[{ + other: [] + }] + } + + // Order dependent! Breaks if the lines below are moved to the top of the file. + entrypoint: used.output + used: #Kubernetes & { + Routes: route: routes + } + @test(eq, { + routes: default: {spec: [{ refs: ["default"] }]} + #Fields: { + input: _ + output: _|_ + } + #Kubernetes: { + Routes: route: {} + input: res1: route: {} + output: [{ route: {} }] + } + entrypoint: [{ route: default: spec: [{ refs: ["default"] }] }] + used: { + Routes: route: default: spec: [{ refs: ["default"] }] + input: res1: route: default: spec: [{ refs: ["default"] }] + output: [{ + route: default: spec: [{ refs: ["default"] }] + }] + } + }) +} +issue3638: reduced: { + input: k1: [string]: a: 1 + input: k1: foo: #x + out: { + for x in input { x } + for x in input { x } + } + #x: { a: int } | *{ b: 2 } + @test(eq, { + input: k1: foo: {a: 1} + out: foo: a: 1 + #x: *{b: 2} | {a: int} + }) +} +// We expect that changing the pattern constraint into a field should give +// not materially change the outcome. +issue3638: compare: { + input: k1: foo: a: 1 + input: k1: foo: #x + out: { + for x in input { x } + for x in input { x } + } + #x: { a: int } | *{ b: 2 } + @test(eq, { + input: k1: foo: {a: 1} + out: foo: a: 1 + #x: *{b: 2} | {a: int} + }) +} +-- out/compile -- +--- in.cue +{ + a: { + foo: { + a: 1 + } + [=~"foo"]: { + b: 1 + name: 〈1;-〉 + } + } + d: (〈0;a〉 & { + foobar: { + c: 2 + } + }) + t1: { + #a: { + [(>"e" & <"z")]: int + } + b: (〈0;#a〉 & { + f: 4 + }) + c: (〈0;#a〉 & { + z: 4 + }) + } + t2: { + #a: { + [("x"|"y")]: int + } + b: (〈0;#a〉 & { + x: 4 + }) + c: (〈0;#a〉 & { + z: 4 + }) + } +} +--- intpattern.cue +{ + issue3670: { + #X: { + [int]: string + } + a: 〈0;#X〉 + a: { + not_int: "c" + } + } + dual: { + _ + [string]: _ + [int]: _ + } +} +--- issue2109.cue +{ + patternCycle: { + issue2109: { + p1: { + countries: [ + "US", + "GB", + "AU", + ] + FlagsURLs: { + [or(〈1;countries〉)]: string + } + 〈0;FlagsURLs〉 + } + } + } + patternCycle: { + issue2109: { + p2: { + FlagsURLs: { + [or(〈1;countries〉)]: string + } + 〈0;FlagsURLs〉 + countries: [ + "US", + "GB", + "AU", + ] + } + } + } + patternCycle: { + issue2109: { + p3: { + 〈0;FlagsURLs〉 + FlagsURLs: { + [or(〈1;countries〉)]: string + } + countries: [ + "US", + "GB", + "AU", + ] + } + } + } + patternCycle: { + t1: { + p1: { + countries: ("US"|"GB"|"AU") + FlagsURLs: { + [〈1;countries〉]: string + } + 〈0;FlagsURLs〉 + } + } + } + patternCycle: { + t1: { + p2: { + 〈0;FlagsURLs〉 + countries: ("US"|"GB"|"AU") + FlagsURLs: { + [〈1;countries〉]: string + } + } + } + } + patternCycle: { + t1: { + p3: { + 〈0;FlagsURLs〉 + FlagsURLs: { + [〈1;countries〉]: string + } + countries: ("US"|"GB"|"AU") + } + } + } +} +--- multi.cue +{ + issue3638: { + full: { + routes: { + default: {} + } + routes: { + [string]: { + spec: [ + { + refs: [ + { + "default" + }, + ] + }, + ] + } + } + #Fields: { + input: _ + output: [ + for _, x in 〈1;input〉 { + 〈1;x〉 + }, + ] + ... + } + #Kubernetes: { + (〈1;#Fields〉 & { + Routes: { + route: { + [_]: { + spec!: 〈5;let HTTPROUTESPEC#1〉.#x + } + } + } + }) + 〈1;#Fields〉 + Routes: _ + input: { + res1: 〈1;Routes〉 + } + } + let HTTPROUTESPEC#1 = { + #x: ([ + ...{ + refs: [ + ...{ + string + }, + ] + }, + ]|*[ + { + other: [] + }, + ]) + } + entrypoint: 〈0;used〉.output + used: (〈0;#Kubernetes〉 & { + Routes: { + route: 〈2;routes〉 + } + }) + } + } + issue3638: { + reduced: { + input: { + k1: { + [string]: { + a: 1 + } + } + } + input: { + k1: { + foo: 〈2;#x〉 + } + } + out: { + for _, x in 〈1;input〉 { + 〈1;x〉 + } + for _, x in 〈1;input〉 { + 〈1;x〉 + } + } + #x: ({ + a: int + }|*{ + b: 2 + }) + } + } + issue3638: { + compare: { + input: { + k1: { + foo: { + a: 1 + } + } + } + input: { + k1: { + foo: 〈2;#x〉 + } + } + out: { + for _, x in 〈1;input〉 { + 〈1;x〉 + } + for _, x in 〈1;input〉 { + 〈1;x〉 + } + } + #x: ({ + a: int + }|*{ + b: 2 + }) + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/closed_disjunction.txtar b/internal/core/compile/testdata/sync/eval/closed_disjunction.txtar new file mode 100644 index 000000000..39efab7f3 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/closed_disjunction.txtar @@ -0,0 +1,40 @@ +-- in.cue -- +#A: { + b?: int + *{} | {c?: int} | {d?: int} | {e?: int} +} @test(eq, *{b?: int} | {b?: int, c?: int} | {b?: int, d?: int} | {b?: int, e?: int}) + +a: #A & { + b: 3 + c: 3 +} @test(eq, {b: 3, c: 3}) @test(closed) + +b: #A & { + c: 3 + d: 4 +} @test(err, code=eval, contains="2 errors in empty disjunction",, + suberr=(code=eval, contains="field not allowed", pos=[1:2]), + suberr=(code=eval, contains="field not allowed", pos=[2:2]) +) +-- out/compile -- +--- in.cue +{ + #A: { + b?: int + (*{}|{ + c?: int + }|{ + d?: int + }|{ + e?: int + }) + } + a: (〈0;#A〉 & { + b: 3 + c: 3 + }) + b: (〈0;#A〉 & { + c: 3 + d: 4 + }) +} diff --git a/internal/core/compile/testdata/sync/eval/closedness.txtar b/internal/core/compile/testdata/sync/eval/closedness.txtar new file mode 100644 index 000000000..4f8cfae6f --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/closedness.txtar @@ -0,0 +1,2290 @@ +// Issue #852 +-- in.cue -- +#E: { + c: int +} +#A: { + b: int + q: { + #E + d: int + } +} +a: #A & { + b: 3 + q: { + c: 2 + e: 43 + } +} @test(err, code=eval, contains="field not allowed", pos=[4:3]) + +// A constraint validation error fails to trigger when a field violating a +// regex pattern constraint is duplicated via a for-loop comprehension. +// https://cuelang.org/issue/852 +// `a` is evaluated through the comprehension first. Ensure that +// this does not bypass closedness checks. +issue852: { + #A: { + [=~"^a-z$"]: string + } + + a: #A + + a: Foo: "foo" + + for k, v in a { + b: "\(k)": v + } +} @test(err, code=eval, contains="field not allowed", pos=[7:5]) + +dynamic: { + #D: { + key: "foo" + (key): int + } + d: #D & {foo: 3} + @test(eq, { + #D: {key: "foo", foo: int} + d: {foo: 3, key: "foo"} + }) +} + +// Closedness appeared to be lost when using a comprehension: CUE incorrectly +// produced "incomplete value" errors for disjunctions inside if/for blocks. +// https://cuelang.org/issue/4180 +// The `if true` comprehension would lead to ambiguity in out.iter.FooOrBar, +// even though {foo: "is foo"} does not unify with `#Bar & {...}`. +issue4180: { + out: { + if true { + iter: #Schema & { + FooOrBar: foo: "is foo" + } + } + } + + #Foo: foo: string + #Bar: bar: string + #Schema: { + FooOrBar: {...} + FooOrBar: #Foo | #Bar + } + @test(eq, { + out: {iter: {FooOrBar: {foo: "is foo"}}} + #Foo: {foo: string} + #Bar: {bar: string} + #Schema: { + FooOrBar: {foo: string} | {bar: string} + } + }) +} +-- embed.cue -- +// evalv3: ordering of embedded structs affects template definition evaluation, +// causing validation errors that shouldn't occur when structs are reordered. +// https://cuelang.org/issue/3325 +issue3325: ok: { + #Items: [Name=string]: { + name: Name + } + + #Base: { + name: "base" + type: string + + items: #Items + } + + #Extended: #Base & { + type: "extended" + items: "my-item": {} + } + + broken: { + #Base + #Extended + } + + works: { + #Extended + #Base + } + @test(eq, { + #Items: {} + #Base: {name: "base", type: string, items: {}} + #Extended: { + type: "extended" + items: {"my-item": {name: "my-item"}} + name: "base" + } + broken: { + name: "base" + type: "extended" + items: {"my-item": {name: "my-item"}} + } + works: { + type: "extended" + items: {"my-item": {name: "my-item"}} + name: "base" + } + }) +} + +patterns: shallow: { + #a: [>="k"]: int + #b: [<="m"]: int + #c: [>="w"]: int + #d: [<="y"]: int + + single: { + X: #a // "k" <= x + err: X @test(err, code=eval, path=j, contains="field not allowed", pos=[1:8]) + err: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + + and: p1: { + X: #a & #b // "k" <= x && x <= "m" + + err: X @test(err, code=eval, path=j, contains="field not allowed", pos=[-16:6, 1:8]) + err: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + + and: p2: { + X: #b & #a // "k" <= x && x <= "m" + err: X @test(err, code=eval, path=j, contains="field not allowed", pos=[-25:6, 1:8]) + err: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + + andEmbed: p1: { + X: { #a & #b } // "k" <= x && x <= "m" + + err: X @test(err, code=eval, path=j, contains="field not allowed", pos=[-35:6, 1:8]) + err: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + + andEmbed: p2: { + X: { #b & #a } // "k" <= x && x <= "m" + err: X @test(err, code=eval, path=j, contains="field not allowed", pos=[-44:6, 1:8]) + err: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + + orEmbed: p1: { + X: { #a, #b } // "k" <= x && x <= "m" + + ok1: X @test(eq, {j: 3}) + ok1: j: 3 + + ok2: X @test(eq, {k: 3}) + ok2: k: 3 + } + + orEmbed: p2: { + X: { #b, #a } // "k" <= x && x <= "m" + ok1: X @test(eq, {j: 3}) + ok1: j: 3 + + ok2: X @test(eq, {k: 3}) + ok2: k: 3 + } + + andOrEmbed: t1: p1: { + // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") + X: { + #a & #b + #c & #d + } + err1: X @test(eq, {j: 3}) + err1: j: 3 + + ok1: X @test(eq, {k: 3}) + ok1: k: 3 + } + + andOrEmbed: t1: p2: { + // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") + X: { + #c & #d + #a & #b + } + err1: X @test(eq, {j: 3}) + err1: j: 3 + + ok1: X @test(eq, {k: 3}) + ok1: k: 3 + } + + andOrEmbed: t2: { + // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") || x == "p" + X: { + #a & #b + #c & #d + ["p"]: int + } + err1: X @test(eq, {j: 3}) + err1: j: 3 + + ok1: X @test(eq, {k: 3}) + ok1: k: 3 + + ok2: X @test(eq, {p: 3}) + ok2: p: 3 + } + + // The last indirection is not a definition. + indirect: { + a: [>="k"]: int + #a: a + + p1: { // XXX // link to code + X: #a + err1: X @test(err, code=eval, path=j, contains="field not allowed", pos=[1:10]) + err1: j: 3 + + err2: X & __no_sharing + err2: j: 3 @test(err, code=eval, contains="field not allowed", pos=[0:10]) + + ok: X + ok:k: 3 @test(eq, 3) + } + + p2: { + #a: a & __no_sharing + X: #a + + err1: X + err1: j: 3 @test(err, code=eval, contains="field not allowed", pos=[0:10]) + + err2: X & __no_sharing @test(err, code=eval, path=j, contains="field not allowed", pos=[1:10]) + err2: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + + p3: { + X: #a & __no_sharing + + err1: X @test(err, code=eval, path=j, contains="field not allowed", pos=[1:10]) + err1: j: 3 + + err2: X & __no_sharing @test(err, code=eval, path=j, contains="field not allowed", pos=[1:10]) + err2: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + + p4: { + #a: a & __no_sharing + X: #a + X: #a & __no_sharing + + err1: X @test(err, code=eval, path=j, contains="field not allowed", pos=[1:10]) + err1: j: 3 + + err2: X & __no_sharing @test(err, code=eval, path=j, contains="field not allowed", pos=[1:10]) + err2: j: 3 + + ok: X @test(eq, {k: 3}) + ok: k: 3 + } + } +} + +patterns: nested: { + #a: x: y: [>="k"]: int + #b: x: y: [<="m"]: int + #c: x: y: [>="w"]: int + #d: x: y: [<="y"]: int + + single: { + X: #a // "k" <= x + err: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:14]) + err: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + and: p1: { + X: #a & #b // "k" <= x && x <= "m" + + err: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[-16:12, 1:14]) + err: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + and: p2: { + X: #b & #a // "k" <= x && x <= "m" + err: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[-25:12, 1:14]) + err: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + andEmbed: p1: { + X: { #a & #b } // "k" <= x && x <= "m" + + err: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[-35:12, 1:14]) + err: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + andEmbed: p2: { + X: { #b & #a } // "k" <= x && x <= "m" + err: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[-44:12, 1:14]) + err: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + orEmbed: p1: { + X: { #a, #b } // "k" <= x && x <= "m" + + ok1: X @test(eq, {x: {y: {j: 3}}}) + ok1: x: y: j: 3 + + ok2: X @test(eq, {x: {y: {k: 3}}}) + ok2: x: y: k: 3 + } + + orEmbed: p2: { + X: { #b, #a } // "k" <= x && x <= "m" + ok1: X @test(eq, {x: {y: {j: 3}}}) + ok1: x: y: j: 3 + + ok2: X @test(eq, {x: {y: {k: 3}}}) + ok2: x: y: k: 3 + } + + andOrEmbed: t1: p1: { + // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") + X: { + #a & #b + #c & #d + } + err1: X @test(eq, {x: {y: {j: 3}}}) + err1: x: y: j: 3 + + ok1: X @test(eq, {x: {y: {k: 3}}}) + ok1: x: y: k: 3 + } + + andOrEmbed: t1: p2: { + // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") + X: { + #c & #d + #a & #b + } + err1: X @test(eq, {x: {y: {j: 3}}}) + err1: x: y: j: 3 + + ok1: X @test(eq, {x: {y: {k: 3}}}) + ok1: x: y: k: 3 + } + + andOrEmbed: t2: { + // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") || x == "p" + X: { + #a & #b + #c & #d + ["p"]: int + } + err1: X @test(eq, {x: {y: {j: 3}}}) + err1: x: y: j: 3 + + ok1: X @test(eq, {x: {y: {k: 3}}}) + ok1: x: y: k: 3 + + ok2: X @test(eq, {x: {y: {p: 3}}}) + ok2: x: y: p: 3 + } + + // The last indirection is not a definition. + indirect: { + a: x: y: [>="k"]: int + #a: a + + p1: { + X: #a + err1: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err1: x: y: j: 3 + + err2: X & __no_sharing @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err2: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + p2: { + #a: a & __no_sharing + X: #a + + err1: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err1: x: y: j: 3 + + err2: X & __no_sharing @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err2: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + p3: { + X: #a & __no_sharing + + err1: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err1: x: y: j: 3 + + err2: X & __no_sharing @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err2: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + + p4: { + #a: a & __no_sharing + X: #a + X: #a & __no_sharing + + err1: X @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err1: x: y: j: 3 + + err2: X & __no_sharing @test(err, code=eval, path=x.y.j, contains="field not allowed", pos=[1:16]) + err2: x: y: j: 3 + + ok: X @test(eq, {x: {y: {k: 3}}}) + ok: x: y: k: 3 + } + } +} @test(err, code=eval, contains="field not allowed", pos=[168:16]) + +// Embedding a definition doesn't recursively close the embedder: closedness +// is not propagated correctly when a definition is embedded in an open struct. +// https://cuelang.org/issue/2241 +issue2241: { + #close: {} + + a: { + x: q: 2 + #close + } + + b: a + b: x: r: 4 +} @test(err, code=eval, path=b.x.r, contains="field not allowed", pos=[9:8]) + +-- ellipsis.cue -- +// evalv3 regression: unification with {...} allowed extra fields where evalv2 +// correctly rejected them as "field not allowed". +// https://cuelang.org/issue/3778 +issue3778: full: { + #x: a?: string + #y: #x & { ... } + z: #y & { + a: "ok" + b: "something" + } + @test(err, code=eval, path=z.b, contains="field not allowed", pos=[5:3]) +} +issue3778: { + keepOpen: { + #x: { a?: string, ... } + #y: #x & { ... } + z: #y & { + a: "ok" + b: "something" + } + @test(eq, { + #x: {a?: string} + #y: {a?: string} + z: {a: "ok", b: "something"} + }) + } +} + +// Unification of a closed struct in a subfield does not close it: the evaluator +// incorrectly allows adding fields to a closed struct unified with ellipsis. +// https://cuelang.org/issue/1867 +// All three reproducers below should fail with "field not allowed". +issue1867: one: { + #T: close({}) + #T: {...} + x: #T + x: foo: "foo" + @test(err, code=eval, path=x.foo, contains="field not allowed", pos=[4:5]) +} +issue1867: two: { + #S: {} + #T: s: #S + #T: s: {...} + x: #T.s + x: foo: "foo" + @test(err, code=eval, path=x.foo, contains="field not allowed", pos=[5:5]) +} +// This third version used to not fail as expected on evalv2. +issue1867: three: { + #T: s: close({}) + #T: s: {...} + x: #T.s + x: foo: "foo" + @test(err, code=eval, contains="field not allowed", pos=[4:5]) +} +// evalv3 regression in detecting closedness: "field not allowed" errors were +// incorrectly suppressed when validating nested structures with closedness constraints. +// https://cuelang.org/issue/3924 +issue3924: one: { + #Schema: { + ... + {[string]: #SchemaInner} + } + #SchemaInner: allowed?: string + + out: #Schema & {foo: disallowed: "foo"} // should fail + @test(err, code=eval, path=out.foo.disallowed, contains="field not allowed", pos=[7:23]) +} +issue3924: two: { + #Schema: { + {[string]: #job} + + #job: matchN(1, [{ + other?: string + ... + }]) & close({ + allowed?: string + }) + } + out: #Schema & {foo: disallowed: "bar"} // should fail + @test(err, code=eval, path=out.foo.disallowed, contains="field not allowed", pos=[4:9, 11:23]) +} +issue3924: three: t1: { + {foo: #job & {disallowed: "bar"}} + #job: { other?: string } + #job: #def + #def: allowed?: string + @test(err, code=eval, path=foo.disallowed, contains="field not allowed", pos=[1:16]) +} +issue3924: three: t2: { + {foo: #job & {disallowed: "bar"}} + #job: { other?: string, ... } + #job: #def + #def: allowed?: string + @test(err, code=eval, path=foo.disallowed, contains="field not allowed", pos=[1:16]) +} +issue3924: three: t3: { + #job: { ... } + #job: #def + #def: {} + foo: #job & {disallowed: "bar"} + @test(err, code=eval, path=foo.disallowed, contains="field not allowed", pos=[4:15]) +} +issue3924: four: { + A: { {foo: #B} } + #B: allowed?: string + out: A & {foo: disallowed: "foo"} // should fail + @test(err, code=eval, contains="field not allowed", pos=[3:17]) +} +-- reroot.cue -- +import "list" + +// evalv3 panic "unexpected uninitialized node" while processing certain +// config files using list.Concat with definitions. +// https://cuelang.org/issue/3330 +issue3330: { + let: ok: { + #struct: { + let empty = {} + + field: null | { n: int } + field: empty & { n: 3 } + } + + out: list.Concat([[#struct]]) + @test(eq, { + #struct: {field: {n: 3}} + out: [{ + field: n: 3 + }] + }) + } + matthew: ok1: { + #struct: { + field: { n: 3 } & g + g: {} + } + + out: #struct & {} + @test(eq, { + #struct: {field: {n: 3}, g: {}} + out: {field: {n: 3}, g: {}} + }) + } + matthew: ok2: { + #struct: { + field: { n: 3 } & g + g: {} + } + + out: #struct + out2: out & {} + @test(eq, { + #struct: {field: {n: 3}, g: {}} + out: {field: {n: 3}, g: {}} + out2: {field: {n: 3}, g: {}} + }) + } +} +// evalv3 "field not allowed" regression: a valid struct with a let binding and +// field unification incorrectly produces "field not allowed". +// https://cuelang.org/issue/3331 +issue3331: { + original: ok: { + #A: { + let b = {} + c: b & { + d: 1 + } + } + list.Concat([[#A]]) + @test(eq, { + #A: {c: {d: 1}} + [{c: {d: 1}}] + }) + } + variant1: ok: { + #A: { + let b = {} + c: b & { + d: 1 + } + } + [[#A]] + @test(eq, { + #A: {c: {d: 1}} + [[{c: {d: 1}}]] + }) + } + @test(eq, { + original: {ok: { + #A: {c: {d: 1}} + [{c: {d: 1}}] + }} + variant1: {ok: { + #A: {c: {d: 1}} + [[{c: {d: 1}}]] + }} + }) +} + +// indirect tests cases where a reference indirectly crosses a node that +// references a definition, thereby indirectly referencing it. +indirect: { + embed: err1: { + #A: { + x: {#x, #y} + zx: x.a + } + + #x: {a: b: 1} + #y: {a: c: 2} + + b: #A + + b1: b.zx + b1: d: 1 // This should fail as b.zx crosses a reference to definition. + @test(err:todo) + @test(eq, { + #A: {x: {a: {b: 1, c: 2}}, zx: {b: 1, c: 2}} + #x: {a: {b: 1}} + #y: {a: {c: 2}} + b: {x: {a: {b: 1, c: 2}}, zx: {b: 1, c: 2}} + b1: {d: 1, b: 1, c: 2} + }) + } + closed: err1: { + X: { + // refer to a value that will be closed after unification in another struct. + a: b + b: {} + a: e: 1 + } + Y: X + Y: { + b: c + c: #X + } + #X: {} + @test(err, at=Y.a.e, code=eval, contains="field not allowed", pos=[5:7]) + } +} +// nested.a +nested: ok1: { + #A: { + b: {} + + #B: { + c: b & { + d: 1 + } + } + } + x: #A + @test(eq, { + #A: {b: {}, #B: {c: {d: 1}}} + x: {b: {}, #B: {c: {d: 1}}} + }) +} +nested: embed: ok: { + x: #A + #A: { + k + } + k: { + d: b & {e: int} + b: {} + } + @test(eq, { + x: {d: {e: int}, b: {}} + #A: {d: {e: int}, b: {}} + k: {d: {e: int}, b: {}} + }) +} +// nested.b tests insertion of a field (b) that has a conjunct rooted within +// the tree it is referred in as well as a conjunct outside of it that refers +// to a definition. +nested: err1: { + x: #A + #A: { + b: f: 1 + v: #V + #V: { + c: b & { // Fails as #B is not compatible. + d: 1 + } + } + } + x: b: #B + #B: g: 1 + @test(err, at=x.#V.c.d, code=eval, contains="field not allowed", pos=[7:5]) +} + +nested: err2: { + #A: { + b: {} // error only reported here. + c: b & { + // error (g not allowed) not reported here, as it would be okay if b + // were valid. Instead, it is reported at b only. This is conform + // the spec. + d: 1 + } + } + x: #A + x: b: g: 1 + @test(err, at=x.b.g, code=eval, contains="field not allowed", pos=[11:8]) +} + +inline: { + #x: y: z?: name: string + + // TODO: not an error!? + err1: (#x & {y: z: _}).y.z & { + name: "a" + age1: 5 // not allowed + } @test(err:todo, code=eval, contains="field not allowed") + err2: (#x.y & {z: _}).z & { + name: "a" + age2: 5 // not allowed + } @test(err:todo, code=eval, contains="field not allowed") + @test(eq, { + #x: {y: {z?: {name: string}}} + err1: {name: "a", age1: 5} + err2: {name: "a", age2: 5} + }) +} + +// minInDef defines examples where a definition is mixed into an open struct, +// where then this struct refers to a field that is closed by the definition. +mixInDef: { + refInside: { + #x: b: c: {d: {}, e: f: {} } + a: #x + a: b: c: d: {} + a: b: c: e: c.d + @test(eq, { + #x: {b: {c: {d: {}, e: {f: {}}}}} + a: {b: {c: {d: {}, e: {f: {}}}}} + }) + } + refEdge: { + #x: c: {d: {}, e: f: {} } + a: #x + a: c: d: {} + a: c: e: c.d + @test(eq, { + #x: {c: {d: {}, e: {f: {}}}} + a: {c: {d: {}, e: {f: {}}}} + }) + } + refOutside: { + #x: c: {d: {}, e: f: {} } + a: #x + a: c: d: {} + a: c: e: a.c.d // crosses definition + @test(eq, { + #x: {c: {d: {}, e: {f: {}}}} + a: {c: {d: {}, e: {f: {}}}} + }) + } +} + +// evalv3 "field not allowed" regression: out.foo.final.version incorrectly +// rejected when embedding a definition's output through a transformed struct. +// https://cuelang.org/issue/3601 +issue3601: original: { + out: { + #Transform.output + } + #Transform: output: (#Patch & {}).output + #Patch: { + target: {} + output: foo: { + final: target + final: version: "v1" + } + } + @test(eq, { + out: {foo: {final: {version: "v1"}}} + #Transform: { + output: {foo: {final: {version: "v1"}}} + } + #Patch: { + target: {} + output: {foo: {final: {version: "v1"}}} + } + }) +} +issue3601: originalNoShare: { + // Like the original, but with explicit no sharing. + out: { + #Transform.output + } + #Transform: output: (#Patch & __no_sharing).output + #Patch: { + target: {} + output: foo: { + final: target + final: version: "v1" + } + } + @test(eq, { + out: {foo: {final: {version: "v1"}}} + #Transform: { + output: {foo: {final: {version: "v1"}}} + } + #Patch: { + target: {} + output: {foo: {final: {version: "v1"}}} + } + }) +} +issue3601: reduced: { + #X: { + a: b: c: "v1" + a: b: empty + empty: {} + } + + original: { + Y: (#X & __no_sharing).a + out: Y & __no_sharing + } + moreInlining: { + out: (#X & {}).a & {} + } + noInline: { + Y: #X & __no_sharing + Z: Y & __no_sharing + out: Z.a & __no_sharing + } + moreNesting: { + #X: { + a: b: c: d: "v1" + a: b: c: empty + empty: {} + } + Y: (#X.a & __no_sharing).b + Z: Y & __no_sharing + } + @test(eq, { + #X: {a: {b: {c: "v1"}}, empty: {}} + original: {Y: {b: {c: "v1"}}, out: {b: {c: "v1"}}} + moreInlining: {out: {b: {c: "v1"}}} + noInline: { + Y: {a: {b: {c: "v1"}}, empty: {}} + Z: {a: {b: {c: "v1"}}, empty: {}} + out: {b: {c: "v1"}} + } + moreNesting: { + #X: {a: {b: {c: {d: "v1"}}}, empty: {}} + Y: {c: {d: "v1"}} + Z: {c: {d: "v1"}} + } + }) +} + +-- validation.cue -- +import "list" + +// evalv3: struct with only list.MinItems does not allow a valid list field to +// exist, reporting "field not allowed" instead of accepting it. +// https://cuelang.org/issue/3332 +issue3332: { + #def: field: list.MinItems(1) + use: #def & { + field: ["value"] + } + @test(eq, { + #def: {field: list.MinItems(1)} + use: {field: ["value"]} + }) +} + +-- out/compile -- +--- ellipsis.cue +{ + issue3778: { + full: { + #x: { + a?: string + } + #y: (〈0;#x〉 & { + ... + }) + z: (〈0;#y〉 & { + a: "ok" + b: "something" + }) + } + } + issue3778: { + keepOpen: { + #x: { + a?: string + ... + } + #y: (〈0;#x〉 & { + ... + }) + z: (〈0;#y〉 & { + a: "ok" + b: "something" + }) + } + } + issue1867: { + one: { + #T: close({}) + #T: { + ... + } + x: 〈0;#T〉 + x: { + foo: "foo" + } + } + } + issue1867: { + two: { + #S: {} + #T: { + s: 〈1;#S〉 + } + #T: { + s: { + ... + } + } + x: 〈0;#T〉.s + x: { + foo: "foo" + } + } + } + issue1867: { + three: { + #T: { + s: close({}) + } + #T: { + s: { + ... + } + } + x: 〈0;#T〉.s + x: { + foo: "foo" + } + } + } + issue3924: { + one: { + #Schema: { + ... + { + [string]: 〈2;#SchemaInner〉 + } + } + #SchemaInner: { + allowed?: string + } + out: (〈0;#Schema〉 & { + foo: { + disallowed: "foo" + } + }) + } + } + issue3924: { + two: { + #Schema: { + { + [string]: 〈1;#job〉 + } + #job: (matchN(1, [ + { + other?: string + ... + }, + ]) & close({ + allowed?: string + })) + } + out: (〈0;#Schema〉 & { + foo: { + disallowed: "bar" + } + }) + } + } + issue3924: { + three: { + t1: { + { + foo: (〈1;#job〉 & { + disallowed: "bar" + }) + } + #job: { + other?: string + } + #job: 〈0;#def〉 + #def: { + allowed?: string + } + } + } + } + issue3924: { + three: { + t2: { + { + foo: (〈1;#job〉 & { + disallowed: "bar" + }) + } + #job: { + other?: string + ... + } + #job: 〈0;#def〉 + #def: { + allowed?: string + } + } + } + } + issue3924: { + three: { + t3: { + #job: { + ... + } + #job: 〈0;#def〉 + #def: {} + foo: (〈0;#job〉 & { + disallowed: "bar" + }) + } + } + } + issue3924: { + four: { + A: { + { + foo: 〈2;#B〉 + } + } + #B: { + allowed?: string + } + out: (〈0;A〉 & { + foo: { + disallowed: "foo" + } + }) + } + } +} +--- embed.cue +{ + issue3325: { + ok: { + #Items: { + [string]: { + name: 〈1;-〉 + } + } + #Base: { + name: "base" + type: string + items: 〈1;#Items〉 + } + #Extended: (〈0;#Base〉 & { + type: "extended" + items: { + "my-item": {} + } + }) + broken: { + 〈1;#Base〉 + 〈1;#Extended〉 + } + works: { + 〈1;#Extended〉 + 〈1;#Base〉 + } + } + } + patterns: { + shallow: { + #a: { + [>="k"]: int + } + #b: { + [<="m"]: int + } + #c: { + [>="w"]: int + } + #d: { + [<="y"]: int + } + single: { + X: 〈1;#a〉 + err: 〈0;X〉 + err: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + and: { + p1: { + X: (〈2;#a〉 & 〈2;#b〉) + err: 〈0;X〉 + err: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + } + and: { + p2: { + X: (〈2;#b〉 & 〈2;#a〉) + err: 〈0;X〉 + err: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + } + andEmbed: { + p1: { + X: { + (〈3;#a〉 & 〈3;#b〉) + } + err: 〈0;X〉 + err: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + } + andEmbed: { + p2: { + X: { + (〈3;#b〉 & 〈3;#a〉) + } + err: 〈0;X〉 + err: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + } + orEmbed: { + p1: { + X: { + 〈3;#a〉 + 〈3;#b〉 + } + ok1: 〈0;X〉 + ok1: { + j: 3 + } + ok2: 〈0;X〉 + ok2: { + k: 3 + } + } + } + orEmbed: { + p2: { + X: { + 〈3;#b〉 + 〈3;#a〉 + } + ok1: 〈0;X〉 + ok1: { + j: 3 + } + ok2: 〈0;X〉 + ok2: { + k: 3 + } + } + } + andOrEmbed: { + t1: { + p1: { + X: { + (〈4;#a〉 & 〈4;#b〉) + (〈4;#c〉 & 〈4;#d〉) + } + err1: 〈0;X〉 + err1: { + j: 3 + } + ok1: 〈0;X〉 + ok1: { + k: 3 + } + } + } + } + andOrEmbed: { + t1: { + p2: { + X: { + (〈4;#c〉 & 〈4;#d〉) + (〈4;#a〉 & 〈4;#b〉) + } + err1: 〈0;X〉 + err1: { + j: 3 + } + ok1: 〈0;X〉 + ok1: { + k: 3 + } + } + } + } + andOrEmbed: { + t2: { + X: { + (〈3;#a〉 & 〈3;#b〉) + (〈3;#c〉 & 〈3;#d〉) + ["p"]: int + } + err1: 〈0;X〉 + err1: { + j: 3 + } + ok1: 〈0;X〉 + ok1: { + k: 3 + } + ok2: 〈0;X〉 + ok2: { + p: 3 + } + } + } + indirect: { + a: { + [>="k"]: int + } + #a: 〈0;a〉 + p1: { + X: 〈1;#a〉 + err1: 〈0;X〉 + err1: { + j: 3 + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + p2: { + #a: (〈1;a〉 & _|_(no sharing)) + X: 〈0;#a〉 + err1: 〈0;X〉 + err1: { + j: 3 + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + p3: { + X: (〈1;#a〉 & _|_(no sharing)) + err1: 〈0;X〉 + err1: { + j: 3 + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + p4: { + #a: (〈1;a〉 & _|_(no sharing)) + X: 〈0;#a〉 + X: (〈0;#a〉 & _|_(no sharing)) + err1: 〈0;X〉 + err1: { + j: 3 + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + j: 3 + } + ok: 〈0;X〉 + ok: { + k: 3 + } + } + } + } + } + patterns: { + nested: { + #a: { + x: { + y: { + [>="k"]: int + } + } + } + #b: { + x: { + y: { + [<="m"]: int + } + } + } + #c: { + x: { + y: { + [>="w"]: int + } + } + } + #d: { + x: { + y: { + [<="y"]: int + } + } + } + single: { + X: 〈1;#a〉 + err: 〈0;X〉 + err: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + and: { + p1: { + X: (〈2;#a〉 & 〈2;#b〉) + err: 〈0;X〉 + err: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + } + and: { + p2: { + X: (〈2;#b〉 & 〈2;#a〉) + err: 〈0;X〉 + err: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + } + andEmbed: { + p1: { + X: { + (〈3;#a〉 & 〈3;#b〉) + } + err: 〈0;X〉 + err: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + } + andEmbed: { + p2: { + X: { + (〈3;#b〉 & 〈3;#a〉) + } + err: 〈0;X〉 + err: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + } + orEmbed: { + p1: { + X: { + 〈3;#a〉 + 〈3;#b〉 + } + ok1: 〈0;X〉 + ok1: { + x: { + y: { + j: 3 + } + } + } + ok2: 〈0;X〉 + ok2: { + x: { + y: { + k: 3 + } + } + } + } + } + orEmbed: { + p2: { + X: { + 〈3;#b〉 + 〈3;#a〉 + } + ok1: 〈0;X〉 + ok1: { + x: { + y: { + j: 3 + } + } + } + ok2: 〈0;X〉 + ok2: { + x: { + y: { + k: 3 + } + } + } + } + } + andOrEmbed: { + t1: { + p1: { + X: { + (〈4;#a〉 & 〈4;#b〉) + (〈4;#c〉 & 〈4;#d〉) + } + err1: 〈0;X〉 + err1: { + x: { + y: { + j: 3 + } + } + } + ok1: 〈0;X〉 + ok1: { + x: { + y: { + k: 3 + } + } + } + } + } + } + andOrEmbed: { + t1: { + p2: { + X: { + (〈4;#c〉 & 〈4;#d〉) + (〈4;#a〉 & 〈4;#b〉) + } + err1: 〈0;X〉 + err1: { + x: { + y: { + j: 3 + } + } + } + ok1: 〈0;X〉 + ok1: { + x: { + y: { + k: 3 + } + } + } + } + } + } + andOrEmbed: { + t2: { + X: { + (〈3;#a〉 & 〈3;#b〉) + (〈3;#c〉 & 〈3;#d〉) + ["p"]: int + } + err1: 〈0;X〉 + err1: { + x: { + y: { + j: 3 + } + } + } + ok1: 〈0;X〉 + ok1: { + x: { + y: { + k: 3 + } + } + } + ok2: 〈0;X〉 + ok2: { + x: { + y: { + p: 3 + } + } + } + } + } + indirect: { + a: { + x: { + y: { + [>="k"]: int + } + } + } + #a: 〈0;a〉 + p1: { + X: 〈1;#a〉 + err1: 〈0;X〉 + err1: { + x: { + y: { + j: 3 + } + } + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + p2: { + #a: (〈1;a〉 & _|_(no sharing)) + X: 〈0;#a〉 + err1: 〈0;X〉 + err1: { + x: { + y: { + j: 3 + } + } + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + p3: { + X: (〈1;#a〉 & _|_(no sharing)) + err1: 〈0;X〉 + err1: { + x: { + y: { + j: 3 + } + } + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + p4: { + #a: (〈1;a〉 & _|_(no sharing)) + X: 〈0;#a〉 + X: (〈0;#a〉 & _|_(no sharing)) + err1: 〈0;X〉 + err1: { + x: { + y: { + j: 3 + } + } + } + err2: (〈0;X〉 & _|_(no sharing)) + err2: { + x: { + y: { + j: 3 + } + } + } + ok: 〈0;X〉 + ok: { + x: { + y: { + k: 3 + } + } + } + } + } + } + } + issue2241: { + #close: {} + a: { + x: { + q: 2 + } + 〈1;#close〉 + } + b: 〈0;a〉 + b: { + x: { + r: 4 + } + } + } +} +--- in.cue +{ + #E: { + c: int + } + #A: { + b: int + q: { + 〈2;#E〉 + d: int + } + } + a: (〈0;#A〉 & { + b: 3 + q: { + c: 2 + e: 43 + } + }) + issue852: { + #A: { + [=~"^a-z$"]: string + } + a: 〈0;#A〉 + a: { + Foo: "foo" + } + for k, v in 〈0;a〉 { + b: { + "\(〈2;k〉)": 〈2;v〉 + } + } + } + dynamic: { + #D: { + key: "foo" + 〈0;key〉: int + } + d: (〈0;#D〉 & { + foo: 3 + }) + } + issue4180: { + out: { + if true { + iter: (〈2;#Schema〉 & { + FooOrBar: { + foo: "is foo" + } + }) + } + } + #Foo: { + foo: string + } + #Bar: { + bar: string + } + #Schema: { + FooOrBar: { + ... + } + FooOrBar: (〈1;#Foo〉|〈1;#Bar〉) + } + } +} +--- reroot.cue +{ + issue3330: { + let: { + ok: { + #struct: { + let empty#1 = {} + field: (null|{ + n: int + }) + field: (〈0;let empty#1〉 & { + n: 3 + }) + } + out: 〈import;list〉.Concat([ + [ + 〈2;#struct〉, + ], + ]) + } + } + matthew: { + ok1: { + #struct: { + field: ({ + n: 3 + } & 〈0;g〉) + g: {} + } + out: (〈0;#struct〉 & {}) + } + } + matthew: { + ok2: { + #struct: { + field: ({ + n: 3 + } & 〈0;g〉) + g: {} + } + out: 〈0;#struct〉 + out2: (〈0;out〉 & {}) + } + } + } + issue3331: { + original: { + ok: { + #A: { + let b#2 = {} + c: (〈0;let b#2〉 & { + d: 1 + }) + } + 〈import;list〉.Concat([ + [ + 〈2;#A〉, + ], + ]) + } + } + variant1: { + ok: { + #A: { + let b#3 = {} + c: (〈0;let b#3〉 & { + d: 1 + }) + } + [ + [ + 〈2;#A〉, + ], + ] + } + } + } + indirect: { + embed: { + err1: { + #A: { + x: { + 〈2;#x〉 + 〈2;#y〉 + } + zx: 〈0;x〉.a + } + #x: { + a: { + b: 1 + } + } + #y: { + a: { + c: 2 + } + } + b: 〈0;#A〉 + b1: 〈0;b〉.zx + b1: { + d: 1 + } + } + } + closed: { + err1: { + X: { + a: 〈0;b〉 + b: {} + a: { + e: 1 + } + } + Y: 〈0;X〉 + Y: { + b: 〈0;c〉 + c: 〈1;#X〉 + } + #X: {} + } + } + } + nested: { + ok1: { + #A: { + b: {} + #B: { + c: (〈1;b〉 & { + d: 1 + }) + } + } + x: 〈0;#A〉 + } + } + nested: { + embed: { + ok: { + x: 〈0;#A〉 + #A: { + 〈1;k〉 + } + k: { + d: (〈0;b〉 & { + e: int + }) + b: {} + } + } + } + } + nested: { + err1: { + x: 〈0;#A〉 + #A: { + b: { + f: 1 + } + v: 〈0;#V〉 + #V: { + c: (〈1;b〉 & { + d: 1 + }) + } + } + x: { + b: 〈1;#B〉 + } + #B: { + g: 1 + } + } + } + nested: { + err2: { + #A: { + b: {} + c: (〈0;b〉 & { + d: 1 + }) + } + x: 〈0;#A〉 + x: { + b: { + g: 1 + } + } + } + } + inline: { + #x: { + y: { + z?: { + name: string + } + } + } + err1: ((〈0;#x〉 & { + y: { + z: _ + } + }).y.z & { + name: "a" + age1: 5 + }) + err2: ((〈0;#x〉.y & { + z: _ + }).z & { + name: "a" + age2: 5 + }) + } + mixInDef: { + refInside: { + #x: { + b: { + c: { + d: {} + e: { + f: {} + } + } + } + } + a: 〈0;#x〉 + a: { + b: { + c: { + d: {} + } + } + } + a: { + b: { + c: { + e: 〈1;c〉.d + } + } + } + } + refEdge: { + #x: { + c: { + d: {} + e: { + f: {} + } + } + } + a: 〈0;#x〉 + a: { + c: { + d: {} + } + } + a: { + c: { + e: 〈1;c〉.d + } + } + } + refOutside: { + #x: { + c: { + d: {} + e: { + f: {} + } + } + } + a: 〈0;#x〉 + a: { + c: { + d: {} + } + } + a: { + c: { + e: 〈2;a〉.c.d + } + } + } + } + issue3601: { + original: { + out: { + 〈1;#Transform〉.output + } + #Transform: { + output: (〈1;#Patch〉 & {}).output + } + #Patch: { + target: {} + output: { + foo: { + final: 〈2;target〉 + final: { + version: "v1" + } + } + } + } + } + } + issue3601: { + originalNoShare: { + out: { + 〈1;#Transform〉.output + } + #Transform: { + output: (〈1;#Patch〉 & _|_(no sharing)).output + } + #Patch: { + target: {} + output: { + foo: { + final: 〈2;target〉 + final: { + version: "v1" + } + } + } + } + } + } + issue3601: { + reduced: { + #X: { + a: { + b: { + c: "v1" + } + } + a: { + b: 〈1;empty〉 + } + empty: {} + } + original: { + Y: (〈1;#X〉 & _|_(no sharing)).a + out: (〈0;Y〉 & _|_(no sharing)) + } + moreInlining: { + out: ((〈1;#X〉 & {}).a & {}) + } + noInline: { + Y: (〈1;#X〉 & _|_(no sharing)) + Z: (〈0;Y〉 & _|_(no sharing)) + out: (〈0;Z〉.a & _|_(no sharing)) + } + moreNesting: { + #X: { + a: { + b: { + c: { + d: "v1" + } + } + } + a: { + b: { + c: 〈2;empty〉 + } + } + empty: {} + } + Y: (〈0;#X〉.a & _|_(no sharing)).b + Z: (〈0;Y〉 & _|_(no sharing)) + } + } + } +} +--- validation.cue +{ + issue3332: { + #def: { + field: 〈import;list〉.MinItems(1) + } + use: (〈0;#def〉 & { + field: [ + "value", + ] + }) + } +} diff --git a/internal/core/compile/testdata/sync/eval/comprehensions.txtar b/internal/core/compile/testdata/sync/eval/comprehensions.txtar new file mode 100644 index 000000000..2b522efc2 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/comprehensions.txtar @@ -0,0 +1,311 @@ +// Tests comprehension evaluation including for-loop filters, let bindings in +// comprehensions, if-conditioned field insertions, and field-match ordering +// in structs. Also covers panic fixes for nested comprehensions with pattern +// constraints (issue 3691). +-- in.cue -- +import "strings" + +a: {x: 10, y: 100, z: 50} @test(eq, {x: 10, y: 100, z: 50}) +b: { + for k, v in a if v <= 50 { + "\(k)": v + } + x: int + if x > 3 { + k: 20 + } + k: int + if k > 0 { + l: 40 + } + @test(eq, {x: 10, k: 20, l: 40, z: 50}) +} + +c: { + for k, v in a let y = v + 10 if y > 50 { + "\(k)": y + } + @test(eq, {y: 110, z: 60}) +} + +A: { + X: run: "dfoo" + @test(eq, {X: {run: "dfoo", files: "dfoo"}}) +} + +if true { + A: X: { + run: string + files: "\(strings.Join([ run], "\n"))" + } +} + +matchOrder: { + a1: { + out: [string]: Val: 1 + out: in.a + + in: a: { + if true { + b: {} + } + } + @test(eq, {out: {b: {Val: 1}}, in: {a: {b: {}}}}) + } + a2: { + out: [string]: Val: 1 + + in: a: { + if true { + b: {} + } + } + + out: in.a + @test(eq, {out: {b: {Val: 1}}, in: {a: {b: {}}}}) + } + a3: { + + in: a: { + if true { + b: {} + } + } + + out: [string]: Val: 1 + out: in.a + @test(eq, {in: {a: {b: {}}}, out: {b: {Val: 1}}}) + } + a4: { + out: in.a + out: [string]: Val: 1 + + in: a: { + if true { + b: {} + } + } + @test(eq, {out: {b: {Val: 1}}, in: {a: {b: {}}}}) + } + a5: { + out: in.a + + in: a: { + if true { + b: {} + } + } + + out: [string]: Val: 1 + @test(eq, {out: {b: {Val: 1}}, in: {a: {b: {}}}}) + } + a6: { + in: a: { + if true { + b: {} + } + } + + out: in.a + out: [string]: Val: 1 + @test(eq, {in: {a: {b: {}}}, out: {b: {Val: 1}}}) + } +} +-- issue3691.cue -- +// evalv3 panic: incDependent "already closed" when processing conditional +// field definitions inside a comprehension with nested object structures. +// https://cuelang.org/issue/3691 +// Ensure that parent nodes are properly processed, even when a pending arc +// is evaluated early. +issue3691: original: { + X: [string]: string + a: [string]: X + a: { + if true { + b: c: 1 + } + } + @test(err, code=eval, at=a.b.c, contains="conflicting values", args=[string, 1], pos=[1:15, 2:15, 3:5, 4:3, 5:10]) +} +// Structural cycles follow a different code path. +issue3691: structuralCycle: { + X: [string]: string + a: [string]: X + a: { + if true { + b: c: a + } + } + @test(err, code=eval, at=a.b.c, contains="conflicting values", pos=[1:15, 2:5, 2:15, 3:5, 4:3, 5:10]) +} +-- out/compile -- +--- in.cue +{ + a: { + x: 10 + y: 100 + z: 50 + } + b: { + for k, v in 〈1;a〉 if (〈0;v〉 <= 50) { + "\(〈1;k〉)": 〈1;v〉 + } + x: int + if (〈0;x〉 > 3) { + k: 20 + } + k: int + if (〈0;k〉 > 0) { + l: 40 + } + } + c: { + for k, v in 〈1;a〉 let y = (〈0;v〉 + 10) if (〈0;y〉 > 50) { + "\(〈2;k〉)": 〈1;y〉 + } + } + A: { + X: { + run: "dfoo" + } + } + if true { + A: { + X: { + run: string + files: "\(〈import;strings〉.Join([ + 〈1;run〉, + ], "\n"))" + } + } + } + matchOrder: { + a1: { + out: { + [string]: { + Val: 1 + } + } + out: 〈0;in〉.a + in: { + a: { + if true { + b: {} + } + } + } + } + a2: { + out: { + [string]: { + Val: 1 + } + } + in: { + a: { + if true { + b: {} + } + } + } + out: 〈0;in〉.a + } + a3: { + in: { + a: { + if true { + b: {} + } + } + } + out: { + [string]: { + Val: 1 + } + } + out: 〈0;in〉.a + } + a4: { + out: 〈0;in〉.a + out: { + [string]: { + Val: 1 + } + } + in: { + a: { + if true { + b: {} + } + } + } + } + a5: { + out: 〈0;in〉.a + in: { + a: { + if true { + b: {} + } + } + } + out: { + [string]: { + Val: 1 + } + } + } + a6: { + in: { + a: { + if true { + b: {} + } + } + } + out: 〈0;in〉.a + out: { + [string]: { + Val: 1 + } + } + } + } +} +--- issue3691.cue +{ + issue3691: { + original: { + X: { + [string]: string + } + a: { + [string]: 〈1;X〉 + } + a: { + if true { + b: { + c: 1 + } + } + } + } + } + issue3691: { + structuralCycle: { + X: { + [string]: string + } + a: { + [string]: 〈1;X〉 + } + a: { + if true { + b: { + c: 〈3;a〉 + } + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/conflicts.txtar b/internal/core/compile/testdata/sync/eval/conflicts.txtar new file mode 100644 index 000000000..dbc863137 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/conflicts.txtar @@ -0,0 +1,54 @@ +-- in.cue -- +i: int +s: string + +t0: { + @test(err, code=eval, at=v, + contains="conflicting values", + args=[int, string], + pos=[-3:4, -2:4, 5:5, 5:9]) + v: i & s +} + +t1: { + @test(err, code=eval, at=x.a.b, + contains="conflicting values", + args=[3, 4], + pos=[6:9, 10:9, 13:5, 13:11]) + #d1: { + a: b: 3 + } + + #d2: { + a: b: 4 + } + + x: #d1 & #d2 + @test(eq, { + #d1: a: b: 3 + #d2: a: b: 4 + x: a: b: _|_ + }) +} +-- out/compile -- +--- in.cue +{ + i: int + s: string + t0: { + v: (〈1;i〉 & 〈1;s〉) + } + t1: { + #d1: { + a: { + b: 3 + } + } + #d2: { + a: { + b: 4 + } + } + x: (〈0;#d1〉 & 〈0;#d2〉) + } +} diff --git a/internal/core/compile/testdata/sync/eval/conjuncts.txtar b/internal/core/compile/testdata/sync/eval/conjuncts.txtar new file mode 100644 index 000000000..92e2bd1ad --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/conjuncts.txtar @@ -0,0 +1,189 @@ +// These tests are related to issue 2351. +// Tests conjunct unification with disjunctions and comprehensions, including +// regression fixes for undefined field errors (issue 2351) and cycle errors +// (issue 2355) in the v3 evaluator. +-- in.cue -- + +conjunct: t1: ({ + #early: *"X" | string + #early +} & { + #early: *"X" | string + string +}) @test(eq, *{"X", #early: *"X" | string} | {string, #early: *"X" | string}) + +conjunct: t2: { + #early: *"X" | string + #early +} +conjunct: t2: { + #early: *"X" | string + string +} @test(eq, *{"X", #early: *"X" | string} | {string, #early: *"X" | string}) + +conjunct: t3: (conjunct.t1 & conjunct.t2) @test(eq, *{"X", #early: *"X" | string} | {string, #early: *"X" | string}) + +handleComprehensions: { + if false { + subs: #sub2 & 2 + } + #sub2: 2 + @test(eq, {#sub2: 2}) +} + +-- issue2351.cue -- +// Regression between v0.4.3 and v0.5.0: "undefined field" error when embedding +// a for comprehension, caused by incorrect error reporting for let/hidden fields. +// https://cuelang.org/issue/2351 +issue2351: let: { + let _param = "foo" + ({ + param: _param & [{}] + gen: [for p in param {p}] + }).gen + @test(err, code=eval, contains="conflicting values", pos=[0:17, 1:15, 2:2, 3:10, 3:19]) +} + +issue2351: hidden: { + _in1: ["foo"] + { + in2: _in1 + out: [for x in in2 {x}] + }.out + @test(skip, hint="TODO(inline): allow ignoring hidden values.") + @test(eq:todo, { + @test(final) + ["foo"] + }) +} + +-- issue2355.cue -- +// Regression v0.4.3→v0.5.0: cycle error when using let fields within nested +// struct embeddings, breaking previously working code. +// https://cuelang.org/issue/2355 +issue2355: { + #GetF1: { + in: _ + out: in.f1 @test(err, code=incomplete, contains="%s undefined as %s is incomplete (type %s)", args=[in.f1, in, _], pos=[0:8]) + } + + #PutOut1: { + in: _ + out: out1: "\(in)" @test(err, code=incomplete, contains="invalid interpolation", pos=[0:14]) + } + + export: { + let data = {f1: "foo"} + (#PutOut1 & { + in: (#GetF1 & { + in: data + }).out + }).out + } + @test(eq, { + #GetF1: { + in: _ + out: _|_ + } + #PutOut1: { + in: _ + out: { + out1: _|_ + } + } + export: {out1: "foo"} + }) +} + +-- out/compile -- +--- in.cue +{ + conjunct: { + t1: ({ + #early: (*"X"|string) + 〈0;#early〉 + } & { + #early: (*"X"|string) + string + }) + } + conjunct: { + t2: { + #early: (*"X"|string) + 〈0;#early〉 + } + } + conjunct: { + t2: { + #early: (*"X"|string) + string + } + } + conjunct: { + t3: (〈1;conjunct〉.t1 & 〈1;conjunct〉.t2) + } + handleComprehensions: { + if false { + subs: (〈1;#sub2〉 & 2) + } + #sub2: 2 + } +} +--- issue2351.cue +{ + issue2351: { + let: { + let _param#1 = "foo" + { + param: (〈1;let _param#1〉 & [ + {}, + ]) + gen: [ + for _, p in 〈1;param〉 { + 〈1;p〉 + }, + ] + }.gen + } + } + issue2351: { + hidden: { + _in1: [ + "foo", + ] + { + in2: 〈1;_in1〉 + out: [ + for _, x in 〈1;in2〉 { + 〈1;x〉 + }, + ] + }.out + } + } +} +--- issue2355.cue +{ + issue2355: { + #GetF1: { + in: _ + out: 〈0;in〉.f1 + } + #PutOut1: { + in: _ + out: { + out1: "\(〈1;in〉)" + } + } + export: { + let data#2 = { + f1: "foo" + } + (〈1;#PutOut1〉 & { + in: (〈2;#GetF1〉 & { + in: 〈2;let data#2〉 + }).out + }).out + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/counters.txtar b/internal/core/compile/testdata/sync/eval/counters.txtar new file mode 100644 index 000000000..87a076954 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/counters.txtar @@ -0,0 +1,316 @@ +// Tests various evaluator stability fixes: panic in recursive disjunctions with +// list.FlattenN (issue3750), negative reference counter panic with pattern +// constraints and comprehensions (issue3780), fields dropped by for loop in let +// binding with disjunction (issue3770), and unexpected uninitialized node panic +// with if comprehensions and list comprehensions (issue3824). +-- issue3750.cue -- +package p + +import "list" + +// evalv3 panic "incDependent: already closed" triggered by recursive +// disjunctions combined with list.FlattenN comprehensions. +// https://cuelang.org/issue/3750 +issue3750: original: { + out: #Foo & { + sub: #Foo + } + + #Foo: { + sub: #Foo | #Bar + meta: { + strs: [...string] + for _, w in list.FlattenN([strs], 1) {} + } + } + + + #Bar: { + kind: "bar" + meta: strs: [...string] + } + @test(eq, { + out: { + sub: { + sub: { + sub: { + sub: {kind: "bar", meta: {strs: []}} + meta: {strs: []} + } |{kind: "bar", meta: {strs: []}} + meta: {strs: []} + } | {kind: "bar", meta: {strs: []}} + meta: {strs: []} + } + meta: {strs: []} + } + #Foo: { + sub: {kind: "bar", meta: {strs: []}} + meta: {strs: []} + } + #Bar: {kind: "bar", meta: {strs: []}} + }) +} + +issue3750: reduced: { + out: Foo & { sub: Foo } + + Foo: { + sub: Foo | {a: b: _} + a: { + b: _ + for _, w in list.FlattenN([b], 1) {} + } + } + @test(eq, { + out: { + sub: { + sub: {sub: {sub: {a: {b: _}}, a: {b: _}} | {a: {b: _}}, a: {b: _}} | {a: {b: _}} + a: {b: _} + } + a: {b: _} + } + Foo: {sub: {a: {b: _}}, a: {b: _}} + }) +} +-- issue3780.cue -- +import "strings" + +// evalv3 "negative reference counter" panic when combining pattern +// constraints with comprehensions and conditional logic. +// https://cuelang.org/issue/3780 +issue3780: panic1: { + objs: #Objects & {} + param!: bool + if param { + objs: obj1: { + one: 1 + two: 2 + } + } + #Objects: [strings.HasPrefix("obj")]: { + kind: "object" + ... + } + @test(err, code=incomplete, hint="required field missing: param") +} +issue3780: panic2: { + parent: { + objs: #Objects & {} + param?: bool + if param != _|_ { + objs: obj1: { + one: 1 + two: 2 + } + } + #Objects: [strings.HasPrefix("obj")]: { + kind: "object" + ... + } + } + @test(eq, { + parent: {objs: {}, param?: bool, #Objects: {}} + }) +} +-- issue3770.cue -- +// evalv3 regression: fields generated by a for loop in a let binding were +// dropped after unifying with a disjunctive type constraint. +// https://cuelang.org/issue/3770 +issue3770: task: { + m: { + let t = ["x"] + for m in t { + (m): a: 1 + } + x: b: 1 + } + m: null | { } + out: m.x.a + @test(eq, {m: {x: {b: 1, a: 1}}, out: 1}) +} +-- issue3824.cue -- +// evalv3 panic: "unexpected uninitialized node" when combining if comprehensions +// with list comprehensions and disjunctive type constraints. +// https://cuelang.org/issue/3824 +issue3824: panic: { + thing: { + spec: name: string + outputField: string + } + + val: string + things: [_]: thing + + things: [_]: { + spec: *{ + name: "self-signed" + } | {...} + } + + if true { + things: "name": {} + val: things["name"].outputField + } + @test(eq, { + thing: { + spec: {name: string} + outputField: string + } + val: string + things: { + name: { + spec: *{name: "self-signed"} | {name: string} + outputField: string + } + } + }) +} +-- out/compile -- +--- issue3750.cue +{ + issue3750: { + original: { + out: (〈0;#Foo〉 & { + sub: 〈1;#Foo〉 + }) + #Foo: { + sub: (〈1;#Foo〉|〈1;#Bar〉) + meta: { + strs: [ + ...string, + ] + for _, w in 〈import;list〉.FlattenN([ + 〈1;strs〉, + ], 1) {} + } + } + #Bar: { + kind: "bar" + meta: { + strs: [ + ...string, + ] + } + } + } + } + issue3750: { + reduced: { + out: (〈0;Foo〉 & { + sub: 〈1;Foo〉 + }) + Foo: { + sub: (〈1;Foo〉|{ + a: { + b: _ + } + }) + a: { + b: _ + for _, w in 〈import;list〉.FlattenN([ + 〈1;b〉, + ], 1) {} + } + } + } + } +} +--- issue3770.cue +{ + issue3770: { + task: { + m: { + let t#1 = [ + "x", + ] + for _, m in 〈0;let t#1〉 { + 〈1;m〉: { + a: 1 + } + } + x: { + b: 1 + } + } + m: (null|{}) + out: 〈0;m〉.x.a + } + } +} +--- issue3780.cue +{ + issue3780: { + panic1: { + objs: (〈0;#Objects〉 & {}) + param!: bool + if 〈0;param〉 { + objs: { + obj1: { + one: 1 + two: 2 + } + } + } + #Objects: { + [〈import;strings〉.HasPrefix("obj")]: { + kind: "object" + ... + } + } + } + } + issue3780: { + panic2: { + parent: { + objs: (〈0;#Objects〉 & {}) + param?: bool + if (〈0;param〉 != _|_(explicit error (_|_ literal) in source)) { + objs: { + obj1: { + one: 1 + two: 2 + } + } + } + #Objects: { + [〈import;strings〉.HasPrefix("obj")]: { + kind: "object" + ... + } + } + } + } + } +} +--- issue3824.cue +{ + issue3824: { + panic: { + thing: { + spec: { + name: string + } + outputField: string + } + val: string + things: { + [_]: 〈1;thing〉 + } + things: { + [_]: { + spec: (*{ + name: "self-signed" + }|{ + ... + }) + } + } + if true { + things: { + name: {} + } + val: 〈0;things〉["name"].outputField + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/cycles_ref.txtar b/internal/core/compile/testdata/sync/eval/cycles_ref.txtar new file mode 100644 index 000000000..38ed4184c --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/cycles_ref.txtar @@ -0,0 +1,24 @@ +-- in.cue -- +a: b + 100 @test(eq, 200) +b: a - 100 @test(eq, 100) +a: 200 + +c: d & {b: 2} @test(eq, {a: 1, b: 2}) +d: e @test(eq, {a: 1, b: 2}) +e: {a: 1} @test(eq, {a: 1, b: 2}) +e: c +-- out/compile -- +--- in.cue +{ + a: (〈0;b〉 + 100) + b: (〈0;a〉 - 100) + a: 200 + c: (〈0;d〉 & { + b: 2 + }) + d: 〈0;e〉 + e: { + a: 1 + } + e: 〈0;c〉 +} diff --git a/internal/core/compile/testdata/sync/eval/deref.txtar b/internal/core/compile/testdata/sync/eval/deref.txtar new file mode 100644 index 000000000..58415a40c --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/deref.txtar @@ -0,0 +1,89 @@ +-- in.cue -- +issue4011: full: { + let _hugoEnvironments = { + default: "_default" + production: "production" + } + + site: cls: _ + site: [_]: { + fs: { + Create: { + for envID, envName in _hugoEnvironments + let envConfig = hugo[envID] + if envConfig != _|_ { + config: Contents: envConfig + } + } + } + + hugo: _ + } + + site: [_]: hugo: production: {} + @test(eq, {site: cls: { + fs: Create: config: Contents: {} + hugo: production: {} + }}) +} +issue4011: reduced: { + @test(eq, {result: foo: true, envs: foo: {}}) + result: { + for envName in ["foo"] + let env = envs[envName] + if env != _|_ { + (envName): true + } + } + envs: foo: {} +} +-- out/compile -- +--- in.cue +{ + issue4011: { + full: { + let _hugoEnvironments#1 = { + default: "_default" + production: "production" + } + site: { + cls: _ + } + site: { + [_]: { + fs: { + Create: { + for envID, envName in 〈4;let _hugoEnvironments#1〉 let envConfig = 〈3;hugo〉[〈0;envID〉] if (〈0;envConfig〉 != _|_(explicit error (_|_ literal) in source)) { + config: { + Contents: 〈2;envConfig〉 + } + } + } + } + hugo: _ + } + } + site: { + [_]: { + hugo: { + production: {} + } + } + } + } + } + issue4011: { + reduced: { + result: { + for _, envName in [ + "foo", + ] let env = 〈2;envs〉[〈0;envName〉] if (〈0;env〉 != _|_(explicit error (_|_ literal) in source)) { + 〈2;envName〉: true + } + } + envs: { + foo: {} + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/discontinuous.txtar b/internal/core/compile/testdata/sync/eval/discontinuous.txtar new file mode 100644 index 000000000..94fd97b92 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/discontinuous.txtar @@ -0,0 +1,51 @@ +This test tests a case where a child node needs to be evaluated +before evaluating a parent has completed. +-- in.cue -- +a: [for c in foo.bar.baz { + c +}] + +a: [{name: "http"}] @test(eq, [{name: "http", port: 8080}]) + +foo: { + x.D + + bar: baz: [{port: 8080}] + @test(eq, {bar: {baz: [{port: 8080}]}}) +} + +x: { + D: bar: DSpec + DSpec: {} + @test(eq, {D: bar: {}, DSpec: {}}) +} +-- out/compile -- +--- in.cue +{ + a: [ + for _, c in 〈1;foo〉.bar.baz { + 〈1;c〉 + }, + ] + a: [ + { + name: "http" + }, + ] + foo: { + 〈1;x〉.D + bar: { + baz: [ + { + port: 8080 + }, + ] + } + } + x: { + D: { + bar: 〈1;DSpec〉 + } + DSpec: {} + } +} diff --git a/internal/core/compile/testdata/sync/eval/disjselfcycle.txtar b/internal/core/compile/testdata/sync/eval/disjselfcycle.txtar new file mode 100644 index 000000000..b412fcc70 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/disjselfcycle.txtar @@ -0,0 +1,174 @@ +-- in.cue -- +-- comprehensions.cue -- +// Panic "vertex not initialized" in v0.14.0+ with recursive comprehensions +// referencing a field being defined, particularly across subdirectories. +// https://cuelang.org/issue/4119 +issue4119: reduced: { + x: [...] + x: _ | *[{f: 123}] + x: [ + for i in x { + f: i.f + } + ] + @test(eq, {x: *[{ + f: 123 + }] | []}) +} +// This test is added to test the memory management bug isn't triggered +// one level deeper. This test is expected to fail, as it now triggers +// a structural cycle in the right disjunct, leaving an incomplete error +// on the left disjunct. +issue4119: reducedNested: { + x: {y: [...]} + x: {y: _} | *{y: [{f: 123}]} + x: {y: [ + for i in x { + f: i.f + } + ]} + @test(err, code=eval, path=x.y.0.f, contains="undefined field: %s", args=[f], pos=[5:9]) +} +issue4119: full: { + _img: img={ + val: string + accounts: { + groups: img.accounts.groups | *[{gid: 65532}] + + // Recursive comprehension - this triggers the bug + groups: [ + for g in groups + let _gid = g.gid { + gid: [ + if _gid != _|_ {_gid}, + 65532, + ][0] + }, + ] + } + } + + art: { + images: [string]: #Image + for k, v in images { + images: (k): _img & v + } + } + #Image: { + val: string + accounts?: { + groups?: [...] + } + } + art: images: ko: { + val: "test" + } + @test(eq, { + _img: { + val: string + accounts: {groups: [{ gid: 65532 }]} + } + art: images: ko: { + val: "test" + accounts: {groups: *[{ gid: 65532 }] | []} + } + #Image: {val: string, accounts?: groups?: []} + }) +} +-- out/compile -- +--- comprehensions.cue +{ + issue4119: { + reduced: { + x: [ + ..., + ] + x: (_|*[ + { + f: 123 + }, + ]) + x: [ + for _, i in 〈1;x〉 { + f: 〈1;i〉.f + }, + ] + } + } + issue4119: { + reducedNested: { + x: { + y: [ + ..., + ] + } + x: ({ + y: _ + }|*{ + y: [ + { + f: 123 + }, + ] + }) + x: { + y: [ + for _, i in 〈2;x〉 { + f: 〈1;i〉.f + }, + ] + } + } + } + issue4119: { + full: { + _img: { + val: string + accounts: { + groups: (〈2〉.accounts.groups|*[ + { + gid: 65532 + }, + ]) + groups: [ + for _, g in 〈1;groups〉 let _gid = 〈0;g〉.gid { + gid: [ + if (〈2;_gid〉 != _|_(explicit error (_|_ literal) in source)) { + 〈3;_gid〉 + }, + 65532, + ][0] + }, + ] + } + } + art: { + images: { + [string]: 〈2;#Image〉 + } + for k, v in 〈0;images〉 { + images: { + 〈2;k〉: (〈4;_img〉 & 〈2;v〉) + } + } + } + #Image: { + val: string + accounts?: { + groups?: [ + ..., + ] + } + } + art: { + images: { + ko: { + val: "test" + } + } + } + } + } +} +--- in.cue +{} diff --git a/internal/core/compile/testdata/sync/eval/disjunctioncross.txtar b/internal/core/compile/testdata/sync/eval/disjunctioncross.txtar new file mode 100644 index 000000000..4474eef10 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/disjunctioncross.txtar @@ -0,0 +1,306 @@ +-- in.cue -- +#OneOrTwo: #One | #Two +#One: { + kind: "one" + one: oneField: "value" +} +#Two: { + kind: "two" + two: optional?: string +} +_appDefaults: two: two: optional: *"optional set" | string + +// Use a discriminator field to disambiguation additional per-disjunct +// information. +valueDiscriminator: crossing: { + out: #Application & { oneOrTwo: kind: "two" } + #Application: { + oneOrTwo: #OneOrTwo + // oneOrTwo.kind resolves will resolve to "two" regardless of whether + // it resolves to the original oneOrTwo or the disjunct that is being + // processed. + oneOrTwo: *_appDefaults[oneOrTwo.kind] | _ + } + @test(eq, { + out: { + oneOrTwo: + *{kind: "two", two: {optional: *"optional set" | string}} | + {kind: "two", two: {optional?: string}} + } + #Application: { + oneOrTwo: + *{kind: "two", two: {optional: *"optional set" | string}} | + {kind: "one", one: {oneField: "value"}} | + {kind: "two", two: {optional?: string}} + } + }) +} + +valueDiscriminator: local: { + out: #Application & { oneOrTwo: kind: "two" } + #Application: { + oneOrTwo: #OneOrTwo + // oneOrTwo.kind always resolves to the value of the disjunct. + // Alternative writing for future features based on various proposals: + // oneOrTwo~X: *_appDefaults[X.kind] | _ + // oneOrTwo: *_appDefaults[self.kind] | _ + // try { oneOrTwo: _appDefaults.(self.kind)? } + oneOrTwo: X={ *_appDefaults[X.kind] | _ } + } + @test(eq, { + out: oneOrTwo: + *{kind: "two", two: {optional: *"optional set" | string}} | + {kind: "two", two: {optional?: string}} + #Application: oneOrTwo: + *{kind: "two", two: {optional: *"optional set" | string}} | + {kind: "one", one: {oneField: "value"}} | + {kind: "two", two: {optional?: string}} + }) +} + +// Use a value that is available AFTER a disjunction is resolved to augment +// values. We may not want to support this in perpetuity, as this relies on +// closedness to discrimnate the disjuncts. But for now, as there is no +// alternative to discriminating based on fields, we will support it. +fieldDiscriminator: crossing:{ + out: #Application & { oneOrTwo: two: {} } + #Application: { + oneOrTwo: #OneOrTwo + // The value of oneOrTwo.kind depends on whether oneOrTwo resolves + // to the disjunct currently being processed, the original before + // a disjunct has been selected, or a disjunct after it has been + // selected. + oneOrTwo: *_appDefaults[oneOrTwo.kind] | _ + } + @test(eq, { + out: oneOrTwo: + *{two: {optional: *"optional set" | string}, kind: "two"} | + {two: {optional?: string}, kind: "two"} + #Application: oneOrTwo: + *{kind: "two", two: {optional: *"optional set" | string}} | + {kind: "one", one: {oneField: "value"}} | + {kind: "two", two: {optional?: string}} + }) +} + +fieldDiscriminator: local:{ + out: #Application & { oneOrTwo: two: {} } + #Application: { + oneOrTwo: #OneOrTwo + // oneOrTwo.kind always resolves to the value of the disjunct. + oneOrTwo: X={ *_appDefaults[X.kind] | _ } + } + @test(eq, { + out: { + oneOrTwo: + *{two: {optional: *"optional set" | string}, kind: "two"} | + {two: {optional?: string}, kind: "two"} + } + #Application: { + oneOrTwo: + *{kind: "two", two: {optional: *"optional set" | string}} | + {kind: "one", one: {oneField: "value"}} | + {kind: "two", two: {optional?: string}} + } + }) +} + +// Do not hide error messages. Here, the inner failure of both disjuncts means +// that an enclosing field cannot be resolved as it needs to look up a value +// inside the disjunction. The failure to do this lookup is not the underlying +// cause, though: the inner failure is. For this reason, we should report all +// errors. +// evalv3 regression: misleading "undefined field" error instead of the expected +// circular dependency error when processing disjunctions with cyclic conditionals. +// https://cuelang.org/issue/3967 +issue3967: error: nested: { + out: #Application & { + oneOrTwo: two: {} + } + #Application: X={ + oneOrTwo: #OneOrTwo & { + if X.oneOrTwo.kind == "two" { + two: { + if X.oneOrTwo.two.optional == _|_ { + optional: "optional set" + } + } + } + if X.oneOrTwo.kind == "never" { + } + } + if X.oneOrTwo.kind == "never" { + } + } + @test(eq, { + out: {oneOrTwo: {two: {}}} + #Application: { + oneOrTwo: {kind: "one", one: {oneField: "value"}} + } + }) +} +issue3967: { + error: local: { + out: #Application & { + oneOrTwo: two: {} + } + #Application: { + oneOrTwo: X= { #OneOrTwo & { + if X.kind == "two" { + two: { + if X.two.optional == _|_ { + optional: "optional set" + } + } + } + if X.kind == "never" { + } + }} + } + } + @test(eq, { + error: { + nested: { + out: {oneOrTwo: {two: {}}} + #Application: { + oneOrTwo: {kind: "one", one: {oneField: "value"}} + } + } + local: { + out: {oneOrTwo: {two: {}}} + #Application: { + oneOrTwo: {kind: "one", one: {oneField: "value"}} + } + } + } + }) +} +-- out/compile -- +--- in.cue +{ + #OneOrTwo: (〈0;#One〉|〈0;#Two〉) + #One: { + kind: "one" + one: { + oneField: "value" + } + } + #Two: { + kind: "two" + two: { + optional?: string + } + } + _appDefaults: { + two: { + two: { + optional: (*"optional set"|string) + } + } + } + valueDiscriminator: { + crossing: { + out: (〈0;#Application〉 & { + oneOrTwo: { + kind: "two" + } + }) + #Application: { + oneOrTwo: 〈3;#OneOrTwo〉 + oneOrTwo: (*〈3;_appDefaults〉[〈0;oneOrTwo〉.kind]|_) + } + } + } + valueDiscriminator: { + local: { + out: (〈0;#Application〉 & { + oneOrTwo: { + kind: "two" + } + }) + #Application: { + oneOrTwo: 〈3;#OneOrTwo〉 + oneOrTwo: { + (*〈4;_appDefaults〉[〈1〉.kind]|_) + } + } + } + } + fieldDiscriminator: { + crossing: { + out: (〈0;#Application〉 & { + oneOrTwo: { + two: {} + } + }) + #Application: { + oneOrTwo: 〈3;#OneOrTwo〉 + oneOrTwo: (*〈3;_appDefaults〉[〈0;oneOrTwo〉.kind]|_) + } + } + } + fieldDiscriminator: { + local: { + out: (〈0;#Application〉 & { + oneOrTwo: { + two: {} + } + }) + #Application: { + oneOrTwo: 〈3;#OneOrTwo〉 + oneOrTwo: { + (*〈4;_appDefaults〉[〈1〉.kind]|_) + } + } + } + } + issue3967: { + error: { + nested: { + out: (〈0;#Application〉 & { + oneOrTwo: { + two: {} + } + }) + #Application: { + oneOrTwo: (〈4;#OneOrTwo〉 & { + if (〈2〉.oneOrTwo.kind == "two") { + two: { + if (〈4〉.oneOrTwo.two.optional == _|_(explicit error (_|_ literal) in source)) { + optional: "optional set" + } + } + } + if (〈2〉.oneOrTwo.kind == "never") {} + }) + if (〈1〉.oneOrTwo.kind == "never") {} + } + } + } + } + issue3967: { + error: { + local: { + out: (〈0;#Application〉 & { + oneOrTwo: { + two: {} + } + }) + #Application: { + oneOrTwo: { + (〈5;#OneOrTwo〉 & { + if (〈2〉.kind == "two") { + two: { + if (〈4〉.two.optional == _|_(explicit error (_|_ literal) in source)) { + optional: "optional set" + } + } + } + if (〈2〉.kind == "never") {} + }) + } + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/disjunctions.txtar b/internal/core/compile/testdata/sync/eval/disjunctions.txtar new file mode 100644 index 000000000..51495a004 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/disjunctions.txtar @@ -0,0 +1,1097 @@ +-- in.cue -- +a: *1 | int @test(eq, *1 | int) +aa: *1 | *2 | int @test(eq, *1 | *2 | int) + +b: { + name: "int" + val: int +} | { + name: "str" + val: string +} @test(eq, {name: "int", val: int} | {name: "str", val: string}) + +d: b & {val: 3} @test(eq, {val: 3, name: "int"}) +c: b & {name: "int", val: 3} @test(eq, {name: "int", val: 3}) +e: b & {val: "foo"} @test(eq, {val: "foo", name: "str"}) +f: b & {name: "str", val: 3} @test(err, + suberr=(code=eval, contains="conflicting values", pos=[-10:8, 0:4, 0:15]), + suberr=(code=eval, contains="conflicting values", pos=[-6:8, 0:4, 0:27])) + +// Disjunct elimination based on type. +e1: { + a: null | {bar: 2} + b: (a & {}).bar + @test(eq, {a: null | {bar: 2}, b: 2}) +} + +d1: { + a: (null | {c: 1}) & {} + b: {} & (null | {c: 1}) + @test(eq, {a: {c: 1}, b: {c: 1}}) +} + +d2: { + a: ([...] | {c: 1}) & {} + b: {} & ([...] | {c: 1}) + @test(eq, {a: {c: 1}, b: {c: 1}}) +} + +d3: { + a: (string | {c: 1}) & {} + b: {} & (string | {c: 1}) + @test(eq, {a: {c: 1}, b: {c: 1}}) +} + +d4: { + a: (string | {c: 1}) & {} + b: {} & (string | {c: 1}) + @test(eq, {a: {c: 1}, b: {c: 1}}) +} + +d5: { + a: (number | {c: 1}) & {} + b: {} & (number | {c: 1}) + @test(eq, {a: {c: 1}, b: {c: 1}}) +} + +d6: { + a: (int | {c: 1}) & {} + b: {} & (int | {c: 1}) + @test(eq, {a: {c: 1}, b: {c: 1}}) +} + +t10: p1: { + // @test(permute, count=120) // TODO(inline): we could reduce this by grouping fields. + schema: test + schema: string | {name: string} + #A: {string | {name: string}} + + test: name: "Test" + test: #A + @test(eq, { + schema: {name: "Test"} + #A: string | {name: string} + test: {name: "Test"} + }) +} + +t10: p2: { + schema: string | {name: string} + schema: test + #A: {string | {name: string}} + + test: name: "Test" + test: #A + @test(eq, { + schema: {name: "Test"} + #A: string | {name: string} + test: {name: "Test"} + }) +} + +t10: p3: { + #A: {string | {name: string}} + + test: name: "Test" + test: #A + + schema: string | {name: string} + schema: test + @test(eq, { + #A: string | {name: string} + test: {name: "Test"} + schema: {name: "Test"} + }) +} + +t11: p1: { + a: #A + a: b + + b: #A & ["b"] + #A: ["a" | "b"] | {} + @test(eq, { + a: ["b"] + b: ["b"] + #A: ["a" | "b"] | {} + }) +} + +t11: p2: { + b: #A & ["b"] + #A: ["a" | "b"] | {} + + a: b + a: #A + @test(eq, { + b: ["b"] + #A: ["a" | "b"] | {} + a: ["b"] + }) +} + +cross: { + a: *"word" | string + a: string | *"word" + @test(eq, {a: *"word" | string}) +} + +d100: { + // Should we allow a selector to imply a struct or list? Would be convenient. + // This would be a spec change. Disallow for now. + i: null | {bar: 2} + j: i.bar + @test(eq, { + i: null | {bar: 2} + j: _|_ @test(err, code=incomplete, contains="d100.j: unresolved disjunction null | {bar:2} (type (null|struct))", pos=[142:5]) + }) +} + +// Regression test for empty disjunction with combined definitions and +// template constraints where valid unification was incorrectly rejected. +// https://cuelang.org/issue/641 +issue641: { + #A: { + type: "a" + x: "" + } + + #B: { + type: "b" + x: string + } + + #C: { + b: #A | #B + } + + e: [string]: #C & { + b: #A | #B + } + + e: foobar: #C & { + b: #B & { + x: "foobar" + } + } + @test(eq, { + #A: {type: "a", x: ""} + #B: {type: "b", x: string} + #C: { + b: {type: "a", x: ""} | {type: "b", x: string} + } + e: {foobar: {b: {x: "foobar", type: "b"}}} + }) +} +-- issue3406.cue -- +// evalv3 panic with inconsistent state when unifying a struct with itself +// embedded via a disjunction field. +// https://cuelang.org/issue/3406 +issue3406: { + out: d & { d } + d: kind: "foo" | "bar" + d: { kind: "foo" } | { kind: "bar" } + @test(eq, { + out: {kind: "foo"} | {kind: "bar"} + d: {kind: "foo"} | {kind: "bar"} + }) +} +-- issue3411.cue -- +// evalv3 nil pointer dereference when unifying optional fields with defaults. +// https://cuelang.org/issue/3411 +issue3411: { + x: y?: [...string] + x: {y: ["foo"]} | *{y: ["bar"]} + @test(eq, {x: *{y: ["bar"]} | {y: ["foo"]}}) +} +-- issue3490.cue -- +// evalv3 "incDependent: already closed" panic regression involving disjunctions. +// https://cuelang.org/issue/3490 +issue3490: nested: p1: { + ("a"|"b") | "b" + "a"|"b" + @test(eq, { + "a" + @test(eq) + } | { + "b" + @test(eq) + }) +} +issue3490: nested: p2: { + "a"|"b" + ("a"|"b") | "b" + @test(eq, { + "a" + @test(eq) + } | { + "b" + @test(eq) + }) +} +issue3490: full: { + data: [...#Schema] + data: [#Schema & {}] + #Schema: { + runs?: "foo" | ([#D1] | [#D1, #D2]) + #D1: "d1" + #D2: "d2" + } + @test(eq, { + data: [{ + runs?: "foo" | ["d1"] | ["d1", "d2"] + #D1: "d1" + #D2: "d2" + }] + #Schema: { + runs?: "foo" | ["d1"] | ["d1", "d2"] + #D1: "d1" + #D2: "d2" + } + }) +} +-- issue3434.cue -- +// evalv3 panic "unexpected overlay in next" with disjunctions inside definitions. +// https://cuelang.org/issue/3434 +issue3434: t1: { + ({} | {}) + {["x"]: 1} + {["y"]: 2} + @test(eq, {["x"]: 1, ["y"]: 2}) +} +issue3434: full: { + out: #Schema & { + steps: [{run: "example"}] + } + #Schema: { + steps: [...{run: string}] + #matrixConfig: string | [...#matrixConfig] + matrix?: ({...} | string) & { + {[=~"^foo"]: [...{[string]: #matrixConfig}]} + {[=~"^bar"]: [...#matrixConfig] | string} + } + } + @test(eq, { + out: { + steps: [{ run: "example" }] + #matrixConfig: string | [] + matrix?: {} + } + #Schema: { + steps: [] + #matrixConfig: string | [] + matrix?: {} + } + }) +} +-- issue3597.cue -- +// evalv3 index out of range panic in overlayContext.allocCC with let inside +// a disjunction within a definition applied via a pattern constraint. +// https://cuelang.org/issue/3597 +issue3597: t1: { + #Schema: { + _ok: bool + {} | { + _ok: true + let Ok = _ok + {} | {x: Ok} + } + } + + [string]: #Schema + + foo: bar + bar: {} + @test(eq, { + #Schema: {_ok: bool} | {_ok: true} | {_ok: true, x: true} + foo: {_ok: bool} | {_ok: true} | {_ok: true, x: true} + bar: {_ok: bool} | {_ok: true} | {_ok: true, x: true} + }) +} +issue3597: t2: { + ok: true + X: _ | { + let Ok = ok + _ | {x: Ok} + } + foo: X & {X} + @test(eq, { + ok: true + X: _ | _ | {x: true} + foo: _ | _ | {x: true} + }) +} +-- dependencies.cue -- +// evalv3 incorrectly allowed a field inside a struct disjunction that should +// have been rejected as "field not allowed". +// https://cuelang.org/issue/3606 +issue3606: { + data: { + notAllowed: true + } & #S + + #S: string | {} + + @test(err, code=eval, + suberr=(code=eval, path=data, contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[{notAllowed:true}, string, struct, string], pos=[1:8, 3:6, 5:6]), + suberr=(code=eval, path=data.notAllowed, contains="field not allowed", pos=[2:3])) +} + +// evalv3 gives a different result vs evalv2 when openinline is enabled; list +// element count is wrong after unifying nested disjunctions through definitions. +// https://cuelang.org/issue/3672 +issue3672: { + #A: string | {y: true} + #B: #A | {a: "append"} | {b: "prepend"} + + #fn: { + #C: #B + #out: x: [...#C] + } + + // The unification inline appears to be critical + #def: (#fn & {}).#out + + v: #def + v: x: [{y: true}] // Should be one element + @test(eq, { + #A: string | {y: true} + #B: string | {y: true} | {a: "append"} | {b: "prepend"} + #fn: { + #C: string | {y: true} | {a: "append"} | {b: "prepend"} + #out: {x: []} + } + #def: {x: []} + v: {x: [{ + y: true + }]} + }) +} +// Regression giving "non-concrete value _ (type _)" error when interpolating +// a string default from a disjunction via a definition alias. +// https://cuelang.org/issue/3681 +issue3681: { + // Order dependent! These two fields need to go first. + out: one: #strDefaultDef + out: two: "\(strDefault)" + + strDefault: *"fallback" | string + #strDefaultDef: strDefault + @test(eq, { + out: { + one: *"fallback" | string + two: "fallback" + } + strDefault: *"fallback" | string + #strDefaultDef: *"fallback" | string + }) +} +// evalv3 "undefined field" regression when a comprehension condition references +// a field whose default is provided by a disjunction. +// https://cuelang.org/issue/3699 +issue3699: { + reduced: p1: { + y: { if x.z { 1 } } + x: *{z: true} | {} + } + reduced: p2: { + y: { if x.z { 1 } } + x: *{z: true} | {} + } + reduced: full: { + _res: { + _fooTrue: {} | *{foo: true} + _msgSwitch: [ + if _fooTrue.foo { msg: "foo" }, + { msg: "bar" }, + ][0] + out: _msgSwitch.msg + } + let res = { + out: (_res & {}).out + } + out: res.out + } + @test(eq, { + reduced: { + p1: {y: 1, x: *{z: true} | {}} + p2: {y: 1, x: *{z: true} | {}} + full: { + _res: { + _fooTrue: *{foo: true} | {} + _msgSwitch: {msg: "foo"} + out: "foo" + } + out: "foo" + } + } + }) +} +-- indexelim.cue -- +import "math/bits" + +indexElimination: { + inStruct: x: { a: *x[0] | 0 }.a @test(eq, 0) + inList1: x: [x[0]][0] @test(eq, _) + inList2: x: [*x[0] | 0][0] @test(eq, 0) + // evalv3 strange behavior with chaining of list comprehensions, + // incorrect results when indexing the output of a for loop. + // https://cuelang.org/issue/3124 + issue3124: full: { + x: [...bool] + x: [true, false, true, true] + y: [for _, v in x {[if v {1}, 0][0]}] + z: [for i, v in y {bits.Set(*z[i-1] | 0, len(y)-i-1, v)}][3] + @test(eq, { + x: [true, false, true, true] + y: [1, 0, 1, 1] + z: 1 + }) + } +} +-- issue3899.cue -- +// evalv3 "invalid type _" regression that is order-dependent, triggered when +// a string interpolation references an optional field inside a disjunction. +// https://cuelang.org/issue/3899 +issue3899: reduced: { + @test(permute, count=2) + b: c + "" | string + c?: string + @test(eq, {b: string, c?: string}) +} +issue3899: full: { + out: #Schema & { + name: "foo" + } + #Schema: { + _versions: foo: "123" + spec: limits: true + name!: string + spec: image: string | *"\(name)" + deployImage: _versions[spec.image] @test(err, code=incomplete, + contains="invalid non-ground value %s (must be concrete %s)", + args=[string, string], pos=[-1:18]) + } + @test(eq, { + out: { + name: "foo" + _versions: {foo: "123"} + spec: {limits: true, image: *"foo" | string} + deployImage: "123" + } + #Schema: { + _versions: {foo: "123"} + spec: {limits: true, image: string} + name!: string + deployImage: _|_ + } + }) +} +-- issue3891.cue -- +// evalv3 "incomplete value" regression with repeated disjunctions where a +// field referencing a default via another field yields an incomplete error. +// https://cuelang.org/issue/3891 +issue3891: reduced: { + {x: _} | null + {x: _} | null + x: *a.y | _ + a: b @test(shareID=r3891ab) + @test(shareID=r3891ab, at=b) + b: y: 1 + @test(eq, {x: *1 | _, a: {y: 1}, b: {y: 1}}) +} +issue3891: full: { + out: #Foo | "never" + out: #Foo | "never" + out: _fooTemplate & { + _input: (_transform & {in: sub1: sub2: "bar"}).out + } + _transform: { + in: _ + out: in + } + #Foo: foo?: _ + _fooTemplate: { + _input: _ + foo: *_input.sub1.sub2 | _ + } + @test(eq, { + out: { + _input: {sub1: {sub2: "bar"}} + foo: *"bar" | _ + } + _transform: {in: _, out: _} + #Foo: {foo?: _} + _fooTemplate: {_input: _, foo: _} + }) +} +-- out/compile -- +--- dependencies.cue +{ + issue3606: { + data: ({ + notAllowed: true + } & 〈0;#S〉) + #S: (string|{}) + } + issue3672: { + #A: (string|{ + y: true + }) + #B: (〈0;#A〉|{ + a: "append" + }|{ + b: "prepend" + }) + #fn: { + #C: 〈1;#B〉 + #out: { + x: [ + ...〈2;#C〉, + ] + } + } + #def: (〈0;#fn〉 & {}).#out + v: 〈0;#def〉 + v: { + x: [ + { + y: true + }, + ] + } + } + issue3681: { + out: { + one: 〈1;#strDefaultDef〉 + } + out: { + two: "\(〈1;strDefault〉)" + } + strDefault: (*"fallback"|string) + #strDefaultDef: 〈0;strDefault〉 + } + issue3699: { + reduced: { + p1: { + y: { + if 〈1;x〉.z { + 1 + } + } + x: (*{ + z: true + }|{}) + } + } + reduced: { + p2: { + y: { + if 〈1;x〉.z { + 1 + } + } + x: (*{ + z: true + }|{}) + } + } + reduced: { + full: { + _res: { + _fooTrue: ({}|*{ + foo: true + }) + _msgSwitch: [ + if 〈1;_fooTrue〉.foo { + msg: "foo" + }, + { + msg: "bar" + }, + ][0] + out: 〈0;_msgSwitch〉.msg + } + let res#1 = { + out: (〈1;_res〉 & {}).out + } + out: 〈0;let res#1〉.out + } + } + } +} +--- in.cue +{ + a: (*1|int) + aa: (*1|*2|int) + b: ({ + name: "int" + val: int + }|{ + name: "str" + val: string + }) + d: (〈0;b〉 & { + val: 3 + }) + c: (〈0;b〉 & { + name: "int" + val: 3 + }) + e: (〈0;b〉 & { + val: "foo" + }) + f: (〈0;b〉 & { + name: "str" + val: 3 + }) + e1: { + a: (null|{ + bar: 2 + }) + b: (〈0;a〉 & {}).bar + } + d1: { + a: ((null|{ + c: 1 + }) & {}) + b: ({} & (null|{ + c: 1 + })) + } + d2: { + a: (([ + ..., + ]|{ + c: 1 + }) & {}) + b: ({} & ([ + ..., + ]|{ + c: 1 + })) + } + d3: { + a: ((string|{ + c: 1 + }) & {}) + b: ({} & (string|{ + c: 1 + })) + } + d4: { + a: ((string|{ + c: 1 + }) & {}) + b: ({} & (string|{ + c: 1 + })) + } + d5: { + a: ((number|{ + c: 1 + }) & {}) + b: ({} & (number|{ + c: 1 + })) + } + d6: { + a: ((int|{ + c: 1 + }) & {}) + b: ({} & (int|{ + c: 1 + })) + } + t10: { + p1: { + schema: 〈0;test〉 + schema: (string|{ + name: string + }) + #A: { + (string|{ + name: string + }) + } + test: { + name: "Test" + } + test: 〈0;#A〉 + } + } + t10: { + p2: { + schema: (string|{ + name: string + }) + schema: 〈0;test〉 + #A: { + (string|{ + name: string + }) + } + test: { + name: "Test" + } + test: 〈0;#A〉 + } + } + t10: { + p3: { + #A: { + (string|{ + name: string + }) + } + test: { + name: "Test" + } + test: 〈0;#A〉 + schema: (string|{ + name: string + }) + schema: 〈0;test〉 + } + } + t11: { + p1: { + a: 〈0;#A〉 + a: 〈0;b〉 + b: (〈0;#A〉 & [ + "b", + ]) + #A: ([ + ("a"|"b"), + ]|{}) + } + } + t11: { + p2: { + b: (〈0;#A〉 & [ + "b", + ]) + #A: ([ + ("a"|"b"), + ]|{}) + a: 〈0;b〉 + a: 〈0;#A〉 + } + } + cross: { + a: (*"word"|string) + a: (string|*"word") + } + d100: { + i: (null|{ + bar: 2 + }) + j: 〈0;i〉.bar + } + issue641: { + #A: { + type: "a" + x: "" + } + #B: { + type: "b" + x: string + } + #C: { + b: (〈1;#A〉|〈1;#B〉) + } + e: { + [string]: (〈1;#C〉 & { + b: (〈2;#A〉|〈2;#B〉) + }) + } + e: { + foobar: (〈1;#C〉 & { + b: (〈2;#B〉 & { + x: "foobar" + }) + }) + } + } +} +--- indexelim.cue +{ + indexElimination: { + inStruct: { + x: { + a: (*〈1;x〉[0]|0) + }.a + } + inList1: { + x: [ + 〈1;x〉[0], + ][0] + } + inList2: { + x: [ + (*〈1;x〉[0]|0), + ][0] + } + issue3124: { + full: { + x: [ + ...bool, + ] + x: [ + true, + false, + true, + true, + ] + y: [ + for _, v in 〈1;x〉 { + [ + if 〈2;v〉 { + 1 + }, + 0, + ][0] + }, + ] + z: [ + for i, v in 〈1;y〉 { + 〈import;"math/bits"〉.Set((*〈3;z〉[(〈1;i〉 - 1)]|0), ((len(〈3;y〉) - 〈1;i〉) - 1), 〈1;v〉) + }, + ][3] + } + } + } +} +--- issue3406.cue +{ + issue3406: { + out: (〈0;d〉 & { + 〈1;d〉 + }) + d: { + kind: ("foo"|"bar") + } + d: ({ + kind: "foo" + }|{ + kind: "bar" + }) + } +} +--- issue3411.cue +{ + issue3411: { + x: { + y?: [ + ...string, + ] + } + x: ({ + y: [ + "foo", + ] + }|*{ + y: [ + "bar", + ] + }) + } +} +--- issue3434.cue +{ + issue3434: { + t1: { + ({}|{}) + { + ["x"]: 1 + } + { + ["y"]: 2 + } + } + } + issue3434: { + full: { + out: (〈0;#Schema〉 & { + steps: [ + { + run: "example" + }, + ] + }) + #Schema: { + steps: [ + ...{ + run: string + }, + ] + #matrixConfig: (string|[ + ...〈1;#matrixConfig〉, + ]) + matrix?: (({ + ... + }|string) & { + { + [=~"^foo"]: [ + ...{ + [string]: 〈4;#matrixConfig〉 + }, + ] + } + { + [=~"^bar"]: ([ + ...〈3;#matrixConfig〉, + ]|string) + } + }) + } + } + } +} +--- issue3490.cue +{ + issue3490: { + nested: { + p1: { + (("a"|"b")|"b") + ("a"|"b") + } + } + } + issue3490: { + nested: { + p2: { + ("a"|"b") + (("a"|"b")|"b") + } + } + } + issue3490: { + full: { + data: [ + ...〈1;#Schema〉, + ] + data: [ + (〈1;#Schema〉 & {}), + ] + #Schema: { + runs?: ("foo"|([ + 〈1;#D1〉, + ]|[ + 〈1;#D1〉, + 〈1;#D2〉, + ])) + #D1: "d1" + #D2: "d2" + } + } + } +} +--- issue3597.cue +{ + issue3597: { + t1: { + #Schema: { + _ok: bool + ({}|{ + _ok: true + let Ok#2 = 〈0;_ok〉 + ({}|{ + x: 〈1;let Ok#2〉 + }) + }) + } + [string]: 〈0;#Schema〉 + foo: 〈0;bar〉 + bar: {} + } + } + issue3597: { + t2: { + ok: true + X: (_|{ + let Ok#3 = 〈1;ok〉 + (_|{ + x: 〈1;let Ok#3〉 + }) + }) + foo: (〈0;X〉 & { + 〈1;X〉 + }) + } + } +} +--- issue3891.cue +{ + issue3891: { + reduced: { + ({ + x: _ + }|null) + ({ + x: _ + }|null) + x: (*〈0;a〉.y|_) + a: 〈0;b〉 + b: { + y: 1 + } + } + } + issue3891: { + full: { + out: (〈0;#Foo〉|"never") + out: (〈0;#Foo〉|"never") + out: (〈0;_fooTemplate〉 & { + _input: (〈1;_transform〉 & { + in: { + sub1: { + sub2: "bar" + } + } + }).out + }) + _transform: { + in: _ + out: 〈0;in〉 + } + #Foo: { + foo?: _ + } + _fooTemplate: { + _input: _ + foo: (*〈0;_input〉.sub1.sub2|_) + } + } + } +} +--- issue3899.cue +{ + issue3899: { + reduced: { + b: ((〈0;c〉 + "")|string) + c?: string + } + } + issue3899: { + full: { + out: (〈0;#Schema〉 & { + name: "foo" + }) + #Schema: { + _versions: { + foo: "123" + } + spec: { + limits: true + } + name!: string + spec: { + image: (string|*"\(〈1;name〉)") + } + deployImage: 〈0;_versions〉[〈0;spec〉.image] + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/dynamic_field.txtar b/internal/core/compile/testdata/sync/eval/dynamic_field.txtar new file mode 100644 index 000000000..04d4ebedd --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/dynamic_field.txtar @@ -0,0 +1,222 @@ +// Tests dynamic field key resolution including string interpolations, chained +// resolution, and comprehension with let bindings. Covers panic fix for issue799 +// (struct used in string interpolation) and issue3828 (let inside comprehension +// with dynamic field key). +-- in.cue -- +a: "foo" +"\(a)": b: c: d: e +e: 2 @test(eq, 2) + +b: "bar" +X="\(b)": { + a: 1 +} +c: X @test(eq, {a: 1}) + +withError: { + // Panic when running cue eval with a struct used in a string interpolation. + // https://cuelang.org/issue/799 + issue799: {key: int32} & {"\(1 & 2)": 123} + // TODO(inline): access _wrapped_ error somehow: underlying error is + // "conflicting values 2 and 1". + @test(err, code=eval, contains="invalid interpolation", pos=[3:28, 3:31, 3:35]) +} + +parenExprRefParent: { + a: (x): {} + x: "foo" + @test(eq, {a: {foo: {}}, x: "foo"}) +} +parenExprRefEqual: { + (x): {} + x: "foo" + @test(eq, {x: "foo", foo: {}}) +} +chainedResolution: x: { + @test(permute, count=6) + (x.baz): "bar" + (x.foo): "baz" + baz: "foo" + @test(eq, { + baz: "foo", foo: "bar", bar: "baz" + }) +} + +// A dynamic field key that references an incomplete value (string interpolation +// using abstract string) must produce an "incomplete" error, not a spurious +// "cycle error". The error should also include path and position information. +// https://cuelang.org/issue/1407 +noCycleError: { + foo: [_]: { + #ID: "\(string)" + } + foo: bar: entries: (foo.baz.#ID): true + foo: baz: {} + @test(err, at=foo.bar.entries, code=incomplete, + suberr=(code=incomplete, contains="dynamic field must be concrete", pos=[4:22]), + suberr=(code=incomplete, contains="non-concrete value string", pos=[2:8, 2:11]), + ) + @test(err, at=foo.bar.#ID, code=incomplete, contains="non-concrete value string", pos=[2:8, 2:11]) + @test(err, at=foo.baz.#ID, code=incomplete, contains="non-concrete value string", pos=[2:8, 2:11]) + + @test(eq, { + foo: { + bar: { + entries: _|_ + #ID: _|_ + } + baz: { #ID: _|_ } + } + }) +} + +-- constraints.cue -- +constraints: { + t1: "foo" + t2: "bar" + (t1)?: (t2)!: 3 + @test(eq, {t1: "foo", t2: "bar", foo?: {bar!: 3}}) +} +-- issue3828.cue -- +// evalv3 regression: a let inside a comprehension with a dynamic field key +// failed to produce the correct output due to a "cycle with field" error. +// https://cuelang.org/issue/3828 +issue3828: reduced: { + a: b: {} + a: [_]: { + if true let x=str { + (x): true + } + } + str: "foobot1" + @test(eq, {a: {b: {foobot1: true}}, str: "foobot1"}) +} +issue3828: full: { + orgs: org1: { + repos: repo1: {} + } + botUser: "bot1" + orgs: [_]: config={ + for repo_name, _ in config.repos + let orgBotUser = botUser { + collaborators: (repo_name): (orgBotUser): true + } + } + @test(eq, { + orgs: org1: { + repos: {repo1: {}} + collaborators: {repo1: {bot1: true}} + } + botUser: "bot1" + }) +} +-- out/compile -- +--- constraints.cue +{ + constraints: { + t1: "foo" + t2: "bar" + 〈0;t1〉?: { + 〈1;t2〉!: 3 + } + } +} +--- in.cue +{ + a: "foo" + "\(〈0;a〉)": { + b: { + c: { + d: 〈3;e〉 + } + } + } + e: 2 + b: "bar" + "\(〈0;b〉)": { + a: 1 + } + c: 〈0;("\(〈0;b〉)")〉 + withError: { + issue799: ({ + key: &(int, >=-2147483648, <=2147483647) + } & { + "\((1 & 2))": 123 + }) + } + parenExprRefParent: { + a: { + 〈1;x〉: {} + } + x: "foo" + } + parenExprRefEqual: { + 〈0;x〉: {} + x: "foo" + } + chainedResolution: { + x: { + 〈1;x〉.baz: "bar" + 〈1;x〉.foo: "baz" + baz: "foo" + } + } + noCycleError: { + foo: { + [_]: { + #ID: "\(string)" + } + } + foo: { + bar: { + entries: { + 〈3;foo〉.baz.#ID: true + } + } + } + foo: { + baz: {} + } + } +} +--- issue3828.cue +{ + issue3828: { + reduced: { + a: { + b: {} + } + a: { + [_]: { + if true let x = 〈2;str〉 { + 〈1;x〉: true + } + } + } + str: "foobot1" + } + } + issue3828: { + full: { + orgs: { + org1: { + repos: { + repo1: {} + } + } + } + botUser: "bot1" + orgs: { + [_]: { + for repo_name, _ in 〈1〉.repos let orgBotUser = 〈3;botUser〉 { + collaborators: { + 〈3;repo_name〉: { + 〈3;orgBotUser〉: true + } + } + } + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/embed.txtar b/internal/core/compile/testdata/sync/eval/embed.txtar new file mode 100644 index 000000000..5998d132e --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/embed.txtar @@ -0,0 +1,354 @@ +// Tests struct embedding behavior including comprehension-based embeddings and +// closedness enforcement. Verifies that "field not allowed" errors are correctly +// raised when embedding adds fields disallowed by a closed definition, and that +// closedness inversion with open fields works correctly. +-- in.cue -- +#A: { + Common + ... +} + +Common: { + a: int + b: int +} + +x: #A +x: { + c: int + @test(eq, {c: int, a: int, b: int}) +} + +#B: { + if true { + a: int + } + ... +} + +y: #B +y: { + c: int + @test(eq, {c: int, a: int}) +} +-- noclose.cue -- +double: { + a: b?: c: d: "c" + a: {{ + b: {{ + c: e: "member" + }} + }} + @test(eq, {a: {b: {c: {d: "c", e: "member"}}}}) +} +doubleAsComprehension: { + a: b?: c: d: "c" + a: { + if true { + b: { + if true { + c: e: "member" + } + } + } + } + @test(eq, {a: {b: {c: {d: "c", e: "member"}}}}) +} +fieldNotAllowed: { + // This was not correctly enforced in evalv2. + t1: { + #X: { + objs: { + extra: unused: "foo" + ... + } + ... + } + #Y: unused: {} + addTwo: #X & { + #Y + objs: name: "Two" + } + @test(err, at=addTwo.objs.extra, code=eval, contains="field not allowed", pos=[3:5]) + } + t2: { + #AddObjsExtra: { + objs: [string]: { + extra: unused: "foo" + ... + } + ... + } + #EmbedUnused: unused: {} + #AddTwo: #AddObjsExtra & { + #EmbedUnused + objs: two: { + name: "Two" + labels: app: objs.one.name + } + } + out: #AddTwo & { + objs: one: { + name: "One" + } + } + @test(err, at=#AddTwo.objs.two.labels.app, code=incomplete, contains="undefined field: one", pos=[13:23]) + + @test(err, at=#AddTwo.objs.two.extra, code=eval, contains="field not allowed", pos=[3:5]) + @test(err, at=#AddTwo.objs.two.extra.unused, code=eval, contains="field not allowed", pos=[3:12]) + @test(err, at=out.objs.one.extra.unused, code=eval, contains="field not allowed", pos=[3:12]) + @test(err, at=out.objs.one.extra, code=eval, contains="field not allowed", pos=[3:5]) + @test(err, at=out.objs.one.name, code=eval, contains="field not allowed", pos=[18:5]) + @test(err, at=out.objs.two.extra.unused, code=eval, contains="field not allowed", pos=[3:12]) + + // This error is perculated up. + @test(err, code=eval, + hint="the error chosen here is somewhat arbitrary, okay to ignore as long as the others are good", + suberr=(code=eval, path=out.objs.one.name, contains="field not allowed", pos=[18:5]), + suberr=(code=eval, path=out.objs.one.extra, contains="field not allowed", pos=[3:5])) + } + t3: { + x: #X + #X: y: { + z: { + a: [string]: string + b: E: "1" + } + ... + } + + @test(shareID=YY, at=#Y) + @test(shareID=YY, at=x1.y) + x1: y: #Y + #Y: port?: string + + x: y: { + z: b: E: string + port: z.b.E + z: a: c?: string + } @test(eq, { + z: {b: E: "1", a: c?: string} + port: "1" + }) + + if true { + w: x & { + y: x1.y + } + } + @test(err, at=w.y.z.b.E, code=eval, contains="field not allowed", pos=[5:8, 16:10]) + @test(err, at=w.y.z.a, code=eval, contains="field not allowed", pos=[4:5, 18:7]) + @test(err, at=w.y.z.b, code=eval, contains="field not allowed", pos=[5:5, 16:7]) + @test(err, code=eval, + suberr=(code=eval, path=w.y.z.b, contains="field not allowed", pos=[5:5, 16:7]), + suberr=(code=eval, path=w.y.z.a, contains="field not allowed", pos=[4:5, 18:7])) + } +} +closednessInversion: { + base: #X + base: x: #Y + #X: x: {...} + #Y: y: string | *"default" + out: { + base.x + a: b: c: "d" + } + @test(eq, { + base: {x: {y: *"default" | string}} + #X: {x: {}} + #Y: {y: *"default" | string} + out: { + a: {b: {c: "d"}} + y: *"default" | string + } + }) +} +-- out/compile -- +--- in.cue +{ + #A: { + 〈1;Common〉 + ... + } + Common: { + a: int + b: int + } + x: 〈0;#A〉 + x: { + c: int + } + #B: { + if true { + a: int + } + ... + } + y: 〈0;#B〉 + y: { + c: int + } +} +--- noclose.cue +{ + double: { + a: { + b?: { + c: { + d: "c" + } + } + } + a: { + { + b: { + { + c: { + e: "member" + } + } + } + } + } + } + doubleAsComprehension: { + a: { + b?: { + c: { + d: "c" + } + } + } + a: { + if true { + b: { + if true { + c: { + e: "member" + } + } + } + } + } + } + fieldNotAllowed: { + t1: { + #X: { + objs: { + extra: { + unused: "foo" + } + ... + } + ... + } + #Y: { + unused: {} + } + addTwo: (〈0;#X〉 & { + 〈1;#Y〉 + objs: { + name: "Two" + } + }) + } + t2: { + #AddObjsExtra: { + objs: { + [string]: { + extra: { + unused: "foo" + } + ... + } + } + ... + } + #EmbedUnused: { + unused: {} + } + #AddTwo: (〈0;#AddObjsExtra〉 & { + 〈1;#EmbedUnused〉 + objs: { + two: { + name: "Two" + labels: { + app: 〈3;objs〉.one.name + } + } + } + }) + out: (〈0;#AddTwo〉 & { + objs: { + one: { + name: "One" + } + } + }) + } + t3: { + x: 〈0;#X〉 + #X: { + y: { + z: { + a: { + [string]: string + } + b: { + E: "1" + } + } + ... + } + } + x1: { + y: 〈1;#Y〉 + } + #Y: { + port?: string + } + x: { + y: { + z: { + b: { + E: string + } + } + port: 〈0;z〉.b.E + z: { + a: { + c?: string + } + } + } + } + if true { + w: (〈1;x〉 & { + y: 〈2;x1〉.y + }) + } + } + } + closednessInversion: { + base: 〈0;#X〉 + base: { + x: 〈1;#Y〉 + } + #X: { + x: { + ... + } + } + #Y: { + y: (string|*"default") + } + out: { + 〈1;base〉.x + a: { + b: { + c: "d" + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/errunifiy.txtar b/internal/core/compile/testdata/sync/eval/errunifiy.txtar new file mode 100644 index 000000000..2a654b407 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/errunifiy.txtar @@ -0,0 +1,15 @@ +Incomplete errors should not unify with values. +-- in.cue -- +a: or([]) @test(err, code=incomplete, contains="empty list", pos=[0:4]) +a: "t" + +b: _|_ @test(err, code=user, contains="explicit error", pos=[0:4]) +b: "t" +-- out/compile -- +--- in.cue +{ + a: or([]) + a: "t" + b: _|_(explicit error (_|_ literal) in source) + b: "t" +} diff --git a/internal/core/compile/testdata/sync/eval/expressions.txtar b/internal/core/compile/testdata/sync/eval/expressions.txtar new file mode 100644 index 000000000..57ee0661a --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/expressions.txtar @@ -0,0 +1,56 @@ +-- cue.mod/module.cue -- +module: "test.com" +language: version: "v0.15.0" +-- in.cue -- +a: 1 @test(eq, 1) +b: 1 + 2 @test(eq, 3) +c: 3 - 1 @test(eq, 2) +d: rem(5, 3) @test(eq, 2) + +// StructCmp examples - now that the experiment is accepted +structComparison: { + equalStructs: {a: 1, b: 2} == {a: 1, b: 2} @test(eq, true) + differentStructs: {a: 1} == {a: 2} @test(eq, false) + emptyStructs: {} == {} @test(eq, true) +} + +mixedComparison: { + structVsNumber: {a: 1} == 1 @test(eq, false) + listVsStruct: [1, 2] == {a: 1} @test(eq, false) + stringVsNumber: "hello" == 42 @test(eq, false) +} +-- out/compile -- +--- in.cue +{ + a: 1 + b: (1 + 2) + c: (3 - 1) + d: rem(5, 3) + structComparison: { + equalStructs: ({ + a: 1 + b: 2 + } == { + a: 1 + b: 2 + }) + differentStructs: ({ + a: 1 + } == { + a: 2 + }) + emptyStructs: ({} == {}) + } + mixedComparison: { + structVsNumber: ({ + a: 1 + } == 1) + listVsStruct: ([ + 1, + 2, + ] == { + a: 1 + }) + stringVsNumber: ("hello" == 42) + } +} diff --git a/internal/core/compile/testdata/sync/eval/fields.txtar b/internal/core/compile/testdata/sync/eval/fields.txtar new file mode 100644 index 000000000..f38bdc5ed --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/fields.txtar @@ -0,0 +1,28 @@ +-- in.cue -- +bulkToSelf: { + a: { + foo: [string]: int + foo: bar: "3" @test(err, any, code=eval, contains="conflicting values") + } +} +intField: { + @test(err, code=eval, contains="integer fields not supported", pos=[2:3]) + (2): string +} +-- out/compile -- +--- in.cue +{ + bulkToSelf: { + a: { + foo: { + [string]: int + } + foo: { + bar: "3" + } + } + } + intField: { + 2: string + } +} diff --git a/internal/core/compile/testdata/sync/eval/incomplete.txtar b/internal/core/compile/testdata/sync/eval/incomplete.txtar new file mode 100644 index 000000000..b7dcdc435 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/incomplete.txtar @@ -0,0 +1,115 @@ +# Tests incomplete-error reporting for various expressions: string arithmetic, +# non-concrete bounds, self-referential bounds, mutual dependencies, and +# undefined-field lookups. All produce [incomplete] errors except e2 which +# succeeds because "bar" is concrete. issue1837 checks that incomplete errors +# are correctly preferred over cycle errors in conditional comprehensions. +-- in.cue -- +s: string + +e1: s + s @test(err, code=incomplete, + suberr=(code=incomplete, contains="non-concrete value %v in operand to %s", args=[string, +], pos=[0:6, -2:4]), + suberr=(code=incomplete, contains="non-concrete value %v in operand to %s", args=[string, +], pos=[0:6, -2:4]), +) +e2: >"bar" & s @test(eq, >"bar") // okay: "bar" is concrete, result is a valid bound +e3: >s & "foo" @test(err, code=incomplete, contains="non-concrete value s for bound >", pos=[0:7]) +e3b: >s @test(err, code=incomplete, contains="non-concrete value s for bound >", pos=[0:7]) + +e4: >e1 & s @test(err, code=incomplete, pos=[-8:6, -10:4]) +e5: =5 @test(err, code=incomplete, pos=[-1:5, 0:5, 0:11]) +} + +a: int @test(eq, int) +okay: (>10 & "bar" & 〈0;s〉) + e3: (>〈0;s〉 & "foo") + e3b: >〈0;s〉 + e4: (>〈0;e1〉 & 〈0;s〉) + e5: (<〈0;e5〉 & 〈0;s〉) + E: { + a: (〈0;c〉 - 〈0;b〉) + b: (〈0;c〉 - 〈0;a〉) + c: ((〈0;a〉 + 〈0;b〉) & >=5) + } + a: int + okay: ((>10 & <〈0;a〉) + 3) + issue1837: { + p1: { + context: {} + x: 〈0;context〉.b + if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { + message: "a" + } + } + p2: { + if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { + message: "a" + } + x: 〈0;context〉.b + context: {} + } + p3: { + if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { + message: "a" + } + context: {} + x: 〈0;context〉.b + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/incompleteperm.txtar b/internal/core/compile/testdata/sync/eval/incompleteperm.txtar new file mode 100644 index 000000000..89b9769bd --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/incompleteperm.txtar @@ -0,0 +1,60 @@ +#inlinetest:exclude source contains compile-time error expressions (abstract arithmetic, +# bound comparisons) which prevent the inline runner from compiling the source. +// Issue #742 +// Issue #405 +-- in.cue -- +// Issue #129 +permanentlyIncompleteOperands: { + a: string + ":" + string + a: "golang/go:1.13.5" +} + +permanentlyIncompleteOperandsNested: { + a: (int + 1) + (int + 1) +} + +permanentlyIncompleteOperandsDisjunct: { + a: (int + 1) | (int + 1) +} + +// Wrong result for `meet`: multiplying a bound by a concrete value should +// yield an error when the result contradicts the bound. +// https://cuelang.org/issue/680 +issue680: (>10 * 2) & 0 + +// In a definition, 'size: >=100 <=200' should be a compile error since +// applying <= to a bound (>=100) is not valid arithmetic. +// https://cuelang.org/issue/405 +issue405: >=100 <= 200 +-- out/compile -- +permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): + ./in.cue:3:5 +permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): + ./in.cue:3:20 +permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): + ./in.cue:8:6 +permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): + ./in.cue:8:18 +permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): + ./in.cue:12:6 +permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): + ./in.cue:12:18 +issue680: invalid operand >10 ('*' requires concrete value): + ./in.cue:18:12 +issue405: invalid operand >=100 ('<=' requires concrete value): + ./in.cue:23:11 +--- in.cue +{ + permanentlyIncompleteOperands: { + a: ((string + ":") + string) + a: "golang/go:1.13.5" + } + permanentlyIncompleteOperandsNested: { + a: ((int + 1) + (int + 1)) + } + permanentlyIncompleteOperandsDisjunct: { + a: ((int + 1)|(int + 1)) + } + issue680: ((>10 * 2) & 0) + issue405: (>=100 <= 200) +} diff --git a/internal/core/compile/testdata/sync/eval/insertion.txtar b/internal/core/compile/testdata/sync/eval/insertion.txtar new file mode 100644 index 000000000..59225d636 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/insertion.txtar @@ -0,0 +1,254 @@ +# Tests various patterns of insertion of conjuncts. +# See https://cuelang.org/issues/2169 +-- a.cue -- +embeddingDirect: t1: ({ + #a: _ + _ +} & { + #a: "s" + #a +}) @test(eq, {"s", #a: "s"}) + +embeddingExpr: t1: ({ + #a: _ + _ +} & { + #a: "s" + [ #a ][0] +}) @test(eq, {"s", #a: "s"}) + +unifiedDirect: { + t1: { + #a: _ + _ + } + t1: { + #a + #a: _ + } + t1: { + _ + #a: "s" + } +} @test(eq, {t1: {"s", #a: "s"}}) + + +unifiedExpr: { + t1: { + #a: _ + _ + } + t1: { + [ #a ][0] + #a: _ + } + t1: { + #a: "s" + _ + } +} @test(eq, {t1: {"s", #a: "s"}}) + +// These two embeddings both add fields to each other's original source, which +// then, in turn, needs to be added. +cross: t1: { + a: { + b: {v: 1, a: w: 2} + // from b.a: {x: 2, b: y: 5} + } + b: { + a: {x: 2, b: y: 5} + // from a.b: {v: 1, a: v: 2} + } + a + b +} @test(eq, { + a: {b: {v: 1, a: w: 2, y: 5}, x: 2, w: 2} + b: {a: {x: 2, b: y: 5, w: 2}, v: 1, y: 5} + v: 1 + w: 2 + x: 2 + y: 5 +}) + +-- complex.cue -- +// Multiple levels of insertion +recursive: { + t1: { + e: {} + c: d: e: f: 1 + c.d + c: d: + // This part gets embedded within t1, which ends up adding new fields + // to here, when then again need to be embedded in t1, which then + // will add more fields to node e. + c: d: e: g: 1 + } + t2: { + c + c: c: g: 1 + } +} @test(eq, { + t1: { + e: {f: 1, g: 1} + c: d: { + e: {f: 1, g: 1} + c: d: e: g: 1 + } + } + t2: { + c: {c: g: 1, g: 1} + g: 1 + } +}) + +-- issue2169.cue -- +// Evaluator regression where "cannot add field $X: was already used" errors +// appeared incorrectly when a field was referenced before being defined. +// https://cuelang.org/issue/2169 +embeddedFunctionalExpr: { + #fn: { + #in: _ + _ + } & { + #in: "str" + + ({ + #t: _ + #t + } & { + #t: #in + _ + }) + "" + } + #fn +} @test(eq, {"str", #fn: {"str", #in: "str"}, #in: "str"}) +-- out/compile -- +--- a.cue +{ + embeddingDirect: { + t1: ({ + #a: _ + _ + } & { + #a: "s" + 〈0;#a〉 + }) + } + embeddingExpr: { + t1: ({ + #a: _ + _ + } & { + #a: "s" + [ + 〈1;#a〉, + ][0] + }) + } + unifiedDirect: { + t1: { + #a: _ + _ + } + t1: { + 〈0;#a〉 + #a: _ + } + t1: { + _ + #a: "s" + } + } + unifiedExpr: { + t1: { + #a: _ + _ + } + t1: { + [ + 〈1;#a〉, + ][0] + #a: _ + } + t1: { + #a: "s" + _ + } + } + cross: { + t1: { + a: { + b: { + v: 1 + a: { + w: 2 + } + } + } + b: { + a: { + x: 2 + b: { + y: 5 + } + } + } + 〈0;a〉 + 〈0;b〉 + } + } +} +--- complex.cue +{ + recursive: { + t1: { + e: {} + c: { + d: { + e: { + f: 1 + } + } + } + 〈0;c〉.d + c: { + d: { + c: { + d: { + e: { + g: 1 + } + } + } + } + } + } + t2: { + 〈0;c〉 + c: { + c: { + g: 1 + } + } + } + } +} +--- issue2169.cue +{ + embeddedFunctionalExpr: { + #fn: ({ + #in: _ + _ + } & { + #in: "str" + (({ + #t: _ + 〈0;#t〉 + } & { + #t: 〈1;#in〉 + _ + }) + "") + }) + 〈0;#fn〉 + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue1640.txtar b/internal/core/compile/testdata/sync/eval/issue1640.txtar new file mode 100644 index 000000000..5ae38eea7 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue1640.txtar @@ -0,0 +1,54 @@ +# Tests that evaluation of multi-file packages is deterministic regardless of +# field declaration order across files. The two input files a1.cue and a2.cue +# define the same fields x and y but in opposite orders; both must yield the same +# result. Also tests that #MCS (MultiCaseString, with uc: lc) correctly propagates +# concrete values when fact1 and fact2 cross-reference each other. +-- a1.cue -- +package bug + +y: fact2.uc @test(eq, "foo") +x: fact1.uc @test(eq, "foo") +-- a2.cue -- +package bug + +x: fact1.uc @test(eq, "foo") +y: fact2.uc @test(eq, "foo") +-- x.cue -- +package bug + +fact1: #MCS & {lc: fact2.lc} @test(eq, {lc: "foo", uc: "foo"}) @test(closed) +fact2: #MCS & {lc: "foo"} @test(eq, {lc: "foo", uc: "foo"}) @test(closed) + +#MCS: #MultiCaseString @test(eq, {lc: string, uc: string}) @test(closed) @test(shareID=MCS) +#MultiCaseString: { + @test(shareID=MCS) + @test(eq, {lc: string, uc: string}) + @test(closed) + lc: string + uc: lc +} +-- out/compile -- +--- a1.cue +{ + y: 〈0;fact2〉.uc + x: 〈0;fact1〉.uc +} +--- a2.cue +{ + x: 〈0;fact1〉.uc + y: 〈0;fact2〉.uc +} +--- x.cue +{ + fact1: (〈0;#MCS〉 & { + lc: 〈1;fact2〉.lc + }) + fact2: (〈0;#MCS〉 & { + lc: "foo" + }) + #MCS: 〈0;#MultiCaseString〉 + #MultiCaseString: { + lc: string + uc: 〈0;lc〉 + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue1886.txtar b/internal/core/compile/testdata/sync/eval/issue1886.txtar new file mode 100644 index 000000000..b6977edd5 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue1886.txtar @@ -0,0 +1,90 @@ +# Tests cycles and incomplete errors. The cycle struct covers resolvable cycles +# (x=200, x=y+100, y=x-100 resolves because x is grounded at 200) and +# unresolvable ones (a=b+100, b=a-100 — cycle error). The incompleteOne and +# incompleteTwo cases verify that string interpolation with an abstract type +# parameter reports "incomplete" errors correctly regardless of whether the +# hidden template field _t appears before or after its usage site. +-- in.cue -- +cycle: { + x: 200 @test(eq, 200) + x: y + 100 + y: x - 100 @test(eq, 100) + + a: b + 100 @test(err, code=cycle, + suberr=(pos=[0:5], args=[b]), + suberr=(pos=[4:5], args=[a]), + ) + b: a - 100 @test(err, code=cycle, + suberr=(pos=[-4:5], args=[b]), + suberr=(pos=[0:5], args=[a]), + ) +} + +incompleteOne: { + @test(err, code=incomplete, pos=[9:5, 3:7, 4:3], at=r) + _t: { + #p: string + """ + hello \(#p) + """ + } + + r: """ + \(_t) + """ + // TODO: we cannot check for errors on hidden fields yet. + @test(debugCheck, """ + (struct){ + _t: (_|_){ + // [incomplete] incompleteOne._t: invalid interpolation: non-concrete value string (type string): + // in.cue:20:3 + // in.cue:19:7 + #p: (string){ string } + } + r: (_|_){ + // [incomplete] incompleteOne._t: invalid interpolation: invalid interpolation: non-concrete value string (type string): + // in.cue:25:5 + // in.cue:19:7 + // in.cue:20:3 + } + } + """) +} + +incompleteTwo: { + r: """ + \(_t) + """ @test(err, code=incomplete) + + _t: { + #p: string + """ + hello \(#p) + """ + } +} +-- out/compile -- +--- in.cue +{ + cycle: { + x: 200 + x: (〈0;y〉 + 100) + y: (〈0;x〉 - 100) + a: (〈0;b〉 + 100) + b: (〈0;a〉 - 100) + } + incompleteOne: { + _t: { + #p: string + "hello \(〈0;#p〉)" + } + r: "\(〈0;_t〉)" + } + incompleteTwo: { + r: "\(〈0;_t〉)" + _t: { + #p: string + "hello \(〈0;#p〉)" + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue2146.txtar b/internal/core/compile/testdata/sync/eval/issue2146.txtar new file mode 100644 index 000000000..4c760c8cf --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue2146.txtar @@ -0,0 +1,114 @@ +# Tests that let expressions within disjunctions are uniqued per arc, not just +# per Environment. Without the fix, incorrect results were cached and shared +# across arcs, causing the `all` list to evaluate incorrectly under unification. +# https://cuelang.org/issue/2146 +// Issue #2146 +// +// Ensure that let expressions are uniqued not only per Environment, but also +// per arc. This is relevant for disjunctions. Without it, an incorrect +// result may be cached for an arbitrary Environment. +-- in.cue -- +p1: { + #A: { + x?: int + y?: int + + let list = [x, y] + all: [for v in list if v != _|_ {v}] + + *{ + x?: _|_ + y: 1 + } | _ + } + + a: #A & { x: 3 } + b: #A & a + @test(eq, { + #A: *{ + y: 1, all: [1], x?: _|_ @test(err, code=user, contains="explicit error", pos=[10:8]) + } | { + x?: int, y?: int, all: [] + } + a: {x: 3, y?: int, all: [3]} + b: {x: 3, y?: int, all: [3]} + }) +} +p2: { + #A: { + x?: int + y?: int + + let list = [x, y] + all: [for v in list if v != _|_ {v}] + + _ | *{ + x?: _|_ + y: 1 + } + } + + a: #A & { x: 3, y: 2 } + b: #A & a + @test(eq, { + #A: *{ + y: 1, all: [1], x?: _|_ @test(err, code=user, contains="explicit error") + } | { + x?: int, y?: int, all: [] + } + a: {x: 3, y: 2, all: [3, 2]} + b: {x: 3, y: 2, all: [3, 2]} + }) +} + +-- out/compile -- +--- in.cue +{ + p1: { + #A: { + x?: int + y?: int + let list#1 = [ + 〈1;x〉, + 〈1;y〉, + ] + all: [ + for _, v in 〈1;let list#1〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) { + 〈1;v〉 + }, + ] + (*{ + x?: _|_(explicit error (_|_ literal) in source) + y: 1 + }|_) + } + a: (〈0;#A〉 & { + x: 3 + }) + b: (〈0;#A〉 & 〈0;a〉) + } + p2: { + #A: { + x?: int + y?: int + let list#2 = [ + 〈1;x〉, + 〈1;y〉, + ] + all: [ + for _, v in 〈1;let list#2〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) { + 〈1;v〉 + }, + ] + (_|*{ + x?: _|_(explicit error (_|_ literal) in source) + y: 1 + }) + } + a: (〈0;#A〉 & { + x: 3 + y: 2 + }) + b: (〈0;#A〉 & 〈0;a〉) + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue2235.txtar b/internal/core/compile/testdata/sync/eval/issue2235.txtar new file mode 100644 index 000000000..e7ee46793 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue2235.txtar @@ -0,0 +1,268 @@ +# Tests that nested for-loop comprehensions with dynamic field assignments do +# not trigger a nil pointer dereference panic. The issue occurred in the +# evaluator's conjunct handling when processing nested iterations over structs. +# https://cuelang.org/issue/2235 +// Test various orders +// https://cuelang.org/issues/2235 +-- reductions.cue -- +// Each of these tests triggers a slightly different path. + +t1: { + params: x.y + x: y: {} + for _ in x { + if true { + x: y: a: {} + } + } + @test(eq, {params: {a: {}}, x: {y: {a: {}}}}) +} + +t2: { + out: X.y + let X = m.x + m: x: y: {} + for v in m { + if true { + m: x: y: z: {} + } + } + @test(eq, {out: {z: {}}, m: {x: {y: {z: {}}}}}) +} + +t3: { + out: foo.bar + + foo: bar: {} + + for _ in foo { + for name, _ in foo { + foo: (name): _ + } + } + @test(eq, {out: {}, foo: {bar: {}}}) +} + +-- issue2235.cue -- +package kubecluster + +import ( + "strings" + "net" +) + +shorewallParams: close({ + [=~"^[A-Z0-9_]+$"]: [...net.IP] +}) + +#Cluster: { + clusterName: string + shorewallPrefix: "KUBERNETES_\(strings.ToUpper(clusterName))" +} + +clusters: [CLUSTER=string]: #Cluster & { + clusterName: CLUSTER +} + +#Cluster: { + globalIngressControllers: [string]: #GlobalIngressController + globalIngressControllers: admin: #GlobalIngressController & { + class: "admin" + } + for _, c in globalIngressControllers { + objects: c.objects + } +} + +for clusterName, cluster in clusters { + for class, controller in cluster.globalIngressControllers { + let svc = controller.objects.namespaced.ingress.Service["\(class)-nginx-ingress-controller"] + + shorewallParams: "\(cluster.shorewallPrefix)_INGRESS_\(strings.ToUpper(class))": svc.spec.externalIPs + } +} + +#GlobalIngressController: { + class: string + + objects: namespaced: ingress: { + Service: "\(class)-nginx-ingress-controller": { + spec: { + externalIPs: ["127.0.0.1"] + } + } + } + + for kind, objs in objects.namespaced.ingress { + for name, obj in objs { + objects: namespaced: ingress: "\(kind)": "\(name)": metadata: labels: { + "ingress-class": class + stack: "ingress" + ... + } + } + } +} + +clusters: foo: {} + +@test(eq, { + foo: { + clusterName: "foo" + shorewallPrefix: "KUBERNETES_FOO" + globalIngressControllers: admin: { + class: "admin" + objects: namespaced: ingress: Service: { + "admin-nginx-ingress-controller": { + spec: {externalIPs: ["127.0.0.1"]} + metadata: labels: { + "ingress-class": "admin" + stack: "ingress" + } + } + } + } + objects: namespaced: ingress: { + Service: "admin-nginx-ingress-controller": { + spec: {externalIPs: ["127.0.0.1"]} + metadata: labels: { + "ingress-class": "admin" + stack: "ingress" + } + } + } + } +}, at=clusters) + +-- out/compile -- +--- issue2235.cue +{ + shorewallParams: close({ + [=~"^[A-Z0-9_]+$"]: [ + ...〈import;net〉.IP, + ] + }) + #Cluster: { + clusterName: string + shorewallPrefix: "KUBERNETES_\(〈import;strings〉.ToUpper(〈0;clusterName〉))" + } + clusters: { + [string]: (〈1;#Cluster〉 & { + clusterName: 〈1;-〉 + }) + } + #Cluster: { + globalIngressControllers: { + [string]: 〈2;#GlobalIngressController〉 + } + globalIngressControllers: { + admin: (〈2;#GlobalIngressController〉 & { + class: "admin" + }) + } + for _, c in 〈0;globalIngressControllers〉 { + objects: 〈1;c〉.objects + } + } + for clusterName, cluster in 〈0;clusters〉 { + for class, controller in 〈1;cluster〉.globalIngressControllers { + let svc#1multi = 〈1;controller〉.objects.namespaced.ingress.Service["\(〈1;class〉)-nginx-ingress-controller"] + shorewallParams: { + "\(〈4;cluster〉.shorewallPrefix)_INGRESS_\(〈import;strings〉.ToUpper(〈2;class〉))": 〈1;let svc#1〉.spec.externalIPs + } + } + } + #GlobalIngressController: { + class: string + objects: { + namespaced: { + ingress: { + Service: { + "\(〈4;class〉)-nginx-ingress-controller": { + spec: { + externalIPs: [ + "127.0.0.1", + ] + } + } + } + } + } + } + for kind, objs in 〈0;objects〉.namespaced.ingress { + for name, obj in 〈1;objs〉 { + objects: { + namespaced: { + ingress: { + "\(〈6;kind〉)": { + "\(〈5;name〉)": { + metadata: { + labels: { + "ingress-class": 〈11;class〉 + stack: "ingress" + ... + } + } + } + } + } + } + } + } + } + } + clusters: { + foo: {} + } +} +--- reductions.cue +{ + t1: { + params: 〈0;x〉.y + x: { + y: {} + } + for _, _ in 〈0;x〉 { + if true { + x: { + y: { + a: {} + } + } + } + } + } + t2: { + out: 〈0;let X#2〉.y + let X#2 = 〈0;m〉.x + m: { + x: { + y: {} + } + } + for _, v in 〈0;m〉 { + if true { + m: { + x: { + y: { + z: {} + } + } + } + } + } + } + t3: { + out: 〈0;foo〉.bar + foo: { + bar: {} + } + for _, _ in 〈0;foo〉 { + for name, _ in 〈2;foo〉 { + foo: { + 〈2;name〉: _ + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue2337.txtar b/internal/core/compile/testdata/sync/eval/issue2337.txtar new file mode 100644 index 000000000..cdad9e2f1 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue2337.txtar @@ -0,0 +1,92 @@ +# evalv2 reported "x: was already used" instead of "conflicting values" for the +# simple.x case. The issue2473 cases test that comprehension guards do not prevent +# fields referenced in the guard from being further constrained in the outer scope +# — env2 should remain "prod" even after being used as a comprehension condition. +# The "one" variant broke on v0.6.0; the "two" variant also failed on v0.5.0. +-- in.cue -- +// evalv2 failed with the confusing error "x: was already used" +// rather than a friendlier "conflicting values" error. +simple: { + x: "x" @test(err, code=eval, + contains="conflicting values", + args=["foo", "x"], + pos=[0:7, 5:7]) + + (x): "foo" +} +// Worked on CUE v0.5.0, broke on v0.6.0 with "was already used". +// Should succeed, as the comprehension does not change env2. +issue2473: one: { + c: { + env: "prod" + env: "dev" | "prod" + env2: env + } + + if c.env2 == "prod" { + { + c: env2: string + example: c.env2 + } + } + @test(eq, { + c: {env: "prod", env2: "prod"}, + example: "prod"} + ) +} +// A variant of the above which failed on v0.5.0 as well. +issue2473: two: { + env: "prod" + env: "dev" | "prod" + env2: env + + if env2 == "prod" { + { + env2: string + example: env2 + } + } + @test(eq, { + env: "prod" + env2: "prod" + example: "prod" + }) +} +-- out/compile -- +--- in.cue +{ + simple: { + x: "x" + 〈0;x〉: "foo" + } + issue2473: { + one: { + c: { + env: "prod" + env: ("dev"|"prod") + env2: 〈0;env〉 + } + if (〈0;c〉.env2 == "prod") { + { + c: { + env2: string + } + example: 〈0;c〉.env2 + } + } + } + } + issue2473: { + two: { + env: "prod" + env: ("dev"|"prod") + env2: 〈0;env〉 + if (〈0;env2〉 == "prod") { + { + env2: string + example: 〈0;env2〉 + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue2550.txtar b/internal/core/compile/testdata/sync/eval/issue2550.txtar new file mode 100644 index 000000000..bb9abd0da --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue2550.txtar @@ -0,0 +1,24 @@ +# Tests that accessing an undefined field (bar.missing) on a closed empty struct +# (bar: close({})) inside a comprehension guard correctly reports "undefined +# field" rather than panicking or producing a wrong result. The let binding +# (let _bar = bar) inside the comprehension body verifies that let bindings in +# comprehensions interacting with closed structs do not affect the error behavior. +-- in.cue -- +foo: string @test(eq, string) +bar: close({}) @test(eq, {}) @test(closed) + +if bar.missing == "x" { + let _bar = bar + foo: _bar +} +@test(err, code=eval, contains="undefined field", args=[missing], pos=[in.cue:4:8]) +-- out/compile -- +--- in.cue +{ + foo: string + bar: close({}) + if (〈0;bar〉.missing == "x") { + let _bar#1 = 〈1;bar〉 + foo: 〈0;let _bar#1〉 + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue2649.txtar b/internal/core/compile/testdata/sync/eval/issue2649.txtar new file mode 100644 index 000000000..d08e0893b --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue2649.txtar @@ -0,0 +1,14 @@ +# Tests that list.Avg returns a float value (not an integer) when the result +# is mathematically a whole number. Issue: in v0.6.0 the integer representation +# of the float result caused incorrect Int64() reads and panics in Int(). +# https://cuelang.org/issue/2649 +-- in.cue -- +@test(eq, 8.0) +@test(eq:todo, 8) +@test(kind=float) // TODO: should this be a float, or can it also be an int? +(4 + 8 + 12) / 3 +-- out/compile -- +--- in.cue +{ + (((4 + 8) + 12) / 3) +} diff --git a/internal/core/compile/testdata/sync/eval/issue285.txtar b/internal/core/compile/testdata/sync/eval/issue285.txtar new file mode 100644 index 000000000..895cd9208 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue285.txtar @@ -0,0 +1,41 @@ +# Tests that a definition referencing another definition with a nested pattern +# constraint correctly propagates field constraints through Instance.Fill and +# unification. Issue: filling a field in a closed nested struct failed with +# "field not allowed" when the constraint was inherited via a parent definition +# rather than explicitly re-stated. +# https://cuelang.org/issue/285 +-- in.cue -- +#TopLevel: [name=string]: { + path: string + content: string +} + +#Mid: #TopLevel & { + myoutput: path: "/output" +} @test(closed) @test(eq, { + myoutput: {path: "/output", content: string} +}) + +val: #Mid & {} & {myoutput: {content: "foo"}} @test(closed) @test(eq, { + myoutput: {content: "foo", path: "/output"} +}) // Should work. +-- out/compile -- +--- in.cue +{ + #TopLevel: { + [string]: { + path: string + content: string + } + } + #Mid: (〈0;#TopLevel〉 & { + myoutput: { + path: "/output" + } + }) + val: ((〈0;#Mid〉 & {}) & { + myoutput: { + content: "foo" + } + }) +} diff --git a/internal/core/compile/testdata/sync/eval/issue295.txtar b/internal/core/compile/testdata/sync/eval/issue295.txtar new file mode 100644 index 000000000..d6e621c1d --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue295.txtar @@ -0,0 +1,21 @@ +# Tests that a closed struct with an interpolated dynamic field key correctly +# unifies with a regular field of the same name. Issue: `cue vet -c` reported +# "field not allowed in closed struct" when the key was written as `"\("f")":` +# even though the resulting field name is identical to a subsequently declared +# regular field. +# https://cuelang.org/issue/295 +-- in.cue -- +p: close({ + "\("f")": _ +}) @test(eq, {f: 9}) @test(closed) +p: f: 9 +-- out/compile -- +--- in.cue +{ + p: close({ + "\("f")": _ + }) + p: { + f: 9 + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3301.txtar b/internal/core/compile/testdata/sync/eval/issue3301.txtar new file mode 100644 index 000000000..07365cab4 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3301.txtar @@ -0,0 +1,57 @@ +# Tests that closedness is correctly propagated through multiple levels of +# embedded definitions with optional fields and conditional comprehensions. +# #Leaf embeds #Mid (which embeds #Base), all with optional fields. The nested +# if comprehensions inside #Leaf reference optional fields without triggering +# spurious closedness errors. +-- in.cue -- +object: #Leaf & {} @test(eq, {extra?: {}, more?: int}) @test(closed) + +#Base: { + extra?: {...} + @test(eq, {extra?: {}}) + @test(closed) +} + +#Mid: { + #Base + @test(eq, {extra?: {}}) + @test(closed) +} + +#Leaf: { + #Mid + extra?: {...} + more?: int + if extra.foo != _|_ { + if more != _|_ { + foo: "bar" + } + } + @test(eq, {extra?: {}, more?: int}) + @test(closed) +} +-- out/compile -- +--- in.cue +{ + object: (〈0;#Leaf〉 & {}) + #Base: { + extra?: { + ... + } + } + #Mid: { + 〈1;#Base〉 + } + #Leaf: { + 〈1;#Mid〉 + extra?: { + ... + } + more?: int + if (〈0;extra〉.foo != _|_(explicit error (_|_ literal) in source)) { + if (〈1;more〉 != _|_(explicit error (_|_ literal) in source)) { + foo: "bar" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3330.txtar b/internal/core/compile/testdata/sync/eval/issue3330.txtar new file mode 100644 index 000000000..6060ca3e9 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3330.txtar @@ -0,0 +1,77 @@ +-- in.cue -- +import "list" + +// issue3330: out[0] is a list element that shares #A's vertex. +issue3330: { + #A: { + let empty = {} + + // Reference to empty is within the definition that defines it. Closedness + // thus does not trigger. + field: null | { n: int } + field: empty & { n: 3 } + } @test(eq, {field: {n: 3}}) @test(shareID=A) + + out: list.Concat([[#A]]) @test(eq, [{field: {n: 3}}]) @test(shareID=A, at=0) +} + +// eliminated: ensures a definition used only for the empty struct triggers the +// disjunct-elimination code path that caused the original panic in issue3330. +eliminated: { + #empty: {} + x: null | { n: 3 } + x: #empty & { n: 3 } @test(err, code=eval, contains="empty disjunction", + suberr=(pos=[-1:5, 0:5, 0:14], contains="conflicting values", args=[struct, null]), + suberr=(pos=[-1:14, 0:16], contains="not allowed")) + out: len(x) @test(err, code=eval) +} + +// simplified: different take showing the bug is triggered after a definition +// is referenced. +simplified: { + #struct: { + field: { n: 3 } & g + g: {} + } @test(eq, {field: {n: 3}, g: {}}) + + out: #struct & {} @test(eq, {field: {n: 3}, g: {}}) +} +-- out/compile -- +--- in.cue +{ + issue3330: { + #A: { + let empty#1 = {} + field: (null|{ + n: int + }) + field: (〈0;let empty#1〉 & { + n: 3 + }) + } + out: 〈import;list〉.Concat([ + [ + 〈2;#A〉, + ], + ]) + } + eliminated: { + #empty: {} + x: (null|{ + n: 3 + }) + x: (〈0;#empty〉 & { + n: 3 + }) + out: len(〈0;x〉) + } + simplified: { + #struct: { + field: ({ + n: 3 + } & 〈0;g〉) + g: {} + } + out: (〈0;#struct〉 & {}) + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue349.txtar b/internal/core/compile/testdata/sync/eval/issue349.txtar new file mode 100644 index 000000000..dd91e88e9 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue349.txtar @@ -0,0 +1,40 @@ +# Tests that field names overlapping with built-in identifiers (e.g. "html", +# "list") are not reordered to the front of the struct during evaluation. +# Issue: `cue eval` placed such fields before others, violating declaration +# order. +# https://cuelang.org/issue/349 +-- in.cue -- +ex: { + @test(eq, { + aaa: "aaa" + list: "list" + zzz: "zzz" + AAA: "AAA" + html: "html" + HTML: "html" + ZZZ: "ZZZ" + Html: "html" + }) + "aaa": "aaa" + "list": "list" + "zzz": "zzz" + "AAA": "AAA" + "html": "html" + "HTML": "html" + "ZZZ": "ZZZ" + "Html": "html" +} +-- out/compile -- +--- in.cue +{ + ex: { + aaa: "aaa" + list: "list" + zzz: "zzz" + AAA: "AAA" + html: "html" + HTML: "html" + ZZZ: "ZZZ" + Html: "html" + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue353.txtar b/internal/core/compile/testdata/sync/eval/issue353.txtar new file mode 100644 index 000000000..9a55c597e --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue353.txtar @@ -0,0 +1,36 @@ +# Tests that unifying a value with a definition that embeds a disjunction +# correctly retains both disjunction branches after concretizing some fields. +# Issue: after setting e.a = "hello" the two-branch disjunction (one with +# value?, one with externalValue?) should survive intact. +# https://cuelang.org/issue/353 +-- in.cue -- +e: #Example +e: { + a: "hello" + @test(eq, {a: "hello", value?: string} | {a: "hello", externalValue?: string}) +} + +#Example: { + a: string + { + value?: string + } | { + externalValue?: string + } +} +-- out/compile -- +--- in.cue +{ + e: 〈0;#Example〉 + e: { + a: "hello" + } + #Example: { + a: string + ({ + value?: string + }|{ + externalValue?: string + }) + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3672.txtar b/internal/core/compile/testdata/sync/eval/issue3672.txtar new file mode 100644 index 000000000..a763032be --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3672.txtar @@ -0,0 +1,315 @@ +# Tests that inline unification patterns like `(#mkDef & {}).#Type` evaluate +# correctly in the v3 evaluator. The issue caused evalv3 to include unwanted +# disjunction alternatives, making orgSyntax compute the wrong branch result. +# https://cuelang.org/issue/3672 +-- x.cue -- +import "strings" + +import "encoding/json" + +#FinDefSetElemType: { + #Type!: _ +} +#FinDefSetDefinition: { + #Elem!: #FinDefSetElemType + #Alternatives: { + allBut: { + AllBut: [...#Elem.#Type] + } + only: { + Only: [...#Elem.#Type] + } + } +} + +#mkFinDefSet: { + #Definition!: #FinDefSetDefinition + #Type: or([for _, v in #Definition.#Alternatives {v}]) +} + +#FinDefSetElemType: { + #Type: _ + toString!: { + _input: #Type + _output: string + } +} + +#FinDefSetDefinition: { + #Elem!: #FinDefSetElemType + #Alternatives: { + allBut: { + AllBut: [...#Elem.#Type] + let xs = [for x in AllBut {(#Elem.toString & {_input: x})._output}] + let str = strings.Join(xs, "\",\"") + orgSyntax: "AllBut [\(str)]" + } + only: { + Only: [...#Elem.#Type] + let xs = [for x in Only {(#Elem.toString & {_input: x})._output}] + let str = strings.Join(xs, "\",\"") + orgSyntax: "Only [\(str)]" + } + } +} + +#ConfigText: string | {UseSectionName: true} + +#ConfigTextRule: #ConfigText | {Append: #ConfigText} | {Prepend: #ConfigText} + +#ConfigTextRules: #ConfigTextRule | [#ConfigTextRule, #ConfigTextRule, ...#ConfigTextRule] + +#FinDefSetConfigTextElem: #FinDefSetElemType +#FinDefSetConfigTextElem: { + #Type: #ConfigTextRules +} + +#FinDefSetOfConfigText: ( + #mkFinDefSet & { + #Definition: {#Elem: #FinDefSetConfigTextElem} + }).#Type + +#FinDefSetConfigTextElem: { + toString: { + _input: #ConfigTextRules + _output: (#orgForConfigTextRules & {source: _input}).orgSyntax + } +} + +#orgForConfigText: { + IN=source: #ConfigText + orgSyntax: { + let INS = IN & string + let INO = IN & {UseSectionName: _} + [ + if INS != _|_ { + json.Marshal(INS) + }, + if INO != _|_ { + "UseSectionName" + }, + "Impossible", + ][0] + } +} + +#orgForConfigTextRule: { + IN=source: #ConfigTextRule + orgSyntax: { + let INA = IN & {Append: _} + let INP = IN & {Prepend: _} + [ + if INA != _|_ { + "Append " + (#orgForConfigText & {source: INA.Append}).orgSyntax + }, + if INP != _|_ { + "Prepend " + (#orgForConfigText & {source: INP.Prepend}).orgSyntax + }, + (#orgForConfigText & {source: IN}).orgSyntax, + ][0] + } +} + +#orgForConfigTextRules: { + IN=source: #ConfigTextRules + orgSyntax: { + let INL = IN & [...] + [ + if INL != _|_ { + let elems = [for x in IN {(#orgForConfigTextRule & {source: x}).orgSyntax}] + let result = strings.Join(elems, "\",\"") + "[\(result)]" + }, + (#orgForConfigTextRule & {source: IN}).orgSyntax, + ][0] + } +} + +value0: #FinDefSetOfConfigText +value0: Only: [{UseSectionName: true}] +@test(eq, { + Only: [{ UseSectionName: true }] + orgSyntax: "Only [UseSectionName]" +}, at=value0) + +@test(err, at=#mkFinDefSet.#Type, code=incomplete, contains="error in call to %s", args=[or], pos=[-108:9, -108:25]) +// TODO(inline): test wrapped errors +@test(err, at=#orgForConfigTextRules.orgSyntax, code=incomplete, path=elems, contains="invalid interpolation", pos=[-16:5, -18:18]) +@test(err, at=#FinDefSetConfigTextElem.toString._output, code=incomplete, path=elems, contains="invalid interpolation", pos=[-17:5, -19:18]) + +-- out/compile -- +--- x.cue +{ + #FinDefSetElemType: { + #Type!: _ + } + #FinDefSetDefinition: { + #Elem!: 〈1;#FinDefSetElemType〉 + #Alternatives: { + allBut: { + AllBut: [ + ...〈3;#Elem〉.#Type, + ] + } + only: { + Only: [ + ...〈3;#Elem〉.#Type, + ] + } + } + } + #mkFinDefSet: { + #Definition!: 〈1;#FinDefSetDefinition〉 + #Type: or([ + for _, v in 〈1;#Definition〉.#Alternatives { + 〈1;v〉 + }, + ]) + } + #FinDefSetElemType: { + #Type: _ + toString!: { + _input: 〈1;#Type〉 + _output: string + } + } + #FinDefSetDefinition: { + #Elem!: 〈1;#FinDefSetElemType〉 + #Alternatives: { + allBut: { + AllBut: [ + ...〈3;#Elem〉.#Type, + ] + let xs#1 = [ + for _, x in 〈1;AllBut〉 { + (〈5;#Elem〉.toString & { + _input: 〈2;x〉 + })._output + }, + ] + let str#2 = 〈import;strings〉.Join(〈0;let xs#1〉, "\",\"") + orgSyntax: "AllBut [\(〈0;let str#2〉)]" + } + only: { + Only: [ + ...〈3;#Elem〉.#Type, + ] + let xs#3 = [ + for _, x in 〈1;Only〉 { + (〈5;#Elem〉.toString & { + _input: 〈2;x〉 + })._output + }, + ] + let str#4 = 〈import;strings〉.Join(〈0;let xs#3〉, "\",\"") + orgSyntax: "Only [\(〈0;let str#4〉)]" + } + } + } + #ConfigText: (string|{ + UseSectionName: true + }) + #ConfigTextRule: (〈0;#ConfigText〉|{ + Append: 〈1;#ConfigText〉 + }|{ + Prepend: 〈1;#ConfigText〉 + }) + #ConfigTextRules: (〈0;#ConfigTextRule〉|[ + 〈1;#ConfigTextRule〉, + 〈1;#ConfigTextRule〉, + ...〈1;#ConfigTextRule〉, + ]) + #FinDefSetConfigTextElem: 〈0;#FinDefSetElemType〉 + #FinDefSetConfigTextElem: { + #Type: 〈1;#ConfigTextRules〉 + } + #FinDefSetOfConfigText: (〈0;#mkFinDefSet〉 & { + #Definition: { + #Elem: 〈2;#FinDefSetConfigTextElem〉 + } + }).#Type + #FinDefSetConfigTextElem: { + toString: { + _input: 〈2;#ConfigTextRules〉 + _output: (〈2;#orgForConfigTextRules〉 & { + source: 〈1;_input〉 + }).orgSyntax + } + } + #orgForConfigText: { + source: 〈1;#ConfigText〉 + orgSyntax: { + let INS#5 = (〈1;source〉 & string) + let INO#6 = (〈1;source〉 & { + UseSectionName: _ + }) + [ + if (〈1;let INS#5〉 != _|_(explicit error (_|_ literal) in source)) { + 〈import;"encoding/json"〉.Marshal(〈2;let INS#5〉) + }, + if (〈1;let INO#6〉 != _|_(explicit error (_|_ literal) in source)) { + "UseSectionName" + }, + "Impossible", + ][0] + } + } + #orgForConfigTextRule: { + source: 〈1;#ConfigTextRule〉 + orgSyntax: { + let INA#7 = (〈1;source〉 & { + Append: _ + }) + let INP#8 = (〈1;source〉 & { + Prepend: _ + }) + [ + if (〈1;let INA#7〉 != _|_(explicit error (_|_ literal) in source)) { + ("Append " + (〈4;#orgForConfigText〉 & { + source: 〈3;let INA#7〉.Append + }).orgSyntax) + }, + if (〈1;let INP#8〉 != _|_(explicit error (_|_ literal) in source)) { + ("Prepend " + (〈4;#orgForConfigText〉 & { + source: 〈3;let INP#8〉.Prepend + }).orgSyntax) + }, + (〈3;#orgForConfigText〉 & { + source: 〈3;source〉 + }).orgSyntax, + ][0] + } + } + #orgForConfigTextRules: { + source: 〈1;#ConfigTextRules〉 + orgSyntax: { + let INL#9 = (〈1;source〉 & [ + ..., + ]) + [ + if (〈1;let INL#9〉 != _|_(explicit error (_|_ literal) in source)) { + let elems#A = [ + for _, x in 〈4;source〉 { + (〈7;#orgForConfigTextRule〉 & { + source: 〈2;x〉 + }).orgSyntax + }, + ] + let result#B = 〈import;strings〉.Join(〈0;let elems#A〉, "\",\"") + "[\(〈0;let result#B〉)]" + }, + (〈3;#orgForConfigTextRule〉 & { + source: 〈3;source〉 + }).orgSyntax, + ][0] + } + } + value0: 〈0;#FinDefSetOfConfigText〉 + value0: { + Only: [ + { + UseSectionName: true + }, + ] + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3688.txtar b/internal/core/compile/testdata/sync/eval/issue3688.txtar new file mode 100644 index 000000000..91b6685b4 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3688.txtar @@ -0,0 +1,98 @@ +# Tests that #fun1 with a hidden field _in: #TypeA (where #TypeA: string | +# {foo: int}) correctly computes out using comprehensions that select based on +# whether _in is a string or has field foo. evalv2 had closedness bugs where eg2 +# (input {foo: 5}) failed to select "foo" and eg3 (input {foo: 5, bar: "test"}) +# failed to fall through to "impossible". evalv3 fixed these bugs. +-- x.cue -- +package x + +#TypeA: string | {foo: int} + +#fun1: { + _in: #TypeA + out: [ + // either `in` is a string + if (_in & string) != _|_ { + _in + }, + // or `in` is has field `foo` + if _in.foo != _|_ { + "foo" + }, + "impossible", // in & #TypeA != _|_ !! + ][0] +} + +examples: [string]: { + in: _ + res: (#fun1 & {_in: in, _}).out +} + +examples: eg1: { + in: "test" + @test(eq, {in: "test", res: "test"}) +} +examples: eg2: { + in: { + foo: 5 + } + @test(eq, {in: {foo: 5}, res: "foo"}) +} +examples: eg3: { + in: { + foo: 5 + bar: "test" + } + @test(eq, { + in: {foo: 5, bar: "test"} + res: "impossible" + }) +} +-- out/compile -- +--- x.cue +{ + #TypeA: (string|{ + foo: int + }) + #fun1: { + _in(:x): 〈1;#TypeA〉 + out: [ + if ((〈1;_in(:x)〉 & string) != _|_(explicit error (_|_ literal) in source)) { + 〈2;_in(:x)〉 + }, + if (〈1;_in(:x)〉.foo != _|_(explicit error (_|_ literal) in source)) { + "foo" + }, + "impossible", + ][0] + } + examples: { + [string]: { + in: _ + res: (〈2;#fun1〉 & { + _in(:x): 〈1;in〉 + _ + }).out + } + } + examples: { + eg1: { + in: "test" + } + } + examples: { + eg2: { + in: { + foo: 5 + } + } + } + examples: { + eg3: { + in: { + foo: 5 + bar: "test" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3709.txtar b/internal/core/compile/testdata/sync/eval/issue3709.txtar new file mode 100644 index 000000000..5b3b1da55 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3709.txtar @@ -0,0 +1,27 @@ +# Tests that mutually recursive optional definitions across packages do not cause +# the evaluator to hang. Issue: a pattern constraint referencing a type from an +# imported package, where that type and its transitive references form a cycle +# (e.g. #Foo -> #Bar -> #Foo), caused an infinite loop during evaluation. +# https://cuelang.org/issue/3709 +-- cue.mod/module.cue -- +module: "foo.test/bar" +language: version: "v0.11.0" +-- input.cue -- +package p + +import "foo.test/bar/imported" + +out: [string]: imported.#Foo +@test(eq, { out: [string]: {bar?: foo?: _ @test(ignore)} }) +-- imported/imported.cue -- +package imported + +#Foo: bar?: #Bar +#Bar: foo?: #Foo +-- out/compile -- +--- input.cue +{ + out: { + [string]: 〈import;"foo.test/bar/imported"〉.#Foo + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3801.txtar b/internal/core/compile/testdata/sync/eval/issue3801.txtar new file mode 100644 index 000000000..39b4bd75b --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3801.txtar @@ -0,0 +1,309 @@ +# This issue addresses evaluation in nested lets. +-- nested.cue -- +issue3801: let: reduced: { + let F = { + base: { + in: string + let X = {a: "\(in)" }.a + out: X + } + filled: base & {in: "foo"} // failure is here + } + z: F.filled.out + @test(eq, {z: "foo"}) +} +issue3801: nonRooted: reduced: { + #Output: output: { + #base: { + val0: string + msgObj: {a: val0}.a + value: msgObj + } + out: #base & {val0: "foo"} + } + out: (#Output & {}).output // non-concrete + @test(eq, { + #Output: { + output: { + #base: { + val0: string + msgObj: string + value: string + } + out: { + val0: "foo" + msgObj: "foo" + value: "foo" + } + } + } + out: { + #base: { + val0: string + msgObj: string + value: string + } + out: { + val0: "foo" + msgObj: "foo" + value: "foo" + } + } + }) +} +issue3801: let: full: { + #Resource: { + someMsg: string + obs: {} | *{missing: true} + + let pickMsg = [ + if obs.missing {msg: "\(someMsg)"}, + {msg: "bar"}, + ][0] + patches: [{ + op: "add" + path: "/metadata" + value: pickMsg.msg + }] + } + + #Patches: [string]: _ + #JSONPatch: { + namespace?: string + patch: [...#JSONOp] + output: #Patches & {(namespace): patch} + } + #JSONOp: { + op: "add" + path: string + value: _ + } | { + op: "remove" + path: string + } + + #Main: { + NS=namespace: string + + output: jsonPatch.output + + let jsonPatch = #JSONPatch & { + let base = #Resource & {} + let withMsg = base & {someMsg: "foo"} + + namespace: NS + + patch: withMsg.patches + } + } + out: (#Main & {namespace: "ns1"}).output + @test(eq, { + #Resource: { + someMsg: string + obs: *{missing: true} | {} + patches: [{op: "add", path: "/metadata", value: _ @test(ignore)}] + } + #Patches: {} + #JSONPatch: { + namespace?: string + patch: [] + output: _|_ @test(err, code=incomplete, contains="key value of dynamic field must be concrete", pos=[72:24]) + } + #JSONOp: {op: "add", path: string, value: _} | {op: "remove", path: string} + #Main: { + namespace: string + output: _|_ @test(err, code=incomplete) + } + out: { + ns1: [{op: "add", path: "/metadata", value: "foo"}] + } + }) +} +issue3801: nonRooted: full: { + #Output: { + NS=namespace: string + output: (#SubOutput & { + namespace: NS + let base2 = { + let base = #Base & {} + output: base & {val0: "foo"} + } + patch: base2.output.value + }).output @test(err, code=incomplete, contains="key value of dynamic field must be concrete, found %v", args=[string], pos=[15:12, 12:15]) + } + out: (#Output & {namespace: "ns1"}).output + + #SubOutput: { + namespace?: string + + patch: _ + output: (namespace): patch + + // TODO(eval): our message is substituted as a string instead of being wrapped as an error. + @test(err, at=output, code=incomplete, + suberr=(code=incomplete, contains="key value of dynamic field must be concrete, found %v", + args=[_|_(issue3801.nonRooted.full.#SubOutput.output: cannot reference optional field: namespace)], pos=[4:12]), + suberr=(code=incomplete, contains="cannot reference optional field: %s", args=[namespace], pos=[4:12])) + } + + #Base: { + val0: string + let msgObj = [val0][0] + value: msgObj + } + @test(eq, { + #Output: { + namespace: string + output: _|_ + } + out: {ns1: "foo"} + #SubOutput: { + namespace?: string + patch: _ + output: _|_ + } + #Base: {val0: string, value: string} + }) +} +-- out/compile -- +--- nested.cue +{ + issue3801: { + let: { + reduced: { + let F#1 = { + base: { + in: string + let X#2 = { + a: "\(〈1;in〉)" + }.a + out: 〈0;let X#2〉 + } + filled: (〈0;base〉 & { + in: "foo" + }) + } + z: 〈0;let F#1〉.filled.out + } + } + } + issue3801: { + nonRooted: { + reduced: { + #Output: { + output: { + #base: { + val0: string + msgObj: { + a: 〈1;val0〉 + }.a + value: 〈0;msgObj〉 + } + out: (〈0;#base〉 & { + val0: "foo" + }) + } + } + out: (〈0;#Output〉 & {}).output + } + } + } + issue3801: { + let: { + full: { + #Resource: { + someMsg: string + obs: ({}|*{ + missing: true + }) + let pickMsg#4 = [ + if 〈1;obs〉.missing { + msg: "\(〈2;someMsg〉)" + }, + { + msg: "bar" + }, + ][0] + patches: [ + { + op: "add" + path: "/metadata" + value: 〈2;let pickMsg#4〉.msg + }, + ] + } + #Patches: { + [string]: _ + } + #JSONPatch: { + namespace?: string + patch: [ + ...〈2;#JSONOp〉, + ] + output: (〈1;#Patches〉 & { + 〈1;namespace〉: 〈1;patch〉 + }) + } + #JSONOp: ({ + op: "add" + path: string + value: _ + }|{ + op: "remove" + path: string + }) + #Main: { + namespace: string + output: 〈0;let jsonPatch#5〉.output + let jsonPatch#5 = (〈1;#JSONPatch〉 & { + let base#8 = (〈2;#Resource〉 & {}) + let withMsg#9 = (〈0;let base#8〉 & { + someMsg: "foo" + }) + namespace: 〈1;namespace〉 + patch: 〈0;let withMsg#9〉.patches + }) + } + out: (〈0;#Main〉 & { + namespace: "ns1" + }).output + } + } + } + issue3801: { + nonRooted: { + full: { + #Output: { + namespace: string + output: (〈1;#SubOutput〉 & { + namespace: 〈1;namespace〉 + let base2#A = { + let base#B = (〈3;#Base〉 & {}) + output: (〈0;let base#B〉 & { + val0: "foo" + }) + } + patch: 〈0;let base2#A〉.output.value + }).output + } + out: (〈0;#Output〉 & { + namespace: "ns1" + }).output + #SubOutput: { + namespace?: string + patch: _ + output: { + 〈1;namespace〉: 〈1;patch〉 + } + } + #Base: { + val0: string + let msgObj#D = [ + 〈1;val0〉, + ][0] + value: 〈0;let msgObj#D〉 + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3805.txtar b/internal/core/compile/testdata/sync/eval/issue3805.txtar new file mode 100644 index 000000000..698745dd8 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3805.txtar @@ -0,0 +1,330 @@ +# Tests that complex schema definitions with multiple type aliases, comprehensions, +# and nested struct unification evaluate correctly in the v3 evaluator. The issue +# reported that evalv3 produced validation errors for code accepted by evalv2. +# https://cuelang.org/issue/3805 +-- x.cue -- +#PatientViewSections: { + [string]: #PatientViewSection +} + +#PatientViewSection: #PvSection @test(shareID=pvSection) + +#PvSection: { + @test(shareID=pvSection) + Section: { + display?: string + entries: #PatientViewEntries + } + _json: [for k, v in Section.entries {(k): v._json}] +} + +#PatientViewEntries: [string]: #PatientViewEntry + +#PatientViewEntry: { + #PvSingleForm | #PvLink +} + +#PvSingleForm: { + SingleForm: { + formId: string + showNumberOfInstances?: bool + } + _json: [{ + "iDoc": "singleFormIDoc" + "X-FormId": SingleForm.formId + }] +} + +#PvLink: { + Link: { + icon?: string + sections: #PatientViewSections + } + _json: [for k, v in Link.sections {(k): v._json}] +} + +#TabcatsJson: { + config: { + tabcats: #PatientViewSections + ... + } + json: { + //tabcats: #OrgContents + tabcats: [for k, v in config.tabcats {(k): v._json}] + } +} + +tabcatsExample: #TabcatsJson +tabcatsExample: { + _e1: #PatientViewEntry + _e1: { + Link: { + sections: "Formulare": { + Section: entries: "Fotodokumentation": _e2 + } + } + } + _e2: #PatientViewEntry + _e2: { + SingleForm: { + formId: "fotodokumentation" + } + } + _s: #PvSection + _s: Section: entries: "Dokumentation": _e1 + config: { + tabcats: "02": _s + } + @test(eq, { + _e1: { + Link: { + sections: { + Formulare: { + Section: { + entries: { + Fotodokumentation: { + SingleForm: { + formId: "fotodokumentation" + showNumberOfInstances?: bool + } + _json: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + } + } + display?: string + } + _json: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + } + } + icon?: string + } + _json: [{ + Formulare: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + }] + } + _e2: { + SingleForm: { + formId: "fotodokumentation" + showNumberOfInstances?: bool + } + _json: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + } + _s: { + Section: { + entries: Dokumentation: { + Link: { + sections: Formulare: { + Section: { + entries: Fotodokumentation: { + SingleForm: { + formId: "fotodokumentation" + showNumberOfInstances?: bool + } + _json: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + } + display?: string + } + _json: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + } + icon?: string + } + _json: [{ + Formulare: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + }] + } + display?: string + } + _json: [{ + Dokumentation: [{ + Formulare: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + }] + }] + } + config: tabcats: "02": { + Section: { + entries: { + Dokumentation: { + Link: { + sections: Formulare: { + Section: { + entries: Fotodokumentation: { + SingleForm: { + formId: "fotodokumentation" + showNumberOfInstances?: bool + } + _json: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + } + display?: string + } + _json: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + } + icon?: string + } + _json: [{ + Formulare: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + }] + } + } + display?: string + } + _json: [{ + Dokumentation: [{ Formulare: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + }] }] + } + json: tabcats: [{ "02": [{ Dokumentation: [{ Formulare: [{ + Fotodokumentation: [{ + iDoc: "singleFormIDoc" + "X-FormId": "fotodokumentation" + }] + }] + }] }] }] + }) +} +-- out/compile -- +--- x.cue +{ + #PatientViewSections: { + [string]: 〈1;#PatientViewSection〉 + } + #PatientViewSection: 〈0;#PvSection〉 + #PvSection: { + Section: { + display?: string + entries: 〈2;#PatientViewEntries〉 + } + _json: [ + for k, v in 〈1;Section〉.entries { + 〈1;k〉: 〈1;v〉._json + }, + ] + } + #PatientViewEntries: { + [string]: 〈1;#PatientViewEntry〉 + } + #PatientViewEntry: { + (〈1;#PvSingleForm〉|〈1;#PvLink〉) + } + #PvSingleForm: { + SingleForm: { + formId: string + showNumberOfInstances?: bool + } + _json: [ + { + iDoc: "singleFormIDoc" + "X-FormId": 〈2;SingleForm〉.formId + }, + ] + } + #PvLink: { + Link: { + icon?: string + sections: 〈2;#PatientViewSections〉 + } + _json: [ + for k, v in 〈1;Link〉.sections { + 〈1;k〉: 〈1;v〉._json + }, + ] + } + #TabcatsJson: { + config: { + tabcats: 〈2;#PatientViewSections〉 + ... + } + json: { + tabcats: [ + for k, v in 〈2;config〉.tabcats { + 〈1;k〉: 〈1;v〉._json + }, + ] + } + } + tabcatsExample: 〈0;#TabcatsJson〉 + tabcatsExample: { + _e1: 〈1;#PatientViewEntry〉 + _e1: { + Link: { + sections: { + Formulare: { + Section: { + entries: { + Fotodokumentation: 〈6;_e2〉 + } + } + } + } + } + } + _e2: 〈1;#PatientViewEntry〉 + _e2: { + SingleForm: { + formId: "fotodokumentation" + } + } + _s: 〈1;#PvSection〉 + _s: { + Section: { + entries: { + Dokumentation: 〈3;_e1〉 + } + } + } + config: { + tabcats: { + "02": 〈2;_s〉 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3813.txtar b/internal/core/compile/testdata/sync/eval/issue3813.txtar new file mode 100644 index 000000000..94a66ed85 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3813.txtar @@ -0,0 +1,37 @@ +# Tests that a struct with an open pattern constraint unifies correctly with a +# definition and an embed, producing the expected closed result. Issue: evalv3 +# incorrectly reported "field not allowed" for `y.f` when the struct was opened +# via a pattern constraint `[string]: _` and then closed through unification +# with a definition. +# https://cuelang.org/issue/3813 +-- x.cue -- +x: {[string]: _} @test(closed) @test(eq, { + f: _ + [string]: _ +}) +x: #d +#d: f: _ + +y: { + @test(eq, {f: true}) + @test(closed) + x +} +y: f: true +-- out/compile -- +--- x.cue +{ + x: { + [string]: _ + } + x: 〈0;#d〉 + #d: { + f: _ + } + y: { + 〈1;x〉 + } + y: { + f: true + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3905.txtar b/internal/core/compile/testdata/sync/eval/issue3905.txtar new file mode 100644 index 000000000..ab95afdc8 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3905.txtar @@ -0,0 +1,149 @@ +# Tests that dynamic field keys with disjunctive default values evaluate correctly. +# The v3 evaluator incorrectly reported a cycle error for `(parameters.gatewayNamespace)` +# when the value was a disjunction like `string | *"foo"`, working fine in evalv2. +# https://cuelang.org/issue/3905 +-- in.cue -- +issue3905: reduced: { + #Schema: { + params: name: string | *"foo" + + result: (params.name): "bar" + } + + (#Schema).result + @test(eq, { + #Schema: { + params: {name: *"foo" | string} + result: {foo: "bar"} + } + foo: "bar" + }) +} +issue3905: full: { + #ReferenceGrantBuilder: { + parameters: { + namespace: string + gatewayNamespace: string | *"foo" + } + + referenceGrant: (parameters.gatewayNamespace): #ReferenceGrant & { + metadata: name: parameters.gatewayNamespace + metadata: namespace: parameters.namespace + } + } + + (#ReferenceGrantBuilder & { + parameters: namespace: "foo" + }).referenceGrant + + #ReferenceGrant: { + apiVersion: "gateway.networking.k8s.io/v1beta1" + kind: "ReferenceGrant" + metadata!: { + name!: string + namespace!: string + labels?: { + [string]: string + } + annotations?: { + [string]: string + } + } + } + @test(eq, { + #ReferenceGrantBuilder: { + parameters: { + namespace: string + gatewayNamespace: *"foo" | string + } + referenceGrant: { + foo: { + metadata: { + name: *"foo" | string + namespace: string + labels?: {} + annotations?: {} + } + apiVersion: "gateway.networking.k8s.io/v1beta1" + kind: "ReferenceGrant" + } + } + } + #ReferenceGrant: { + apiVersion: "gateway.networking.k8s.io/v1beta1" + kind: "ReferenceGrant" + metadata!: { + name!: string + namespace!: string + labels?: {} + annotations?: {} + } + } + foo: { + metadata: { + name: *"foo" | string + namespace: "foo" + labels?: {} + annotations?: {} + } + apiVersion: "gateway.networking.k8s.io/v1beta1" + kind: "ReferenceGrant" + } + }) +} +-- out/compile -- +--- in.cue +{ + issue3905: { + reduced: { + #Schema: { + params: { + name: (string|*"foo") + } + result: { + 〈1;params〉.name: "bar" + } + } + 〈0;#Schema〉.result + } + } + issue3905: { + full: { + #ReferenceGrantBuilder: { + parameters: { + namespace: string + gatewayNamespace: (string|*"foo") + } + referenceGrant: { + 〈1;parameters〉.gatewayNamespace: (〈2;#ReferenceGrant〉 & { + metadata: { + name: 〈3;parameters〉.gatewayNamespace + } + metadata: { + namespace: 〈3;parameters〉.namespace + } + }) + } + } + (〈0;#ReferenceGrantBuilder〉 & { + parameters: { + namespace: "foo" + } + }).referenceGrant + #ReferenceGrant: { + apiVersion: "gateway.networking.k8s.io/v1beta1" + kind: "ReferenceGrant" + metadata!: { + name!: string + namespace!: string + labels?: { + [string]: string + } + annotations?: { + [string]: string + } + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue3919.txtar b/internal/core/compile/testdata/sync/eval/issue3919.txtar new file mode 100644 index 000000000..14e5cd449 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue3919.txtar @@ -0,0 +1,234 @@ +# Tests that builtin function calls with arguments depending on later-defined +# default values evaluate correctly in evalv3. The issue caused math.Abs to fail +# with "non-concrete value" when the port field had a default defined after the call. +# https://cuelang.org/issue/3919 +-- in.cue -- +import "math" + +full: { + out: { + env: { + if true { + PORT: math.Abs(out.port) + } + } + if true { + port: int | *30080 + } + } + @test(eq, { + out: {env: {PORT: 30080}, port: *30080 | int} + }) +} +reduced: { + if true { + a: math.Abs(port) + } + port: int | *30080 + @test(eq, {a: 30080, port: *30080 | int}) +} +-- secondary.cue -- +related: { + [string]: { + if true { + shared: all_total: foo.fooData.total + } + } + foo: fooData: { + total: tags: _hidden + _hidden: extra: {} + } + #Tags: [string]: {} + bar: { + shared: { + [string]: tags: #Tags + bar_total: foo.fooData.total + } + } + @test(eq, { + foo: { + fooData: { + total: {tags: {extra: {}}} + _hidden: {extra: {}} + } + shared: {all_total: {tags: {extra: {}}}} + } + #Tags: {} + bar: { + shared: { + bar_total: {tags: {extra: {}}} + all_total: {tags: {extra: {}}} + } + } + }) +} +-- let.cue -- +// issue3931: evalv3 raises "field set was already referenced" when processing +// optional field specs with let bindings that evalv2 accepts without error. +// https://cuelang.org/issue/3931 +issue3931: full: { + bar: [string]: spec?: Spec + if true { + foo: label: "foo" + bar: bar1: spec: selector: foo + } + let Spec = { + selector?: Selector + } + let Selector = { + label?: string + expr?: [...string] + } + @test(eq, { + bar: { + bar1: { + spec: {selector: {label: "foo", expr?: []}} + } + } + foo: {label: "foo"} + }) +} +-- issue3946.cue -- +// issue3946: evalv3 regression reporting a cyclic reference error when a field +// is inserted and then referenced within a comprehension expression. +// https://cuelang.org/issue/3946 +issue3946: reduced:{ + out: [for _, v in _inputs { v }] + _inputs: [_]: { + doExtra?: bool + if doExtra != _|_ { + if true { + extra: "yes" + } + } + } + if true { + _inputs: input1: name: "input1" + } + @test(eq, { + out: [{ + doExtra?: bool + name: "input1" + }] + _inputs: { + input1: {name: "input1", doExtra?: bool} + } + }) +} +-- out/compile -- +--- in.cue +{ + full: { + out: { + env: { + if true { + PORT: 〈import;math〉.Abs(〈3;out〉.port) + } + } + if true { + port: (int|*30080) + } + } + } + reduced: { + if true { + a: 〈import;math〉.Abs(〈1;port〉) + } + port: (int|*30080) + } +} +--- issue3946.cue +{ + issue3946: { + reduced: { + out: [ + for _, v in 〈1;_inputs〉 { + 〈1;v〉 + }, + ] + _inputs: { + [_]: { + doExtra?: bool + if (〈0;doExtra〉 != _|_(explicit error (_|_ literal) in source)) { + if true { + extra: "yes" + } + } + } + } + if true { + _inputs: { + input1: { + name: "input1" + } + } + } + } + } +} +--- let.cue +{ + issue3931: { + full: { + bar: { + [string]: { + spec?: 〈2;let Spec#1〉 + } + } + if true { + foo: { + label: "foo" + } + bar: { + bar1: { + spec: { + selector: 〈3;foo〉 + } + } + } + } + let Spec#1 = { + selector?: 〈1;let Selector#2〉 + } + let Selector#2 = { + label?: string + expr?: [ + ...string, + ] + } + } + } +} +--- secondary.cue +{ + related: { + [string]: { + if true { + shared: { + all_total: 〈3;foo〉.fooData.total + } + } + } + foo: { + fooData: { + total: { + tags: 〈1;_hidden〉 + } + _hidden: { + extra: {} + } + } + } + #Tags: { + [string]: {} + } + bar: { + shared: { + [string]: { + tags: 〈3;#Tags〉 + } + bar_total: 〈2;foo〉.fooData.total + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue494.txtar b/internal/core/compile/testdata/sync/eval/issue494.txtar new file mode 100644 index 000000000..a9f831596 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue494.txtar @@ -0,0 +1,69 @@ +-- in.cue -- +_Q: [{pos: 0}, {pos: 1}] + +a: [rn=string]: _Q[0:len(a[rn])] +a: ben: [{}] @test(eq, [{pos: 0}]) + +b: [rn=string]: _Q[0:1] +b: ben: [{}] @test(eq, [{pos: 0}]) + +c: [rn=string]: [...{l: len(a[rn])}] +c: ben: [{}] @test(eq, [{l: 1}]) + +#d: {[rn=string]: [...{pos: uint}] & _Q[0:len(#d[rn])]} @test(shareID=D) +#d: ben: [{}] @test(eq, [{pos: 0}]) + +d: #d @test(shareID=D) +-- out/compile -- +--- in.cue +{ + _Q: [ + { + pos: 0 + }, + { + pos: 1 + }, + ] + a: { + [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] + } + a: { + ben: [ + {}, + ] + } + b: { + [string]: 〈1;_Q〉[0:1] + } + b: { + ben: [ + {}, + ] + } + c: { + [string]: [ + ...{ + l: len(〈3;a〉[〈2;-〉]) + }, + ] + } + c: { + ben: [ + {}, + ] + } + #d: { + [string]: ([ + ...{ + pos: &(int, >=0) + }, + ] & 〈1;_Q〉[0:len(〈1;#d〉[〈0;-〉])]) + } + #d: { + ben: [ + {}, + ] + } + d: 〈0;#d〉 +} diff --git a/internal/core/compile/testdata/sync/eval/issue500.txtar b/internal/core/compile/testdata/sync/eval/issue500.txtar new file mode 100644 index 000000000..11258b1cb --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue500.txtar @@ -0,0 +1,64 @@ +-- in.cue -- +package x + +import "strings" +import "list" + +a: strings.Join(strings.Split("test", "")[1:], "") @test(eq, "est") + +b: strings.Join(["t", "e", "s", "t"][1:], "") @test(eq, "est") + +c: ["t", "e", "s", "t"][1:] @test(eq, ["e", "s", "t"]) +d: strings.Join(c, "") @test(eq, "est") + +e: strings.Join(list.Concat([["a"], ["b"]]), "") @test(eq, "ab") + +f: list.Concat([["a"], ["b"]]) @test(eq, ["a", "b"]) +g: strings.Join(f, "") @test(eq, "ab") + +h: strings.Join(list.Repeat(["a"], 3), "") @test(eq, "aaa") + +i: list.Repeat(["b"], 3) @test(eq, ["b", "b", "b"]) +j: strings.Join(i, "") @test(eq, "bbb") +-- out/compile -- +--- in.cue +{ + a: 〈import;strings〉.Join(〈import;strings〉.Split("test", "")[1:], "") + b: 〈import;strings〉.Join([ + "t", + "e", + "s", + "t", + ][1:], "") + c: [ + "t", + "e", + "s", + "t", + ][1:] + d: 〈import;strings〉.Join(〈0;c〉, "") + e: 〈import;strings〉.Join(〈import;list〉.Concat([ + [ + "a", + ], + [ + "b", + ], + ]), "") + f: 〈import;list〉.Concat([ + [ + "a", + ], + [ + "b", + ], + ]) + g: 〈import;strings〉.Join(〈0;f〉, "") + h: 〈import;strings〉.Join(〈import;list〉.Repeat([ + "a", + ], 3), "") + i: 〈import;list〉.Repeat([ + "b", + ], 3) + j: 〈import;strings〉.Join(〈0;i〉, "") +} diff --git a/internal/core/compile/testdata/sync/eval/issue545.txtar b/internal/core/compile/testdata/sync/eval/issue545.txtar new file mode 100644 index 000000000..3d2f7f32f --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue545.txtar @@ -0,0 +1,101 @@ +# Tests that recursive definitions using disjunctions of validators and self-references +# do not produce duplicate constraints. A regression caused nested applications to +# accumulate redundant conjunctions instead of preserving the recursive structure. +# https://cuelang.org/issue/545 +title: Simplification of validators. +-- in.cue -- +package main + +import ( + "strings" + "time" +) + +t1: { + #Test: { + #HTTP: =~"^http://" + #SSH: !~"^ssh://" + #USER: strings.MinRunes(3) + source: #HTTP | #SSH | #USER | #Test + } + + foo: #Test & { + source: "http://blablabla" + } + + bar: #Test & { + source: foo + } + @test(eq, { + #Test: { + #HTTP: =~"^http://" + #SSH: !~"^ssh://" + #USER: strings.MinRunes(3) + source: =~"^http://" | !~"^ssh://" | strings.MinRunes(3) + } + foo: { + source: "http://blablabla" + #HTTP: =~"^http://" + #SSH: !~"^ssh://" + #USER: strings.MinRunes(3) + } + bar: { + source: { + source: "http://blablabla" + #HTTP: =~"^http://" + #SSH: !~"^ssh://" + #USER: strings.MinRunes(3) + } + #HTTP: =~"^http://" + #SSH: !~"^ssh://" + #USER: strings.MinRunes(3) + } + }) +} + +t2: { + str: "foo" + a: =~str + b: =~"foo" + c: a & b & a & b + + d: time.Time + e: time.Time() + f: d & e & d & e + @test(eq, { + str: "foo" + a: =~"foo" + b: =~"foo" + c: =~"foo" + d: time.Time() + e: time.Time() + f: time.Time() + }) +} +-- out/compile -- +--- in.cue +{ + t1: { + #Test: { + #HTTP: =~"^http://" + #SSH: !~"^ssh://" + #USER: 〈import;strings〉.MinRunes(3) + source: (〈0;#HTTP〉|〈0;#SSH〉|〈0;#USER〉|〈1;#Test〉) + } + foo: (〈0;#Test〉 & { + source: "http://blablabla" + }) + bar: (〈0;#Test〉 & { + source: 〈1;foo〉 + }) + } + t2: { + str: "foo" + a: =~〈0;str〉 + b: =~"foo" + c: (((〈0;a〉 & 〈0;b〉) & 〈0;a〉) & 〈0;b〉) + d: 〈import;time〉.Time + e: 〈import;time〉.Time() + f: (((〈0;d〉 & 〈0;e〉) & 〈0;d〉) & 〈0;e〉) + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue599.txtar b/internal/core/compile/testdata/sync/eval/issue599.txtar new file mode 100644 index 000000000..bc6e8576d --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue599.txtar @@ -0,0 +1,182 @@ +# Tests that closedness is correctly tracked when combining schemas through +# inheritance and embedding using the & operator. The issue caused CUE to reject +# fields that should be permitted under the merged schema definitions. +# https://cuelang.org/issue/599 +-- in.cue -- +package deps + +a: { + #A: { + n: string + depends_on: [...#AnyA] + } + + #AnyA: { + n: string + depends_on: [...#AnyA] + ... + } + + #A1: { + #A + x: int + y: z: string // Comment to avoid error + } + + #A2: { + #A + i: string + } + + s: [Name=string]: #AnyA & {n: Name} + + s: foo: #A1 & { + x: 10 + y: z: "z" // Comment to avoid error + } + + s: bar: #A2 & { + i: "hello bar" + depends_on: [s.foo] + } + @test(eq, { + #A: {n: string, depends_on: []} + #AnyA: {n: string, depends_on: []} + #A1: { + x: int + y: {z: string} + n: string + depends_on: [] + } + #A2: { + i: string + n: string + depends_on: [] + } + s: { + foo: { + x: 10 + y: {z: "z"} + n: "foo" + depends_on: [] + } + bar: { + i: "hello bar" + depends_on: [{ + x: 10 + y: {z: "z"} + n: "foo" + depends_on: [] + }] + n: "bar" + } + } + }) +} + +b: { + #A: { + f: {...} + } + + #A1: { + #A + // f: {...} // Uncomment to fix + } + + #C: { + d: {...} + } + + s: [string]: #A1 + + s: foo: { + f: #C & { + d: foo: "bar" + } + } + @test(eq, { + #A: {f: {}} + #A1: {f: {}} + #C: {d: {}} + s: {foo: {f: {d: {foo: "bar"}}}} + }) +} +-- out/compile -- +--- in.cue +{ + a: { + #A: { + n: string + depends_on: [ + ...〈2;#AnyA〉, + ] + } + #AnyA: { + n: string + depends_on: [ + ...〈2;#AnyA〉, + ] + ... + } + #A1: { + 〈1;#A〉 + x: int + y: { + z: string + } + } + #A2: { + 〈1;#A〉 + i: string + } + s: { + [string]: (〈1;#AnyA〉 & { + n: 〈1;-〉 + }) + } + s: { + foo: (〈1;#A1〉 & { + x: 10 + y: { + z: "z" + } + }) + } + s: { + bar: (〈1;#A2〉 & { + i: "hello bar" + depends_on: [ + 〈3;s〉.foo, + ] + }) + } + } + b: { + #A: { + f: { + ... + } + } + #A1: { + 〈1;#A〉 + } + #C: { + d: { + ... + } + } + s: { + [string]: 〈1;#A1〉 + } + s: { + foo: { + f: (〈2;#C〉 & { + d: { + foo: "bar" + } + }) + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/issue962.txtar b/internal/core/compile/testdata/sync/eval/issue962.txtar new file mode 100644 index 000000000..f83f9647b --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/issue962.txtar @@ -0,0 +1,24 @@ +# Tests that an indirect reference through a hidden field to a dynamic index +# correctly propagates an "incomplete" error rather than a misleading "cycle" +# error. Issue: indexing foo[_what] via a hidden variable _obj caused a "cycle +# error" instead of "invalid non-ground value" when _what was abstract. +# https://cuelang.org/issue/962 +-- in.cue -- +import "encoding/yaml" + +foo: bar: "something" + +text: yaml.Marshal(_obj) @test(err, code=incomplete, pos=[2:8], contains="invalid non-ground value") + +_what: string +_obj: foo[_what] @test(err, code=incomplete, pos=[-1:8], contains="invalid non-ground value") +-- out/compile -- +--- in.cue +{ + foo: { + bar: "something" + } + text: 〈import;"encoding/yaml"〉.Marshal(〈0;_obj〉) + _what: string + _obj: 〈0;foo〉[〈0;_what〉] +} diff --git a/internal/core/compile/testdata/sync/eval/let.txtar b/internal/core/compile/testdata/sync/eval/let.txtar new file mode 100644 index 000000000..d85242bcf --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/let.txtar @@ -0,0 +1,430 @@ +-- in.cue -- + let A = 3 * 3 +let B = A + A +let C = B + B +let D = C + C +let E = D + D +let F = E + E +b: { + let G = F + F + let H = G + G + let I = H + H + let J = I + I + let K = J + J + let L = K + K + let M = L + L + let N = M + M + let O = N + N + let P = O + O + let Q = P + P + let R = Q + Q + let S = R + R + let T = S + S + + a: T + b: F +} @test(eq, {a: 4718592, b: 288}) + +// Nil pointer in *core/adt.Environment.evalCached caused by a let binding +// that references a list comprehension over another let-bound list. +// https://cuelang.org/issue/1828 +issue1828: { + volumes: L3 + + let L3 = { + for v2 in [for v1 in L2 {}] {} + } + + let L2 = L1 + let L1 = [] + + @test(eq, {volumes: {}}) +} +ignoreErrorInLet: { + let X = 1 & 2 + disjunction: *X | 3 + + @test(eq, {disjunction: 3}) +} +-- incomprehension.cue -- +// for comprehensions in list do not have to split the let as each instance +// is already associated with a separate environment. +list: { + l: [ 1, 2, 3 ] + c: [ + for v in l { + let X = v*4 // can share + X + } + ] + @test(eq, {l: [1, 2, 3], c: [{4}, {8}, {12}]}) +} + +referencesForDirectly: { + l: [ 1, 2, 3 ] + for k, v in l { + let Y = v*4 // multi + "\(k)": Y + } + @test(eq, { + l: [1, 2, 3] + "0": 4 + "1": 8 + "2": 12 + }) +} + +referencesForViaLet: { + l: [ 1, 2, 3 ] + for k, v in l let X = v*4 { + let Y = X // multi + "\(k)": Y + } + @test(eq, { + l: [1, 2, 3] + "0": 4 + "1": 8 + "2": 12 + }) +} + +letClauseReferencesInert: { + x: 2 + l: [ 1, 2, 3 ] + for k, v in l let X = x { + let Y = X // can share + "\(k)": Y + } + @test(eq, { + x: 2 + l: [1, 2, 3] + "0": 2 + "1": 2 + "2": 2 + }) +} + +// for indirect references, it is okay to not "split" a let clause, as the +// it will only fail as a result of not splitting if the referred values +// would fail as well. +indirectReference: { + l: [ 1, 2, 3 ] + for k, v in l { + y: v // fails if v differs for each y. + let X = y*4 // can share, as y fails if let fails. + "\(k)": X + } + @test(err, code=eval, + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[2, 1], pos=[0:20, 1:7, 1:10, 2:2, 3:6]), + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[3, 1], pos=[0:20, 1:7, 1:13, 2:2, 3:6])) + +} @test(err, code=eval, + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[2, 1], pos=[0:20, 1:7, 1:10, 2:2, 3:6]), + suberr=(code=eval, path=y, contains="conflicting values %s and %s", args=[3, 1], pos=[0:20, 1:7, 1:13, 2:2, 3:6])) + +nestedFor: { + for k, y in [ 4, 5 ] { + let X = { + for x in [ 1, 2 ] { + let X = x + "\(X)": X + } + } + "\(k)": X + } + @test(eq, { + "0": {"1": 1, "2": 2} + "1": {"1": 1, "2": 2} + }) +} +-- issue2166.cue -- +// Using a let clause inside a field comprehension to create a dynamic key +// caused an "invalid interpolation: conflicting values" error. +// https://cuelang.org/issue/2166 +letWithDynamicInComprehension: { + _i: { + a: "d" + b: "e" + } + + for k, v in _i { + let T = v + (T): "1" + } + @test(eq, {_i: {a: "d", b: "e"}, e: "1", d: "1"}) +} +-- issue2218.cue -- +// Earlier let evaluation results in the wrong value: a let inside a for +// comprehension picked up an outer binding instead of the loop variable. +// https://cuelang.org/issue/2218 +_parent_configs: { + PARENT: true +} @test(eq) +_configs: { + CHILD1: { + property: true + } + CHILD2: { + property: true + parent: "PARENT" + } +} @test(ignore) +disabled_parent_test: { + for k, v in _configs { + let parent_config = (*_parent_configs[v.parent] | false) + "\(k)": { + "parent_config": parent_config + } + } + @test(eq, { + CHILD1: {parent_config: false} + CHILD2: {parent_config: *true | false} + }) +} + +-- issue2063.cue -- +import ( + "encoding/yaml" + "strings" +) + +// Issue #2063 +// tools/flow: unsupported node import "list" in yaml.Marshal; let bindings +// inside a struct referencing an undefined field must not block descending. +// https://cuelang.org/issue/2063 +keepDescending: t1: { + ec: {} + bs: { + let m = ec.b + if m == _|_ { } + x: y: "" + } + @test(eq, {ec: {}, bs: {x: {y: ""}}}) +} + +keepDescending: t2: { + x: yaml.Marshal(bs) + + ec: {} + bs: { + let m = ec.b + if m.b == _|_ { } + X: Y: strings.Join([], "") + } + @test(eq, { + x: "X:\n \"Y\": \"\"\n" + ec: {} + bs: {X: {Y: ""}} + }) +} +-- interpolation.cue -- +// evalv3 closedness regression with disjunctions and ellipses where a let +// binding shadowed a loop variable inside a for comprehension. +// https://cuelang.org/issue/4022 +issue4022: full: { + envScript: [ for v in _env let v = _env["KEY"] {"\(v)"} ] + _env: { + KEY: *"" | _ + } + @test(eq, {envScript: [""], _env: {KEY: *"" | _}}) +} +-- out/compile -- +--- in.cue +{ + let A#1 = (3 * 3) + let B#2 = (〈0;let A#1〉 + 〈0;let A#1〉) + let C#3 = (〈0;let B#2〉 + 〈0;let B#2〉) + let D#4 = (〈0;let C#3〉 + 〈0;let C#3〉) + let E#5 = (〈0;let D#4〉 + 〈0;let D#4〉) + let F#6 = (〈0;let E#5〉 + 〈0;let E#5〉) + b: { + let G#7 = (〈1;let F#6〉 + 〈1;let F#6〉) + let H#8 = (〈0;let G#7〉 + 〈0;let G#7〉) + let I#9 = (〈0;let H#8〉 + 〈0;let H#8〉) + let J#A = (〈0;let I#9〉 + 〈0;let I#9〉) + let K#B = (〈0;let J#A〉 + 〈0;let J#A〉) + let L#C = (〈0;let K#B〉 + 〈0;let K#B〉) + let M#D = (〈0;let L#C〉 + 〈0;let L#C〉) + let N#E = (〈0;let M#D〉 + 〈0;let M#D〉) + let O#F = (〈0;let N#E〉 + 〈0;let N#E〉) + let P#10 = (〈0;let O#F〉 + 〈0;let O#F〉) + let Q#11 = (〈0;let P#10〉 + 〈0;let P#10〉) + let R#12 = (〈0;let Q#11〉 + 〈0;let Q#11〉) + let S#13 = (〈0;let R#12〉 + 〈0;let R#12〉) + let T#14 = (〈0;let S#13〉 + 〈0;let S#13〉) + a: 〈0;let T#14〉 + b: 〈1;let F#6〉 + } + issue1828: { + volumes: 〈0;let L3#15〉 + let L3#15 = { + for _, v2 in [ + for _, v1 in 〈2;let L2#16〉 {}, + ] {} + } + let L2#16 = 〈0;let L1#17〉 + let L1#17 = [] + } + ignoreErrorInLet: { + let X#18 = (1 & 2) + disjunction: (*〈0;let X#18〉|3) + } +} +--- incomprehension.cue +{ + list: { + l: [ + 1, + 2, + 3, + ] + c: [ + for _, v in 〈1;l〉 { + let X#19 = (〈1;v〉 * 4) + 〈0;let X#19〉 + }, + ] + } + referencesForDirectly: { + l: [ + 1, + 2, + 3, + ] + for k, v in 〈0;l〉 { + let Y#1Amulti = (〈1;v〉 * 4) + "\(〈1;k〉)": 〈0;let Y#1A〉 + } + } + referencesForViaLet: { + l: [ + 1, + 2, + 3, + ] + for k, v in 〈0;l〉 let X = (〈0;v〉 * 4) { + let Y#1Bmulti = 〈1;X〉 + "\(〈2;k〉)": 〈0;let Y#1B〉 + } + } + letClauseReferencesInert: { + x: 2 + l: [ + 1, + 2, + 3, + ] + for k, v in 〈0;l〉 let X = 〈1;x〉 { + let Y#1C = 〈1;X〉 + "\(〈2;k〉)": 〈0;let Y#1C〉 + } + } + indirectReference: { + l: [ + 1, + 2, + 3, + ] + for k, v in 〈0;l〉 { + y: 〈1;v〉 + let X#1D = (〈0;y〉 * 4) + "\(〈1;k〉)": 〈0;let X#1D〉 + } + } + nestedFor: { + for k, y in [ + 4, + 5, + ] { + let X#1Emulti = { + for _, x in [ + 1, + 2, + ] { + let X#1Fmulti = 〈1;x〉 + "\(〈0;let X#1F〉)": 〈0;let X#1F〉 + } + } + "\(〈1;k〉)": 〈0;let X#1E〉 + } + } +} +--- interpolation.cue +{ + issue4022: { + full: { + envScript: [ + for _, v in 〈1;_env〉 let v = 〈2;_env〉["KEY"] { + "\(〈1;v〉)" + }, + ] + _env: { + KEY: (*""|_) + } + } + } +} +--- issue2063.cue +{ + keepDescending: { + t1: { + ec: {} + bs: { + let m#21 = 〈1;ec〉.b + if (〈0;let m#21〉 == _|_(explicit error (_|_ literal) in source)) {} + x: { + y: "" + } + } + } + } + keepDescending: { + t2: { + x: 〈import;"encoding/yaml"〉.Marshal(〈0;bs〉) + ec: {} + bs: { + let m#22 = 〈1;ec〉.b + if (〈0;let m#22〉.b == _|_(explicit error (_|_ literal) in source)) {} + X: { + Y: 〈import;strings〉.Join([], "") + } + } + } + } +} +--- issue2166.cue +{ + letWithDynamicInComprehension: { + _i: { + a: "d" + b: "e" + } + for k, v in 〈0;_i〉 { + let T#23multi = 〈1;v〉 + 〈0;let T#23〉: "1" + } + } +} +--- issue2218.cue +{ + _parent_configs: { + PARENT: true + } + _configs: { + CHILD1: { + property: true + } + CHILD2: { + property: true + parent: "PARENT" + } + } + disabled_parent_test: { + for k, v in 〈1;_configs〉 { + let parent_config#24multi = (*〈3;_parent_configs〉[〈1;v〉.parent]|false) + "\(〈1;k〉)": { + parent_config: 〈1;let parent_config#24〉 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/letjoin.txtar b/internal/core/compile/testdata/sync/eval/letjoin.txtar new file mode 100644 index 000000000..c40ff81d6 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/letjoin.txtar @@ -0,0 +1,339 @@ +-- in.cue -- +// Test that an error in a let that is merged with itself from two different +// origins does not result in an error as long as the error is not referenced +// outside the let. +t1: { + x: { + a: int + y: { + let X = { + b: a + c: 1 + } + v: X.c + } + } + + x1: x + x1: a: 1 + + x2: x + x2: a: 2 + + xy: x1.y & x2.y + @test(eq, { + x: {a: int, y: {v: 1}} + x1: {a: 1, y: {v: 1}} + x2: {a: 2, y: {v: 1}} + xy: {v: 1} + }) +} + +t2: { + x: { + a: {} + y: { + let X = { + b: a + c: 1 + } + v: X.c + } + } + + x1: x + x1: a: q: 1 + + x2: x + x2: a: r: 2 + + xy: x1 & x2 + @test(eq, { + x: {a: {}, y: {v: 1}} + x1: {a: {q: 1}, y: {v: 1}} + x2: {a: {r: 2}, y: {v: 1}} + xy: {a: {q: 1, r: 2}, y: {v: 1}} + }) +} +-- issue3590.cue -- +// Conflicting values in for loop with let expressions: two chained let bindings +// inside a for comprehension incorrectly caused a conflict error. +// https://cuelang.org/issue/3590 +issue3590: reduced: { + result: [_]: [string]: string + + _input: { + A: p: "A" + B: p: "B" + } + + for _, v in _input { + let Var1 = v.p + + // Second let variable required here; just using Var1 with Items not + // sufficient + let Var2 = Var1 + + let Items = { + item: Var2 + } + + result: "conflicting-\(v.p)": Items + } + @test(eq, { + result: { + "conflicting-A": {item: "A"} + "conflicting-B": {item: "B"} + } + _input: {A: {p: "A"}, B: {p: "B"}} + }) +} +issue3590: { + full: { + #Result: [_]: {[string]: string} + + result: #Result + + #Input: { + p: "A" | "B" + } + + _input: [Parm=_]: #Input & { + p: Parm + } + + _input: { + A: {} + B: {} + } + + for _, v in _input { + let Var1 = v.p + let Var2 = Var1 + + let Items = { + "item": Var2 + } + + result: "conflicting-\(v.p)": Items + } + } + @test(eq, { + reduced: { + result: { + "conflicting-A": {item: "A"} + "conflicting-B": {item: "B"} + } + _input: {A: {p: "A"}, B: {p: "B"}} + } + full: { + #Result: {} + result: { + "conflicting-A": {item: "A"} + "conflicting-B": {item: "B"} + } + #Input: {p: "A" | "B"} + _input: {A: {p: "A"}, B: {p: "B"}} + } + }) +} +// Issue #3591 is related +// Missing items in for loop with let expressions: items produced inside a +// for comprehension via let were dropped from the output. +// https://cuelang.org/issue/3591 +issue3591: missing: { + #Result: [_]: {[string]: string} + + result: #Result + + #Input: { + p: "A" | "B" + } + + _input: [Parm=_]: #Input & { + p: Parm + } + + _input: { + A: {} + B: {} + } + + for _, v in _input { + let Var1 = v.p + let Var2 = Var1 + + let Items = { + "item": { + key1: Var2 + } + } + + result: "missing-items-\(v.p)": { + for s, attr in Items { + if attr.key1 != _|_ {(s): attr.key1} + } + } + } + @test(eq, { + #Result: {} + result: { + "missing-items-A": {item: "A"} + "missing-items-B": {item: "B"} + } + #Input: {p: "A" | "B"} + _input: {A: {p: "A"}, B: {p: "B"}} + }) +} +-- out/compile -- +--- in.cue +{ + t1: { + x: { + a: int + y: { + let X#1 = { + b: 〈2;a〉 + c: 1 + } + v: 〈0;let X#1〉.c + } + } + x1: 〈0;x〉 + x1: { + a: 1 + } + x2: 〈0;x〉 + x2: { + a: 2 + } + xy: (〈0;x1〉.y & 〈0;x2〉.y) + } + t2: { + x: { + a: {} + y: { + let X#2 = { + b: 〈2;a〉 + c: 1 + } + v: 〈0;let X#2〉.c + } + } + x1: 〈0;x〉 + x1: { + a: { + q: 1 + } + } + x2: 〈0;x〉 + x2: { + a: { + r: 2 + } + } + xy: (〈0;x1〉 & 〈0;x2〉) + } +} +--- issue3590.cue +{ + issue3590: { + reduced: { + result: { + [_]: { + [string]: string + } + } + _input: { + A: { + p: "A" + } + B: { + p: "B" + } + } + for _, v in 〈0;_input〉 { + let Var1#3multi = 〈1;v〉.p + let Var2#4multi = 〈0;let Var1#3〉 + let Items#5 = { + item: 〈1;let Var2#4〉 + } + result: { + "conflicting-\(〈2;v〉.p)": 〈1;let Items#5〉 + } + } + } + } + issue3590: { + full: { + #Result: { + [_]: { + [string]: string + } + } + result: 〈0;#Result〉 + #Input: { + p: ("A"|"B") + } + _input: { + [_]: (〈1;#Input〉 & { + p: 〈1;-〉 + }) + } + _input: { + A: {} + B: {} + } + for _, v in 〈0;_input〉 { + let Var1#6multi = 〈1;v〉.p + let Var2#7multi = 〈0;let Var1#6〉 + let Items#8 = { + item: 〈1;let Var2#7〉 + } + result: { + "conflicting-\(〈2;v〉.p)": 〈1;let Items#8〉 + } + } + } + } + issue3591: { + missing: { + #Result: { + [_]: { + [string]: string + } + } + result: 〈0;#Result〉 + #Input: { + p: ("A"|"B") + } + _input: { + [_]: (〈1;#Input〉 & { + p: 〈1;-〉 + }) + } + _input: { + A: {} + B: {} + } + for _, v in 〈0;_input〉 { + let Var1#9multi = 〈1;v〉.p + let Var2#Amulti = 〈0;let Var1#9〉 + let Items#B = { + item: { + key1: 〈2;let Var2#A〉 + } + } + result: { + "missing-items-\(〈2;v〉.p)": { + for s, attr in 〈2;let Items#B〉 { + if (〈1;attr〉.key1 != _|_(explicit error (_|_ literal) in source)) { + 〈2;s〉: 〈2;attr〉.key1 + } + } + } + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/lists.txtar b/internal/core/compile/testdata/sync/eval/lists.txtar new file mode 100644 index 000000000..58049dae0 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/lists.txtar @@ -0,0 +1,40 @@ +-- in.cue -- +a: [...int] +a: [1, 2, 3, 5] +a: [1, 2, 3, d] @test(eq, [1, 2, 3, 5]) + +b: a[3] @test(eq, 5) +d: 5 @test(eq, 5) + +c: [for x in [[1, 2]][0] {x + d}] @test(eq, [6, 7]) +-- out/compile -- +--- in.cue +{ + a: [ + ...int, + ] + a: [ + 1, + 2, + 3, + 5, + ] + a: [ + 1, + 2, + 3, + 〈1;d〉, + ] + b: 〈0;a〉[3] + d: 5 + c: [ + for _, x in [ + [ + 1, + 2, + ], + ][0] { + (〈1;x〉 + 〈3;d〉) + }, + ] +} diff --git a/internal/core/compile/testdata/sync/eval/merge.txtar b/internal/core/compile/testdata/sync/eval/merge.txtar new file mode 100644 index 000000000..b5d5d7d9e --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/merge.txtar @@ -0,0 +1,60 @@ +# TODO: image field is not pre-evaluated (not a huge deal) +# TODO: allow dynamic fields +-- in.cue -- +key: "app01" @test(eq, "app01") +manifests: [ + { + deployment: #map: [string]: {name: string, image: string, desc: string} + deployment: #map: "\(key)": name: "app01" + }, + { + deployment: #map: app01: image: "image01" + // TODO: allow + // deployment: #map: "\("app03")": image: "image01" + }, +] +// unify +results: _ @test(eq, {deployment: #map: { + app01: {image: "image01", name: "app01", desc: string} +}}) +for _, manifest in manifests { + results: manifest +} +-- out/compile -- +--- in.cue +{ + key: "app01" + manifests: [ + { + deployment: { + #map: { + [string]: { + name: string + image: string + desc: string + } + } + } + deployment: { + #map: { + "\(〈4;key〉)": { + name: "app01" + } + } + } + }, + { + deployment: { + #map: { + app01: { + image: "image01" + } + } + } + }, + ] + results: _ + for _, manifest in 〈0;manifests〉 { + results: 〈1;manifest〉 + } +} diff --git a/internal/core/compile/testdata/sync/eval/nonrooted.txtar b/internal/core/compile/testdata/sync/eval/nonrooted.txtar new file mode 100644 index 000000000..a693fbfa4 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/nonrooted.txtar @@ -0,0 +1,125 @@ +# Tests non-rooted inline expressions and let bindings where the inline +# expression conflicts with a definition constraint. The evaluation should +# use the local context (overriding the definition's value), even when +# that creates a conflict detectable from the root. +# https://cuelang.org/issue/3977 +-- in.cue -- +issue3977: inlineExpr: { + #NetworkID: 1 + #fn: { + x: #NetworkID + out: x + 1 + } + + err: (#fn & {x: 2}).out @test(err, code=eval, + contains="conflicting values", args=[1, 2]) +} +issue3977: inlineDisj1: { + #NetworkID: "2" | "3" | "4" + #fn: { + x: #NetworkID + out: "value=\(x)" + } + + err: (#fn & {x: "invalid"}).out @test(err, code=eval, + suberr=(code=eval, path=x, contains="conflicting values %s and %s", args=["2", "invalid"], pos=[-6:14, -4:8, 0:8, 0:18]), + suberr=(code=eval, path=x, contains="conflicting values %s and %s", args=["3", "invalid"], pos=[-6:20, -4:8, 0:8, 0:18]), + suberr=(code=eval, path=x, contains="conflicting values %s and %s", args=["4", "invalid"], pos=[-6:26, -4:8, 0:8, 0:18]), + ) +} +issue3977: inlineDisj2: { + #NetworkID: 1 + #fn: { + x: #NetworkID + out: x + 10 + } + + err: (#fn & {x: *2 | 4}).out @test(err, code=eval, + suberr=(contains="conflicting values", args=[1, 2]), + suberr=(contains="conflicting values", args=[4, 1])) +} +issue3977: inlineDisj3: { + #NetworkID: 1 + #fn: { + x: #NetworkID + out: x + 10 + } + + ok: (#fn & {x: *2 | int}).out @test(eq, 11) +} +issue3977: inlineLet: { + #NetworkID: 1 + let p = { + x: #NetworkID + out: x + 10 + } & { + x: 2 + } + + err: p.out @test(eq, 12, incorrect) @test(err:todo, p=1, code=eval, + contains="conflicting values", args=[1, 2]) +} +-- out/compile -- +--- in.cue +{ + issue3977: { + inlineExpr: { + #NetworkID: 1 + #fn: { + x: 〈1;#NetworkID〉 + out: (〈0;x〉 + 1) + } + err: (〈0;#fn〉 & { + x: 2 + }).out + } + } + issue3977: { + inlineDisj1: { + #NetworkID: ("2"|"3"|"4") + #fn: { + x: 〈1;#NetworkID〉 + out: "value=\(〈0;x〉)" + } + err: (〈0;#fn〉 & { + x: "invalid" + }).out + } + } + issue3977: { + inlineDisj2: { + #NetworkID: 1 + #fn: { + x: 〈1;#NetworkID〉 + out: (〈0;x〉 + 10) + } + err: (〈0;#fn〉 & { + x: (*2|4) + }).out + } + } + issue3977: { + inlineDisj3: { + #NetworkID: 1 + #fn: { + x: 〈1;#NetworkID〉 + out: (〈0;x〉 + 10) + } + ok: (〈0;#fn〉 & { + x: (*2|int) + }).out + } + } + issue3977: { + inlineLet: { + #NetworkID: 1 + let p#1 = ({ + x: 〈1;#NetworkID〉 + out: (〈0;x〉 + 10) + } & { + x: 2 + }) + err: 〈0;let p#1〉.out + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/notify.txtar b/internal/core/compile/testdata/sync/eval/notify.txtar new file mode 100644 index 000000000..accada19a --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/notify.txtar @@ -0,0 +1,106 @@ +-- in.cue -- +t1: { + @test(permute) + a + a: a: 2|1 + // TODO(inline): fix args passing: match brackets + @test(err, code=eval, contains="empty disjunction", + suberr=(code=eval, contains="conflicting values", pos=[0:5, 2:2, 3:10]), + suberr=(code=eval, contains="conflicting values", pos=[0:5, 2:2, 3:8]), + ) +} +t2: { + @test(permute, count=2) + d: d.a + d: a: a: 2|1 + @test(err, code=eval, contains="empty disjunction", + suberr=(code=eval, contains="conflicting values", pos=[2:5, 3:5, 3:13]), + suberr=(code=eval, contains="conflicting values", pos=[2:5, 3:5, 3:11]), + ) +} +t3: { + @test(permute, count=6) + b: a + b: (1|2) | 2 + a: 1 | 2 + @test(eq, {b: 1 | 2, a: 1 | 2}) +} +-- issue3437.cue -- +// Panic with a structurally recursive disjunction where a field aliases to +// itself via a self-referential disjunction path. +// https://cuelang.org/issue/3437 +issue3437: { + r: L=L.a + d: a: a: a: {b: 4}|d + out: r&d + // TODO(perf): either use structure sharing or stronger pruning. This seems + // disproportional. + @test(eq, { + r: _|_ @test(err, code=incomplete, contains="issue3437.r: undefined field: a", pos=[5:9]) + d: {a: {a: {a: {b: 4}}}} + out: {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}}, b: 4} | {a: {a: { + a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}} + }, b: 4} | {a: { + a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4}, b: 4} | {a: {a: {a: {b: 4}}, b: 4}} + }}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4}, b: 4} | {a: {a: {a: {b: 4}}, b: 4}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}, b: 4} | {a: {a: {a: {b: 4}}, b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}, b: 4} | {a: {a: {a: {b: 4}, b: 4}, b: 4}}}}}}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}}, b: 4} | {a: {a: { + a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}} + }, b: 4} | {a: { + a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4}, b: 4} | {a: {a: {a: {b: 4}}, b: 4}} + }}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}}, b: 4} | {a: { + a: {a: {b: 4}, b: 4} | {a: {a: {a: {b: 4}}, b: 4}} + }}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}}, b: 4} | {a: {a: {a: {b: 4} | {a: {a: {a: {b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}}}}, b: 4} | {a: {a: {a: {b: 4}, b: 4} | {a: {a: {a: {b: 4}}, b: 4}}, b: 4} | {a: {a: {a: {b: 4}, b: 4}, b: 4} | {a: {a: {a: {b: 4}, b: 4}, b: 4}}}}}}}}}} + }) +} +-- out/compile -- +--- in.cue +{ + t1: { + 〈0;a〉 + a: { + a: (2|1) + } + } + t2: { + d: 〈0;d〉.a + d: { + a: { + a: (2|1) + } + } + } + t3: { + b: 〈0;a〉 + b: ((1|2)|2) + a: (1|2) + } +} +--- issue3437.cue +{ + issue3437: { + r: 〈0〉.a + d: { + a: { + a: { + a: ({ + b: 4 + }|〈3;d〉) + } + } + } + out: (〈0;r〉 & 〈0;d〉) + } +} diff --git a/internal/core/compile/testdata/sync/eval/openinline.txtar b/internal/core/compile/testdata/sync/eval/openinline.txtar new file mode 100644 index 000000000..92aa5c6f3 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/openinline.txtar @@ -0,0 +1,191 @@ +# This test is important in locking in the closedness behavior +# of evalv2, where inline structs cause some closedness errors +# to be ignored. evalv3 mimics this behavior for the sake of +# backwards compatibility and not breaking existing users. +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- in.cue -- +import ( + pkg "foo.com/example" +) + +// This test tests that closeness errors are eliminated that occur within an +// inline struct. +inlineErr: { + #D: {a: 1} + + // Allow a closedness error that occurs within an inline struct. + def: x: (#D & {b: 2}).b + @test(eq, {#D: {a: 1}, def: {x: 2}}) +} + +// These tests test that selecting into an inlined struct recursively opens this +// struct in OpenInline. +outerErr: { + _inToOut: { + in: _ + out: in.foo + } + + // evalv3 regression: when a definition with extra fields allowed (...) + // is unified with the output of an inline function that returns a closed + // definition, evalv3 spuriously reported "field not allowed" where evalv2 + // correctly accepted the value. The closedness of #Inner must be opened + // when used in OpenInline mode so the outer open struct can accept its fields. + // https://cuelang.org/issue/3534 + issue3534: { + #Inner: foo: minor: 2 + #Outer: version: { major: 1, ... } + + t1: #Outer + t1: version: (_inToOut & {in: #Inner}).out + @test(eq, { + #Inner: {foo: {minor: 2}} + #Outer: {version: {major: 1}} + t1: {version: {major: 1, minor: 2}} + }) + } + + // Test that the same principle works with the close builtin. + usingClose: { + // Same as above, but with an additional level of nesting. + #Inner: foo: close({minor: 2}) + #Outer: version: { major: 1, ... } + + t1: #Outer + t1: version: (_inToOut & {in: #Inner}).out + @test(err, code=eval, at=t1.version.major, contains="field not allowed", pos=[3:22]) + } + + // Test that the mechanism still works with extra nesting: the closedness of + // #Inner should be opened recursively in OpenInline mode. + extraNesting: { + // Same as above, but with an additional level of nesting. + #Inner: foo: x: minor: 2 + #Outer: version: x: { major: 1, ... } + + t1: #Outer + t1: version: (_inToOut & {in: #Inner}).out + @test(eq, { + #Inner: {foo: {x: {minor: 2}}} + #Outer: {version: {x: {major: 1}}} + t1: {version: {x: {major: 1, minor: 2}}} + }) + } +} + +// Here OpenInline does _not_ erase the error, as the error is already present +// in the referred definitions. + +// faulty struct referenced from package +refFromPkg: (pkg.#E).b @test(eq, 1) + +refFromLet: { + let X = { + #D: a: 2 + #E: #D & {b: 1} + } + x: (X.#E).b + @test(eq, {x: 1}) +} + +-- cue.mod/pkg/foo.com/example/example.cue -- +package example + +#D: a: 1 +#E: #D & {b: 1} + +-- out/compile -- +--- in.cue +{ + inlineErr: { + #D: { + a: 1 + } + def: { + x: (〈1;#D〉 & { + b: 2 + }).b + } + } + outerErr: { + _inToOut: { + in: _ + out: 〈0;in〉.foo + } + issue3534: { + #Inner: { + foo: { + minor: 2 + } + } + #Outer: { + version: { + major: 1 + ... + } + } + t1: 〈0;#Outer〉 + t1: { + version: (〈2;_inToOut〉 & { + in: 〈2;#Inner〉 + }).out + } + } + usingClose: { + #Inner: { + foo: close({ + minor: 2 + }) + } + #Outer: { + version: { + major: 1 + ... + } + } + t1: 〈0;#Outer〉 + t1: { + version: (〈2;_inToOut〉 & { + in: 〈2;#Inner〉 + }).out + } + } + extraNesting: { + #Inner: { + foo: { + x: { + minor: 2 + } + } + } + #Outer: { + version: { + x: { + major: 1 + ... + } + } + } + t1: 〈0;#Outer〉 + t1: { + version: (〈2;_inToOut〉 & { + in: 〈2;#Inner〉 + }).out + } + } + } + refFromPkg: 〈import;"foo.com/example"〉.#E.b + refFromLet: { + let X#1 = { + #D: { + a: 2 + } + #E: (〈0;#D〉 & { + b: 1 + }) + } + x: 〈0;let X#1〉.#E.b + } +} diff --git a/internal/core/compile/testdata/sync/eval/required.txtar b/internal/core/compile/testdata/sync/eval/required.txtar new file mode 100644 index 000000000..d24d47a35 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/required.txtar @@ -0,0 +1,231 @@ +-- in.cue -- +self: t1: { + a?: int + @test(eq, {a?: int}) +} + +self: t2: { + a!: int + a!: int + @test(eq, {a!: int}) +} + +unify: t1: { + @test(permute, count=2) + a!: int + a: int + @test(eq, {a: int}) +} + +unify: t2: { + @test(permute) + a!: int + a?: int + @test(eq, {a!: int}) +} + +#Def: t1: { + a!: int + @test(eq, {a!: int}) +} + +// Required fields do not cause vet to fail with definitions: a required field +// in one definition should block a disallowed field from another definition. +// https://cuelang.org/issue/2306 +allowed: { + issue2306: { + #A: a!: int + #A: #B @test(err, code=eval, path=a, contains="field not allowed", pos=[-1:7]) + + #B: b!: int + } +} + +reference: { + toWithinDefinition: { + @test(permute, count=2) + #Foo: a!: int + b: #Foo.a @test(err, code=incomplete, contains="required field missing: %s", args=[a], pos=[0:11]) + } + toFieldFromDefinition: { + @test(permute, count=6) + #Foo: a!: int + b: #Foo + c: b.a @test(err, code=incomplete, contains="required field missing: %s", args=[a], pos=[0:8]) + } + toNonDefinition: { + @test(permute, count=2) + x: y!: _ + b: x.y @test(err, code=incomplete, contains="required field missing: %s", args=[y], pos=[0:8]) + } + toConcrete: { + @test(permute, count=2) + a!: 1 + b: a + 1 @test(err, code=incomplete, contains="required field missing: %s", args=[a], pos=[0:6]) + } +} +-- issue3918.cue -- +import "strings" + +// Required fields do not work on the function pattern: a required field used +// as an input to a definition-based function was not satisfied at the call site. +// https://cuelang.org/issue/3918 +issue3918: { + reduced: { + #disjuncts: { + in!: [...string] + out: strings.Join(in, "|") @test(err, code=incomplete, contains="required field missing: %s", args=[in], pos=[0:22]) + } + + x: (#disjuncts & { + in: ["foo", "bar"] + }).out + @test(eq, { + #disjuncts: { + in!: [] + out: _|_ + } + x: "foo|bar" + }) + } + noFunction: { + #disjuncts: { + in!: [...string] + out: in @test(err, code=incomplete, contains="required field missing: %s", args=[in], pos=[0:9]) + } + _foo: #disjuncts & {} @test(err, at=out, code=incomplete, contains="required field missing: %s", args=[in], pos=[-2:9]) + x: _foo.out @test(err, code=incomplete, path=_foo.out, contains="required field missing: %s", args=[in], pos=[-3:9]) + @test(eq, { + #disjuncts: { + in!: [] + out: _|_ + } + _foo: { + in!: [] + out: _|_ + } + x: _|_ + }) + } +} +// A required field error is incomplete error. Ensure that setting a vertex +// to this error does not escalate it to an evaluation error. +doNotEscalateError: { + a: { + in: _ + out: in.self @test(err, code=incomplete, contains="%s undefined as %s is incomplete (type %s)", args=[in.self, in, _], pos=[0:8]) + } + b: { + required!: _ + pass: (a & {in: required}).out @test(err, code=incomplete, contains="undefined field: %s", args=[self], pos=[-4:11]) + } +} +-- out/compile -- +--- in.cue +{ + self: { + t1: { + a?: int + } + } + self: { + t2: { + a!: int + a!: int + } + } + unify: { + t1: { + a!: int + a: int + } + } + unify: { + t2: { + a!: int + a?: int + } + } + #Def: { + t1: { + a!: int + } + } + allowed: { + issue2306: { + #A: { + a!: int + } + #A: 〈0;#B〉 + #B: { + b!: int + } + } + } + reference: { + toWithinDefinition: { + #Foo: { + a!: int + } + b: 〈0;#Foo〉.a + } + toFieldFromDefinition: { + #Foo: { + a!: int + } + b: 〈0;#Foo〉 + c: 〈0;b〉.a + } + toNonDefinition: { + x: { + y!: _ + } + b: 〈0;x〉.y + } + toConcrete: { + a!: 1 + b: (〈0;a〉 + 1) + } + } +} +--- issue3918.cue +{ + issue3918: { + reduced: { + #disjuncts: { + in!: [ + ...string, + ] + out: 〈import;strings〉.Join(〈0;in〉, "|") + } + x: (〈0;#disjuncts〉 & { + in: [ + "foo", + "bar", + ] + }).out + } + noFunction: { + #disjuncts: { + in!: [ + ...string, + ] + out: 〈0;in〉 + } + _foo: (〈0;#disjuncts〉 & {}) + x: 〈0;_foo〉.out + } + } + doNotEscalateError: { + a: { + in: _ + out: 〈0;in〉.self + } + b: { + required!: _ + pass: (〈1;a〉 & { + in: 〈1;required〉 + }).out + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/resolve_basic.txtar b/internal/core/compile/testdata/sync/eval/resolve_basic.txtar new file mode 100644 index 000000000..437a88f3d --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/resolve_basic.txtar @@ -0,0 +1,23 @@ +-- in.cue -- +a: 1 @test(eq, 1) +b: a + 1 @test(eq, 2) +d: { + x: _ + y: b + x @test(err, code=incomplete, contains="non-concrete value", pos=[0:5, -1:5]) +} +e: d & { + x: 5 +} @test(eq, {x: 5, y: 7}) +-- out/compile -- +--- in.cue +{ + a: 1 + b: (〈0;a〉 + 1) + d: { + x: _ + y: (〈1;b〉 + 〈0;x〉) + } + e: (〈0;d〉 & { + x: 5 + }) +} diff --git a/internal/core/compile/testdata/sync/eval/resolve_env.txtar b/internal/core/compile/testdata/sync/eval/resolve_env.txtar new file mode 100644 index 000000000..7ba69a297 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/resolve_env.txtar @@ -0,0 +1,45 @@ +-- in.cue -- +a: { + d: int + b: { + c: d + } + @test(eq, { + d: int + b: c: int + }) +} +x: { + d: 2 @test(eq, 2) + b: a.b.c @test(eq, int) +} +a1: y: 5 +a1: a2: a3: a4: a5: a1.y +b: a1.a2.a3.a4.a5 @test(eq, 5) +-- out/compile -- +--- in.cue +{ + a: { + d: int + b: { + c: 〈1;d〉 + } + } + x: { + d: 2 + b: 〈1;a〉.b.c + } + a1: { + y: 5 + } + a1: { + a2: { + a3: { + a4: { + a5: 〈4;a1〉.y + } + } + } + } + b: 〈0;a1〉.a2.a3.a4.a5 +} diff --git a/internal/core/compile/testdata/sync/eval/selectors.txtar b/internal/core/compile/testdata/sync/eval/selectors.txtar new file mode 100644 index 000000000..ecbce39f2 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/selectors.txtar @@ -0,0 +1,45 @@ +-- in.cue -- +a: 1 @test(eq, 1) +b: a + 1 @test(eq, 2) +d: { + x: _ + y: b + x @test(err, code=incomplete, pos=[0:5, -1:5], contains="non-concrete value") +} +e: d & { + x: 5 +} @test(eq, {x: 5, y: 7}) +f: { + a: "foo-bar": 3 + b: a."foo-bar" +} @test(eq, {a: {"foo-bar": 3}, b: 3}) +g: { + a: "foo-bar": c: 3 + b: a."foo-bar".c +} @test(eq, {a: {"foo-bar": {c: 3}}, b: 3}) +-- out/compile -- +--- in.cue +{ + a: 1 + b: (〈0;a〉 + 1) + d: { + x: _ + y: (〈1;b〉 + 〈0;x〉) + } + e: (〈0;d〉 & { + x: 5 + }) + f: { + a: { + "foo-bar": 3 + } + b: 〈0;a〉."foo-bar" + } + g: { + a: { + "foo-bar": { + c: 3 + } + } + b: 〈0;a〉."foo-bar".c + } +} diff --git a/internal/core/compile/testdata/sync/eval/sharing.txtar b/internal/core/compile/testdata/sync/eval/sharing.txtar new file mode 100644 index 000000000..842f2496c --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/sharing.txtar @@ -0,0 +1,704 @@ +-- in.cue -- +// evalv3 "incDependent: already closed" panic on valid CUE involving +// structure sharing between definitions and regular fields. +// https://cuelang.org/issue/3062 +issue3062: ok1: { + #S: "a" + #o: x: #S + o: #o + o: X + X: x: A + A: "a" + + @test(eq, { + #S: "a" + #o: {x: "a"} + o: {x: "a"} + X: {x: "a"} + A: "a" + }) +} + +// evalv3 "field not allowed" regression from v2 involving structure sharing +// when a field is unified with a shared vertex that has a self-referential path. +// https://cuelang.org/issue/3601 +issue3601: ok1: { + Y: (X & __no_sharing).a + X: a: b: a.b + out: Y & __no_sharing + + @test(eq, {Y: {b: _}, X: {a: {b: _}}, out: {b: _}}) +} + +// Test debug facilities to turn of sharing. +debug: { + sharingOn: { + a: b @test(shareID=sharingOn_ab) + b: {c: 1} @test(shareID=sharingOn_ab) + @test(eq, {a: {c: 1}, b: {c: 1}}) + } + sharingOff: t1: { + a: b & __no_sharing + b: c: 1 + @test(eq, {a: {c: 1}, b: {c: 1}}) + } + sharingOff: t2: { + a: b + a: __no_sharing + b: c: 1 + @test(eq, {a: {c: 1}, b: {c: 1}}) + } + sharingOff: t3: { + a: __no_sharing + a: b + b: c: 1 + @test(eq, {a: {c: 1}, b: {c: 1}}) + } +} +-- dupshare.cue -- +// This file contains tests where unifying the same field multiple times into +// a field with different "closedness" history should compute closedness +// correctly. + +// "field not allowed" regression in evalv3 when the same definition is +// unified into a field multiple times with different closedness histories. +// https://cuelang.org/issue/3641 +issue3641: simplified: t1: { + #Context1: {ctx: {}} @test(shareID=t1ctx1) + Context2: {ctx: {}} @test(shareID=t1ctx2) + + // Must both refer to #Context1 + #Config1: {cfg: #Context1 @test(shareID=t1ctx1)} + #Config3: {cfg: #Context1 @test(shareID=t1ctx1)} + + Config2: {cfg: Context2 @test(shareID=t1ctx2)} + + Config: #Config1 & Config2 + + // order matters + out: Config // Indirection necessary. + out: #Config3 + + @test(eq, { + #Context1: {ctx: {}} + Context2: {ctx: {}} + #Config1: {cfg: {ctx: {}}} + #Config3: {cfg: {ctx: {}}} + Config2: {cfg: {ctx: {}}} + Config: {cfg: {ctx: {}}} + out: {cfg: {ctx: {}}} + }) +} +issue3641: simplified: t2: { + #Context1: {ctx: {}} @test(shareID=t2ctx1) + Context2: {ctx: {}} @test(shareID=t2ctx2) + + // Must both refer to #Context1 + #Config1: {cfg: #Context1 @test(shareID=t2ctx1)} + #Config3: {cfg: #Context1 @test(shareID=t2ctx1)} + + Config2: {cfg: Context2 @test(shareID=t2ctx2)} + + Config: #Config1 & Config2 + + // order matters + out: Config // Indirection necessary. + out: #Config3 + + @test(eq, { + #Context1: {ctx: {}} + Context2: {ctx: {}} + #Config1: {cfg: {ctx: {}}} + #Config3: {cfg: {ctx: {}}} + Config2: {cfg: {ctx: {}}} + Config: {cfg: {ctx: {}}} + out: {cfg: {ctx: {}}} + }) +} +// Variant where sharing is explicitly disabled. +issue3641: simplified: t3: { + #Context1: {ctx: {}} @test(shareID=t3ctx1) + Context2: {ctx: {}} @test(shareID=t3ctx2) + + // Must both refer to #Context1 + #Config1: {cfg: #Context1 @test(shareID=t3ctx1)} + #Config3: {cfg: #Context1 @test(shareID=t3ctx1)} + + Config2: {cfg: Context2 @test(shareID=t3ctx2)} + + Config: #Config1 & Config2 + + // order matters + out: __no_sharing + out: Config // Indirection necessary. + out: #Config3 + + @test(eq, { + #Context1: {ctx: {}} + Context2: {ctx: {}} + #Config1: {cfg: {ctx: {}}} + #Config3: {cfg: {ctx: {}}} + Config2: {cfg: {ctx: {}}} + Config: {cfg: {ctx: {}}} + out: {cfg: {ctx: {}}} + }) +} +issue3641: full: { + #Context1: {ctx: {}} @test(shareID=fullctx1) + #Context2: {ctx: {}} @test(shareID=fullctx2) + + #Config1: {cfg: #Context1 @test(shareID=fullctx1)} @test(shareID=fullcfg1) + #Config2: {cfg: #Context2 @test(shareID=fullctx2)} + + #Schema: {sch: #Config1 @test(shareID=fullcfg1)} + + #Config: #Config1 & #Config2 + + let config = #Config + out: #Schema & { + sch: config + } + + @test(eq, { + #Context1: {ctx: {}} + #Context2: {ctx: {}} + #Config1: {cfg: {ctx: {}}} + #Config2: {cfg: {ctx: {}}} + #Schema: {sch: {cfg: {ctx: {}}}} + #Config: {cfg: {ctx: {}}} + out: {sch: {cfg: {ctx: {}}}} + }) +} +// "field not allowed" evalv3 regression with lists: a list value shared from +// a definition constraint was incorrectly rejected in a regular field. +// https://cuelang.org/issue/3546 +issue3546: reduced: { + all: ["a"] + #all: all + + #Network: list: #List + #List: [...string] + + val: #Network + val: list: #all + + out: #Network + out: val + + @test(eq, { + all: ["a"] + #all: ["a"] + #Network: {list: []} + #List: [] + val: {list: ["a"]} + out: {list: ["a"]} + }) +} +-- sharecycle.cue -- +shareCycle: t1: { + #X: {} + Y: { + x: #X & Y + } + @test(err, code=structural_cycle, path=Y.x.x, contains="structural cycle", pos=[]) +} +shareCycle: t2: { + #X: int + Y: { + x: #X & Y + } + @test(err, code=eval, path=Y.x, + contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[int, {x:(#X & Y)}, int, struct], pos=[1:6, 2:5, 3:6, 3:11]) +} +shareCycle: t3: { + #X: {} + Y: { + x: Y & #X + } + @test(err, code=structural_cycle, at=Y.x.x, contains="structural cycle", pos=[]) +} +-- acrossdisjunction.cue -- +import "list" + +// evalv3 incomplete value regression involving builtin calls: list.Repeat +// result shared across a disjunction boundary was not properly unshared. +// https://cuelang.org/issue/3679 +issue3679: { + // The result of list.Repeat is structure shared in env. This needs to be + // "unshared" within the disjunction. Ensure that unsharing a shared Vertex + // works arcross disjunction boundaries. + b: null | [string] + b: list.Repeat([for k, v in [0] { "bar" }], 1) + + @test(eq, {b: ["bar"]}) +} +-- issue3835.cue -- +// evalv3 regression with "cycle with field" error involving a comprehension +// with a let that references a top-level field via a pattern constraint. +// https://cuelang.org/issue/3835 +issue3835: { + foo: {} + + _global: "global value" + + [string]: { + if true let orgBotUser = _global { + out: "prefix: " + orgBotUser + } + } + + @test(eq, { + foo: {out: "prefix: global value"} + _global: "global value" + }) +} +-- pendingarcs.cue -- +pending: t1: { + a: X + if true { + a: b: c: e: 1 + } + X: {b: Y @test(shareID=pendXbY)} + Y: {c: d: int} @test(shareID=pendXbY) + + @test(eq, { + a: {b: {c: {e: 1, d: int}}} + X: {b: {c: {d: int}}} + Y: {c: {d: int}} + }) +} +// evalv3 "field not allowed" regression with a comprehension that conditionally +// sets a field inside a definition with an optional nested definition. +// https://cuelang.org/issue/3849 +issue3849: { + dep: #Deployment & {} + if true { + dep: metadata: name: app: "mysql" + } + #Deployment: metadata?: #ObjectMeta + #ObjectMeta: name?: [string]: string + + // TODO(inline): investigate why these do not match. Optionals? + // @test(shareID=Meta, at=#Deployment.metadata) + // @test(shareID=Meta, at=#ObjectMeta) + + @test(eq, { + dep: {metadata: {name: {app: "mysql"}}} + #Deployment: {metadata?: {name?: {}}} + #ObjectMeta: {name?: {}} + }) +} +-- let.cue -- +import "list" + +// evalv3 structural cycle regression vs evalv2 when a let binding holds a +// flattened list that is iterated and used to populate a dynamic field. +// https://cuelang.org/issue/3903 +issue3903: full: { + _input: null | *{name: "foo"} + + let _inputList = list.FlattenN([_input], 0) + + _inputByName: { + for input in _inputList { + (input.name): input + } + } + + for name, _input in _inputByName { + (name): _template & { + input: _input + } + } + _template: { + input: name: string + result: "result-\(input.name)" @test(err, code=incomplete, + contains="non-concrete value string (type string)", + pos=[0:11, -1:16]) + } + @test(eq, { + _input: *{name: "foo"} | null + _inputByName: {foo: {name: "foo"}} + _template: { + input: {name: string} + result: _|_ + } + foo: { + input: {name: "foo"} + result: "result-foo" + } + }) +} +issue3903: noshare: { + _input: null | *{name: "foo"} + + let _inputList = list.FlattenN([_input], 0) + + _inputByName: { + for input in (_inputList & __no_sharing) { + (input.name): input + } + } + for name, _input in _inputByName { + (name): _template & { + input: _input + } + } + _template: { + input: name: string + result: "result-\(input.name)" @test(err, code=incomplete, + contains="non-concrete value string (type string)", + pos=[0:11, -1:17]) + } + @test(eq, { + _input: *{name: "foo"} | null + _inputByName: {foo: {name: "foo"}} + _template: { + input: {name: string} + result: _|_ + } + foo: { + input: {name: string} + result: _|_ @test(err, code=incomplete, + contains="non-concrete value string (type string)") + } + }) +} +-- out/compile -- +--- acrossdisjunction.cue +{ + issue3679: { + b: (null|[ + string, + ]) + b: 〈import;list〉.Repeat([ + for k, v in [ + 0, + ] { + "bar" + }, + ], 1) + } +} +--- dupshare.cue +{ + issue3641: { + simplified: { + t1: { + #Context1: { + ctx: {} + } + Context2: { + ctx: {} + } + #Config1: { + cfg: 〈1;#Context1〉 + } + #Config3: { + cfg: 〈1;#Context1〉 + } + Config2: { + cfg: 〈1;Context2〉 + } + Config: (〈0;#Config1〉 & 〈0;Config2〉) + out: 〈0;Config〉 + out: 〈0;#Config3〉 + } + } + } + issue3641: { + simplified: { + t2: { + #Context1: { + ctx: {} + } + Context2: { + ctx: {} + } + #Config1: { + cfg: 〈1;#Context1〉 + } + #Config3: { + cfg: 〈1;#Context1〉 + } + Config2: { + cfg: 〈1;Context2〉 + } + Config: (〈0;#Config1〉 & 〈0;Config2〉) + out: 〈0;Config〉 + out: 〈0;#Config3〉 + } + } + } + issue3641: { + simplified: { + t3: { + #Context1: { + ctx: {} + } + Context2: { + ctx: {} + } + #Config1: { + cfg: 〈1;#Context1〉 + } + #Config3: { + cfg: 〈1;#Context1〉 + } + Config2: { + cfg: 〈1;Context2〉 + } + Config: (〈0;#Config1〉 & 〈0;Config2〉) + out: _|_(no sharing) + out: 〈0;Config〉 + out: 〈0;#Config3〉 + } + } + } + issue3641: { + full: { + #Context1: { + ctx: {} + } + #Context2: { + ctx: {} + } + #Config1: { + cfg: 〈1;#Context1〉 + } + #Config2: { + cfg: 〈1;#Context2〉 + } + #Schema: { + sch: 〈1;#Config1〉 + } + #Config: (〈0;#Config1〉 & 〈0;#Config2〉) + let config#1 = 〈0;#Config〉 + out: (〈0;#Schema〉 & { + sch: 〈1;let config#1〉 + }) + } + } + issue3546: { + reduced: { + all: [ + "a", + ] + #all: 〈0;all〉 + #Network: { + list: 〈1;#List〉 + } + #List: [ + ...string, + ] + val: 〈0;#Network〉 + val: { + list: 〈1;#all〉 + } + out: 〈0;#Network〉 + out: 〈0;val〉 + } + } +} +--- in.cue +{ + issue3062: { + ok1: { + #S: "a" + #o: { + x: 〈1;#S〉 + } + o: 〈0;#o〉 + o: 〈0;X〉 + X: { + x: 〈1;A〉 + } + A: "a" + } + } + issue3601: { + ok1: { + Y: (〈0;X〉 & _|_(no sharing)).a + X: { + a: { + b: 〈1;a〉.b + } + } + out: (〈0;Y〉 & _|_(no sharing)) + } + } + debug: { + sharingOn: { + a: 〈0;b〉 + b: { + c: 1 + } + } + sharingOff: { + t1: { + a: (〈0;b〉 & _|_(no sharing)) + b: { + c: 1 + } + } + } + sharingOff: { + t2: { + a: 〈0;b〉 + a: _|_(no sharing) + b: { + c: 1 + } + } + } + sharingOff: { + t3: { + a: _|_(no sharing) + a: 〈0;b〉 + b: { + c: 1 + } + } + } + } +} +--- issue3835.cue +{ + issue3835: { + foo: {} + _global: "global value" + [string]: { + if true let orgBotUser = 〈1;_global〉 { + out: ("prefix: " + 〈1;orgBotUser〉) + } + } + } +} +--- let.cue +{ + issue3903: { + full: { + _input: (null|*{ + name: "foo" + }) + let _inputList#2 = 〈import;list〉.FlattenN([ + 〈1;_input〉, + ], 0) + _inputByName: { + for _, input in 〈1;let _inputList#2〉 { + 〈1;input〉.name: 〈1;input〉 + } + } + for name, _input in 〈0;_inputByName〉 { + 〈1;name〉: (〈2;_template〉 & { + input: 〈2;_input〉 + }) + } + _template: { + input: { + name: string + } + result: "result-\(〈0;input〉.name)" + } + } + } + issue3903: { + noshare: { + _input: (null|*{ + name: "foo" + }) + let _inputList#3 = 〈import;list〉.FlattenN([ + 〈1;_input〉, + ], 0) + _inputByName: { + for _, input in (〈1;let _inputList#3〉 & _|_(no sharing)) { + 〈1;input〉.name: 〈1;input〉 + } + } + for name, _input in 〈0;_inputByName〉 { + 〈1;name〉: (〈2;_template〉 & { + input: 〈2;_input〉 + }) + } + _template: { + input: { + name: string + } + result: "result-\(〈0;input〉.name)" + } + } + } +} +--- pendingarcs.cue +{ + pending: { + t1: { + a: 〈0;X〉 + if true { + a: { + b: { + c: { + e: 1 + } + } + } + } + X: { + b: 〈1;Y〉 + } + Y: { + c: { + d: int + } + } + } + } + issue3849: { + dep: (〈0;#Deployment〉 & {}) + if true { + dep: { + metadata: { + name: { + app: "mysql" + } + } + } + } + #Deployment: { + metadata?: 〈1;#ObjectMeta〉 + } + #ObjectMeta: { + name?: { + [string]: string + } + } + } +} +--- sharecycle.cue +{ + shareCycle: { + t1: { + #X: {} + Y: { + x: (〈1;#X〉 & 〈1;Y〉) + } + } + } + shareCycle: { + t2: { + #X: int + Y: { + x: (〈1;#X〉 & 〈1;Y〉) + } + } + } + shareCycle: { + t3: { + #X: {} + Y: { + x: (〈1;Y〉 & 〈1;#X〉) + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/shortcircuit.txtar b/internal/core/compile/testdata/sync/eval/shortcircuit.txtar new file mode 100644 index 000000000..f97ce58e2 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/shortcircuit.txtar @@ -0,0 +1,48 @@ +# Tests for @experiment(shortcircuit): short-circuit evaluation of && and ||. +# When the left operand alone determines the result, the right operand is not +# evaluated and any error or incomplete value it carries is suppressed. +-- cue.mod/module.cue -- +module: "test.com" +language: version: "v0.17.0" +-- in.cue -- +@experiment(shortcircuit) + +// Incomplete fields used as right operands in short-circuit tests. +incompleteInt: int +incompleteBool: bool + +// Short-circuit && : false && anything = false. +// Right operand not evaluated; errors/incomplete values suppressed. +andFalseBottom: false && _|_ @test(eq, false) +andFalseIncomplete: false && incompleteInt @test(eq, false) +andFalseTrue: false && true @test(eq, false) + +// No short-circuit: && falls through when left is true. +andTrueTrue: true && true @test(eq, true) +andTrueFalse: true && false @test(eq, false) + +// Short-circuit || : true || anything = true. +// Right operand not evaluated; errors/incomplete values suppressed. +orTrueBottom: true || _|_ @test(eq, true) +orTrueIncomplete: true || incompleteBool @test(eq, true) +orTrueTrue: true || true @test(eq, true) + +// No short-circuit: || falls through when left is false. +orFalseFalse: false || false @test(eq, false) +orFalseTrue: false || true @test(eq, true) +-- out/compile -- +--- in.cue +{ + incompleteInt: int + incompleteBool: bool + andFalseBottom: (false && _|_(explicit error (_|_ literal) in source)) + andFalseIncomplete: (false && 〈0;incompleteInt〉) + andFalseTrue: (false && true) + andTrueTrue: (true && true) + andTrueFalse: (true && false) + orTrueBottom: (true || _|_(explicit error (_|_ literal) in source)) + orTrueIncomplete: (true || 〈0;incompleteBool〉) + orTrueTrue: (true || true) + orFalseFalse: (false || false) + orFalseTrue: (false || true) +} diff --git a/internal/core/compile/testdata/sync/eval/shortcircuit_noexp.txtar b/internal/core/compile/testdata/sync/eval/shortcircuit_noexp.txtar new file mode 100644 index 000000000..30bde5eee --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/shortcircuit_noexp.txtar @@ -0,0 +1,16 @@ +# Verifies that without @experiment(shortcircuit), errors on the right operand +# of && and || still propagate (pre-v0.17.0 behavior is unchanged). +-- cue.mod/module.cue -- +module: "test.com" +language: version: "v0.17.0" +-- in.cue -- +// Without @experiment(shortcircuit), both operands are always evaluated. +// Errors on the right side propagate even when left would short-circuit. +noExpAnd: false && _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[0:20]) +noExpOr: true || _|_ @test(err, code=user, contains="explicit error (_|_ literal) in source", pos=[0:20]) +-- out/compile -- +--- in.cue +{ + noExpAnd: (false && _|_(explicit error (_|_ literal) in source)) + noExpOr: (true || _|_(explicit error (_|_ literal) in source)) +} diff --git a/internal/core/compile/testdata/sync/eval/structs.txtar b/internal/core/compile/testdata/sync/eval/structs.txtar new file mode 100644 index 000000000..fb4cfc426 --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/structs.txtar @@ -0,0 +1,11 @@ +-- in.cue -- +import "struct" + +v: {a: struct.MaxFields(2) & {}}.a @test(eq, {}) @test(eq:todo, struct.MaxFields(2) & {}) +-- out/compile -- +--- in.cue +{ + v: { + a: (〈import;struct〉.MaxFields(2) & {}) + }.a +} diff --git a/internal/core/compile/testdata/sync/eval/unify.txtar b/internal/core/compile/testdata/sync/eval/unify.txtar new file mode 100644 index 000000000..e760f60df --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/unify.txtar @@ -0,0 +1,39 @@ +-- in.cue -- +a: d: { + #base + #info: {...} + Y: #info.X @test(eq, "foo") @test(closed) +} @test(closed) + +#base: { + #info: {...} +} @test(closed) + +a: [Name=string]: {#info: { + X: "foo" +}} @test(closed=false) +-- out/compile -- +--- in.cue +{ + a: { + d: { + 〈2;#base〉 + #info: { + ... + } + Y: 〈0;#info〉.X + } + } + #base: { + #info: { + ... + } + } + a: { + [string]: { + #info: { + X: "foo" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/v0.7.txtar b/internal/core/compile/testdata/sync/eval/v0.7.txtar new file mode 100644 index 000000000..8373ffb0d --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/v0.7.txtar @@ -0,0 +1,843 @@ +# Some new cases specific to v0.7 +-- builtins.cue -- +import "strings" + +mutualBuiltin: t1: ok: { + // Results in incomplete error in v0.6 + s3: strings.ContainsAny(s4) @test(eq, strings.ContainsAny("dd")) + s4: strings.ContainsAny(s3) + s4: "dd" @test(eq, "dd") +} + +mutualBuiltin: t2: ok: { + s3: strings.ContainsAny(s5, "dd") @test(eq, true) + s5: s6 + s6: "dd" +} + +-- comprehensions.cue -- +comprehensions: t1: ok: { + src: ["foo"] + for v in src { "\(v)": v } + @test(eq, {src: ["foo"], foo: "foo"}) +} + +-- dynamic.cue -- +dynamic: t1: ok: { + [X=string]: {name: X} + (x.y): {} + x: y: "foo" + @test(eq, { + x: {y: "foo", name: "x"} + foo: {name: "foo"} + }) +} + +dynamic: t2: ok: { + foo: #X + #X: { + a: b: C: 1 + for _ in a { + a: ("b"): D: 2 + } + } + @test(eq, { + foo: {a: {b: {C: 1, D: 2}}} + #X: {a: {b: {C: 1, D: 2}}} + }) +} + +-- definition.cue -- +definition: t0: err: { + #D1: env: {} + d1: env: c: "C" @test(err, code=eval, contains="field not allowed", pos=[0:11]) + d1: #D1 +} + +definition: t1: err: { + a: #A + a: c: 1 @test(err, code=eval, contains="field not allowed", pos=[0:5]) + // defining after first reference triggers notification mechanism to kick in. + #A: {} +} + +definition: t2: ok: p1: { + #A: { + ... + {a: int} + } + x: #A & { c: int } + @test(eq, {#A: {a: int}, x: {c: int, a: int}}) +} + +definition: t2: ok: p2: { + #A: { + {a: int} + ... + } + x: #A & { c: int } + @test(eq, {#A: {a: int}, x: {c: int, a: int}}) +} + +definition: t2: ok: p3: { + x: #A & { c: int } + #A: { + ... + {a: int} + } + @test(eq, {x: {c: int, a: int}, #A: {a: int}}) +} + +definition: t2: ok: p4: { + x: #A & { c: int } + #A: { + {a: int} + ... + } + @test(eq, {x: {c: int, a: int}, #A: {a: int}}) +} + +-- expr.cue -- +expr: t1: ok: { + a: X + X: 5.0 + X: Y / 2 + Y: a * 2 + @test(eq, {a: 5.0, X: 5.0, Y: 10.0}) +} + +expr: t2: ok: { + A: X + 2 + X: 5 + X: A - 2 + @test(eq, {A: 7, X: 5}) +} + +expr: t3: ok: p1: { + a0: X + X: 5.0 + X: a0 * 1 + @test(eq, {a0: 5.0, X: 5.0}) +} + +expr: t3: ok: p2: { + b: Y * 1 + Y: b * 1 + Y: 5.0 + @test(eq, {b: 5.0, Y: 5.0}) +} + +expr: t4: ok: { + // -> a0 -> X -> b1 -> b0 -> a1 -> a0 + a0: X @test(eq, 5.0) // Need all conjuncts known from X + b0: a1 @test(eq, 7.0) + a1: a0 + 2 @test(eq, 7.0) + b1: b0 - 2 @test(eq, 5.0) + a0: X // defined earlier + X: b1 + X: 5.0 @test(eq, 5.0) +} + +-- in.cue -- +mutual: t0: ok: { + c: e & {b: 2} + e: {a: 1} + e: c + @test(eq, {c: {b: 2, a: 1}, e: {a: 1, b: 2}}) +} + +mutual: t1: ok: { + a: { + b + b: {b: f: 1} + } + a: a.b + a: b: {b: f: 1} + @test(eq, {a: {b: {b: {f: 1}, f: 1}, f: 1}}) +} + +mutual: t2: ok: { + x: a: a: f: 1 + x: y.a + y: a: a: e: 1 + y: x.a + @test(eq, { + x: {a: {a: {f: 1}, e: 1}, f: 1} + y: {a: {a: {e: 1}, f: 1}, e: 1} + }) +} + +mutual: t3: ok: { + d: e: f: 1 + d + d: d: e: g: 1 + @test(eq, { + d: {e: {f: 1, g: 1}, d: {e: {g: 1}}} + e: {f: 1, g: 1} + }) +} + +// This test fails for some permutations in v0.6. +mutual: t4: ok: { + p0: { + z: x.b + x: b: y.c + x: b: {d: b: 2} + y: c: z.d + z: d: {a: 1} + @test(eq, { + z: {d: {a: 1, b: 2}, a: 1, b: 2} + x: {b: {d: {b: 2}, a: 1, b: 2}} + y: {c: {a: 1, b: 2}} + }) + } + + p1: { + x: b: y.c + z: x.b + x: b: {d: b: 2} + y: c: z.d + z: d: {a: 1} + @test(eq, { + x: {b: {d: {b: 2}, a: 1, b: 2}} + z: {d: {a: 1, b: 2}, a: 1, b: 2} + y: {c: {a: 1, b: 2}} + }) + } + + p2: { + x: b: y.c + x: b: {d: b: 2} + y: c: z.d + z: x.b + z: d: {a: 1} + @test(eq, { + x: {b: {d: {b: 2}, a: 1, b: 2}} + y: {c: {a: 1, b: 2}} + z: {d: {a: 1, b: 2}, a: 1, b: 2} + }) + } + + p3: { + x: b: {d: b: 2} + y: c: z.d + z: x.b + x: b: y.c + z: d: {a: 1} + @test(eq, { + x: {b: {d: {b: 2}, a: 1, b: 2}} + y: {c: {a: 1, b: 2}} + z: {d: {a: 1, b: 2}, a: 1, b: 2} + }) + } + + p4: { + z: x.b + x: b: {d: b: 2} + y: c: z.d + x: b: y.c + z: d: {a: 1} + @test(eq, { + z: {d: {a: 1, b: 2}, a: 1, b: 2} + x: {b: {d: {b: 2}, a: 1, b: 2}} + y: {c: {a: 1, b: 2}} + }) + } + + p5: { + x: b: {d: b: 2} + y: c: z.d + x: b: y.c + z: x.b + z: d: {a: 1} + @test(eq, { + x: {b: {d: {b: 2}, a: 1, b: 2}} + y: {c: {a: 1, b: 2}} + z: {d: {a: 1, b: 2}, a: 1, b: 2} + }) + } + + check: p1 & p2 & p3 & p4 & p5 @test(eq, { + x: {b: {d: {b: 2}, a: 1, b: 2}} + z: {d: {a: 1, b: 2}, a: 1, b: 2} + y: {c: {a: 1, b: 2}} + }) +} + +-- equality.cue -- +// evalv3 nil pointer dereference panic in equalTerminal with repeated +// unifications of the same default disjunction inside a close() call. +// https://cuelang.org/issue/3194 +issue3194: reduced: { + A: *0 | >10 + A: *0 | >10 + { + out: close({ b: A }) + out: b: A + }.out + + @test(eq, {A: *0 | >10, b: *0 | >10}) +} + +-- chained.cue -- +import "encoding/yaml" + +// evalv3 "field set was already referenced" regression when a chained field +// lookup resolves through a dynamic field to a yaml.Marshal call. +// https://cuelang.org/issue/3925 +issue3925: reduced: { + out: yaml.Marshal(in.b.actual) + in: { + a: "actual" + a: "actual" | "other" + b: (a): c: "str" + } + + @test(eq, { + out: """ + c: str + + """ + in: {a: "actual", b: {actual: {c: "str"}}} + }) +} +issue3925: full: { + for name, _ in _inputs { + out: (name): early: "early value" + } + _inputs: input1: { + name: "actual" + config: (name): one: "one value" + } + _inputs: [_]: { + name: "actual" | "other" + } + for name, input in _inputs { + out: (name): lateYAML: yaml.Marshal(input.config[input.name]) + } + + @test(eq, { + out: { + input1: { + early: "early value" + lateYAML: """ + one: one value + + """ + } + } + _inputs: { + input1: { + name: "actual" + config: {actual: {one: "one value"}} + } + } + }) +} +-- out/compile -- +--- builtins.cue +{ + mutualBuiltin: { + t1: { + ok: { + s3: 〈import;strings〉.ContainsAny(〈0;s4〉) + s4: 〈import;strings〉.ContainsAny(〈0;s3〉) + s4: "dd" + } + } + } + mutualBuiltin: { + t2: { + ok: { + s3: 〈import;strings〉.ContainsAny(〈0;s5〉, "dd") + s5: 〈0;s6〉 + s6: "dd" + } + } + } +} +--- chained.cue +{ + issue3925: { + reduced: { + out: 〈import;"encoding/yaml"〉.Marshal(〈0;in〉.b.actual) + in: { + a: "actual" + a: ("actual"|"other") + b: { + 〈1;a〉: { + c: "str" + } + } + } + } + } + issue3925: { + full: { + for name, _ in 〈0;_inputs〉 { + out: { + 〈2;name〉: { + early: "early value" + } + } + } + _inputs: { + input1: { + name: "actual" + config: { + 〈1;name〉: { + one: "one value" + } + } + } + } + _inputs: { + [_]: { + name: ("actual"|"other") + } + } + for name, input in 〈0;_inputs〉 { + out: { + 〈2;name〉: { + lateYAML: 〈import;"encoding/yaml"〉.Marshal(〈3;input〉.config[〈3;input〉.name]) + } + } + } + } + } +} +--- comprehensions.cue +{ + comprehensions: { + t1: { + ok: { + src: [ + "foo", + ] + for _, v in 〈0;src〉 { + "\(〈1;v〉)": 〈1;v〉 + } + } + } + } +} +--- definition.cue +{ + definition: { + t0: { + err: { + #D1: { + env: {} + } + d1: { + env: { + c: "C" + } + } + d1: 〈0;#D1〉 + } + } + } + definition: { + t1: { + err: { + a: 〈0;#A〉 + a: { + c: 1 + } + #A: {} + } + } + } + definition: { + t2: { + ok: { + p1: { + #A: { + ... + { + a: int + } + } + x: (〈0;#A〉 & { + c: int + }) + } + } + } + } + definition: { + t2: { + ok: { + p2: { + #A: { + { + a: int + } + ... + } + x: (〈0;#A〉 & { + c: int + }) + } + } + } + } + definition: { + t2: { + ok: { + p3: { + x: (〈0;#A〉 & { + c: int + }) + #A: { + ... + { + a: int + } + } + } + } + } + } + definition: { + t2: { + ok: { + p4: { + x: (〈0;#A〉 & { + c: int + }) + #A: { + { + a: int + } + ... + } + } + } + } + } +} +--- dynamic.cue +{ + dynamic: { + t1: { + ok: { + [string]: { + name: 〈1;-〉 + } + 〈0;x〉.y: {} + x: { + y: "foo" + } + } + } + } + dynamic: { + t2: { + ok: { + foo: 〈0;#X〉 + #X: { + a: { + b: { + C: 1 + } + } + for _, _ in 〈0;a〉 { + a: { + "b": { + D: 2 + } + } + } + } + } + } + } +} +--- equality.cue +{ + issue3194: { + reduced: { + A: (*0|>10) + A: (*0|>10) + { + out: close({ + b: 〈2;A〉 + }) + out: { + b: 〈2;A〉 + } + }.out + } + } +} +--- expr.cue +{ + expr: { + t1: { + ok: { + a: 〈0;X〉 + X: 5.0 + X: (〈0;Y〉 / 2) + Y: (〈0;a〉 * 2) + } + } + } + expr: { + t2: { + ok: { + A: (〈0;X〉 + 2) + X: 5 + X: (〈0;A〉 - 2) + } + } + } + expr: { + t3: { + ok: { + p1: { + a0: 〈0;X〉 + X: 5.0 + X: (〈0;a0〉 * 1) + } + } + } + } + expr: { + t3: { + ok: { + p2: { + b: (〈0;Y〉 * 1) + Y: (〈0;b〉 * 1) + Y: 5.0 + } + } + } + } + expr: { + t4: { + ok: { + a0: 〈0;X〉 + b0: 〈0;a1〉 + a1: (〈0;a0〉 + 2) + b1: (〈0;b0〉 - 2) + a0: 〈0;X〉 + X: 〈0;b1〉 + X: 5.0 + } + } + } +} +--- in.cue +{ + mutual: { + t0: { + ok: { + c: (〈0;e〉 & { + b: 2 + }) + e: { + a: 1 + } + e: 〈0;c〉 + } + } + } + mutual: { + t1: { + ok: { + a: { + 〈0;b〉 + b: { + b: { + f: 1 + } + } + } + a: 〈0;a〉.b + a: { + b: { + b: { + f: 1 + } + } + } + } + } + } + mutual: { + t2: { + ok: { + x: { + a: { + a: { + f: 1 + } + } + } + x: 〈0;y〉.a + y: { + a: { + a: { + e: 1 + } + } + } + y: 〈0;x〉.a + } + } + } + mutual: { + t3: { + ok: { + d: { + e: { + f: 1 + } + } + 〈0;d〉 + d: { + d: { + e: { + g: 1 + } + } + } + } + } + } + mutual: { + t4: { + ok: { + p0: { + z: 〈0;x〉.b + x: { + b: 〈1;y〉.c + } + x: { + b: { + d: { + b: 2 + } + } + } + y: { + c: 〈1;z〉.d + } + z: { + d: { + a: 1 + } + } + } + p1: { + x: { + b: 〈1;y〉.c + } + z: 〈0;x〉.b + x: { + b: { + d: { + b: 2 + } + } + } + y: { + c: 〈1;z〉.d + } + z: { + d: { + a: 1 + } + } + } + p2: { + x: { + b: 〈1;y〉.c + } + x: { + b: { + d: { + b: 2 + } + } + } + y: { + c: 〈1;z〉.d + } + z: 〈0;x〉.b + z: { + d: { + a: 1 + } + } + } + p3: { + x: { + b: { + d: { + b: 2 + } + } + } + y: { + c: 〈1;z〉.d + } + z: 〈0;x〉.b + x: { + b: 〈1;y〉.c + } + z: { + d: { + a: 1 + } + } + } + p4: { + z: 〈0;x〉.b + x: { + b: { + d: { + b: 2 + } + } + } + y: { + c: 〈1;z〉.d + } + x: { + b: 〈1;y〉.c + } + z: { + d: { + a: 1 + } + } + } + p5: { + x: { + b: { + d: { + b: 2 + } + } + } + y: { + c: 〈1;z〉.d + } + x: { + b: 〈1;y〉.c + } + z: 〈0;x〉.b + z: { + d: { + a: 1 + } + } + } + check: ((((〈0;p1〉 & 〈0;p2〉) & 〈0;p3〉) & 〈0;p4〉) & 〈0;p5〉) + } + } + } +} diff --git a/internal/core/compile/testdata/sync/eval/v0.7errorprop.txtar b/internal/core/compile/testdata/sync/eval/v0.7errorprop.txtar new file mode 100644 index 000000000..34daad2ec --- /dev/null +++ b/internal/core/compile/testdata/sync/eval/v0.7errorprop.txtar @@ -0,0 +1,17 @@ +// NOTE: do not add more tests to this file, as it may obfuscate the test case. +-- in.cue -- +a: #A +a: c: 1 @test(err, code=eval, + contains="field not allowed", + pos=[in.cue:2:4], + hint="more positions may be allowed, see out/todo.txt for details") +#A: {} @test(eq, {}) +-- out/compile -- +--- in.cue +{ + a: 〈0;#A〉 + a: { + c: 1 + } + #A: {} +} diff --git a/internal/core/compile/testdata/sync/export/000.txtar b/internal/core/compile/testdata/sync/export/000.txtar new file mode 100644 index 000000000..1bc7c95b0 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/000.txtar @@ -0,0 +1,8 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +"hello" +-- out/compile -- +--- in.cue +{ + "hello" +} diff --git a/internal/core/compile/testdata/sync/export/001.txtar b/internal/core/compile/testdata/sync/export/001.txtar new file mode 100644 index 000000000..ba7a70147 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/001.txtar @@ -0,0 +1,8 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +'hello' +-- out/compile -- +--- in.cue +{ + 'hello' +} diff --git a/internal/core/compile/testdata/sync/export/002.txtar b/internal/core/compile/testdata/sync/export/002.txtar new file mode 100644 index 000000000..37cd7fa22 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/002.txtar @@ -0,0 +1,8 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +'hello\nworld' +-- out/compile -- +--- in.cue +{ + 'hello\nworld' +} diff --git a/internal/core/compile/testdata/sync/export/003.txtar b/internal/core/compile/testdata/sync/export/003.txtar new file mode 100644 index 000000000..b23e444fd --- /dev/null +++ b/internal/core/compile/testdata/sync/export/003.txtar @@ -0,0 +1,8 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +"hello\nworld" +-- out/compile -- +--- in.cue +{ + "hello\nworld" +} diff --git a/internal/core/compile/testdata/sync/export/004.txtar b/internal/core/compile/testdata/sync/export/004.txtar new file mode 100644 index 000000000..094f91b74 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/004.txtar @@ -0,0 +1,18 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + $type: 3 + "_": int + "_foo": int + _bar: int +} +-- out/compile -- +--- in.cue +{ + { + $type: 3 + "_": int + "_foo": int + _bar: int + } +} diff --git a/internal/core/compile/testdata/sync/export/005.txtar b/internal/core/compile/testdata/sync/export/005.txtar new file mode 100644 index 000000000..63bfc9fb7 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/005.txtar @@ -0,0 +1,15 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: 1, b: a + 2, c: null, d: true, e: _, f: string} +-- out/compile -- +--- in.cue +{ + { + a: 1 + b: (〈0;a〉 + 2) + c: null + d: true + e: _ + f: string + } +} diff --git a/internal/core/compile/testdata/sync/export/006.txtar b/internal/core/compile/testdata/sync/export/006.txtar new file mode 100644 index 000000000..11816be60 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/006.txtar @@ -0,0 +1,17 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: {b: 2.0, s: "abc"}, b: a.b, c: a.c, d: a["d"], e: a.t[2:3]} +-- out/compile -- +--- in.cue +{ + { + a: { + b: 2.0 + s: "abc" + } + b: 〈0;a〉.b + c: 〈0;a〉.c + d: 〈0;a〉["d"] + e: 〈0;a〉.t[2:3] + } +} diff --git a/internal/core/compile/testdata/sync/export/007.txtar b/internal/core/compile/testdata/sync/export/007.txtar new file mode 100644 index 000000000..8fdc8917c --- /dev/null +++ b/internal/core/compile/testdata/sync/export/007.txtar @@ -0,0 +1,23 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + #a: {b: 2.0, s: "abc"} + b: #a.b + c: #a.c + d: #a["d"] + e: #a.t[2:3] +} +-- out/compile -- +--- in.cue +{ + { + #a: { + b: 2.0 + s: "abc" + } + b: 〈0;#a〉.b + c: 〈0;#a〉.c + d: 〈0;#a〉["d"] + e: 〈0;#a〉.t[2:3] + } +} diff --git a/internal/core/compile/testdata/sync/export/008.txtar b/internal/core/compile/testdata/sync/export/008.txtar new file mode 100644 index 000000000..c2b151f2c --- /dev/null +++ b/internal/core/compile/testdata/sync/export/008.txtar @@ -0,0 +1,12 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: [ 3 & 4]} +-- out/compile -- +--- in.cue +{ + { + a: [ + (3 & 4), + ] + } +} diff --git a/internal/core/compile/testdata/sync/export/009.txtar b/internal/core/compile/testdata/sync/export/009.txtar new file mode 100644 index 000000000..641506493 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/009.txtar @@ -0,0 +1,38 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +import "list" + +{ + a: list.Repeat([int], 5) + a: [1, 2, ...] + e: [...int] + e: [1, 2, ...] + f: [1, 2, ...] +} +-- out/compile -- +--- in.cue +{ + { + a: 〈import;list〉.Repeat([ + int, + ], 5) + a: [ + 1, + 2, + ..., + ] + e: [ + ...int, + ] + e: [ + 1, + 2, + ..., + ] + f: [ + 1, + 2, + ..., + ] + } +} diff --git a/internal/core/compile/testdata/sync/export/010.txtar b/internal/core/compile/testdata/sync/export/010.txtar new file mode 100644 index 000000000..f70934b8d --- /dev/null +++ b/internal/core/compile/testdata/sync/export/010.txtar @@ -0,0 +1,39 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +import "list" + +{ + a: list.Repeat([int], 5) + a: [1, 2, ...] + e: [...int] + e: [1, 2, ...] + f: [1, 2, ...] +} +-- out/compile -- +--- in.cue +{ + { + a: 〈import;list〉.Repeat([ + int, + ], 5) + a: [ + 1, + 2, + ..., + ] + e: [ + ...int, + ] + e: [ + 1, + 2, + ..., + ] + f: [ + 1, + 2, + ..., + ] + } +} diff --git a/internal/core/compile/testdata/sync/export/011.txtar b/internal/core/compile/testdata/sync/export/011.txtar new file mode 100644 index 000000000..eec9d52eb --- /dev/null +++ b/internal/core/compile/testdata/sync/export/011.txtar @@ -0,0 +1,15 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: {b: []}, c: a.b, d: a["b"]} +-- out/compile -- +--- in.cue +{ + { + a: { + b: [] + } + c: 〈0;a〉.b + d: 〈0;a〉["b"] + } +} diff --git a/internal/core/compile/testdata/sync/export/012.txtar b/internal/core/compile/testdata/sync/export/012.txtar new file mode 100644 index 000000000..8cffd1dc7 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/012.txtar @@ -0,0 +1,12 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: *"foo" | *"bar" | *string | int, b: a[2:3]} +-- out/compile -- +--- in.cue +{ + { + a: (*"foo"|*"bar"|*string|int) + b: 〈0;a〉[2:3] + } +} diff --git a/internal/core/compile/testdata/sync/export/013.txtar b/internal/core/compile/testdata/sync/export/013.txtar new file mode 100644 index 000000000..acf45519d --- /dev/null +++ b/internal/core/compile/testdata/sync/export/013.txtar @@ -0,0 +1,12 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + a: >=0 & <=10 & !=1 +} +-- out/compile -- +--- in.cue +{ + { + a: ((>=0 & <=10) & !=1) + } +} diff --git a/internal/core/compile/testdata/sync/export/014.txtar b/internal/core/compile/testdata/sync/export/014.txtar new file mode 100644 index 000000000..ed327f54f --- /dev/null +++ b/internal/core/compile/testdata/sync/export/014.txtar @@ -0,0 +1,13 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + a: >=0 & <=10 & !=1 +} +-- out/compile -- +--- in.cue +{ + { + a: ((>=0 & <=10) & !=1) + } +} diff --git a/internal/core/compile/testdata/sync/export/015.txtar b/internal/core/compile/testdata/sync/export/015.txtar new file mode 100644 index 000000000..ea24da33c --- /dev/null +++ b/internal/core/compile/testdata/sync/export/015.txtar @@ -0,0 +1,18 @@ +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + a: (*1 | 2) & (1 | *2) + b: [(*1 | 2) & (1 | *2)] +} +-- out/compile -- +--- in.cue +{ + { + a: ((*1|2) & (1|*2)) + b: [ + ((*1|2) & (1|*2)), + ] + } +} diff --git a/internal/core/compile/testdata/sync/export/016.txtar b/internal/core/compile/testdata/sync/export/016.txtar new file mode 100644 index 000000000..4c95e917f --- /dev/null +++ b/internal/core/compile/testdata/sync/export/016.txtar @@ -0,0 +1,38 @@ +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + u16: int & >=0 & <=65535 + u32: uint32 + u64: uint64 + u128: uint128 + u8: uint8 + ua: uint16 & >0 + us: >=0 & <10_000 & int + i16: >=-32768 & int & <=32767 + i32: int32 & >0 + i64: int64 + i128: int128 + f64: float64 + fi: float64 & int +} +-- out/compile -- +--- in.cue +{ + { + u16: ((int & >=0) & <=65535) + u32: &(int, >=0, <=4294967295) + u64: &(int, >=0, <=18446744073709551615) + u128: &(int, >=0, <=340282366920938463463374607431768211455) + u8: &(int, >=0, <=255) + ua: (&(int, >=0, <=65535) & >0) + us: ((>=0 & <10000) & int) + i16: ((>=-32768 & int) & <=32767) + i32: (&(int, >=-2147483648, <=2147483647) & >0) + i64: &(int, >=-9223372036854775808, <=9223372036854775807) + i128: &(int, >=-170141183460469231731687303715884105728, <=170141183460469231731687303715884105727) + f64: &(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308) + fi: (&(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308) & int) + } +} diff --git a/internal/core/compile/testdata/sync/export/017.txtar b/internal/core/compile/testdata/sync/export/017.txtar new file mode 100644 index 000000000..a123c52c3 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/017.txtar @@ -0,0 +1,19 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: [1, 2], b: {for k, v in a if v > 1 {"\(k)": v}}} +-- out/compile -- +--- in.cue +{ + { + a: [ + 1, + 2, + ] + b: { + for k, v in 〈1;a〉 if (〈0;v〉 > 1) { + "\(〈1;k〉)": 〈1;v〉 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/export/018.txtar b/internal/core/compile/testdata/sync/export/018.txtar new file mode 100644 index 000000000..6e40e15d0 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/018.txtar @@ -0,0 +1,19 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: [1, 2], b: [for k, v in a {v}]} +-- out/compile -- +--- in.cue +{ + { + a: [ + 1, + 2, + ] + b: [ + for k, v in 〈1;a〉 { + 〈1;v〉 + }, + ] + } +} diff --git a/internal/core/compile/testdata/sync/export/019.txtar b/internal/core/compile/testdata/sync/export/019.txtar new file mode 100644 index 000000000..32e40dbc3 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/019.txtar @@ -0,0 +1,12 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: >=0 & <=10, b: "Count: \(a) times"} +-- out/compile -- +--- in.cue +{ + { + a: (>=0 & <=10) + b: "Count: \(〈0;a〉) times" + } +} diff --git a/internal/core/compile/testdata/sync/export/020.txtar b/internal/core/compile/testdata/sync/export/020.txtar new file mode 100644 index 000000000..0e56148cd --- /dev/null +++ b/internal/core/compile/testdata/sync/export/020.txtar @@ -0,0 +1,12 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{a: "", b: len(a)} +-- out/compile -- +--- in.cue +{ + { + a: "" + b: len(〈0;a〉) + } +} diff --git a/internal/core/compile/testdata/sync/export/021.txtar b/internal/core/compile/testdata/sync/export/021.txtar new file mode 100644 index 000000000..df297fb3c --- /dev/null +++ b/internal/core/compile/testdata/sync/export/021.txtar @@ -0,0 +1,30 @@ +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + b: { + idx: a[str] + str: string + } + b: a: b: 4 + a: b: 3 +} +-- out/compile -- +--- in.cue +{ + { + b: { + idx: 〈1;a〉[〈0;str〉] + str: string + } + b: { + a: { + b: 4 + } + } + a: { + b: 3 + } + } +} diff --git a/internal/core/compile/testdata/sync/export/022.txtar b/internal/core/compile/testdata/sync/export/022.txtar new file mode 100644 index 000000000..88408f927 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/022.txtar @@ -0,0 +1,43 @@ +raw: true +eval: true +noOpt: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + job: [Name=_]: { + name: Name + replicas: uint | *1 @protobuf(10) + command: string + } + + job: list: command: "ls" + + job: nginx: { + command: "nginx" + replicas: 2 + } +} +-- out/compile -- +--- in.cue +{ + { + job: { + [_]: { + name: 〈1;-〉 + replicas: (&(int, >=0)|*1) + command: string + } + } + job: { + list: { + command: "ls" + } + } + job: { + nginx: { + command: "nginx" + replicas: 2 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/export/023.txtar b/internal/core/compile/testdata/sync/export/023.txtar new file mode 100644 index 000000000..62c32ee21 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/023.txtar @@ -0,0 +1,54 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + #emb: { + a: 1 + + sub: { + f: 3 + } + } + #def: { + #emb + + b: 2 + } + #f: a: 10 + #e: { + #f + + b: int + {[_]: <100} + {[_]: <300} + } +} +-- out/compile -- +--- in.cue +{ + { + #emb: { + a: 1 + sub: { + f: 3 + } + } + #def: { + 〈1;#emb〉 + b: 2 + } + #f: { + a: 10 + } + #e: { + 〈1;#f〉 + b: int + { + [_]: <100 + } + { + [_]: <300 + } + } + } +} diff --git a/internal/core/compile/testdata/sync/export/024.txtar b/internal/core/compile/testdata/sync/export/024.txtar new file mode 100644 index 000000000..abdd90843 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/024.txtar @@ -0,0 +1,41 @@ +raw: true +eval: true +noOpt: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + reg: {foo: 1, bar: {baz: 3}} + #def: { + a: 1 + + sub: reg + } + val: #def + #def2: { + a: {b: int} + } + val2: #def2 +} +-- out/compile -- +--- in.cue +{ + { + reg: { + foo: 1 + bar: { + baz: 3 + } + } + #def: { + a: 1 + sub: 〈1;reg〉 + } + val: 〈0;#def〉 + #def2: { + a: { + b: int + } + } + val2: 〈0;#def2〉 + } +} diff --git a/internal/core/compile/testdata/sync/export/025.txtar b/internal/core/compile/testdata/sync/export/025.txtar new file mode 100644 index 000000000..c5098255d --- /dev/null +++ b/internal/core/compile/testdata/sync/export/025.txtar @@ -0,0 +1,32 @@ +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + b: [{ + {[X=_]: int} + if a > 4 { + f: 4 + } + }][a] + a: int + c: *1 | 2 +} +-- out/compile -- +--- in.cue +{ + { + b: [ + { + { + [_]: int + } + if (〈2;a〉 > 4) { + f: 4 + } + }, + ][〈0;a〉] + a: int + c: (*1|2) + } +} diff --git a/internal/core/compile/testdata/sync/export/026.txtar b/internal/core/compile/testdata/sync/export/026.txtar new file mode 100644 index 000000000..33c612afb --- /dev/null +++ b/internal/core/compile/testdata/sync/export/026.txtar @@ -0,0 +1,21 @@ +raw: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + if false { + {a: 1} | {b: 1} + } +} +-- out/compile -- +--- in.cue +{ + { + if false { + ({ + a: 1 + }|{ + b: 1 + }) + } + } +} diff --git a/internal/core/compile/testdata/sync/export/027.txtar b/internal/core/compile/testdata/sync/export/027.txtar new file mode 100644 index 000000000..931d56df7 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/027.txtar @@ -0,0 +1,22 @@ + +TODO: Should #Bar result in string or #Foo | string? + + +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + #Foo: { + #Bar: #Foo | string + } +} +-- out/compile -- +--- in.cue +{ + { + #Foo: { + #Bar: (〈1;#Foo〉|string) + } + } +} diff --git a/internal/core/compile/testdata/sync/export/028.txtar b/internal/core/compile/testdata/sync/export/028.txtar new file mode 100644 index 000000000..1afc37a1d --- /dev/null +++ b/internal/core/compile/testdata/sync/export/028.txtar @@ -0,0 +1,26 @@ +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + #FindInMap: { + #: "Fn::FindInMap": [string | #FindInMap] + } + a: [...string] +} +-- out/compile -- +--- in.cue +{ + { + #FindInMap: { + #: { + "Fn::FindInMap": [ + (string|〈3;#FindInMap〉), + ] + } + } + a: [ + ...string, + ] + } +} diff --git a/internal/core/compile/testdata/sync/export/029.txtar b/internal/core/compile/testdata/sync/export/029.txtar new file mode 100644 index 000000000..52d152bc1 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/029.txtar @@ -0,0 +1,33 @@ +raw: true +eval: true +noOpt: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + #And: { + #: "Fn::And": [...(3 | #And)] + } + #Ands: #And & { + #: "Fn::And": [_] + } +} +-- out/compile -- +--- in.cue +{ + { + #And: { + #: { + "Fn::And": [ + ...(3|〈3;#And〉), + ] + } + } + #Ands: (〈0;#And〉 & { + #: { + "Fn::And": [ + _, + ] + } + }) + } +} diff --git a/internal/core/compile/testdata/sync/export/030.txtar b/internal/core/compile/testdata/sync/export/030.txtar new file mode 100644 index 000000000..81ce20770 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/030.txtar @@ -0,0 +1,38 @@ +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + #Foo: { + sgl: #Bar + ref: null | #Foo + ext: #Bar | null + ref: null | #Foo + ref2: null | #Foo.sgl + ... + } + #Foo: { + "#Foo": 2 + ... + } + #Bar: string +} +-- out/compile -- +--- in.cue +{ + { + #Foo: { + sgl: 〈1;#Bar〉 + ref: (null|〈1;#Foo〉) + ext: (〈1;#Bar〉|null) + ref: (null|〈1;#Foo〉) + ref2: (null|〈1;#Foo〉.sgl) + ... + } + #Foo: { + "#Foo": 2 + ... + } + #Bar: string + } +} diff --git a/internal/core/compile/testdata/sync/export/031.txtar b/internal/core/compile/testdata/sync/export/031.txtar new file mode 100644 index 000000000..d11e0127f --- /dev/null +++ b/internal/core/compile/testdata/sync/export/031.txtar @@ -0,0 +1,22 @@ +raw: true +eval: true +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + A: [uint] + B: A & ([10] | [192]) +} +-- out/compile -- +--- in.cue +{ + { + A: [ + &(int, >=0), + ] + B: (〈0;A〉 & ([ + 10, + ]|[ + 192, + ])) + } +} diff --git a/internal/core/compile/testdata/sync/export/032.txtar b/internal/core/compile/testdata/sync/export/032.txtar new file mode 100644 index 000000000..7454956ef --- /dev/null +++ b/internal/core/compile/testdata/sync/export/032.txtar @@ -0,0 +1,14 @@ +#inlinetest:exclude skip — tests export format, not evaluator semantics +-- in.cue -- +{ + [string]: _ + foo: 3 +} +-- out/compile -- +--- in.cue +{ + { + [string]: _ + foo: 3 + } +} diff --git a/internal/core/compile/testdata/sync/export/issue2119.txtar b/internal/core/compile/testdata/sync/export/issue2119.txtar new file mode 100644 index 000000000..c2ab100f8 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/issue2119.txtar @@ -0,0 +1,92 @@ +-- in.cue -- +import ( + "encoding/yaml" + "regexp" +) + +simplified: { + x: d: R={ + ".*" + [R+""][0] + } + out: yaml.Marshal(x) + @test(eq, {x: {d: ".*"}, out: "d: .*\n"}) +} + +original: { + #testableRegexp: R={ + string + + #test: close({ + in: string + out: regexp.FindSubmatch("^"+R+"$", in)[1] + }) + } + + rule: { + #patterns: { + bar: #testableRegexp & { + "(.*)" + #test: {in: "testcontent", out: "testcontent"} + } + } + } + out: yaml.Marshal(rule) + @test(eq, { + #testableRegexp: { + string + #test: { + in: string + out: _|_ @test(err, code=incomplete, contains="original.#testableRegexp.#test.out: non-concrete value string in operand to +", pos=[21:29, 16:21, 17:3]) + } + } + rule: { + #patterns: { + bar: { + "(.*)" + #test: {in: "testcontent", out: "testcontent"} + } + } + } + out: """ + {} + + """ + }) +} +-- out/compile -- +--- in.cue +{ + simplified: { + x: { + d: { + ".*" + [ + (〈2〉 + ""), + ][0] + } + } + out: 〈import;"encoding/yaml"〉.Marshal(〈0;x〉) + } + original: { + #testableRegexp: { + string + #test: close({ + in: string + out: 〈import;regexp〉.FindSubmatch((("^" + 〈2〉) + "$"), 〈0;in〉)[1] + }) + } + rule: { + #patterns: { + bar: (〈2;#testableRegexp〉 & { + "(.*)" + #test: { + in: "testcontent" + out: "testcontent" + } + }) + } + } + out: 〈import;"encoding/yaml"〉.Marshal(〈0;rule〉) + } +} diff --git a/internal/core/compile/testdata/sync/export/issue2244.txtar b/internal/core/compile/testdata/sync/export/issue2244.txtar new file mode 100644 index 000000000..b974d8cd0 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/issue2244.txtar @@ -0,0 +1,71 @@ +-- in.cue -- +package x + +import ( + "strings" +) + +_#matchPattern: { + #pattern: string + [ + // can't remove this builtin call + if strings.HasSuffix(#pattern, "*") { + + // this let is required _within_ the if block + // i.e. it can't be "inlined" with the if that + // currently contains it + let prefix = strings.TrimSuffix(#pattern, "*") + + prefix + }, + "'\(#pattern)'", + ][0] +} + +_#isReleaseTag: _#matchPattern & {#pattern: "refs/tags/v*", _} + +#step: { + if: number | string +} + +m: #step & { + if: _#isReleaseTag +} +@test(eq, { + _#matchPattern$x: {_|_, #pattern: string} + _#isReleaseTag$x: { + "refs/tags/v" + #pattern: "refs/tags/v*" + } + #step: {if: number | string} + m: { + if: { + "refs/tags/v" + #pattern: "refs/tags/v*" + } + } +}) +-- out/compile -- +--- in.cue +{ + _#matchPattern(:x): { + #pattern: string + [ + if 〈import;strings〉.HasSuffix(〈1;#pattern〉, "*") { + let prefix#1 = 〈import;strings〉.TrimSuffix(〈2;#pattern〉, "*") + 〈0;let prefix#1〉 + }, + "'\(〈1;#pattern〉)'", + ][0] + } + _#isReleaseTag(:x): (〈0;_#matchPattern(:x)〉 & { + #pattern: "refs/tags/v*" + _ + }) + #step: { + if: (number|string) + } + m: (〈0;#step〉 & { + if: 〈1;_#isReleaseTag(:x)〉 + }) +} diff --git a/internal/core/compile/testdata/sync/export/issue854.txtar b/internal/core/compile/testdata/sync/export/issue854.txtar new file mode 100644 index 000000000..d2eddee26 --- /dev/null +++ b/internal/core/compile/testdata/sync/export/issue854.txtar @@ -0,0 +1,26 @@ +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- a.cue -- +package a + +import "mod.test/b" + +theb: b.name @test(err, code=incomplete, path=b, contains="undefined field: %s", args=[c], pos=[b/b.cue:5:6]) +-- b/b.cue -- +package b + +import "mod.test/c" + +b: c.c & { + other: "name" +} + +name: b.other +-- c/c.cue -- +package c +-- out/compile -- +--- a.cue +{ + theb: 〈import;"mod.test/b"〉.name +} diff --git a/internal/core/compile/testdata/sync/fulleval/000_detect_conflicting_value.txtar b/internal/core/compile/testdata/sync/fulleval/000_detect_conflicting_value.txtar new file mode 100644 index 000000000..1a79e45cc --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/000_detect_conflicting_value.txtar @@ -0,0 +1,13 @@ +# Tests that a float value conflicting with a disjunction of an int value and int type +# reports an empty disjunction error. Issue: regression test for early evaluator behavior. +-- in.cue -- +a: 8000.9 +a: 7080 | int @test(err, code=eval, + suberr=(code=eval, contains="conflicting values", args=[8000.9, 7080], pos=[in.cue:1:4, in.cue:2:4]), + suberr=(code=eval, contains="conflicting values", args=[8000.9, int], pos=[in.cue:1:4, in.cue:2:11])) +-- out/compile -- +--- in.cue +{ + a: 8000.9 + a: (7080|int) +} diff --git a/internal/core/compile/testdata/sync/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar b/internal/core/compile/testdata/sync/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar new file mode 100644 index 000000000..4c2949f3a --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar @@ -0,0 +1,25 @@ +#name: conflicts in optional fields are okay +#evalFull +-- in.cue -- +d: {a: 1, b?: 3} | {a: 2} @test(eq, {a: 1, b?: 3} | {a: 2}) + +// the following conjunction should not eliminate any disjuncts +c: d & {b?: 4} @test(eq, { + b?: _|_ @test(err, code=eval, contains="conflicting values", args=[3, 4], pos=[1:15, 4:4, 4:13]) + a: 1 +} | { + b?: 4, a: 2 +}) +-- out/compile -- +--- in.cue +{ + d: ({ + a: 1 + b?: 3 + }|{ + a: 2 + }) + c: (〈0;d〉 & { + b?: 4 + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/002_resolve_all_disjunctions.txtar b/internal/core/compile/testdata/sync/fulleval/002_resolve_all_disjunctions.txtar new file mode 100644 index 000000000..e99f1bcec --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/002_resolve_all_disjunctions.txtar @@ -0,0 +1,40 @@ +-- in.cue -- +service: [Name=string]: { + name: string | *Name + port: int | *7080 +} +service: foo: _ @test(eq, { + name: *"foo" | string + port: *7080 | int +}) +service: bar: {port: 8000} @test(eq, { + port: 8000 + name: *"bar" | string +}) +service: baz: {name: "foobar"} @test(eq, { + name: "foobar" + port: *7080 | int +}) +-- out/compile -- +--- in.cue +{ + service: { + [string]: { + name: (string|*〈1;-〉) + port: (int|*7080) + } + } + service: { + foo: _ + } + service: { + bar: { + port: 8000 + } + } + service: { + baz: { + name: "foobar" + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/003_field_templates.txtar b/internal/core/compile/testdata/sync/fulleval/003_field_templates.txtar new file mode 100644 index 000000000..f311e7fc6 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/003_field_templates.txtar @@ -0,0 +1,52 @@ +-- in.cue -- +a: { + {[name=_]: int} + k: 1 + @test(eq, {k: 1}) +} +b: { + {[X=_]: {x: 0, y: *1 | int}} + v: {} @test(eq, {x: 0, y: *1 | int}) + w: {y: 0} @test(eq, {y: 0, x: 0}) +} +b: {[y=_]: {}} // TODO: allow different name +c: { + {[Name=_]: {name: Name, y: 1}} + foo: {} @test(eq, {name: "foo", y: 1}) + bar: _ @test(eq, {name: "bar", y: 1}) +} +-- out/compile -- +--- in.cue +{ + a: { + { + [_]: int + } + k: 1 + } + b: { + { + [_]: { + x: 0 + y: (*1|int) + } + } + v: {} + w: { + y: 0 + } + } + b: { + [_]: {} + } + c: { + { + [_]: { + name: 〈1;-〉 + y: 1 + } + } + foo: {} + bar: _ + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/004_field_comprehension.txtar b/internal/core/compile/testdata/sync/fulleval/004_field_comprehension.txtar new file mode 100644 index 000000000..1be88ba27 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/004_field_comprehension.txtar @@ -0,0 +1,43 @@ +-- in.cue -- +a: { + for k, v in b + if k < "d" + if v > b.a { + "\(k)": v + } + @test(eq, {b: 2, c: 3}) +} +b: { + a: 1 + b: 2 + c: 3 + d: 4 +} +c: { + for k, v in b + if k < "d" + if v > b.a { + "\(k)": v + } + @test(eq, {b: 2, c: 3}) +} +-- out/compile -- +--- in.cue +{ + a: { + for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { + "\(〈1;k〉)": 〈1;v〉 + } + } + b: { + a: 1 + b: 2 + c: 3 + d: 4 + } + c: { + for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { + "\(〈1;k〉)": 〈1;v〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/005_conditional_field.txtar b/internal/core/compile/testdata/sync/fulleval/005_conditional_field.txtar new file mode 100644 index 000000000..0574a9b0e --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/005_conditional_field.txtar @@ -0,0 +1,47 @@ +-- in.cue -- +a: { + @test(eq, { + b: true + a: "foo" + }) + if b { + a: "foo" + } + b: true +} +c: { + a: 3 + if a > 1 { + a: 3 + } + @test(eq, { a: 3 }) +} +d: { + a: int + if a > 1 { + a: 3 + } + @test(err, code=(cycle|incomplete)) +} +-- out/compile -- +--- in.cue +{ + a: { + if 〈0;b〉 { + a: "foo" + } + b: true + } + c: { + a: 3 + if (〈0;a〉 > 1) { + a: 3 + } + } + d: { + a: int + if (〈0;a〉 > 1) { + a: 3 + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/006_referencing_field_in_field_comprehension.txtar b/internal/core/compile/testdata/sync/fulleval/006_referencing_field_in_field_comprehension.txtar new file mode 100644 index 000000000..00e51347e --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/006_referencing_field_in_field_comprehension.txtar @@ -0,0 +1,26 @@ +-- in.cue -- +a: {b: c: 4} +a: { + @test(eq, {b: {c: 4, d: 5}, c: 4, d: 5}) + b: d: 5 + for k, v in b { + "\(k)": v + } +} +-- out/compile -- +--- in.cue +{ + a: { + b: { + c: 4 + } + } + a: { + b: { + d: 5 + } + for k, v in 〈0;b〉 { + "\(〈1;k〉)": 〈1;v〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/007_different_labels_for_templates.txtar b/internal/core/compile/testdata/sync/fulleval/007_different_labels_for_templates.txtar new file mode 100644 index 000000000..5d5f1eec2 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/007_different_labels_for_templates.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +a: [X=string]: {name: X} +a: [Name=string]: {name: Name} +a: foo: {} @test(eq, {name: "foo"}) +-- out/compile -- +--- in.cue +{ + a: { + [string]: { + name: 〈1;-〉 + } + } + a: { + [string]: { + name: 〈1;-〉 + } + } + a: { + foo: {} + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/008_nested_templates_in_one_field.txtar b/internal/core/compile/testdata/sync/fulleval/008_nested_templates_in_one_field.txtar new file mode 100644 index 000000000..f8d68b3fb --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/008_nested_templates_in_one_field.txtar @@ -0,0 +1,49 @@ +-- in.cue -- +a: [A=string]: b: [B=string]: { + name: A + kind: B +} +a: "A": b: "B": _ @test(eq, {name: "A", kind: "B"}) +a: "C": b: "D": _ @test(eq, {name: "C", kind: "D"}) +a: "EE": b: "FF": {c: "bar"} @test(eq, { + c: "bar" + name: "EE" + kind: "FF" +}) +-- out/compile -- +--- in.cue +{ + a: { + [string]: { + b: { + [string]: { + name: 〈3;-〉 + kind: 〈1;-〉 + } + } + } + } + a: { + A: { + b: { + B: _ + } + } + } + a: { + C: { + b: { + D: _ + } + } + } + a: { + EE: { + b: { + FF: { + c: "bar" + } + } + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/009_template_unification_within_one_struct.txtar b/internal/core/compile/testdata/sync/fulleval/009_template_unification_within_one_struct.txtar new file mode 100644 index 000000000..b37bb6bb4 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/009_template_unification_within_one_struct.txtar @@ -0,0 +1,41 @@ +-- in.cue -- +a: { + {[A=string]: {name: A}} + + // TODO: allow duplicate alias here + {[X=string]: {kind: X}} +} +a: "A": _ @test(eq, {name: "A", kind: "A"}) +a: "C": _ @test(eq, {name: "C", kind: "C"}) +a: "E": {c: "bar"} @test(eq, { + c: "bar" + name: "E" + kind: "E" +}) +-- out/compile -- +--- in.cue +{ + a: { + { + [string]: { + name: 〈1;-〉 + } + } + { + [string]: { + kind: 〈1;-〉 + } + } + } + a: { + A: _ + } + a: { + C: _ + } + a: { + E: { + c: "bar" + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/010_field_comprehensions_with_multiple_keys.txtar b/internal/core/compile/testdata/sync/fulleval/010_field_comprehensions_with_multiple_keys.txtar new file mode 100644 index 000000000..182a57921 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/010_field_comprehensions_with_multiple_keys.txtar @@ -0,0 +1,72 @@ +-- in.cue -- + +for x in [ + {a: "A", b: "B"}, + {a: "C", b: "D"}, + {a: "E", b: "F"}, +] { + a: "\(x.a)": b: "\(x.b)": x +} + +for x in [ + {a: "A", b: "B"}, + {a: "C", b: "D"}, + {a: "E", b: "F"}, +] { + "\(x.a)": "\(x.b)": x +} + +@test(eq, { + a: { + A: b: B: {a: "A", b: "B"} + C: b: D: {a: "C", b: "D"} + E: b: F: {a: "E", b: "F"} + } + A: B: {a: "A", b: "B"} + C: D: {a: "C", b: "D"} + E: F: {a: "E", b: "F"} +}) +-- out/compile -- +--- in.cue +{ + for _, x in [ + { + a: "A" + b: "B" + }, + { + a: "C" + b: "D" + }, + { + a: "E" + b: "F" + }, + ] { + a: { + "\(〈2;x〉.a)": { + b: { + "\(〈4;x〉.b)": 〈4;x〉 + } + } + } + } + for _, x in [ + { + a: "A" + b: "B" + }, + { + a: "C" + b: "D" + }, + { + a: "E" + b: "F" + }, + ] { + "\(〈1;x〉.a)": { + "\(〈2;x〉.b)": 〈2;x〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/011_field_comprehensions_with_templates.txtar b/internal/core/compile/testdata/sync/fulleval/011_field_comprehensions_with_templates.txtar new file mode 100644 index 000000000..27ce99ec6 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/011_field_comprehensions_with_templates.txtar @@ -0,0 +1,39 @@ +-- in.cue -- +num: 1 +a: { + if num < 5 { + [A=string]: [B=string]: { + name: A + kind: B + } + } +} @test(eq, { + b: c: { + d: "bar" + name: "b" + kind: "c" + } +}) +a: b: c: d: "bar" +-- out/compile -- +--- in.cue +{ + num: 1 + a: { + if (〈1;num〉 < 5) { + [string]: { + [string]: { + name: 〈2;-〉 + kind: 〈1;-〉 + } + } + } + } + a: { + b: { + c: { + d: "bar" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/012_disjunctions_of_lists.txtar b/internal/core/compile/testdata/sync/fulleval/012_disjunctions_of_lists.txtar new file mode 100644 index 000000000..e0d45a068 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/012_disjunctions_of_lists.txtar @@ -0,0 +1,24 @@ +-- in.cue -- +l: *[int, int] | [string, string] + +t1: { + l & ["c", "d"] + @test(eq, ["c", "d"]) +} +-- out/compile -- +--- in.cue +{ + l: (*[ + int, + int, + ]|[ + string, + string, + ]) + t1: { + (〈1;l〉 & [ + "c", + "d", + ]) + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/013_normalization.txtar b/internal/core/compile/testdata/sync/fulleval/013_normalization.txtar new file mode 100644 index 000000000..5372dae2d --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/013_normalization.txtar @@ -0,0 +1,15 @@ +TODO: the new evaluator currently does not normalize disjuncts. +It needs to be determined under which circumstances is desirable. +The redundancy that remains from not normalizing can be useful. + +-- in.cue -- +a: string | string @test(eq, string) +b: *1 | *int @test(eq, *1 | *int) +c: *1.0 | *float @test(eq, *1.0 | *float) +-- out/compile -- +--- in.cue +{ + a: (string|string) + b: (*1|*int) + c: (*1.0|*float) +} diff --git a/internal/core/compile/testdata/sync/fulleval/014_default_disambiguation_and_elimination.txtar b/internal/core/compile/testdata/sync/fulleval/014_default_disambiguation_and_elimination.txtar new file mode 100644 index 000000000..475e7474e --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/014_default_disambiguation_and_elimination.txtar @@ -0,0 +1,23 @@ +-- in.cue -- +a: *1 | int @test(eq, *1 | int) +b: *3 | int @test(eq, *3 | int) +e: *1 | *1 @test(eq, 1) + +c: a & b @test(eq, 1 | 3 | int) + +d: { + b & a + @test(eq, 1 | 3 | int) +} + +-- out/compile -- +--- in.cue +{ + a: (*1|int) + b: (*3|int) + e: (*1|*1) + c: (〈0;a〉 & 〈0;b〉) + d: { + (〈1;b〉 & 〈1;a〉) + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/016_struct_comprehension_with_template.txtar b/internal/core/compile/testdata/sync/fulleval/016_struct_comprehension_with_template.txtar new file mode 100644 index 000000000..0f78462b5 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/016_struct_comprehension_with_template.txtar @@ -0,0 +1,64 @@ +-- in.cue -- +result: [for _, v in service {v}] @test(eq, [{ + name: *"foo" | string + type: "service" + port: *7080 | int +}, { + port: 8000 + name: *"bar" | string + type: "service" +}, { + name: "foobar" + type: "service" + port: *7080 | int +}]) + +service: [Name=string]: { + name: *Name | string + type: "service" + port: *7080 | int +} +service: foo: {} @test(eq, { + name: *"foo" | string + type: "service" + port: *7080 | int +}) +service: bar: {port: 8000} @test(eq, { + port: 8000 + name: *"bar" | string + type: "service" +}) +service: baz: {name: "foobar"} @test(eq, { + name: "foobar" + type: "service" + port: *7080 | int +}) +-- out/compile -- +--- in.cue +{ + result: [ + for _, v in 〈1;service〉 { + 〈1;v〉 + }, + ] + service: { + [string]: { + name: (*〈1;-〉|string) + type: "service" + port: (*7080|int) + } + } + service: { + foo: {} + } + service: { + bar: { + port: 8000 + } + } + service: { + baz: { + name: "foobar" + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/017_resolutions_in_struct_comprehension_keys.txtar b/internal/core/compile/testdata/sync/fulleval/017_resolutions_in_struct_comprehension_keys.txtar new file mode 100644 index 000000000..96c5f6495 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/017_resolutions_in_struct_comprehension_keys.txtar @@ -0,0 +1,13 @@ +-- in.cue -- +a: {for _, b in ["c"] {"\(b+".")": "a"}} @test(eq, {"c.": "a"}) +-- out/compile -- +--- in.cue +{ + a: { + for _, b in [ + "c", + ] { + "\((〈1;b〉 + "."))": "a" + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/018_recursive_evaluation_within_list.txtar b/internal/core/compile/testdata/sync/fulleval/018_recursive_evaluation_within_list.txtar new file mode 100644 index 000000000..aa9b69133 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/018_recursive_evaluation_within_list.txtar @@ -0,0 +1,39 @@ +#name: recursive evaluation within list +#evalFull +-- in.cue -- +l: [a] @test(eq, [{c: "t", d: "t"}]) @test(shareID=L, at=0) +a: b & {c: "t"} @test(eq, {c: "t", d: "t"}) @test(shareID=L) +b: { + d: c + c: string +} @test(eq, {d: string, c: string}) +l1: [a1] @test(eq, [{c: "t", d: "st"}]) @test(shareID=L1, at=0) +a1: b1 & {c: "t"} @test(eq, {c: "t", d: "st"}) @test(shareID=L1) +b1: { + d: "s" + c @test(err, code=incomplete) + c: string +} +-- out/compile -- +--- in.cue +{ + l: [ + 〈1;a〉, + ] + a: (〈0;b〉 & { + c: "t" + }) + b: { + d: 〈0;c〉 + c: string + } + l1: [ + 〈1;a1〉, + ] + a1: (〈0;b1〉 & { + c: "t" + }) + b1: { + d: ("s" + 〈0;c〉) + c: string + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/020_complex_interaction_of_groundness.txtar b/internal/core/compile/testdata/sync/fulleval/020_complex_interaction_of_groundness.txtar new file mode 100644 index 000000000..a3c30ad49 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/020_complex_interaction_of_groundness.txtar @@ -0,0 +1,44 @@ +-- in.cue -- +res: [for x in a for y in x {y & {d: "b"}}] +res: [ a.b.c & {d: "b"}] + +a: b: [C=string]: {d: string, s: "a" + d} +a: b: c: d: string +@test(eq, { + res: [ {d: "b", s: "ab"} ] + a: b: c: { + d: string + s: _|_ @test(err, code=incomplete, pos=[4:34, 4:23, 5:13]) + } +}) +-- out/compile -- +--- in.cue +{ + res: [ + for _, x in 〈1;a〉 for _, y in 〈0;x〉 { + (〈1;y〉 & { + d: "b" + }) + }, + ] + res: [ + (〈1;a〉.b.c & { + d: "b" + }), + ] + a: { + b: { + [string]: { + d: string + s: ("a" + 〈0;d〉) + } + } + } + a: { + b: { + c: { + d: string + } + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/021_complex_groundness_2.txtar b/internal/core/compile/testdata/sync/fulleval/021_complex_groundness_2.txtar new file mode 100644 index 000000000..0bb5d33a4 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/021_complex_groundness_2.txtar @@ -0,0 +1,60 @@ +#name: complex groundness 2 +#evalFull +-- in.cue -- +r1: f1 & {y: "c"} @test(eq, { + y: "c" + res: {d: "c", s: "ac"} +}) + +f1: {y: string, res: a.b.c & {d: y}} @test(eq, { + y: string + res: { + d: string + s: _|_ @test(err, code=incomplete, + pos=[15:25, 6:34, 15:14, 20:23, 21:13]) + } +}) + +a: b: c: {d: string, s: "a" + d} @test(eq, { + d: string + s: _|_ @test(err, code=incomplete, + pos=[15:25, 15:14, 20:23, 21:13]) +}) +a: b: [C=string]: {d: string, s: "a" + d} +a: b: c: d: string +-- out/compile -- +--- in.cue +{ + r1: (〈0;f1〉 & { + y: "c" + }) + f1: { + y: string + res: (〈1;a〉.b.c & { + d: 〈1;y〉 + }) + } + a: { + b: { + c: { + d: string + s: ("a" + 〈0;d〉) + } + } + } + a: { + b: { + [string]: { + d: string + s: ("a" + 〈0;d〉) + } + } + } + a: { + b: { + c: { + d: string + } + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/022_references_from_template_to_concrete.txtar b/internal/core/compile/testdata/sync/fulleval/022_references_from_template_to_concrete.txtar new file mode 100644 index 000000000..c6341ef2d --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/022_references_from_template_to_concrete.txtar @@ -0,0 +1,32 @@ +-- in.cue -- +// res is a list containing t; res[0] shares t's vertex. +res: [t] @test(eq, [{x: {a: "XDDDD", b: str: "DDDD", c: "X"}}]) @test(shareID=T, at=0) +t: { + [X=string]: { + a: c + b.str + b: str: string + c: "X" + } + x: {b: str: "DDDD"} @test(eq, {a: "XDDDD", b: str: "DDDD", c: "X"}) +} @test(shareID=T) +-- out/compile -- +--- in.cue +{ + res: [ + 〈1;t〉, + ] + t: { + [string]: { + a: (〈0;c〉 + 〈0;b〉.str) + b: { + str: string + } + c: "X" + } + x: { + b: { + str: "DDDD" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/024_Issue_#23.txtar b/internal/core/compile/testdata/sync/fulleval/024_Issue_#23.txtar new file mode 100644 index 000000000..17a59d675 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/024_Issue_#23.txtar @@ -0,0 +1,19 @@ +# Tests that unifying a struct with a disjunction where neither branch matches reports +# an empty disjunction error. Issue #23. +-- in.cue -- +x: {a: 1} | {a: 2} +y: x & {a: 3} @test(err, code=eval, + suberr=(code=eval, contains="conflicting values", args=[1, 3], pos=[in.cue:1:8, in.cue:2:4, in.cue:2:12]), + suberr=(code=eval, contains="conflicting values", args=[2, 3], pos=[in.cue:1:17, in.cue:2:4, in.cue:2:12])) +-- out/compile -- +--- in.cue +{ + x: ({ + a: 1 + }|{ + a: 2 + }) + y: (〈0;x〉 & { + a: 3 + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar b/internal/core/compile/testdata/sync/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar new file mode 100644 index 000000000..139a03077 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar @@ -0,0 +1,46 @@ +#name: dont convert incomplete errors to non-incomplete +#evalFull +-- in.cue -- +import "strings" + +n1: {min: min} @test(eq, { + min: _|_ @test(err, code=cycle, contains="n1.max: cycle with field: min (and 1 more errors)", pos=[3:23]) + max: _|_ @test(err, code=cycle, contains="n1.max: cycle with field: min (and 1 more errors)", pos=[3:23]) +}) +n2: -num @test(err, code=incomplete, contains="operand num of '-' not concrete", pos=[0:6]) +n3: +num @test(err, code=incomplete, contains="operand num of '+' not concrete", pos=[0:6]) +n4: num + num @test(err, code=incomplete, contains="non-concrete value <4 in operand to +", pos=[0:5, 12:6]) +n5: num - num @test(err, code=incomplete, contains="non-concrete value <4 in operand to -", pos=[0:5, 11:6]) +n6: num * num @test(err, code=incomplete, contains="non-concrete value <4 in operand to *", pos=[0:5, 10:6]) +n7: num / num @test(err, code=incomplete, contains="non-concrete value <4 in operand to /", pos=[0:5, 9:6]) + +b1: !is @test(err, code=incomplete, contains="operand is of '!' not concrete", pos=[0:6]) + +s1: "\(str)" @test(err, code=incomplete, contains="non-concrete value string", pos=[0:5, 4:6]) +s2: strings.ContainsAny("dd") @test(kind=string) +s3: strings.ContainsAny(str, "dd") @test(err, code=incomplete, contains="non-concrete value string", pos=[0:5, 2:6]) + +str: string @test(eq, string) +num: <4 @test(eq, <4) +is: bool @test(eq, bool) +-- out/compile -- +--- in.cue +{ + n1: { + min: <〈0;max〉 + max: >〈0;min〉 + } + n2: -〈0;num〉 + n3: +〈0;num〉 + n4: (〈0;num〉 + 〈0;num〉) + n5: (〈0;num〉 - 〈0;num〉) + n6: (〈0;num〉 * 〈0;num〉) + n7: (〈0;num〉 / 〈0;num〉) + b1: !〈0;is〉 + s1: "\(〈0;str〉)" + s2: 〈import;strings〉.ContainsAny("dd") + s3: 〈import;strings〉.ContainsAny(〈0;str〉, "dd") + str: string + num: <4 + is: bool +} diff --git a/internal/core/compile/testdata/sync/fulleval/027_len_of_incomplete_types.txtar b/internal/core/compile/testdata/sync/fulleval/027_len_of_incomplete_types.txtar new file mode 100644 index 000000000..1cc44e943 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/027_len_of_incomplete_types.txtar @@ -0,0 +1,47 @@ +-- in.cue -- +args: *[] | [...string] +v1: len(args) @test(eq, 0) +v2: len([]) @test(eq, 0) +v3: len({}) @test(eq, 0) +v4: len({a: 3}) @test(eq, 1) +v5: len({a: 3} | {a: 4}) @test(err, code=incomplete, contains="unresolved disjunction", pos=[0:7]) +v6: len('sf' | 'dd') @test(err, code=incomplete, contains="unresolved disjunction", pos=[0:7]) +v7: len([2] | *[1, 2]) @test(eq, 2) +v8: len([2] | [1, 2]) @test(err, code=incomplete, contains="unresolved disjunction", pos=[0:7]) +v9: len("😂") @test(eq, 4, + hint="len of strings should be deprecated and this should be an error in the future") +v10: len("") @test(eq, 0, + hint="len of strings should be deprecated and this should be an error in the future") +-- out/compile -- +--- in.cue +{ + args: (*[]|[ + ...string, + ]) + v1: len(〈0;args〉) + v2: len([]) + v3: len({}) + v4: len({ + a: 3 + }) + v5: len(({ + a: 3 + }|{ + a: 4 + })) + v6: len(('sf'|'dd')) + v7: len(([ + 2, + ]|*[ + 1, + 2, + ])) + v8: len(([ + 2, + ]|[ + 1, + 2, + ])) + v9: len("😂") + v10: len("") +} diff --git a/internal/core/compile/testdata/sync/fulleval/028_slice_rewrite_bug.txtar b/internal/core/compile/testdata/sync/fulleval/028_slice_rewrite_bug.txtar new file mode 100644 index 000000000..bd84e4f9e --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/028_slice_rewrite_bug.txtar @@ -0,0 +1,37 @@ +-- in.cue -- +t1: { + fn: { + arg: [...int] & [1] + out: arg[1:] + } + fn1: fn & {arg: [1]} + @test(eq, { + fn: { + arg: [1] + out: [] + } + fn1: { + arg: [1] + out: [] + } + }) +} +-- out/compile -- +--- in.cue +{ + t1: { + fn: { + arg: ([ + ...int, + ] & [ + 1, + ]) + out: 〈0;arg〉[1:] + } + fn1: (〈0;fn〉 & { + arg: [ + 1, + ] + }) + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/029_Issue_#94.txtar b/internal/core/compile/testdata/sync/fulleval/029_Issue_#94.txtar new file mode 100644 index 000000000..9c4c17994 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/029_Issue_#94.txtar @@ -0,0 +1,57 @@ +# Tests field visibility and comprehension iteration: comprehensions only iterate +# regular (non-optional, non-hidden, non-definition) fields; select and index access +# have different rules for optional, hidden, and definition fields. Issue #94. +-- in.cue -- +foo: { + opt?: 1 + "txt": 2 + #def: 3 + regular: 4 + _hidden: 5 + @test(eq, {opt?: 1, txt: 2, #def: 3, regular: 4, _hidden: 5}) +} +comp: { for k, v in foo {"\(k)": v} } @test(eq, {txt: 2, regular: 4}) +select: { + opt: foo.opt @test(err, code=incomplete, contains="cannot reference optional field", pos=[0:15]) + "txt": foo.txt @test(eq, 2) + #def: foo.#def @test(eq, 3) + regular: foo.regular @test(eq, 4) + _hidden: foo._hidden @test(eq, 5) +} +index: { + opt: foo["opt"] @test(err, code=incomplete, contains="cannot reference optional field", pos=[0:15]) + "txt": foo["txt"] @test(eq, 2) + #def: foo["#def"] @test(err, code=incomplete, contains="undefined field", pos=[0:15]) + regular: foo["regular"] @test(eq, 4) + _hidden: foo["_hidden"] @test(err, code=incomplete, contains="undefined field", pos=[0:15]) +} +-- out/compile -- +--- in.cue +{ + foo: { + opt?: 1 + txt: 2 + #def: 3 + regular: 4 + _hidden: 5 + } + comp: { + for k, v in 〈1;foo〉 { + "\(〈1;k〉)": 〈1;v〉 + } + } + select: { + opt: 〈1;foo〉.opt + txt: 〈1;foo〉.txt + #def: 〈1;foo〉.#def + regular: 〈1;foo〉.regular + _hidden: 〈1;foo〉._hidden + } + index: { + opt: 〈1;foo〉["opt"] + txt: 〈1;foo〉["txt"] + #def: 〈1;foo〉["#def"] + regular: 〈1;foo〉["regular"] + _hidden: 〈1;foo〉["_hidden"] + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/030_retain_references_with_interleaved_embedding.txtar b/internal/core/compile/testdata/sync/fulleval/030_retain_references_with_interleaved_embedding.txtar new file mode 100644 index 000000000..8d6a9c3de --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/030_retain_references_with_interleaved_embedding.txtar @@ -0,0 +1,44 @@ +#name: retain references with interleaved embedding +#evalFull +-- in.cue -- +a: d: { + #base + #info: {...} + Y: #info.X +} @test(eq, { + #info: {X: "foo"} + Y: "foo" +}) @test(closed) + +#base: { + #info: {...} @test(closed) +} @test(eq, { #info: {} }) + +a: [Name=string]: {#info: { + X: "foo" +}} +-- out/compile -- +--- in.cue +{ + a: { + d: { + 〈2;#base〉 + #info: { + ... + } + Y: 〈0;#info〉.X + } + } + #base: { + #info: { + ... + } + } + a: { + [string]: { + #info: { + X: "foo" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/031_comparison_against_bottom.txtar b/internal/core/compile/testdata/sync/fulleval/031_comparison_against_bottom.txtar new file mode 100644 index 000000000..eaefda056 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/031_comparison_against_bottom.txtar @@ -0,0 +1,43 @@ +-- in.cue -- +a: _|_ == _|_ @test(eq, true) +b: err == 1 & 2 @test(err, code=eval, contains="conflicting values", args=[2, 1], pos=[in.cue:12:6, in.cue:12:10]) // not a literal error, so not allowed +c: err == _|_ @test(eq, true) // allowed +d: err != _|_ @test(eq, false) // allowed +e: err != 1 & 3 @test(err, code=eval, contains="conflicting values", args=[2, 1], pos=[in.cue:12:6, in.cue:12:10]) +// z: err == err // TODO: should infer to be true? +f: ({a: 1} & {a: 2}) == _|_ @test(eq, true) +g: ({a: 1} & {b: 2}) == _|_ @test(eq, false) +h: _|_ == ({a: 1} & {a: 2}) @test(eq, true) +i: _|_ == ({a: 1} & {b: 2}) @test(eq, false) + +err: 1 & 2 @test(err, code=eval, contains="conflicting values 2 and 1", pos=[in.cue:12:6, in.cue:12:10]) +-- out/compile -- +--- in.cue +{ + a: (_|_(explicit error (_|_ literal) in source) == _|_(explicit error (_|_ literal) in source)) + b: ((〈0;err〉 == 1) & 2) + c: (〈0;err〉 == _|_(explicit error (_|_ literal) in source)) + d: (〈0;err〉 != _|_(explicit error (_|_ literal) in source)) + e: ((〈0;err〉 != 1) & 3) + f: (({ + a: 1 + } & { + a: 2 + }) == _|_(explicit error (_|_ literal) in source)) + g: (({ + a: 1 + } & { + b: 2 + }) == _|_(explicit error (_|_ literal) in source)) + h: (_|_(explicit error (_|_ literal) in source) == ({ + a: 1 + } & { + a: 2 + })) + i: (_|_(explicit error (_|_ literal) in source) == ({ + a: 1 + } & { + b: 2 + })) + err: (1 & 2) +} diff --git a/internal/core/compile/testdata/sync/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar b/internal/core/compile/testdata/sync/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar new file mode 100644 index 000000000..5d936b863 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar @@ -0,0 +1,39 @@ +# Tests that the or() builtin does not panic when called with a non-concrete +# (empty) list, such as when no comprehension entries are produced. +# The #JobID field should be an incomplete error in the base definition, but +# successfully resolve to a concrete string once jobs has at least one entry. +#name: or builtin should not fail on non-concrete empty list +#evalFull +-- in.cue -- +#Workflow: { + jobs: { + [jobID=string]: { + } + } + #JobID: or([for k, _ in jobs {k}]) @test(err, code=incomplete, contains="empty list in call to or", pos=[0:10]) + // #JobID is incomplete when jobs has no entries — or([]) is not allowed. +} + +foo: #Workflow & { + jobs: foo: { + } +} @test(eq, {jobs: {foo: {}}, #JobID: "foo"}) +-- out/compile -- +--- in.cue +{ + #Workflow: { + jobs: { + [string]: {} + } + #JobID: or([ + for k, _ in 〈1;jobs〉 { + 〈1;k〉 + }, + ]) + } + foo: (〈0;#Workflow〉 & { + jobs: { + foo: {} + } + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/034_label_and_field_aliases.txtar b/internal/core/compile/testdata/sync/fulleval/034_label_and_field_aliases.txtar new file mode 100644 index 000000000..90c0e180d --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/034_label_and_field_aliases.txtar @@ -0,0 +1,48 @@ +#name: label and field aliases +#evalFull +-- in.cue -- +p: [ID=string]: {name: ID} +p: q: _ @test(eq, {name: "q"}) +A="foo=bar": "str" // TODO(inline): make this work @test(eq, at="foo=bar", "str") +a: A @test(eq, "str") +B=bb: 4 +@test(eq, at=bb, 4) +b1: B @test(eq, 4) +b1: bb +C="\(a)": 5 +c: C @test(eq, 5) + +@test(debugCheck, """ + (struct){ + p: (struct){ + q: (struct){ + name: (string){ "q" } + } + } + "foo=bar": (string){ "str" } + a: (string){ "str" } + bb: (int){ 4 } + b1: (int){ 4 } + c: (int){ 5 } + str: (int){ 5 } + } + """) +-- out/compile -- +--- in.cue +{ + p: { + [string]: { + name: 〈1;-〉 + } + } + p: { + q: _ + } + "foo=bar": "str" + a: 〈0;"foo=bar"〉 + bb: 4 + b1: 〈0;bb〉 + b1: 〈0;bb〉 + "\(〈0;a〉)": 5 + c: 〈0;("\(〈0;a〉)")〉 +} diff --git a/internal/core/compile/testdata/sync/fulleval/035_optionals_with_label_filters.txtar b/internal/core/compile/testdata/sync/fulleval/035_optionals_with_label_filters.txtar new file mode 100644 index 000000000..d13c14b2d --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/035_optionals_with_label_filters.txtar @@ -0,0 +1,81 @@ +#name: optionals with label filters +#evalFull +# Tests that optional fields with label filters enforce their constraints: +# fields not matching the pattern or constraint fail with "field not allowed" +# or bound violations. jobs is the happy path; jobs1, jobs2, jobs3 are faulty. +-- in.cue -- +#JobID: =~"^[a-zA-Z]*$" +#Job: { + name: string + cmd: string +} +#Jobs: { + {[#JobID]: #Job} + + {[=~"Test$"]: name: =~"^test"}// Must work without ... +} + +jobs: foo: name: "allGood" +jobs: foo: name: "allGood" + +jobs1: #Jobs +jobs1: foo1: {} // faulty +@test(err, code=eval, at=jobs1.foo1, contains="field not allowed", pos=[-1:8]) + +jobs2: #Jobs +jobs2: fooTest: name: "badName" // faulty +@test(err, code=eval, at=jobs2.fooTest.name, contains="invalid value", pos=[-12:22, -18:8, -1:23]) + +jobs3: #Jobs +jobs3: [string]: #Job +jobs3: fooTest1: name: "badName" // faulty +@test(err, code=eval, at=jobs3.fooTest1, contains="field not allowed", pos=[-2:8, -1:8]) + +-- out/compile -- +--- in.cue +{ + #JobID: =~"^[a-zA-Z]*$" + #Job: { + name: string + cmd: string + } + #Jobs: { + { + [〈2;#JobID〉]: 〈2;#Job〉 + } + { + [=~"Test$"]: { + name: =~"^test" + } + } + } + jobs: { + foo: { + name: "allGood" + } + } + jobs: { + foo: { + name: "allGood" + } + } + jobs1: 〈0;#Jobs〉 + jobs1: { + foo1: {} + } + jobs2: 〈0;#Jobs〉 + jobs2: { + fooTest: { + name: "badName" + } + } + jobs3: 〈0;#Jobs〉 + jobs3: { + [string]: 〈1;#Job〉 + } + jobs3: { + fooTest1: { + name: "badName" + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/040.txtar b/internal/core/compile/testdata/sync/fulleval/040.txtar new file mode 100644 index 000000000..5e99f260a --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/040.txtar @@ -0,0 +1,43 @@ +# Tests that a disjunction inside a definition resolves correctly when a +# discriminant field is set. After unifying #Task with {op: "pull"}, the +# "pull" branch is selected and expressions using the defaulted tag +# field (tag: *"latest" | string) evaluate concretely. +#evalFull +-- in.cue -- +#Task: { + { + op: "pull" + tag: *"latest" | string + refToTag: tag + tagExpr: tag + "dd" + tagInString: "\(tag)" + } | { + op: "scratch" + } +} + +foo: #Task & {"op": "pull"} @test(eq, { + op: "pull" + tag: *"latest" | string + refToTag: *"latest" | string + tagExpr: "latestdd" + tagInString: "latest" +}) +-- out/compile -- +--- in.cue +{ + #Task: { + ({ + op: "pull" + tag: (*"latest"|string) + refToTag: 〈0;tag〉 + tagExpr: (〈0;tag〉 + "dd") + tagInString: "\(〈0;tag〉)" + }|{ + op: "scratch" + }) + } + foo: (〈0;#Task〉 & { + op: "pull" + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/041.txtar b/internal/core/compile/testdata/sync/fulleval/041.txtar new file mode 100644 index 000000000..ab59f7e25 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/041.txtar @@ -0,0 +1,25 @@ +-- in.cue -- +t: { + #ok: *true | bool + if #ok { + x: int + } + @test(eq, { + #ok: *true | bool + x: int + }) +} +s: t & {#ok: false} @test(eq, {#ok: false}) +-- out/compile -- +--- in.cue +{ + t: { + #ok: (*true|bool) + if 〈0;#ok〉 { + x: int + } + } + s: (〈0;t〉 & { + #ok: false + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/042_cross-dependent_comprehension.txtar b/internal/core/compile/testdata/sync/fulleval/042_cross-dependent_comprehension.txtar new file mode 100644 index 000000000..297e666c6 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/042_cross-dependent_comprehension.txtar @@ -0,0 +1,29 @@ +# Tests that comprehension conditions referencing fields resolve correctly when the +# condition is cross-dependent. x unifies #a with b:true and c:4, resolving the +# comprehension. y is an alias of x with the same value. +-- in.cue -- +#a: { + if b { + c: 4 + } + b: bool + @test(err, code=incomplete, args=[bool], pos=[in.cue:5:5]) +} +x: (#a & {b: true}) & {c: 4} @test(eq, {b: true, c: 4}) @test(shareID=xy) +y: x @test(eq, {b: true, c: 4}) @test(shareID=xy) +-- out/compile -- +--- in.cue +{ + #a: { + if 〈0;b〉 { + c: 4 + } + b: bool + } + x: ((〈0;#a〉 & { + b: true + }) & { + c: 4 + }) + y: 〈0;x〉 +} diff --git a/internal/core/compile/testdata/sync/fulleval/043_optional_expanded_before_lookup.txtar b/internal/core/compile/testdata/sync/fulleval/043_optional_expanded_before_lookup.txtar new file mode 100644 index 000000000..2c47525c2 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/043_optional_expanded_before_lookup.txtar @@ -0,0 +1,33 @@ +#name: optional expanded before lookup +#evalFull +-- in.cue -- +test: [ID=_]: { + name: ID +} + +test: A: { + field1: "1" + field2: "2" +} + +B: test.A & {} @test(eq, { + field1: "1" + field2: "2" + name: "A" +}) +-- out/compile -- +--- in.cue +{ + test: { + [_]: { + name: 〈1;-〉 + } + } + test: { + A: { + field1: "1" + field2: "2" + } + } + B: (〈0;test〉.A & {}) +} diff --git a/internal/core/compile/testdata/sync/fulleval/044_Issue_#178.txtar b/internal/core/compile/testdata/sync/fulleval/044_Issue_#178.txtar new file mode 100644 index 000000000..9c73a7c50 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/044_Issue_#178.txtar @@ -0,0 +1,25 @@ +# Tests that encoding built-in functions called with non-concrete arguments +# correctly return an "incomplete" error rather than panicking. Issue: calling +# csv.Decode or hex.EncodedLen with abstract (non-concrete) values caused a +# nil pointer dereference panic instead of a proper incomplete error. +# https://cuelang.org/issue/178 +#name: Issue #178 +#evalFull +-- in.cue -- +import "encoding/csv" + +import "encoding/hex" + +foo: csv.Decode(data) @test(err, code=incomplete) +data: bytes @test(kind=bytes) + +len: int @test(kind=int) +bar: hex.EncodedLen(len) @test(err, code=incomplete) +-- out/compile -- +--- in.cue +{ + foo: 〈import;"encoding/csv"〉.Decode(〈0;data〉) + data: bytes + len: int + bar: 〈import;"encoding/hex"〉.EncodedLen(〈0;len〉) +} diff --git a/internal/core/compile/testdata/sync/fulleval/046_non-structural_direct_cycles.txtar b/internal/core/compile/testdata/sync/fulleval/046_non-structural_direct_cycles.txtar new file mode 100644 index 000000000..73c201df4 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/046_non-structural_direct_cycles.txtar @@ -0,0 +1,21 @@ +# Tests non-structural direct cycles where a struct is unified with one of its own +# fields. c1 resolves successfully (bar.baz is merged), c2 conflicts because bar:1 +# (int) cannot unify with the struct c2.bar. +-- in.cue -- +c1: {bar: baz: 2} & c1.bar @test(eq, {bar: {baz: 2}, baz: 2}) +c2: {bar: 1} & c2.bar @test(err, code=eval, + contains="conflicting values", + args=[{bar:1}, 1, struct, int], + pos=[0:5, 0:16, 0:21]) +-- out/compile -- +--- in.cue +{ + c1: ({ + bar: { + baz: 2 + } + } & 〈0;c1〉.bar) + c2: ({ + bar: 1 + } & 〈0;c2〉.bar) +} diff --git a/internal/core/compile/testdata/sync/fulleval/047_dont_bind_to_string_labels.txtar b/internal/core/compile/testdata/sync/fulleval/047_dont_bind_to_string_labels.txtar new file mode 100644 index 000000000..d0e3d38ee --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/047_dont_bind_to_string_labels.txtar @@ -0,0 +1,16 @@ +-- in.cue -- + +x: 1 +y: { + "x": 2 + z: x @test(eq, 1) +} +-- out/compile -- +--- in.cue +{ + x: 1 + y: { + x: 2 + z: 〈1;x〉 + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar b/internal/core/compile/testdata/sync/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar new file mode 100644 index 000000000..8843a65eb --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar @@ -0,0 +1,13 @@ +#name: dont pass incomplete values to builtins +#evalFull +-- in.cue -- +import "encoding/json" + +input: string @test(kind=string) +foo: json.Marshal(input) @test(err, code=incomplete) +-- out/compile -- +--- in.cue +{ + input: string + foo: 〈import;"encoding/json"〉.Marshal(〈0;input〉) +} diff --git a/internal/core/compile/testdata/sync/fulleval/049_alias_reuse_in_nested_scope.txtar b/internal/core/compile/testdata/sync/fulleval/049_alias_reuse_in_nested_scope.txtar new file mode 100644 index 000000000..f211173e1 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/049_alias_reuse_in_nested_scope.txtar @@ -0,0 +1,58 @@ +# Tests that let bindings in nested scopes are correctly scoped and can be reused. +# #Foo uses a let alias pointing to an empty or disjunction (error); #A and #B use +# let aliases tied to foo, which become dynamic field keys. b instantiates #B. +-- in.cue -- +#Foo: { + let X = or([for k, _ in {} {k}]) + connection: [X]: X @test(err, code=incomplete, pos=[0:11], contains="in call", args=[or]) + @test(eq, { + connection: _|_ @test(err, code=incomplete, contains="#Foo.X: error in call to or: empty list in call to or", pos=[2:10]) + }) +} +#A: { + foo: "key" + let X = foo + a: foo: [X]: X + @test(eq, {foo: "key", a: {foo: {["key"]: "key"}}}) +} +#B: { + foo: string + let X = foo + a: foo: [X]: X +} +b: #B & {foo: "key"} @test(eq, {foo: "key", a: {foo: {}}}) +-- out/compile -- +--- in.cue +{ + #Foo: { + let X#1 = or([ + for k, _ in {} { + 〈1;k〉 + }, + ]) + connection: { + [〈1;let X#1〉]: 〈1;let X#1〉 + } + } + #A: { + foo: "key" + let X#2 = 〈0;foo〉 + a: { + foo: { + [〈2;let X#2〉]: 〈2;let X#2〉 + } + } + } + #B: { + foo: string + let X#3 = 〈0;foo〉 + a: { + foo: { + [〈2;let X#3〉]: 〈2;let X#3〉 + } + } + } + b: (〈0;#B〉 & { + foo: "key" + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/050_json_Marshaling_detects_incomplete.txtar b/internal/core/compile/testdata/sync/fulleval/050_json_Marshaling_detects_incomplete.txtar new file mode 100644 index 000000000..630a07902 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/050_json_Marshaling_detects_incomplete.txtar @@ -0,0 +1,24 @@ +#name: json Marshaling detects incomplete +#evalFull +-- in.cue -- +import "encoding/json" + +a: json.Marshal({a: string}) @test(err, code=incomplete) + +foo: { + a: 3 @test(eq, 3) + b: foo.c @test(err, code=incomplete) +} +b: json.Marshal(foo) @test(err, code=incomplete) +-- out/compile -- +--- in.cue +{ + a: 〈import;"encoding/json"〉.Marshal({ + a: string + }) + foo: { + a: 3 + b: 〈1;foo〉.c + } + b: 〈import;"encoding/json"〉.Marshal(〈0;foo〉) +} diff --git a/internal/core/compile/testdata/sync/fulleval/051_detectIncompleteYAML.txtar b/internal/core/compile/testdata/sync/fulleval/051_detectIncompleteYAML.txtar new file mode 100644 index 000000000..a2da1f3c6 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/051_detectIncompleteYAML.txtar @@ -0,0 +1,48 @@ +#name: detectIncompleteYAML +#evalFull +-- in.cue -- +package foobar + +import yaml "encoding/yaml" + +#Spec: { + _vars: {something: string} + data: { + #foo: { + use: _vars.something + } + baz: yaml.Marshal(_vars.something) @test(err, code=incomplete, pos=[0:11]) + foobar: yaml.Marshal(#foo) @test(err, code=incomplete, pos=[0:11, -6:21, -3:9]) + } +} +Val: #Spec & { + _vars: something: "var-string" +} @test(eq, { + _vars$foobar: something: "var-string" + data: { + #foo: use: "var-string" + baz: "var-string\n" + foobar: "use: var-string\n" + } +}) +-- out/compile -- +--- in.cue +{ + #Spec: { + _vars(:foobar): { + something: string + } + data: { + #foo: { + use: 〈2;_vars(:foobar)〉.something + } + baz: 〈import;"encoding/yaml"〉.Marshal(〈1;_vars(:foobar)〉.something) + foobar: 〈import;"encoding/yaml"〉.Marshal(〈0;#foo〉) + } + } + Val: (〈0;#Spec〉 & { + _vars(:foobar): { + something: "var-string" + } + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/052_detectIncompleteJSON.txtar b/internal/core/compile/testdata/sync/fulleval/052_detectIncompleteJSON.txtar new file mode 100644 index 000000000..898685d36 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/052_detectIncompleteJSON.txtar @@ -0,0 +1,48 @@ +#name: detectIncompleteJSON +#evalFull +-- in.cue -- +package foobar + +import "encoding/json" + +#Spec: { + _vars: {something: string} + data: { + #foo: { + use: _vars.something + } + baz: json.Marshal(_vars.something) @test(err, code=incomplete) + foobar: json.Marshal(#foo) @test(err, code=incomplete) + } +} +Val: #Spec & { + _vars: something: "var-string" +} @test(eq, { + _vars$foobar: something: "var-string" + data: { + #foo: use: "var-string" + baz: "\"var-string\"" + foobar: "{\"use\":\"var-string\"}" + } +}) +-- out/compile -- +--- in.cue +{ + #Spec: { + _vars(:foobar): { + something: string + } + data: { + #foo: { + use: 〈2;_vars(:foobar)〉.something + } + baz: 〈import;"encoding/json"〉.Marshal(〈1;_vars(:foobar)〉.something) + foobar: 〈import;"encoding/json"〉.Marshal(〈0;#foo〉) + } + } + Val: (〈0;#Spec〉 & { + _vars(:foobar): { + something: "var-string" + } + }) +} diff --git a/internal/core/compile/testdata/sync/fulleval/053_issue312.txtar b/internal/core/compile/testdata/sync/fulleval/053_issue312.txtar new file mode 100644 index 000000000..8eab8cb7c --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/053_issue312.txtar @@ -0,0 +1,24 @@ +# Tests a comprehension with a disjunction of close({}) and a pattern +# constraint. Issue: https://cuelang.org/issue/312 — the default selection +# and closing behavior of a disjunction inside a comprehension should work +# correctly. +#name: issue312 +#evalFull +-- in.cue -- + +for x in [1] { + *close({}) | {[_]: null} +} + +@test(eq, *{} | {}) +-- out/compile -- +--- in.cue +{ + for _, x in [ + 1, + ] { + (*close({})|{ + [_]: null + }) + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/054_issue312.txtar b/internal/core/compile/testdata/sync/fulleval/054_issue312.txtar new file mode 100644 index 000000000..db04be620 --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/054_issue312.txtar @@ -0,0 +1,22 @@ +-- in.cue -- +x: { + y: *1 | {a: 2} + for x in [1] {y} +} @test(eq, { + a: 2 + y: *1 | { a: 2 } +}) +-- out/compile -- +--- in.cue +{ + x: { + y: (*1|{ + a: 2 + }) + for _, x in [ + 1, + ] { + 〈2;y〉 + } + } +} diff --git a/internal/core/compile/testdata/sync/fulleval/055_issue318.txtar b/internal/core/compile/testdata/sync/fulleval/055_issue318.txtar new file mode 100644 index 000000000..d96d30f3d --- /dev/null +++ b/internal/core/compile/testdata/sync/fulleval/055_issue318.txtar @@ -0,0 +1,29 @@ +# Tests that string interpolation consistently detects references to +# non-existent fields. Issue: an interpolation with both a valid and an invalid +# field reference (e.g. "\(arg.x) \(arg.y)") silently swallowed the error for +# the invalid field, while a single invalid reference was correctly reported. +# https://cuelang.org/issue/318 +# +-- in.cue -- +#T: { + arg: x: string + out1: "\(arg.x) \(arg.y)" @test(err, code=eval) + // TODO: is this really an eval error if it is referred to within a + // definitions? + out2: "\(arg.y)" @test(err, code=eval) + vx: arg.x @test(kind=string) + vy: arg.y @test(err, code=eval) +} +-- out/compile -- +--- in.cue +{ + #T: { + arg: { + x: string + } + out1: "\(〈0;arg〉.x) \(〈0;arg〉.y)" + out2: "\(〈0;arg〉.y)" + vx: 〈0;arg〉.x + vy: 〈0;arg〉.y + } +} diff --git a/internal/core/compile/testdata/sync/inlinetest/closedness.txtar b/internal/core/compile/testdata/sync/inlinetest/closedness.txtar new file mode 100644 index 000000000..dc0d64c50 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/closedness.txtar @@ -0,0 +1,73 @@ +-- in.cue -- +t1: close({b: {}}) +t1: _ @test(closed) +t1: b: _ @test(closed=false) +t1: _ @test(allows, "b") +t1: _ @test(allows=false, foo) + +#X: {[=~"^Q*$"]: int} + +#X: _ @test(closed) +#X: _ @test(allows, Q) +#X: _ @test(allows=false, X) +#X: _ @test(allows=false, string) + +t2: #X +t2: _ @test(closed) +t2: _ @test(allows, Q) +t2: _ @test(allows=false, X) +t2: _ @test(allows=false, string) + +#Y: {...} + +t3: #Y +t3: _ @test(closed) +t3: _ @test(allows, Q) +t3: _ @test(allows, X) +t3: _ @test(allows, string) + +// t4: "string" (quoted) targets the literal field named string; +// string (unquoted) targets the any-string pattern constraint. +t4: close({"string": 1}) +t4: _ @test(closed) +t4: _ @test(allows, "string") // quoted: literal field named string +t4: _ @test(allows=false, string) // unquoted: any-string pattern not present +-- out/compile -- +--- in.cue +{ + t1: close({ + b: {} + }) + t1: _ + t1: { + b: _ + } + t1: _ + t1: _ + #X: { + [=~"^Q*$"]: int + } + #X: _ + #X: _ + #X: _ + #X: _ + t2: 〈0;#X〉 + t2: _ + t2: _ + t2: _ + t2: _ + #Y: { + ... + } + t3: 〈0;#Y〉 + t3: _ + t3: _ + t3: _ + t3: _ + t4: close({ + string: 1 + }) + t4: _ + t4: _ + t4: _ +} diff --git a/internal/core/compile/testdata/sync/inlinetest/debug.txtar b/internal/core/compile/testdata/sync/inlinetest/debug.txtar new file mode 100644 index 000000000..6e50d6e8b --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/debug.txtar @@ -0,0 +1,66 @@ +-- in.cue -- +// debugCheck: compare debug-printer output via @test(debugCheck, ...) attributes. + +// ── scalar value ───────────────────────── + +debugCheckScalar: 42 @test(debugCheck, "(int){ 42 }") + +// ── struct value ───────────────────────── + +debugCheckStruct: { + @test(debugCheck, """ + (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + """) + a: 1 + b: 2 +} + +// ── computed struct ─────────────────────── + +debugCheckComputed: { + @test(debugCheck, """ + (struct){ + x: (int){ 10 } + y: (int){ 20 } + } + """) + x: 10 + y: x * 2 +} + +// ── version override: v3 debugCheck takes precedence ── +// Both default and v3 have the same expected output here, +// verifying that versioned attrs are accepted and applied correctly. + +debugCheckVersioned: { + @test(debugCheck, """ + (struct){ + z: (int){ 99 } + } + """) + @test(debugCheck:v3, """ + (struct){ + z: (int){ 99 } + } + """) + z: 99 +} +-- out/compile -- +--- in.cue +{ + debugCheckScalar: 42 + debugCheckStruct: { + a: 1 + b: 2 + } + debugCheckComputed: { + x: 10 + y: (〈0;x〉 * 2) + } + debugCheckVersioned: { + z: 99 + } +} diff --git a/internal/core/compile/testdata/sync/inlinetest/decl_eq.txtar b/internal/core/compile/testdata/sync/inlinetest/decl_eq.txtar new file mode 100644 index 000000000..d718143d2 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/decl_eq.txtar @@ -0,0 +1,29 @@ +-- in.cue -- +// File-level @test(eq, VALUE) as a decl attribute: checks the entire +// file's evaluated value against VALUE. All fields are covered +// implicitly — no per-field @test is required. + +a: 1 +b: a + 1 +c: { + x: "hello" + y: b +} +@test(eq, { + a: 1 + b: 2 + c: { + x: "hello" + y: 2 + } +}) +-- out/compile -- +--- in.cue +{ + a: 1 + b: (〈0;a〉 + 1) + c: { + x: "hello" + y: 〈1;b〉 + } +} diff --git a/internal/core/compile/testdata/sync/inlinetest/decl_eq_mixed.txtar b/internal/core/compile/testdata/sync/inlinetest/decl_eq_mixed.txtar new file mode 100644 index 000000000..dcad78a2a --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/decl_eq_mixed.txtar @@ -0,0 +1,14 @@ +-- in.cue -- +// File-level @test(eq, ...) coexists with field-level @test attributes. +// Both assertions run. The file-level @test covers all fields, so per-field +// coverage is not required, but individual fields may still carry @test. + +x: 1 @test(eq, 1) +y: x + 1 +@test(eq, {x: 1, y: 2}) +-- out/compile -- +--- in.cue +{ + x: 1 + y: (〈0;x〉 + 1) +} diff --git a/internal/core/compile/testdata/sync/inlinetest/decl_eq_pattern.txtar b/internal/core/compile/testdata/sync/inlinetest/decl_eq_pattern.txtar new file mode 100644 index 000000000..6c7d062b5 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/decl_eq_pattern.txtar @@ -0,0 +1,17 @@ +-- in.cue -- +// File-level @test(eq, VALUE) where a pattern constraint contributes +// to the output — the eq check applies to the whole file. + +{[X=string]: baz: X} +bar: {} +@test(eq, {bar: baz: "bar"}) +-- out/compile -- +--- in.cue +{ + { + [string]: { + baz: 〈1;-〉 + } + } + bar: {} +} diff --git a/internal/core/compile/testdata/sync/inlinetest/hidden_fields.txtar b/internal/core/compile/testdata/sync/inlinetest/hidden_fields.txtar new file mode 100644 index 000000000..5678bb5f2 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/hidden_fields.txtar @@ -0,0 +1,55 @@ +-- in.cue -- +// Tests that hidden fields in @test(eq, {...}) must be fully specified. +// A hidden field present in the value but absent from the expected struct +// causes a test failure. A hidden field in the expected struct that is absent +// from the value also causes a failure. + +package foo + +// -- hidden field present in both value and expected -- +// Field-attribute form: hidden field in both value and expected passes. +hiddenInBoth: { + _secret: 42 + a: _secret + 1 +} @test(eq, {_secret$foo: 42, a: 43}) + +// Decl-attribute form. +hiddenDeclForm: { + @test(eq, {_secret$foo: "x", b: "xx"}) + _secret: "x" + b: _secret + _secret +} + +// Hidden definition field in both value and expected. +hiddenDefInBoth: { + _#Meta: {info: "internal"} + a: 1 +} @test(eq, {_#Meta$foo: {info: "internal"}, a: 1}) + +// -- no hidden fields -- + +// No hidden fields on either side: passes trivially. +noHidden: {a: 1, b: 2} @test(eq, {a: 1, b: 2}) + +-- out/compile -- +--- in.cue +{ + hiddenInBoth: { + _secret(:foo): 42 + a: (〈0;_secret(:foo)〉 + 1) + } + hiddenDeclForm: { + _secret(:foo): "x" + b: (〈0;_secret(:foo)〉 + 〈0;_secret(:foo)〉) + } + hiddenDefInBoth: { + _#Meta(:foo): { + info: "internal" + } + a: 1 + } + noHidden: { + a: 1 + b: 2 + } +} diff --git a/internal/core/compile/testdata/sync/inlinetest/permute.txtar b/internal/core/compile/testdata/sync/inlinetest/permute.txtar new file mode 100644 index 000000000..d12ba5254 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/permute.txtar @@ -0,0 +1,101 @@ +-- in.cue -- +// Structural permute tests: @test(permute) placed on the struct whose fields +// should be permuted — either as a decl attr on the container, or as a decl +// attr directly on the 'in' struct. + +// ── Container-level @test(permute): permutes all fields of `in` ── + +threeFieldPermute: { + @test(permute, count=6) + a: b + c + b: 1 + c: 2 + @test(eq, { + a: 3 + b: 1 + c: 2 + }) +} + +twoFieldPermute: { + @test(permute, count=2) + x: y + 1 + y: 5 + @test(eq, { + x: 6 + y: 5 + }) +} + +// ── Decl attr on `in` directly: equivalent syntax ── + +inDeclPermute: { + @test(permute, count=6) + p: q + r + q: 3 + r: 7 + @test(eq, { + p: 10 + q: 3 + r: 7 + }) +} + +// ── Self-contained concrete struct: trivially order-invariant ── + +concretePermute: { + x: { + @test(permute, count=6) + alpha: 1 + beta: 2 + gamma: 3 + } + y: { + @test(permute, count=6) + alpha: 1 + beta: 2 + gamma: 3 + } + @test(eq, { + x: { + alpha: 1 + beta: 2 + gamma: 3 + } + y: { + alpha: 1 + beta: 2 + gamma: 3 + } + }) +} +-- out/compile -- +--- in.cue +{ + threeFieldPermute: { + a: (〈0;b〉 + 〈0;c〉) + b: 1 + c: 2 + } + twoFieldPermute: { + x: (〈0;y〉 + 1) + y: 5 + } + inDeclPermute: { + p: (〈0;q〉 + 〈0;r〉) + q: 3 + r: 7 + } + concretePermute: { + x: { + alpha: 1 + beta: 2 + gamma: 3 + } + y: { + alpha: 1 + beta: 2 + gamma: 3 + } + } +} diff --git a/internal/core/compile/testdata/sync/inlinetest/struct_eq.txtar b/internal/core/compile/testdata/sync/inlinetest/struct_eq.txtar new file mode 100644 index 000000000..fb222a013 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/struct_eq.txtar @@ -0,0 +1,14 @@ +-- in.cue -- +myStruct: { + @test(eq, {a: 1, b: 2}) + a: 1 + b: a + 1 +} +-- out/compile -- +--- in.cue +{ + myStruct: { + a: 1 + b: (〈0;a〉 + 1) + } +} diff --git a/internal/core/compile/testdata/sync/inlinetest/structural.txtar b/internal/core/compile/testdata/sync/inlinetest/structural.txtar new file mode 100644 index 000000000..a880c4b73 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/structural.txtar @@ -0,0 +1,73 @@ +-- in.cue -- +// Tests converted from structural form to inline form. + +// ── error-only ───────────────────────── + +errOnly: 1 & 2 @test(err, code=eval, contains="conflicting values %s and %s", args=[2, 1], pos=[0:10, 0:14]) + +errWithCode: string & 1 @test(err, code=eval, + contains="conflicting values %s and %s (mismatched types %s and %s)", + args=[string, 1, string, int], pos=[0:14, 0:23]) + +// ── eq: computed struct ──────────────── + +eqBasic: {a: 1, b: 2} @test(eq, {a: 1, b: 2}) + +eqComputed: { + @test(eq, {x: 10, y: 20}) + x: 10 + y: x * 2 +} + +// ── skip ────────────────────────────── + +skippedTest: {a: 1} @test(skip, why="demonstrating skip") + +// ── desc ────────────────────────────── + +descTest: {v: "ok"} @test(desc="description") @test(eq, {v: "ok"}) + +// ── version-specific ────────────────── + +versionOverride: {x: 1} @test(eq, {x: 1}) @test(eq:unknown, {x: 3}) + +// ── plain fixture field + references ────────────────── + +// A plain field with no @test is accessible but not a sub-test. +plainFixture: { + x: 42 +} + +refsFixture: plainFixture.x @test(eq, 42) + +// ── mixed inline ────────────────────── + +mixedInline: 42 @test(eq, 42) +-- out/compile -- +--- in.cue +{ + errOnly: (1 & 2) + errWithCode: (string & 1) + eqBasic: { + a: 1 + b: 2 + } + eqComputed: { + x: 10 + y: (〈0;x〉 * 2) + } + skippedTest: { + a: 1 + } + descTest: { + v: "ok" + } + versionOverride: { + x: 1 + } + plainFixture: { + x: 42 + } + refsFixture: 〈0;plainFixture〉.x + mixedInline: 42 +} diff --git a/internal/core/compile/testdata/sync/inlinetest/validators.txtar b/internal/core/compile/testdata/sync/inlinetest/validators.txtar new file mode 100644 index 000000000..195772024 --- /dev/null +++ b/internal/core/compile/testdata/sync/inlinetest/validators.txtar @@ -0,0 +1,23 @@ +-- in.cue -- +import "struct" + +// Validator equality: a value produced by applying a builtin validator +// can be compared with @test(eq, ). + +// Standalone validator: BaseValue of the vertex is the BuiltinValidator +// itself, so equalTerminal is called directly with two BuiltinValidators. +rawMax: struct.MaxFields(2) @test(eq, struct.MaxFields(2)) +rawMin: struct.MinFields(3) @test(eq, struct.MinFields(3)) + +intMixDirect: int & <=1 @test(eq, <=1 & int) +intMixEmbed: {int & <=1} @test(eq, {<=1 & int}) +-- out/compile -- +--- in.cue +{ + rawMax: 〈import;struct〉.MaxFields(2) + rawMin: 〈import;struct〉.MinFields(3) + intMixDirect: (int & <=1) + intMixEmbed: { + (int & <=1) + } +} diff --git a/internal/core/compile/testdata/sync/interpolation/041_interpolation.txtar b/internal/core/compile/testdata/sync/interpolation/041_interpolation.txtar new file mode 100644 index 000000000..ed189578d --- /dev/null +++ b/internal/core/compile/testdata/sync/interpolation/041_interpolation.txtar @@ -0,0 +1,19 @@ +-- in.cue -- +a: "\(4)" @test(eq, "4") +b: "one \(a) two \( a+c )" @test(eq, "one 4 two 4one") +c: "one" @test(eq, "one") +d: "\(r)" @test(err, code=incomplete, contains="invalid interpolation: non-concrete value _", pos=[0:4], hint="position of r itself would be nice") +u: "\(_)" @test(err, code=incomplete|eval, contains="invalid interpolation: non-concrete value _", pos=[0:4, 0:7]) @test(err:todo, code=eval) // literal _ can never resolve. +r: _ +e: "\([])" @test(err, code=eval, contains="invalid interpolation: cannot use [] (type list)", pos=[0:4, 0:7]) +-- out/compile -- +--- in.cue +{ + a: "\(4)" + b: "one \(〈0;a〉) two \((〈0;a〉 + 〈0;c〉))" + c: "one" + d: "\(〈0;r〉)" + u: "\(_)" + r: _ + e: "\([])" +} diff --git a/internal/core/compile/testdata/sync/interpolation/042_multiline_interpolation.txtar b/internal/core/compile/testdata/sync/interpolation/042_multiline_interpolation.txtar new file mode 100644 index 000000000..5655345f5 --- /dev/null +++ b/internal/core/compile/testdata/sync/interpolation/042_multiline_interpolation.txtar @@ -0,0 +1,74 @@ +-- in.cue -- +a1: """ + before + \(4) + after + """ @test(eq, "before\n4\nafter") +a2: """ + before + \(4) + + """ @test(eq, "before\n4\n") +a3: """ + + \(4) + after + """ @test(eq, "\n4\nafter") +a4: """ + + \(4) + + """ @test(eq, "\n4\n") +m1: """ + before + \( + 4) + after + """ @test(eq, "before\n4\nafter") +m2: """ + before + \( + 4) + + """ @test(eq, "before\n4\n") +m3: """ + + \( + + 4) + after + """ @test(eq, "\n4\nafter") +m4: """ + + \( + 4) + + """ @test(eq, "\n4\n") +-- out/compile -- +--- in.cue +{ + a1: "before + \(4) + after" + a2: "before + \(4) + " + a3: " + \(4) + after" + a4: " + \(4) + " + m1: "before + \(4) + after" + m2: "before + \(4) + " + m3: " + \(4) + after" + m4: " + \(4) + " +} diff --git a/internal/core/compile/testdata/sync/interpolation/incomplete.txtar b/internal/core/compile/testdata/sync/interpolation/incomplete.txtar new file mode 100644 index 000000000..80e0e1970 --- /dev/null +++ b/internal/core/compile/testdata/sync/interpolation/incomplete.txtar @@ -0,0 +1,32 @@ +Issue #553 +-- in.cue -- +a: "foo" @test(eq, "foo") +b: "boo" @test(eq, "boo") +commands: { + #c: { + help: "help!" + } +} +out: """ + a is \(a) + b is \(b) + + c is \(commands.#c.help) + d is \(commands.#d.help) + """ @test(err, code=incomplete) +-- out/compile -- +--- in.cue +{ + a: "foo" + b: "boo" + commands: { + #c: { + help: "help!" + } + } + out: "a is \(〈0;a〉) + b is \(〈0;b〉) + + c is \(〈0;commands〉.#c.help) + d is \(〈0;commands〉.#d.help)" +} diff --git a/internal/core/compile/testdata/sync/interpolation/issue487.txtar b/internal/core/compile/testdata/sync/interpolation/issue487.txtar new file mode 100644 index 000000000..9e2fb5603 --- /dev/null +++ b/internal/core/compile/testdata/sync/interpolation/issue487.txtar @@ -0,0 +1,44 @@ +# Tests that string interpolation correctly reports "incomplete" errors when +# the interpolated field is abstract (non-concrete), while still allowing the +# parent struct to be unified with a concrete value. Issue: interpolation inside +# a definition produced an "incomplete" error on the definition field itself, +# but the unified concrete result (e.g. `a: #R & {pos: 67}`) should evaluate +# to a concrete string. +# https://cuelang.org/issue/487 +-- in.cue -- +t1: { + #R: { + pos: uint + name: "hello_\(pos)" @test(err, code=incomplete) + } + a: #R & {pos: 67} @test(eq, {pos: 67, name: "hello_67"}) @test(closed) +} +t2: { + #R: { + pos: string + name: "hello_\(pos)" @test(err, code=incomplete) + } + a: #R & {pos: "a"} @test(eq, {pos: "a", name: "hello_a"}) @test(closed) +} +-- out/compile -- +--- in.cue +{ + t1: { + #R: { + pos: &(int, >=0) + name: "hello_\(〈0;pos〉)" + } + a: (〈0;#R〉 & { + pos: 67 + }) + } + t2: { + #R: { + pos: string + name: "hello_\(〈0;pos〉)" + } + a: (〈0;#R〉 & { + pos: "a" + }) + } +} diff --git a/internal/core/compile/testdata/sync/interpolation/scalars.txtar b/internal/core/compile/testdata/sync/interpolation/scalars.txtar new file mode 100644 index 000000000..1ba03bd2e --- /dev/null +++ b/internal/core/compile/testdata/sync/interpolation/scalars.txtar @@ -0,0 +1,35 @@ +-- in.cue -- +bool1: "1+1=2: \(true)" @test(eq, "1+1=2: true") +bool1: "1+1=2: \(true)" +bool2: "1+1=1: \(false)" @test(eq, "1+1=1: false") + +// one replacement character +b1: 'a\xED\x95a' @test(eq, 'a\xed\x95a') +bytes1s: "\(b1)" @test(eq, "a\uFFFDa") +bytes1b: '\(b1)' @test(eq, 'a\xed\x95a') + +// two replacement characters +b2: 'a\x80\x95a' @test(eq, 'a\x80\x95a') +bytes2s: "\(b2)" @test(eq, "a�a") +bytes2b: '\(b2)' @test(eq, 'a\x80\x95a') + +// preserve precision +n1: "\(1) \(2.00)" @test(eq, "1 2.00") + +// but normalize representation +n2: "\(1e2)" @test(eq, "1E+2") +-- out/compile -- +--- in.cue +{ + bool1: "1+1=2: \(true)" + bool1: "1+1=2: \(true)" + bool2: "1+1=1: \(false)" + b1: 'a\xed\x95a' + bytes1s: "\(〈0;b1〉)" + bytes1b: '\(〈0;b1〉)' + b2: 'a\x80\x95a' + bytes2s: "\(〈0;b2〉)" + bytes2b: '\(〈0;b2〉)' + n1: "\(1) \(2.00)" + n2: "\(1E+2)" +} diff --git a/internal/core/compile/testdata/sync/lists/019_list_types.txtar b/internal/core/compile/testdata/sync/lists/019_list_types.txtar new file mode 100644 index 000000000..0203cb033 --- /dev/null +++ b/internal/core/compile/testdata/sync/lists/019_list_types.txtar @@ -0,0 +1,95 @@ +-- in.cue -- +import "list" + +l0: list.Repeat([int], 3) +l0: [1, 2, 3] @test(eq, [1, 2, 3]) +l2: [...{a: int}] +l2: [{a: 1}, {a: 2, b: 3}] @test(eq, [{a: 1}, {a: 2, b: 3}]) + +// TODO: work out a decent way to specify length ranges of lists. +// l3: <=10*[int] +// l3: [1, 2, 3, ...] + +s1: (list.Repeat([int], 6))[2:3] @test(eq, [int]) +s2: [0, 2, 3][1:2] @test(eq, [2]) + +i1: (list.Repeat([int], 6))[2] @test(eq, int) +i2: [0, 2, 3][2] @test(eq, 3) + +t0: [...{a: 8}] +t0: [{}] @test(eq, [{a: 8}]) +t1: [...] +t1: [...int] @test(eq, []) + +e0: list.Repeat([{}], 2) +e0: [{}] @test(err, code=eval, contains="incompatible list lengths", args=[1, 2], pos=[], hint="missing positions") +e1: [...int] +e1: [...float] @test(eq, []) +-- out/compile -- +--- in.cue +{ + l0: 〈import;list〉.Repeat([ + int, + ], 3) + l0: [ + 1, + 2, + 3, + ] + l2: [ + ...{ + a: int + }, + ] + l2: [ + { + a: 1 + }, + { + a: 2 + b: 3 + }, + ] + s1: 〈import;list〉.Repeat([ + int, + ], 6)[2:3] + s2: [ + 0, + 2, + 3, + ][1:2] + i1: 〈import;list〉.Repeat([ + int, + ], 6)[2] + i2: [ + 0, + 2, + 3, + ][2] + t0: [ + ...{ + a: 8 + }, + ] + t0: [ + {}, + ] + t1: [ + ..., + ] + t1: [ + ...int, + ] + e0: 〈import;list〉.Repeat([ + {}, + ], 2) + e0: [ + {}, + ] + e1: [ + ...int, + ] + e1: [ + ...float, + ] +} diff --git a/internal/core/compile/testdata/sync/lists/020_list_compilefail.txtar b/internal/core/compile/testdata/sync/lists/020_list_compilefail.txtar new file mode 100644 index 000000000..1f6d5cad6 --- /dev/null +++ b/internal/core/compile/testdata/sync/lists/020_list_compilefail.txtar @@ -0,0 +1,61 @@ +#inlinetest:exclude CUE source contains compile-time errors (invalid operands to *) +# which prevent the inline runner from compiling the source. +#name: list arithmetic +#evalPartial +-- in.cue -- +l3: <=2 * [] +l4: <=2 * [int] +l5: <=2 * (int * [int]) +b: <=5 * [int] +b: [1, 2, ...] +c: (>=3 & <=5) * [int] +c: [1, 2, ...] +d: >=2 * [int] +d: [1, 2, ...] +-- out/compile -- +l3: invalid operand <=2 ('*' requires concrete value): + ./in.cue:1:5 +l4: invalid operand <=2 ('*' requires concrete value): + ./in.cue:2:5 +l5: invalid operand <=2 ('*' requires concrete value): + ./in.cue:3:5 +l5: invalid operand int ('*' requires concrete value): + ./in.cue:3:12 +b: invalid operand <=5 ('*' requires concrete value): + ./in.cue:4:5 +d: invalid operand >=2 ('*' requires concrete value): + ./in.cue:8:4 +--- in.cue +{ + l3: (<=2 * []) + l4: (<=2 * [ + int, + ]) + l5: (<=2 * (int * [ + int, + ])) + b: (<=5 * [ + int, + ]) + b: [ + 1, + 2, + ..., + ] + c: ((>=3 & <=5) * [ + int, + ]) + c: [ + 1, + 2, + ..., + ] + d: (>=2 * [ + int, + ]) + d: [ + 1, + 2, + ..., + ] +} diff --git a/internal/core/compile/testdata/sync/lists/021_list_equality.txtar b/internal/core/compile/testdata/sync/lists/021_list_equality.txtar new file mode 100644 index 000000000..ba9f74909 --- /dev/null +++ b/internal/core/compile/testdata/sync/lists/021_list_equality.txtar @@ -0,0 +1,343 @@ +-- in.cue -- +eq0: [] == [] @test(eq, true) +eq1: [...] == [] @test(eq, true) +eq2: [] == [...] @test(eq, true) +eq3: [...] == [...] @test(eq, true) + +eq4: [1] == [1] @test(eq, true) +eq5: [1, ...] == [1] @test(eq, true) +eq6: [1] == [1, ...] @test(eq, true) +eq7: [1, ...] == [1, ...] @test(eq, true) + +eq8: [1, 2] == [1, 2] @test(eq, true) +eq9: [1, 2, ...] == [1, 2] @test(eq, true) +eq10: [1, 2] == [1, 2, ...] @test(eq, true) +eq11: [1, 2, ...] == [1, 2, ...] @test(eq, true) + +ne0: [] != [] @test(eq, false) +ne1: [...] != [] @test(eq, false) +ne2: [] != [...] @test(eq, false) +ne3: [...] != [...] @test(eq, false) + +ne4: [1] != [1] @test(eq, false) +ne5: [1, ...] != [1] @test(eq, false) +ne6: [1] != [1, ...] @test(eq, false) +ne7: [1, ...] != [1, ...] @test(eq, false) + +ne8: [1, 2] != [1, 2] @test(eq, false) +ne9: [1, 2, ...] != [1, 2] @test(eq, false) +ne10: [1, 2] != [1, 2, ...] @test(eq, false) +ne11: [1, 2, ...] != [1, 2, ...] @test(eq, false) + +feq0: [] == [1] @test(eq, false) +feq1: [...] == [1] @test(eq, false) +feq2: [] == [1, ...] @test(eq, false) +feq3: [...] == [1, ...] @test(eq, false) + +feq4: [1] == [] @test(eq, false) +feq5: [1, ...] == [] @test(eq, false) +feq6: [1] == [...] @test(eq, false) +feq7: [1, ...] == [...] @test(eq, false) + +feq8: [1, 2] == [1] @test(eq, false) +feq9: [1, ...] == [1, 2] @test(eq, false) +feq10: [1, 2] == [1, ...] @test(eq, false) +feq11: [1, ...] == [1, 2, ...] @test(eq, false) + +fne0: [] != [1] @test(eq, true) +fne1: [...] != [1] @test(eq, true) +fne2: [] != [1, ...] @test(eq, true) +fne3: [1, ...] != [1, ...] @test(eq, false) + +fne4: [1] != [] @test(eq, true) +fne5: [1, ...] != [] @test(eq, true) +fne6: [1] != [...] @test(eq, true) +fne7: [1, ...] != [...] @test(eq, true) + +fne8: [1, 2] != [1] @test(eq, true) +fne9: [1, ...] != [1, 2] @test(eq, true) +fne10: [1, 2] != [1, ...] @test(eq, true) +fne11: [1, ...] != [1, 2, ...] @test(eq, true) + +eqIncomplete1: [1] == [string] @test(err, code=incomplete, contains="invalid right-hand value to '=='", pos=[0:16]) + +neIncomplete1: [1] != [string] @test(err, code=incomplete, contains="invalid right-hand value to '!='", pos=[0:16]) +-- out/compile -- +--- in.cue +{ + eq0: ([] == []) + eq1: ([ + ..., + ] == []) + eq2: ([] == [ + ..., + ]) + eq3: ([ + ..., + ] == [ + ..., + ]) + eq4: ([ + 1, + ] == [ + 1, + ]) + eq5: ([ + 1, + ..., + ] == [ + 1, + ]) + eq6: ([ + 1, + ] == [ + 1, + ..., + ]) + eq7: ([ + 1, + ..., + ] == [ + 1, + ..., + ]) + eq8: ([ + 1, + 2, + ] == [ + 1, + 2, + ]) + eq9: ([ + 1, + 2, + ..., + ] == [ + 1, + 2, + ]) + eq10: ([ + 1, + 2, + ] == [ + 1, + 2, + ..., + ]) + eq11: ([ + 1, + 2, + ..., + ] == [ + 1, + 2, + ..., + ]) + ne0: ([] != []) + ne1: ([ + ..., + ] != []) + ne2: ([] != [ + ..., + ]) + ne3: ([ + ..., + ] != [ + ..., + ]) + ne4: ([ + 1, + ] != [ + 1, + ]) + ne5: ([ + 1, + ..., + ] != [ + 1, + ]) + ne6: ([ + 1, + ] != [ + 1, + ..., + ]) + ne7: ([ + 1, + ..., + ] != [ + 1, + ..., + ]) + ne8: ([ + 1, + 2, + ] != [ + 1, + 2, + ]) + ne9: ([ + 1, + 2, + ..., + ] != [ + 1, + 2, + ]) + ne10: ([ + 1, + 2, + ] != [ + 1, + 2, + ..., + ]) + ne11: ([ + 1, + 2, + ..., + ] != [ + 1, + 2, + ..., + ]) + feq0: ([] == [ + 1, + ]) + feq1: ([ + ..., + ] == [ + 1, + ]) + feq2: ([] == [ + 1, + ..., + ]) + feq3: ([ + ..., + ] == [ + 1, + ..., + ]) + feq4: ([ + 1, + ] == []) + feq5: ([ + 1, + ..., + ] == []) + feq6: ([ + 1, + ] == [ + ..., + ]) + feq7: ([ + 1, + ..., + ] == [ + ..., + ]) + feq8: ([ + 1, + 2, + ] == [ + 1, + ]) + feq9: ([ + 1, + ..., + ] == [ + 1, + 2, + ]) + feq10: ([ + 1, + 2, + ] == [ + 1, + ..., + ]) + feq11: ([ + 1, + ..., + ] == [ + 1, + 2, + ..., + ]) + fne0: ([] != [ + 1, + ]) + fne1: ([ + ..., + ] != [ + 1, + ]) + fne2: ([] != [ + 1, + ..., + ]) + fne3: ([ + 1, + ..., + ] != [ + 1, + ..., + ]) + fne4: ([ + 1, + ] != []) + fne5: ([ + 1, + ..., + ] != []) + fne6: ([ + 1, + ] != [ + ..., + ]) + fne7: ([ + 1, + ..., + ] != [ + ..., + ]) + fne8: ([ + 1, + 2, + ] != [ + 1, + ]) + fne9: ([ + 1, + ..., + ] != [ + 1, + 2, + ]) + fne10: ([ + 1, + 2, + ] != [ + 1, + ..., + ]) + fne11: ([ + 1, + ..., + ] != [ + 1, + 2, + ..., + ]) + eqIncomplete1: ([ + 1, + ] == [ + string, + ]) + neIncomplete1: ([ + 1, + ] != [ + string, + ]) +} diff --git a/internal/core/compile/testdata/sync/packages/builtin.txtar b/internal/core/compile/testdata/sync/packages/builtin.txtar new file mode 100644 index 000000000..650d1c045 --- /dev/null +++ b/internal/core/compile/testdata/sync/packages/builtin.txtar @@ -0,0 +1,15 @@ +#inlinetest:exclude imports an undefined package "x/y"; the inline runner cannot +# compile the source when package resolution fails. +-- x.cue -- +import "x/y" + +foo: [ + y, +] +-- out/compile -- +--- x.cue +{ + foo: [ + 〈import;"x/y"〉, + ] +} diff --git a/internal/core/compile/testdata/sync/packages/embed.txtar b/internal/core/compile/testdata/sync/packages/embed.txtar new file mode 100644 index 000000000..5fce8d384 --- /dev/null +++ b/internal/core/compile/testdata/sync/packages/embed.txtar @@ -0,0 +1,33 @@ +exec cue eval ./pkg:foo +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- in.cue -- +package foo + +import "mod.test/pkg:bar" + +bar +z: 3 + +@test(eq, {z: 3, foo: {y: 2, x: 1}, y: 2, x: 1}) +-- pkg/bar.cue -- +package bar + +import "mod.test/pkg:baz" + +foo: { + baz + y: 2 +} +foo +-- pkg/baz.cue -- +package baz + +x: 1 +-- out/compile -- +--- in.cue +{ + 〈import;"mod.test/pkg:bar"〉 + z: 3 +} diff --git a/internal/core/compile/testdata/sync/packages/issue398.txtar b/internal/core/compile/testdata/sync/packages/issue398.txtar new file mode 100644 index 000000000..e16b93dac --- /dev/null +++ b/internal/core/compile/testdata/sync/packages/issue398.txtar @@ -0,0 +1,32 @@ +# Tests that transitive package imports are correctly propagated. When foo imports +# bar which imports baz, evaluating foo should include values from all three +# packages rather than omitting the transitively imported baz contents. +# https://cuelang.org/issue/398 +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- foo.cue -- +package foo + +import "mod.test/pkg:bar" + +bar +zz: 3 +@test(eq, {zz: 3, yy: 2, xx: 1}) +-- pkg/bar.cue -- +package bar + +import "mod.test/pkg:baz" + +baz +yy: 2 +-- pkg/baz.cue -- +package baz + +xx: 1 +-- out/compile -- +--- foo.cue +{ + 〈import;"mod.test/pkg:bar"〉 + zz: 3 +} diff --git a/internal/core/compile/testdata/sync/packages/sub.txtar b/internal/core/compile/testdata/sync/packages/sub.txtar new file mode 100644 index 000000000..ea9c52c04 --- /dev/null +++ b/internal/core/compile/testdata/sync/packages/sub.txtar @@ -0,0 +1,24 @@ +exec cue eval ./pkg:foo +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- in.cue -- +package test + +import pkg2 "mod.test/foo/pkg1" + +#pkg1: pkg2.Object + +"Hello \(#pkg1)!" + +@test(eq, {"Hello World!", #pkg1: "World"}) +-- foo/pkg1/file.cue -- +package pkg1 + +Object: "World" +-- out/compile -- +--- in.cue +{ + #pkg1: 〈import;"mod.test/foo/pkg1"〉.Object + "Hello \(〈0;#pkg1〉)!" +} diff --git a/internal/core/compile/testdata/sync/references/alias.txtar b/internal/core/compile/testdata/sync/references/alias.txtar new file mode 100644 index 000000000..5e11f2196 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/alias.txtar @@ -0,0 +1,364 @@ +-- in.cue -- +@experiment(aliasv2) + +// Basic postfix alias - simple form +a1~X1: { + foo: 1 +} +b1: X1.foo + 2 @test(eq, 3) + +a1p~(X1p): { + foo: 1 +} +b1p: X1p.foo + 2 @test(eq, 3) + + +// Basic postfix alias - dual form +a2~(K2,V2): { + name: K2 + val: V2.foo +} +a2: {foo: 42} @test(eq, {name: "a2", val: 42, foo: 42}) + +// Postfix alias with _ for field +a3~(K3,_): { + foo: 1 +} +b3: K3 @test(eq, "a3") + +// Postfix alias with _ for label +a4~(_,V4): { + foo: 1 +} +b4: V4.foo + 2 @test(eq, 3) + +// Dynamic field with postfix alias +("dyn")~X5: { + foo: 1 +} +b5: X5.foo + 10 @test(eq, 11) + +// Dynamic field with dual form +("dyn2")~(K6,V6): { + name: K6 + val: V6.foo +} +dyn2: {foo: 100} @test(eq, {foo: 100, name: "dyn2", val: 100}) + +// Pattern constraint with postfix alias - scoped to value only +// The field alias should create a recursive reference +pattern: { + [string]~(LabelAlias,_): { + labelRef: LabelAlias + } + foo: {} + @test(eq, {foo: {labelRef: "foo"}}) +} + +// Pattern constraint with dual form +pattern2: { + [string]~(LabelName,FieldRef): { + labelVal: LabelName + fieldVal: FieldRef.data + } + foo: {data: 1} + bar: {data: 2} + @test(eq, { + foo: {data: 1, labelVal: "foo", fieldVal: 1} + bar: {data: 2, labelVal: "bar", fieldVal: 2} + }) +} + +// Pattern constraint - field alias creates recursive reference +// TODO: fix this. Note that this is also broken with old aliases. +// pattern3recursive: { +// [string]~(_, FieldAlias): { +// // FieldAlias refers to this field, creating recursion +// recursive: FieldAlias +// } +// foo: {} +// } + +// Nested structs with postfix aliases +nested~X7: { + inner~Y7: { + a: 1 + } + b: Y7.a + X7.inner.a +} +result1: nested.b @test(eq, 2) + +// Multiple fields with aliases referencing each other +multi: { + a~A8: 1 + b~B8: A8 + 2 + c: B8 + 3 + @test(eq, {a: 1, b: 3, c: 6}) +} + +// Postfix alias in comprehension +comp: { + items: [1, 2, 3] + for i, v in items { + "\(i)"~X9: { + index: i + value: v + double: X9.value * 2 + } + } + @test(eq, { + items: [1, 2, 3] + "0": {index: 0, value: 1, double: 2} + "1": {index: 1, value: 2, double: 4} + "2": {index: 2, value: 3, double: 6} + }) +} + +// Postfix alias with constraints +constrained~X10?: { + required: true +} +test1: X10.required @test(err, code=incomplete, contains="cannot reference optional field: constrained", pos=[0:8]) @test(err, code=incomplete, contains="cannot reference optional field: %s", args=[constrained], pos=[0:8]) + +// Interpolation with postfix alias +"\("inter")"~X11: { + foo: 1 +} +b6: X11.foo + 5 @test(eq, 6) + +// Postfix alias with optional and default +opt~X12?: { + a: 1 + b: X12 @test(err, code=incomplete, contains="field not found: opt", pos=[]) +} @test(err, code=incomplete, contains="field not found: %v", args=[opt], pos=[]) + +// TODO: seemingly wrong semantics, but matches old behavior. +def~Y13: { + b: 2 + c: Y13.b +} | {b: 3} @test(eq, {b: 2, c: 2} | {b: 3}) + +// Pattern with blank identifier - label only visible in value +pattern3: { + [string]~(LN14,_): { + labelName: LN14 + } + test: {} + + @test(eq, {test: {labelName: "test"}}) +} + +// Pattern with blank identifier - field only visible in value +pattern4: { + [string]~(_,FR15): { + fieldRef: FR15.x + } + test: {x: 99} + @test(eq, {test: {x: 99, fieldRef: 99}}) +} + +// Multiple aliases in same scope +same: { + a~A16: 1 + b~B16: 2 + c: A16 + B16 + + @test(eq, {a: 1, b: 2, c: 3}) +} + +// Alias referencing earlier alias +chain~X17: { + a: 1 +} @test(eq, {a: 1}) +chain2~Y18: { + ref: X17.a +} @test(eq, {ref: 1}) +result2: Y18.ref @test(eq, 1) + +// Postfix alias with list value +list~X19: [1, 2, 3] +b7: X19[0] + X19[1] @test(eq, 3) + +// Postfix alias with disjunction +disj~X20: 1 | 2 | 3 +b8: X20 @test(eq, 1 | 2 | 3) + +// Nested pattern constraints with aliases +deep: { + [string]~(OuterLabel,_): { + [string]~(InnerLabel, InnerField): { + outer: OuterLabel + inner: InnerLabel + value: InnerField.x + } + foo: {x: 1} + } + bar: {} + @test(eq, { + bar: { + foo: { + x: 1 + outer: "bar" + inner: "foo" + value: 1 + } + } + }) +} + +// Alias with definition +#Def~X21: { + field: 42 +} +usedef: X21.field @test(eq, 42) +-- out/compile -- +--- in.cue +{ + a1: { + foo: 1 + } + b1: (〈0;a1〉.foo + 2) + a1p: { + foo: 1 + } + b1p: (〈0;a1p〉.foo + 2) + a2: { + name: "a2" + val: 〈1;a2〉.foo + } + a2: { + foo: 42 + } + a3: { + foo: 1 + } + b3: "a3" + a4: { + foo: 1 + } + b4: (〈0;a4〉.foo + 2) + "dyn": { + foo: 1 + } + b5: (〈0;("dyn")〉.foo + 10) + "dyn2": { + name: 〈1;-〉 + val: 〈1;("dyn2")〉.foo + } + dyn2: { + foo: 100 + } + pattern: { + [string]: { + labelRef: 〈1;-〉 + } + foo: {} + } + pattern2: { + [string]: { + labelVal: 〈1;-〉 + fieldVal: 〈1;(〈0;-〉)〉.data + } + foo: { + data: 1 + } + bar: { + data: 2 + } + } + nested: { + inner: { + a: 1 + } + b: (〈0;inner〉.a + 〈1;nested〉.inner.a) + } + result1: 〈0;nested〉.b + multi: { + a: 1 + b: (〈0;a〉 + 2) + c: (〈0;b〉 + 3) + } + comp: { + items: [ + 1, + 2, + 3, + ] + for i, v in 〈0;items〉 { + "\(〈1;i〉)": { + index: 〈2;i〉 + value: 〈2;v〉 + double: (〈1;("\(〈1;i〉)")〉.value * 2) + } + } + } + constrained?: { + required: true + } + test1: 〈0;constrained〉.required + "\("inter")": { + foo: 1 + } + b6: (〈0;("\("inter")")〉.foo + 5) + opt?: { + a: 1 + b: 〈1;opt〉 + } + def: ({ + b: 2 + c: 〈1;def〉.b + }|{ + b: 3 + }) + pattern3: { + [string]: { + labelName: 〈1;-〉 + } + test: {} + } + pattern4: { + [string]: { + fieldRef: 〈1;(〈0;-〉)〉.x + } + test: { + x: 99 + } + } + same: { + a: 1 + b: 2 + c: (〈0;a〉 + 〈0;b〉) + } + chain: { + a: 1 + } + chain2: { + ref: 〈1;chain〉.a + } + result2: 〈0;chain2〉.ref + list: [ + 1, + 2, + 3, + ] + b7: (〈0;list〉[0] + 〈0;list〉[1]) + disj: (1|2|3) + b8: 〈0;disj〉 + deep: { + [string]: { + [string]: { + outer: 〈2;-〉 + inner: 〈1;-〉 + value: 〈1;(〈0;-〉)〉.x + } + foo: { + x: 1 + } + } + bar: {} + } + #Def: { + field: 42 + } + usedef: 〈0;#Def〉.field +} diff --git a/internal/core/compile/testdata/sync/references/alias_err.txtar b/internal/core/compile/testdata/sync/references/alias_err.txtar new file mode 100644 index 000000000..f7bbfc1fb --- /dev/null +++ b/internal/core/compile/testdata/sync/references/alias_err.txtar @@ -0,0 +1,60 @@ +#inlinetest:exclude compile-time alias errors prevent CUE source compilation; @test(err) requires successful compile +-- old.cue -- +// issue2527: self-referential alias in key `x=(x):` caused an "unreachable" +// panic (https://cuelang.org/issue/2527). +issue2527: { + x=(x): 3 +} +// issue2094: alias Y referring to a dynamic-key field X declared afterward +// caused a panic due to ordering sensitivity (https://cuelang.org/issue/2094). +issue2094: { + Y=(X): string + X=("foo"): "bar" +} +-- new.cue -- +@experiment(aliasv2) + +// issue2527: self-referential alias in key `(x)~x:` caused an "unreachable" +// panic (https://cuelang.org/issue/2527). +issue2527: { + (x)~x: 3 +} +// issue2094: alias Y referring to a dynamic-key field X declared afterward +// caused a panic due to ordering sensitivity (https://cuelang.org/issue/2094). +issue2094: { + (X)~Y: string + ("foo")~X: "bar" +} +-- out/compile -- +issue2527: cyclic reference in field alias: + ./new.cue:6:3 +issue2094: cyclic reference in field alias: + ./new.cue:11:3 +issue2094: unreferenced alias or let clause Y: + ./new.cue:11:5 +issue2527: cyclic reference in field alias: + ./old.cue:4:5 +issue2094: unreferenced alias or let clause Y: + ./old.cue:9:2 +issue2094: cyclic reference in field alias: + ./old.cue:9:5 +--- new.cue +{ + issue2527: { + 〈0;(_|_(cyclic reference in field alias))〉: 3 + } + issue2094: { + 〈0;("foo")〉: string + "foo": "bar" + } +} +--- old.cue +{ + issue2527: { + 〈0;(_|_(cyclic reference in field alias))〉: 3 + } + issue2094: { + 〈0;("foo")〉: string + "foo": "bar" + } +} diff --git a/internal/core/compile/testdata/sync/references/embed_self.txtar b/internal/core/compile/testdata/sync/references/embed_self.txtar new file mode 100644 index 000000000..36b7a0658 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/embed_self.txtar @@ -0,0 +1,10 @@ +-- in.cue -- +Foo: {} @test(eq, {}) + +Foo +-- out/compile -- +--- in.cue +{ + Foo: {} + 〈0;Foo〉 +} diff --git a/internal/core/compile/testdata/sync/references/errors.txtar b/internal/core/compile/testdata/sync/references/errors.txtar new file mode 100644 index 000000000..bdfecd574 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/errors.txtar @@ -0,0 +1,57 @@ +-- references.cue -- +missingField: { + a: {} + r: a.b @test(err, code=incomplete, contains="undefined field: b", pos=[0:7]) +} + +missingFieldClosed: { + #a: {} + r: #a.b @test(err, code=eval, contains="undefined field: b", pos=[0:8]) +} + +missingFieldNested: { + a: {} + // Must refer to `b` in error + r: a.b.c @test(err, code=incomplete, contains="undefined field: b", pos=[0:7]) +} + +missingFieldNestedClosed: { + #a: {} + + // Must refer to `d` in error + r: #a.d.c @test(err, code=eval, contains="undefined field: d", pos=[0:8]) +} + +missingFieldNestedInInterpolation: { + a: {} + // Must refer to `b` in error + r1: "\(a.b.c)" @test(err, code=incomplete, contains="invalid interpolation: undefined field: b", pos=[0:6, 0:11]) + // Must refer to `d` in error: in case only one error is shown for a + // a location, ensure it doesn't alphabetically sort and pick `c` instead. + r2: "\(a.d.c)" @test(err, code=incomplete, contains="invalid interpolation: undefined field: d", pos=[0:6, 0:11]) +} +-- out/compile -- +--- references.cue +{ + missingField: { + a: {} + r: 〈0;a〉.b + } + missingFieldClosed: { + #a: {} + r: 〈0;#a〉.b + } + missingFieldNested: { + a: {} + r: 〈0;a〉.b.c + } + missingFieldNestedClosed: { + #a: {} + r: 〈0;#a〉.d.c + } + missingFieldNestedInInterpolation: { + a: {} + r1: "\(〈0;a〉.b.c)" + r2: "\(〈0;a〉.d.c)" + } +} diff --git a/internal/core/compile/testdata/sync/references/incomplete.txtar b/internal/core/compile/testdata/sync/references/incomplete.txtar new file mode 100644 index 000000000..1451f7b42 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/incomplete.txtar @@ -0,0 +1,64 @@ +-- in.cue -- +comprehensions: { + a: {} + b: { + if a.b { + } + } @test(err, code=incomplete, contains="undefined field: b", pos=[1:8]) + c: { + for x in a.b {x} + } @test(err, code=incomplete, contains="comprehensions.c: undefined field: b", pos=[1:14]) +} + +openStruct: { + a: {} + b: a.c @test(err, code=incomplete, contains="openStruct.b: undefined field: c", pos=[0:7]) +} + +selectFromTop: { + top: _ + a: top.foo @test(err, code=incomplete, contains="top.foo undefined as top is incomplete", pos=[0:7]) +} + +indexOnTop: { + top: _ + a: top[2] @test(err, code=incomplete, contains="top[2] undefined as top is incomplete", pos=[0:7]) +} + +incompleteIndex: { + top: _ + a: [1][top] @test(err, code=eval, contains="invalid index top (invalid type _)", pos=[0:7, 0:11]) +} +-- out/compile -- +--- in.cue +{ + comprehensions: { + a: {} + b: { + if 〈1;a〉.b {} + } + c: { + for _, x in 〈1;a〉.b { + 〈1;x〉 + } + } + } + openStruct: { + a: {} + b: 〈0;a〉.c + } + selectFromTop: { + top: _ + a: 〈0;top〉.foo + } + indexOnTop: { + top: _ + a: 〈0;top〉[2] + } + incompleteIndex: { + top: _ + a: [ + 1, + ][〈0;top〉] + } +} diff --git a/internal/core/compile/testdata/sync/references/index.txtar b/internal/core/compile/testdata/sync/references/index.txtar new file mode 100644 index 000000000..71a9ae306 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/index.txtar @@ -0,0 +1,88 @@ +-- in.cue -- +intIndex: [2][0] @test(eq, 2) +stringIndex: {foo: "bar"}["foo"] @test(eq, "bar") + +stringOfNumberIndex: {"3": 3}["3"] @test(eq, 3) + +indexToDefault: (*[0] | {})[0] @test(eq, 0) +outOfBoundsDisjunction: (*[] | {})[1] @test(err, code=eval, contains="index out of range [1] with length 0", pos=[0:36]) + +// Ensure these are errors. +indexDoesNotDistribute: (*[] | [1])[0] @test(err, code=eval, contains="index out of range [0] with length 0", pos=[0:37]) +doesNotDistributeType: { + l: [] + a: (*l | {"3": 3})["3"] @test(err, code=eval, contains="undefined field", pos=[0:21]) +} + +stringIndexToList: [2][""] @test(err, code=eval, contains="undefined field", pos=[0:24]) +indexOutOfBounds2: 2[2] @test(err, code=eval, contains="invalid operand 2 (found int, want list or struct)", pos=[0:20]) +booleanIndex: [][true] @test(err, code=eval, contains="invalid index true (invalid type bool)", pos=[0:20, 0:23]) +indexOutOfBounds3: [1, 2, 3][4] @test(err, code=eval, contains="index out of range [4] with length 3", pos=[0:30]) +negativeIndex: [1, 2, 3][-1] @test(err, code=eval, contains="invalid index -1 (index must be non-negative)", pos=[0:20, 0:30]) + +varIndexTooLarge: { + n: 3 + a: [1, 2, 3][n] @test(err, code=eval, contains="index out of range [3] with length 3", pos=[0:15]) +} + +varNegativeIndex: { + n: -1 + a: [1, 2, 3][n] @test(err, code=eval, contains="index n out of range [-1]", pos=[0:5, -1:5, 0:15]) +} +-- out/compile -- +--- in.cue +{ + intIndex: [ + 2, + ][0] + stringIndex: { + foo: "bar" + }["foo"] + stringOfNumberIndex: { + "3": 3 + }["3"] + indexToDefault: (*[ + 0, + ]|{})[0] + outOfBoundsDisjunction: (*[]|{})[1] + indexDoesNotDistribute: (*[]|[ + 1, + ])[0] + doesNotDistributeType: { + l: [] + a: (*〈0;l〉|{ + "3": 3 + })["3"] + } + stringIndexToList: [ + 2, + ][""] + indexOutOfBounds2: 2[2] + booleanIndex: [][true] + indexOutOfBounds3: [ + 1, + 2, + 3, + ][4] + negativeIndex: [ + 1, + 2, + 3, + ][-1] + varIndexTooLarge: { + n: 3 + a: [ + 1, + 2, + 3, + ][〈0;n〉] + } + varNegativeIndex: { + n: -1 + a: [ + 1, + 2, + 3, + ][〈0;n〉] + } +} diff --git a/internal/core/compile/testdata/sync/references/labels.txtar b/internal/core/compile/testdata/sync/references/labels.txtar new file mode 100644 index 000000000..7f88562b7 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/labels.txtar @@ -0,0 +1,273 @@ +-- in.cue -- +// Label aliases + +// direct +a: [X=string]: X +a: bar: _ +@test(eq, {bar: "bar"}, at=a) + +// in struct +b: [X=string]: {X} +b: bar: _ +@test(eq, {bar: "bar"}, at=b) + +// in structs +c: [X=string]: X +c: [Y=string]: {{{Y}}} +c: bar: _ +@test(eq, {bar: "bar"}, at=c) + +// in sub field +d: [X=string]: name: X +d: bar: {} +@test(eq, {bar: {name: "bar"}}, at=d) + +// nested +e: [X=string]: [Y=string]: X + Y +e: foo: bar: _ +@test(eq, {foo: {bar: "foobar"}}, at=e) + +patternField: t1: { + r=[string]: {b: r | null} + a: {r: 0} + @test(eq, {a: {r: 0, b: null}}) +} + +patternField: t2: { + a: {r: 0} + x=[string]: {z: 1, b: x.z} + @test(eq, {a: {r: 0, z: 1, b: 1}}) +} + +// Field aliases + +bar: 3 +f1: C="foo\(bar)": { + name: "xx" + foo: C.name +} +@test(eq, { + foo3: { + name: "xx" + foo: "xx" + foo3baz: {name: "xx", a: "xx", b: "xx"} + } +}, at=f1) + +// nested +f1: D="foo\(bar)": E="foo\(bar)baz": { + name: "xx" + a: D["foo\(bar)baz"].name + b: E.name +} + +// Combo + +c1: C="foo\(bar)": [D=string]: { + name: D + foo: C.x.name +} +c1: foo3: x: _ +@test(eq, {foo3: {x: {name: "x", foo: "x"}}}, at=c1) + + +emptyLabel: { + "": 1 + a: emptyLabel[""] + @test(eq, {"": 1, a: 1}) +} + +underscore: a: { + // Issue #1454 + foo: #Foo + foo: "_": "bar" + #Foo: [=~""]: string + @test(eq, {foo: {"_": "bar"}, #Foo: {}}) +} + +underscore: c: { + foo: "_": "any" + foo: [=~""]: string + @test(eq, {foo: {"_": "any"}}) +} + +underscore: d: { + bar: "_": "any" + #bar: [string]: string + bar: #bar + @test(eq, {bar: {"_": "any"}, #bar: {}}) +} + +underscore: e: { + baz: "_h": "any" + #baz: [=~"_"]: string + baz: #baz + @test(eq, {baz: {"_h": "any"}, #baz: {}}) +} + +// TODO: support. Also not yet supported in old implementation. +// c10: { +// C=[string]: { +// name: "x" +// foo: C.name +// } +// } +// c2: c1 & { x: _ } + +invalidPattern: { + [=~"BAD)" & =~"x"]: string + y: 123 + @test(err, code=eval, contains="invalid regexp", pos=[1:22]) +} +-- out/compile -- +--- in.cue +{ + a: { + [string]: 〈0;-〉 + } + a: { + bar: _ + } + b: { + [string]: { + 〈1;-〉 + } + } + b: { + bar: _ + } + c: { + [string]: 〈0;-〉 + } + c: { + [string]: { + { + { + 〈3;-〉 + } + } + } + } + c: { + bar: _ + } + d: { + [string]: { + name: 〈1;-〉 + } + } + d: { + bar: {} + } + e: { + [string]: { + [string]: (〈1;-〉 + 〈0;-〉) + } + } + e: { + foo: { + bar: _ + } + } + patternField: { + t1: { + [string]: { + b: (〈1;(〈0;-〉)〉|null) + } + a: { + r: 0 + } + } + } + patternField: { + t2: { + a: { + r: 0 + } + [string]: { + z: 1 + b: 〈1;(〈0;-〉)〉.z + } + } + } + bar: 3 + f1: { + "foo\(〈1;bar〉)": { + name: "xx" + foo: 〈1;("foo\(〈1;bar〉)")〉.name + } + } + f1: { + "foo\(〈1;bar〉)": { + "foo\(〈2;bar〉)baz": { + name: "xx" + a: 〈2;("foo\(〈1;bar〉)")〉["foo\(〈3;bar〉)baz"].name + b: 〈1;("foo\(〈2;bar〉)baz")〉.name + } + } + } + c1: { + "foo\(〈1;bar〉)": { + [string]: { + name: 〈1;-〉 + foo: 〈2;("foo\(〈1;bar〉)")〉.x.name + } + } + } + c1: { + foo3: { + x: _ + } + } + emptyLabel: { + "": 1 + a: 〈1;emptyLabel〉[""] + } + underscore: { + a: { + foo: 〈0;#Foo〉 + foo: { + "_": "bar" + } + #Foo: { + [=~""]: string + } + } + } + underscore: { + c: { + foo: { + "_": "any" + } + foo: { + [=~""]: string + } + } + } + underscore: { + d: { + bar: { + "_": "any" + } + #bar: { + [string]: string + } + bar: 〈0;#bar〉 + } + } + underscore: { + e: { + baz: { + "_h": "any" + } + #baz: { + [=~"_"]: string + } + baz: 〈0;#baz〉 + } + } + invalidPattern: { + [(=~"BAD)" & =~"x")]: string + y: 123 + } +} diff --git a/internal/core/compile/testdata/sync/references/labelstop.txtar b/internal/core/compile/testdata/sync/references/labelstop.txtar new file mode 100644 index 000000000..939bd7d15 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/labelstop.txtar @@ -0,0 +1,16 @@ +TODO: add matching when bulk optional fields are allowed +alongside other fields. +-- in.cue -- +{[X=string]: baz: X} +bar: {} +@test(eq, {bar: baz: "bar"}) +-- out/compile -- +--- in.cue +{ + { + [string]: { + baz: 〈1;-〉 + } + } + bar: {} +} diff --git a/internal/core/compile/testdata/sync/references/let.txtar b/internal/core/compile/testdata/sync/references/let.txtar new file mode 100644 index 000000000..d31e281f1 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/let.txtar @@ -0,0 +1,304 @@ +-- in.cue -- +import "list" + +a1list: [{1}] +let A1 = a1list +a1: 100*A1[0] + A1[0] @test(eq, 101) + +a2list: [{2}] +let A2 = a2list +a2: b: 100*A2[0] + A2[0] @test(eq, 202) + +a3list: [{3}] +let A3 = a3list +a3: b: c: 100*A3[0] + A3[0] @test(eq, 303) + +a4list: [{4}] +let A4 = a4list +a4: [for x in A4 {v: 404}] @test(eq, [{v: 404}]) + +a5list: [{5}] +let A5 = a5list +a5: b: [for x in A5 {v: 505}] @test(eq, [{v: 505}]) + +a6list: [{6}] +let A6 = a6list +a6: b: c: [for x in A6 {v: 606}] @test(eq, [{v: 606}]) + +a7list: [{7}] +let A7 = a7list +a7: {for x in A7 {v: 707}} @test(eq, {v: 707}) + +a8list: [{8}] +let A8 = a8list +a8: b: {for x in A8 {v: 808}} @test(eq, {v: 808}) + +a9list: [{9}] +let A9 = a9list +a9: b: c: {for x in A9 {v: 909}} @test(eq, {v: 909}) + +// Issue #609: +// When a let value resolved to an incomplete value, it should pass this +// incomplete status to the expression in which it used. But 609 reported +// a gobbling of this incomplete status. The problem seemed to be not +// exclusive to the use of let, though. +incompleteLet: { + input: [1, 2, 3, 4, 5] + + last: { + min: list.Min(input) + max: list.Max(input) + } + + bar: { + let mn = last.min + let mx = list.max + + min: mn + max: mx @test(err, code=incomplete, contains="undefined field: max", pos=[-3:17]) + } + + x: { + if list.max < 0 { + } + } + @test(eq, { + input: [1, 2, 3, 4, 5] + last: {min: 1, max: 5} + bar: { + min: 1 + max: _|_ @test(err, code=incomplete, contains="incompleteLet.bar.max: undefined field: max", pos=[54:17]) + } + x: _|_ @test(err, code=incomplete, contains="incompleteLet.x: undefined field: max", pos=[61:11]) + }) +} + +// Let references should also work inside embedded scalars. +// Issue #1955 +scalarReference: { + inScalar: p0: { + 5 + let x = 6 + #b: x + @test(eq, {5, #b: 6}) + } + inScalar: p1: { + #b: x + let x = 6 + 5 + @test(eq, {5, #b: 6}) + } + inList: p0: { + let x = { a: 1 } + [ x ] + @test(eq, [{a: 1}]) + } + inList: p1: { + [ x ] + let x = { a: 1 } + @test(eq, [{a: 1}]) + } +} + +// Strange let declaration behavior: accessing the last element of a list via +// a let-bound variable failed when the let appeared before the list definition. +// https://cuelang.org/issue/1116 +issue1116: { + a: { + #a: ["a", "b"] + let List = #a + List[len(List)-1] + @test(eq, {"b", #a: ["a", "b"]}) + } + b: { + let List = #a + List[len(List)-1] + #a: ["a", "b"] + @test(eq, {"b", #a: ["a", "b"]}) + } +} +-- out/compile -- +--- in.cue +{ + a1list: [ + { + 1 + }, + ] + let A1#1 = 〈0;a1list〉 + a1: ((100 * 〈0;let A1#1〉[0]) + 〈0;let A1#1〉[0]) + a2list: [ + { + 2 + }, + ] + let A2#2 = 〈0;a2list〉 + a2: { + b: ((100 * 〈1;let A2#2〉[0]) + 〈1;let A2#2〉[0]) + } + a3list: [ + { + 3 + }, + ] + let A3#3 = 〈0;a3list〉 + a3: { + b: { + c: ((100 * 〈2;let A3#3〉[0]) + 〈2;let A3#3〉[0]) + } + } + a4list: [ + { + 4 + }, + ] + let A4#4 = 〈0;a4list〉 + a4: [ + for _, x in 〈1;let A4#4〉 { + v: 404 + }, + ] + a5list: [ + { + 5 + }, + ] + let A5#5 = 〈0;a5list〉 + a5: { + b: [ + for _, x in 〈2;let A5#5〉 { + v: 505 + }, + ] + } + a6list: [ + { + 6 + }, + ] + let A6#6 = 〈0;a6list〉 + a6: { + b: { + c: [ + for _, x in 〈3;let A6#6〉 { + v: 606 + }, + ] + } + } + a7list: [ + { + 7 + }, + ] + let A7#7 = 〈0;a7list〉 + a7: { + for _, x in 〈1;let A7#7〉 { + v: 707 + } + } + a8list: [ + { + 8 + }, + ] + let A8#8 = 〈0;a8list〉 + a8: { + b: { + for _, x in 〈2;let A8#8〉 { + v: 808 + } + } + } + a9list: [ + { + 9 + }, + ] + let A9#9 = 〈0;a9list〉 + a9: { + b: { + c: { + for _, x in 〈3;let A9#9〉 { + v: 909 + } + } + } + } + incompleteLet: { + input: [ + 1, + 2, + 3, + 4, + 5, + ] + last: { + min: 〈import;list〉.Min(〈1;input〉) + max: 〈import;list〉.Max(〈1;input〉) + } + bar: { + let mn#A = 〈1;last〉.min + let mx#B = 〈import;list〉.max + min: 〈0;let mn#A〉 + max: 〈0;let mx#B〉 + } + x: { + if (〈import;list〉.max < 0) {} + } + } + scalarReference: { + inScalar: { + p0: { + 5 + let x#C = 6 + #b: 〈0;let x#C〉 + } + } + inScalar: { + p1: { + #b: 〈0;let x#D〉 + let x#D = 6 + 5 + } + } + inList: { + p0: { + let x#E = { + a: 1 + } + [ + 〈1;let x#E〉, + ] + } + } + inList: { + p1: { + [ + 〈1;let x#F〉, + ] + let x#F = { + a: 1 + } + } + } + } + issue1116: { + a: { + #a: [ + "a", + "b", + ] + let List#10 = 〈0;#a〉 + 〈0;let List#10〉[(len(〈0;let List#10〉) - 1)] + } + b: { + let List#11 = 〈0;#a〉 + 〈0;let List#11〉[(len(〈0;let List#11〉) - 1)] + #a: [ + "a", + "b", + ] + } + } +} diff --git a/internal/core/compile/testdata/sync/references/letcycle.txtar b/internal/core/compile/testdata/sync/references/letcycle.txtar new file mode 100644 index 000000000..0e4f0b770 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/letcycle.txtar @@ -0,0 +1,161 @@ +#inlinetest:exclude mutually recursive let bindings produce compile-time cycle errors +# which prevent the inline runner from compiling the source. Issue #1042. +#expandLetExpr: true +-- in.cue -- +import "list" + +cycles: { + a: { + let A = {c: B} + let B = A + out: A + } + + b: { + let A = {c: B} + let B = {A.c} + out: A + } + + issue1042: { + #FullAdder: { + // IN + a: bool + b: bool + c: bool + // OUT + sum: bool + carry: bool + } + + #Add16: { + a: [bool] * 16 + b: [bool] * 16 + out: [bool] * 16 + + let fulladders = [ + for i in list.Range(0, 4, 1) { + #FullAdder & {"a": a[i], "b": b[i], c: carries[i]} + }, + ] + let carries = [ + false, + for i in list.Range(0, 4, 1) {fulladders[i].carry}, + ] + out: [ + for i in list.Range(0, 4, 1) {fulladders[i].sum}, + ] + } + } +} +-- out/compile -- +cycles.a.let[].c: cyclic references in let clause or alias: + ./in.cue:5:15 +cycles.b.let[].c: cyclic references in let clause or alias: + ./in.cue:11:15 +cycles.issue1042.#Add16.let[].for[].c: cyclic references in let clause or alias: + ./in.cue:34:45 +--- in.cue +{ + cycles: { + a: { + let A#1 = { + c: 〈1;let B#2〉=>〈0;let A#1〉=>{ + c: 〈1;let B#2〉=>_|_(cyclic references in let clause or alias) + } + } + let B#2 = 〈0;let A#1〉=>{ + c: 〈1;let B#2〉=>_|_(cyclic references in let clause or alias) + } + out: 〈0;let A#1〉=>{ + c: 〈1;let B#2〉=>_|_(cyclic references in let clause or alias) + } + } + b: { + let A#3 = { + c: 〈1;let B#4〉=>{ + 〈1;let A#3〉=>{ + c: 〈1;let B#4〉=>_|_(cyclic references in let clause or alias) + }.c + } + } + let B#4 = { + 〈1;let A#3〉=>{ + c: 〈1;let B#4〉=>_|_(cyclic references in let clause or alias) + }.c + } + out: 〈0;let A#3〉=>{ + c: 〈1;let B#4〉=>_|_(cyclic references in let clause or alias) + } + } + issue1042: { + #FullAdder: { + a: bool + b: bool + c: bool + sum: bool + carry: bool + } + #Add16: { + a: ([ + bool, + ] * 16) + b: ([ + bool, + ] * 16) + out: ([ + bool, + ] * 16) + let fulladders#5 = [ + for _, i in 〈import;list〉.Range(0, 4, 1) { + (〈4;#FullAdder〉 & { + a: 〈4;a〉[〈2;i〉] + b: 〈4;b〉[〈2;i〉] + c: 〈4;let carries#6〉=>[ + false, + for _, i in 〈import;list〉.Range(0, 4, 1) { + 〈3;let fulladders#5〉=>[ + for _, i in 〈import;list〉.Range(0, 4, 1) { + (〈4;#FullAdder〉 & { + a: 〈4;a〉[〈2;i〉] + b: 〈4;b〉[〈2;i〉] + c: 〈4;let carries#6〉=>_|_(cyclic references in let clause or alias)[〈2;i〉] + }) + }, + ][〈1;i〉].carry + }, + ][〈2;i〉] + }) + }, + ] + let carries#6 = [ + false, + for _, i in 〈import;list〉.Range(0, 4, 1) { + 〈3;let fulladders#5〉=>[ + for _, i in 〈import;list〉.Range(0, 4, 1) { + (〈4;#FullAdder〉 & { + a: 〈4;a〉[〈2;i〉] + b: 〈4;b〉[〈2;i〉] + c: 〈4;let carries#6〉=>_|_(cyclic references in let clause or alias)[〈2;i〉] + }) + }, + ][〈1;i〉].carry + }, + ] + out: [ + for _, i in 〈import;list〉.Range(0, 4, 1) { + 〈3;let fulladders#5〉=>[ + for _, i in 〈import;list〉.Range(0, 4, 1) { + (〈4;#FullAdder〉 & { + a: 〈4;a〉[〈2;i〉] + b: 〈4;b〉[〈2;i〉] + c: 〈4;let carries#6〉=>_|_(cyclic references in let clause or alias)[〈2;i〉] + }) + }, + ][〈1;i〉].sum + }, + ] + } + } + } +} diff --git a/internal/core/compile/testdata/sync/references/optional.txtar b/internal/core/compile/testdata/sync/references/optional.txtar new file mode 100644 index 000000000..28dd6fff0 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/optional.txtar @@ -0,0 +1,27 @@ +-- in.cue -- +t1: a: { + foo?: int + + b: foo @test(err, code=incomplete) +} +t2: a: { + b: foo @test(err, code=incomplete) + + foo?: int +} +-- out/compile -- +--- in.cue +{ + t1: { + a: { + foo?: int + b: 〈0;foo〉 + } + } + t2: { + a: { + b: 〈0;foo〉 + foo?: int + } + } +} diff --git a/internal/core/compile/testdata/sync/references/package.txtar b/internal/core/compile/testdata/sync/references/package.txtar new file mode 100644 index 000000000..6ea24ad5d --- /dev/null +++ b/internal/core/compile/testdata/sync/references/package.txtar @@ -0,0 +1,32 @@ +-- cue.mod/module.cue -- +module: "mod.test" +language: version: "v0.9.0" +-- in.cue -- +package exitcode + +import ( + pkg "foo.com/example" +) + +a: 1 + +incomplete: pkg.Settings +@test(eq, { + a: 1 + incomplete: {} +}) +-- cue.mod/pkg/foo.com/example/example.cue -- +package example + +// An incomplete error in a package is not transferred to a +// package that is using it. +// +// Issue #550 +blah: Settings.anyKey +Settings: {} +-- out/compile -- +--- in.cue +{ + a: 1 + incomplete: 〈import;"foo.com/example"〉.Settings +} diff --git a/internal/core/compile/testdata/sync/references/self.txtar b/internal/core/compile/testdata/sync/references/self.txtar new file mode 100644 index 000000000..f1a443413 --- /dev/null +++ b/internal/core/compile/testdata/sync/references/self.txtar @@ -0,0 +1,208 @@ +Test various self reference cases. +-- in.cue -- +@experiment(aliasv2) + +// Basic self usage - top level +a: self.b @test(eq, "hello") +b: "hello" + +// Nested self usage - should refer to x struct +x: { + y: self.z + z: "world" +} @test(eq, {y: "world", z: "world"}) + +// Shorthand notation - self should refer to foo struct +foo: bar: self.baz @test(eq, "greeting") +foo: baz: "greeting" @test(eq, "greeting") // TODO(inline): reference marking does not work with "self" + +// Multiple levels of nesting +nested: { + level1: { + field: self.value + value: "level1 value" + } +} @test(eq, { + level1: { + field: "level1 value" + value: "level1 value" + } +}) + +// Self in list context +listTest: { + items: [1, 2, self[0], self[1]] + first: 1 + second: 2 +} @test(eq, { + items: [1, 2, 1, 2] + first: 1 + second: 2 +}) + +// Self with computed selectors +computed: { + key: "test" + value: self["key"] +} @test(eq, {key: "test", value: "test"}) + +// Cyclic reference detection +cycle: self.cycle @test(eq, _) + +-- list.cue -- +@experiment(aliasv2) +import "list" + +#IntStrings: {list.Repeat([int, string], div(len(self), 2))} +listCheck: ok1: #IntStrings +listCheck: ok1: [1, "foo", 2, "bar"] @test(eq, [1, "foo", 2, "bar"]) + +listCheck: err: #IntStrings +listCheck: err: [1, "foo", "bar", 2] @test(err, code=eval, path=2, contains="conflicting values %s and %s (mismatched types %s and %s)", args=["bar", int, string, int], pos=[-5:14, -5:15, -5:28, -1:17, 0:28]) + +-- withlet.cue -- +@experiment(aliasv2) + +withLet: { + let X = self + foo: 1 + + bar: { + baz: X.foo + } +} @test(eq, {foo: 1, bar: {baz: 1}}) +-- validator.cue -- +@experiment(structcmp) +@experiment(aliasv2) + +validator: { + err1: {{{{== (self + 1)}}}} @test(err, code=eval, + contains="invalid value %v (out of bound %s)", args=[2, ==3], + pos=[0:12, 0:8, 4:8] + ) + err1: 2 + + err2: {== (self + 1)} @test(err, code=eval, + contains="invalid value %v (out of bound %s)", args=[2, ==3], + pos=[0:9, 0:8, 4:8] + ) + err2: 2 +} + +cyclicErr: { + err3: == (self + 1) @test(err, code=eval, + contains="invalid operands %s and %s to '%s' (type %s and %s)", + pos=[0:12, -1:12, 0:19] + ) + err3: 4 +} + +-- experiment_test.cue -- +// Test self usage without experiment enabled (should fail) + +a: { + b: self.c + c: 3 +} + +-- out/compile -- +--- in.cue +{ + a: 〈1〉.b + b: "hello" + x: { + y: 〈1〉.z + z: "world" + } + foo: { + bar: 〈1〉.baz + } + foo: { + baz: "greeting" + } + nested: { + level1: { + field: 〈1〉.value + value: "level1 value" + } + } + listTest: { + items: [ + 1, + 2, + 〈1〉[0], + 〈1〉[1], + ] + first: 1 + second: 2 + } + computed: { + key: "test" + value: 〈1〉["key"] + } + cycle: 〈1〉.cycle +} +--- list.cue +{ + #IntStrings: { + 〈import;list〉.Repeat([ + int, + string, + ], div(len(〈1〉), 2)) + } + listCheck: { + ok1: 〈1;#IntStrings〉 + } + listCheck: { + ok1: [ + 1, + "foo", + 2, + "bar", + ] + } + listCheck: { + err: 〈1;#IntStrings〉 + } + listCheck: { + err: [ + 1, + "foo", + "bar", + 2, + ] + } +} +--- validator.cue +{ + validator: { + err1: { + { + { + { + ==(〈1〉 + 1) + } + } + } + } + err1: 2 + err2: { + ==(〈1〉 + 1) + } + err2: 2 + } + cyclicErr: { + err3: ==(〈1〉 + 1) + err3: 4 + } +} +--- withlet.cue +{ + withLet: { + let X#1 = 〈1〉 + foo: 1 + bar: { + baz: 〈1;let X#1〉.foo + } + } +} diff --git a/internal/core/compile/testdata/sync/references/value.txtar b/internal/core/compile/testdata/sync/references/value.txtar new file mode 100644 index 000000000..90efe82ee --- /dev/null +++ b/internal/core/compile/testdata/sync/references/value.txtar @@ -0,0 +1,50 @@ +-- in.cue -- +structShorthand: X={b: 3, c: X.b} @test(eq, {b: 3, c: 3}) + +// Note that X and Y are subtly different, as they have different bindings: +// one binds to the field, the other to the value. In this case, that does not +// make a difference. +fieldAndValue: X=foo: Y={3, #sum: X + Y} @test(eq, {3, #sum: 6}) + +valueCycle: b: X=3 + X @test(err, code=cycle, contains="cycle with field", pos=[0:22]) + +// Issue #1003 +listValueAlias: X = [1, 2, X[0]] @test(eq, [1, 2, 1]) + +-- err.cue -- +@experiment(structcmp) + +cycleErr: X={ + err3: == (X + 1) + err3: 4 + @test(err, code=eval, contains="invalid operands", pos=[1:12, 0:13, 1:16]) +} +-- out/compile -- +--- err.cue +{ + cycleErr: { + err3: ==(〈1〉 + 1) + err3: 4 + } +} +--- in.cue +{ + structShorthand: { + b: 3 + c: 〈1〉.b + } + fieldAndValue: { + foo: { + 3 + #sum: (〈1;foo〉 + 〈1〉) + } + } + valueCycle: { + b: (3 + 〈0〉) + } + listValueAlias: [ + 1, + 2, + 〈1〉[0], + ] +} diff --git a/internal/core/compile/testdata/sync/resolve/000_convert___to_top.txtar b/internal/core/compile/testdata/sync/resolve/000_convert___to_top.txtar new file mode 100644 index 000000000..f062a8861 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/000_convert___to_top.txtar @@ -0,0 +1,11 @@ +# Tests that a pattern constraint [_]: _ over an open struct results in +# an open struct without any concrete fields. +-- in.cue -- +a: {[_]: _} @test(eq, {}) +-- out/compile -- +--- in.cue +{ + a: { + [_]: _ + } +} diff --git a/internal/core/compile/testdata/sync/resolve/001.txtar b/internal/core/compile/testdata/sync/resolve/001.txtar new file mode 100644 index 000000000..0ff008e6c --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/001.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +a: b.c.d @test(eq, 3) +b: {c: {d: 3}} +c: {c: d.d} @test(eq, {c: 2}) +d: {d: 2} +-- out/compile -- +--- in.cue +{ + a: 〈0;b〉.c.d + b: { + c: { + d: 3 + } + } + c: { + c: 〈1;d〉.d + } + d: { + d: 2 + } +} diff --git a/internal/core/compile/testdata/sync/resolve/004.txtar b/internal/core/compile/testdata/sync/resolve/004.txtar new file mode 100644 index 000000000..e2ecd836c --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/004.txtar @@ -0,0 +1,16 @@ +-- in.cue -- +a: _ +b: a @test(eq, {d: 1}) @test(shareID=ba) +a: {d: 1, d: _} @test(eq, {d: 1}) @test(shareID=ba) +b: _ +-- out/compile -- +--- in.cue +{ + a: _ + b: 〈0;a〉 + a: { + d: 1 + d: _ + } + b: _ +} diff --git a/internal/core/compile/testdata/sync/resolve/005_JSON.txtar b/internal/core/compile/testdata/sync/resolve/005_JSON.txtar new file mode 100644 index 000000000..bbb2bcfac --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/005_JSON.txtar @@ -0,0 +1,16 @@ +-- in.cue -- +a="a": 3 +@test(eq, at=a, 3) +b: a @test(eq, 3) +o: {"a\nb": 2} @test(eq, {"a\nb": 2}) +c: o["a\nb"] @test(eq, 2) +-- out/compile -- +--- in.cue +{ + a: 3 + b: 〈0;a〉 + o: { + "a\nb": 2 + } + c: 〈0;o〉["a\nb"] +} diff --git a/internal/core/compile/testdata/sync/resolve/006_arithmetic.txtar b/internal/core/compile/testdata/sync/resolve/006_arithmetic.txtar new file mode 100644 index 000000000..bdd94a79d --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/006_arithmetic.txtar @@ -0,0 +1,19 @@ +# Tests arithmetic operations including division producing floats and +# conflicting types (int & float). +-- in.cue -- +v1: 1.0T / 2.0 @test(eq, 5.0e+11) +v2: 2.0 == 2 @test(eq, true) +n1: 1 @test(eq, 1) @test(kind=int) +v5: 2.0 / n1 @test(eq, 2.0) +v6: 1.0 / 1.0 @test(eq, 1.0) @test(kind:todo=int, hint="may consider this") +e2: int & 4.0/2.0 @test(err, code=eval, contains="conflicting values int and 2.0", pos=[0:5, 0:11]) +-- out/compile -- +--- in.cue +{ + v1: (1000000000000 / 2.0) + v2: (2.0 == 2) + n1: 1 + v5: (2.0 / 〈0;n1〉) + v6: (1.0 / 1.0) + e2: (int & (4.0 / 2.0)) +} diff --git a/internal/core/compile/testdata/sync/resolve/007_inequality.txtar b/internal/core/compile/testdata/sync/resolve/007_inequality.txtar new file mode 100644 index 000000000..e5c74df6e --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/007_inequality.txtar @@ -0,0 +1,17 @@ +-- in.cue -- +a: 1 != 2 @test(eq, true) +b: 1 != null @test(eq, true) +c: true == null @test(eq, false) +d: null != {} @test(eq, true) +e: null == [] @test(eq, false) +f: 0 == 0.0 @test(eq, true) // types are unified first TODO: make this consistent +-- out/compile -- +--- in.cue +{ + a: (1 != 2) + b: (1 != null) + c: (true == null) + d: (null != {}) + e: (null == []) + f: (0 == 0.0) +} diff --git a/internal/core/compile/testdata/sync/resolve/008_attributes.txtar b/internal/core/compile/testdata/sync/resolve/008_attributes.txtar new file mode 100644 index 000000000..04053f78c --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/008_attributes.txtar @@ -0,0 +1,20 @@ +-- in.cue -- +a: {foo: 1 @foo() @baz(1)} @test(eq, {foo: 1 @foo() @baz(1)}) +b: {foo: 1 @bar() @foo()} @test(eq, {foo: 1 @foo() @bar()}) +c: a & b @test(eq, {foo: 1 @foo() @baz(1) @bar()}) + +e: a & {foo: 1 @foo(other)} @test(eq, {foo: 1 @foo(other) @foo() @baz(1)}) +-- out/compile -- +--- in.cue +{ + a: { + foo: 1 + } + b: { + foo: 1 + } + c: (〈0;a〉 & 〈0;b〉) + e: (〈0;a〉 & { + foo: 1 + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/009_optional_field_unification.txtar b/internal/core/compile/testdata/sync/resolve/009_optional_field_unification.txtar new file mode 100644 index 000000000..8b3eeb0cc --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/009_optional_field_unification.txtar @@ -0,0 +1,31 @@ +-- in.cue -- +a: {foo?: string} @test(eq, {foo?: string}) +b: {foo: "foo"} @test(eq, {foo: "foo"}) +c: a & b @test(eq, {foo: "foo"}) +d: a & {"foo"?: "bar"} @test(eq, {foo?: "bar"}) + +e: { + g1: 1 + "g\(1)"?: 1 + "g\(2)"?: 2 + @test(eq, {g1: 1, g2?: 2}) +} +-- out/compile -- +--- in.cue +{ + a: { + foo?: string + } + b: { + foo: "foo" + } + c: (〈0;a〉 & 〈0;b〉) + d: (〈0;a〉 & { + foo?: "bar" + }) + e: { + g1: 1 + "g\(1)"?: 1 + "g\(2)"?: 2 + } +} diff --git a/internal/core/compile/testdata/sync/resolve/010_optional_field_resolves_to_incomplete.txtar b/internal/core/compile/testdata/sync/resolve/010_optional_field_resolves_to_incomplete.txtar new file mode 100644 index 000000000..c3d915974 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/010_optional_field_resolves_to_incomplete.txtar @@ -0,0 +1,15 @@ +-- in.cue -- +r: { + a?: 3 + b: a @test(err, code=incomplete, contains="cannot reference optional field: a", pos=[0:6]) + c: r["a"] @test(err, code=incomplete, contains="cannot reference optional field: a", pos=[0:8]) +} +-- out/compile -- +--- in.cue +{ + r: { + a?: 3 + b: 〈0;a〉 + c: 〈1;r〉["a"] + } +} diff --git a/internal/core/compile/testdata/sync/resolve/011_bounds.txtar b/internal/core/compile/testdata/sync/resolve/011_bounds.txtar new file mode 100644 index 000000000..3d6287693 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/011_bounds.txtar @@ -0,0 +1,120 @@ +-- in.cue -- +i1: >1 & 5 @test(eq, 5) +i2: (>=0 & <=10) & 5 @test(eq, 5) +i3: !=null & [] @test(eq, []) +i4: !=2 & !=4 @test(eq, !=2 & !=4) + +s1: >=0 & <=10 & !=1 @test(eq, >=0 & <=10 & !=1) // no simplification +s2: >=0 & <=10 & !=11 @test(eq, >=0 & <=10) +s3: >5 & !=5 @test(eq, >5) +s4: <10 & !=10 @test(eq, <10) +s5: !=2 & !=2 @test(eq, !=2) + +// TODO: could change inequality +s6: !=2 & >=2 @test(eq, >=2 & !=2) @test(eq:todo, >2) +s7: >=2 & !=2 @test(eq, >=2 & !=2) @test(eq:todo, >2) + +s8: !=5 & >5 @test(eq, >5) + +s10: >=0 & <=10 & <12 & >1 @test(eq, >1 & <=10) // >1 & <=10 +s11: >0 & >=0 & <=12 & <12 @test(eq, >0 & <12) // >0 & <12 + +s20: >=10 & <=10 @test(eq, >=10 & <=10) @test(eq:todo, ==10) + +s22: >5 & <=6 @test(eq, >5 & <=6) // no simplification +s22a: >5 & (<=6 & int) @test(eq, >5 & <=6 & int) @test(eq:todo, ==6) +s22b: (int & >5) & <=6 @test(eq, >5 & <=6 & int) @test(eq:todo, ==6) +s22c: >=5 & (<6 & int) @test(eq, >=5 & <6 & int) @test(eq:todo, ==5) +s22d: (int & >=5) & <6 @test(eq, >=5 & <6 & int) @test(eq:todo, ==5) +s22e: (>=5 & <6) & int @test(eq, >=5 & <6 & int) @test(eq:todo, ==5) +s22f: int & (>=5 & <6) @test(eq, >=5 & <6 & int) @test(eq:todo, ==5) + +s23: >0 & <2 @test(eq, >0 & <2) // no simplification +s23a: (>0 & <2) & int @test(eq, >0 & <2 & int) @test(eq:todo, ==1) +s23b: int & (>0 & <2) @test(eq, >0 & <2 & int) @test(eq:todo, ==1) +s23c: (int & >0) & <2 @test(eq, >0 & <2 & int) @test(eq:todo, ==1) +s23d: >0 & (int & <2) @test(eq, >0 & <2 & int) @test(eq:todo, ==1) +s23e: >0.0 & <2.0 @test(eq, >0.0 & <2.0) // no simplification + +s30: >0 & int @test(eq, >0 & int) + +floats: { + [string]: float + f1: <10.0 & <=5.0 @test(eq, <=5.0 & float) + f2: <=10.0 & <5.0 @test(eq, <5.0 & float) + f3: <1.1 & <=1.1 @test(eq, <1.1 & float) + f4: <=1.1 & <=1.1 @test(eq, <=1.1 & float) + f5: >1.1 & >=1.1 @test(eq, >1.1 & float) + f6: >=1.1 & >1.1 @test(eq, >1.1 & float) + f7: >=1.1 & <=1.1 @test(eq, >=1.1 & <=1.1 & float) + + issue1310: >=2.1 & <=1.0 @test(err, code=eval, contains="incompatible number bounds", pos=[0:21, 0:13]) + fe2: >2.1 & <=2.1 @test(err, code=eval, contains="incompatible number bounds", pos=[0:20, 0:13]) + + fe3: float & >2 & <=3 @test(eq, >2 & <=3 & float) +} + +e1: null & !=null @test(err, code=eval, contains="conflicting values null and !=null", pos=[0:5, 0:12]) +e2: !=null & null @test(err, code=eval, contains="conflicting values null and !=null", pos=[0:5, 0:14]) +e3: >1 & 1 @test(err, code=eval, contains="invalid value 1", pos=[0:5, 0:10]) +e4: <0 & 0 @test(err, code=eval, contains="invalid value 0", pos=[0:5, 0:10]) +e5: >1 & <0 @test(err, code=eval, contains="incompatible number bounds", pos=[0:10, 0:5]) +e6: >11 & <11 @test(err, code=eval, contains="incompatible number bounds", pos=[0:11, 0:5]) +e7: >=11 & <11 @test(err, code=eval, contains="incompatible number bounds", pos=[0:12, 0:5]) +e8: >11 & <=11 @test(err, code=eval, contains="incompatible number bounds", pos=[0:11, 0:5]) +e9: >"a" & <1 @test(err, code=eval, contains="conflicting values", pos=[0:5, 0:12]) +-- out/compile -- +--- in.cue +{ + i1: (>1 & 5) + i2: ((>=0 & <=10) & 5) + i3: (!=null & []) + i4: (!=2 & !=4) + s1: ((>=0 & <=10) & !=1) + s2: ((>=0 & <=10) & !=11) + s3: (>5 & !=5) + s4: (<10 & !=10) + s5: (!=2 & !=2) + s6: (!=2 & >=2) + s7: (>=2 & !=2) + s8: (!=5 & >5) + s10: (((>=0 & <=10) & <12) & >1) + s11: (((>0 & >=0) & <=12) & <12) + s20: (>=10 & <=10) + s22: (>5 & <=6) + s22a: (>5 & (<=6 & int)) + s22b: ((int & >5) & <=6) + s22c: (>=5 & (<6 & int)) + s22d: ((int & >=5) & <6) + s22e: ((>=5 & <6) & int) + s22f: (int & (>=5 & <6)) + s23: (>0 & <2) + s23a: ((>0 & <2) & int) + s23b: (int & (>0 & <2)) + s23c: ((int & >0) & <2) + s23d: (>0 & (int & <2)) + s23e: (>0.0 & <2.0) + s30: (>0 & int) + floats: { + [string]: float + f1: (<10.0 & <=5.0) + f2: (<=10.0 & <5.0) + f3: (<1.1 & <=1.1) + f4: (<=1.1 & <=1.1) + f5: (>1.1 & >=1.1) + f6: (>=1.1 & >1.1) + f7: (>=1.1 & <=1.1) + issue1310: (>=2.1 & <=1.0) + fe2: (>2.1 & <=2.1) + fe3: ((float & >2) & <=3) + } + e1: (null & !=null) + e2: (!=null & null) + e3: (>1 & 1) + e4: (<0 & 0) + e5: (>1 & <0) + e6: (>11 & <11) + e7: (>=11 & <11) + e8: (>11 & <=11) + e9: (>"a" & <1) +} diff --git a/internal/core/compile/testdata/sync/resolve/012_bound_conversions.txtar b/internal/core/compile/testdata/sync/resolve/012_bound_conversions.txtar new file mode 100644 index 000000000..4435dbb39 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/012_bound_conversions.txtar @@ -0,0 +1,30 @@ +-- in.cue -- +r0: int & >0.1 & <=1.9 @test(eq, >0.1 & <=1.9 & int) +r1: int & >0.1 & <1.9 @test(eq, >0.1 & <1.9 & int) +r2: int & >=0.1 & <1.9 @test(eq, >=0.1 & <1.9 & int) +r3: int & >=-1.9 & <=-0.1 @test(eq, >=-1.9 & <=-0.1 & int) +r4: int & >-1.9 & <=-0.1 @test(eq, >-1.9 & <=-0.1 & int) + +r5: >=1.1 & <=1.1 @test(eq, >=1.1 & <=1.1) @test(eq:todo, ==1.1) +r6: r5 & 1.1 @test(eq, 1.1) + +c1: (1.2 & >1.3) & <2 @test(err, code=eval, contains="invalid value 1.2", pos=[0:12, 0:6]) +c2: 1.2 & (>1.3 & <2) @test(err, code=eval, contains="invalid value 1.2", pos=[0:12, 0:5]) + +c3: 1.2 & (>=1 & <2) @test(eq, 1.2) +c4: 1.2 & (>=1 & <2 & int) @test(err, code=eval, contains="conflicting values 1.2 and int", pos=[0:5, 0:23]) +-- out/compile -- +--- in.cue +{ + r0: ((int & >0.1) & <=1.9) + r1: ((int & >0.1) & <1.9) + r2: ((int & >=0.1) & <1.9) + r3: ((int & >=-1.9) & <=-0.1) + r4: ((int & >-1.9) & <=-0.1) + r5: (>=1.1 & <=1.1) + r6: (〈0;r5〉 & 1.1) + c1: ((1.2 & >1.3) & <2) + c2: (1.2 & (>1.3 & <2)) + c3: (1.2 & (>=1 & <2)) + c4: (1.2 & ((>=1 & <2) & int)) +} diff --git a/internal/core/compile/testdata/sync/resolve/013_custom_validators.txtar b/internal/core/compile/testdata/sync/resolve/013_custom_validators.txtar new file mode 100644 index 000000000..975c7db86 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/013_custom_validators.txtar @@ -0,0 +1,21 @@ +-- in.cue -- +import "strings" + +a: strings.ContainsAny("ab") +a: "after" @test(eq, "after") + +b: strings.ContainsAny("c") +b: "dog" @test(err, code=eval, contains="invalid value \"dog\"", pos=[-1:4, -1:24, 0:4]) + +c: strings.ContainsAny("d") & strings.ContainsAny("g") +c: "dog" @test(eq, "dog") +-- out/compile -- +--- in.cue +{ + a: 〈import;strings〉.ContainsAny("ab") + a: "after" + b: 〈import;strings〉.ContainsAny("c") + b: "dog" + c: (〈import;strings〉.ContainsAny("d") & 〈import;strings〉.ContainsAny("g")) + c: "dog" +} diff --git a/internal/core/compile/testdata/sync/resolve/014_null_coalescing.txtar b/internal/core/compile/testdata/sync/resolve/014_null_coalescing.txtar new file mode 100644 index 000000000..795527a28 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/014_null_coalescing.txtar @@ -0,0 +1,11 @@ +-- in.cue -- +a: null @test(eq, null) +b: a.x | "b" @test(eq, "b") +c: a["x"] | "c" @test(eq, "c") +-- out/compile -- +--- in.cue +{ + a: null + b: (〈0;a〉.x|"b") + c: (〈0;a〉["x"]|"c") +} diff --git a/internal/core/compile/testdata/sync/resolve/016_index.txtar b/internal/core/compile/testdata/sync/resolve/016_index.txtar new file mode 100644 index 000000000..97201970f --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/016_index.txtar @@ -0,0 +1,71 @@ +-- in.cue -- +a: [2][0] @test(eq, 2) +b: {foo: "bar"}["foo"] @test(eq, "bar") +c: (*l | {"3": 3})["3"] @test(err, code=eval, contains="undefined field", pos=[0:20]) +d: (*[] | [1])[0] @test(err, code=eval, contains="index out of range [0]", pos=[0:16]) +l: [] @test(eq, []) + +e1: [2][""] @test(err, code=eval, contains="undefined field", pos=[0:9]) +e2: 2[2] @test(err, code=eval, contains="invalid operand 2", pos=[0:5]) +e3: [][true] @test(err, code=eval, contains="invalid index true", pos=[0:5, 0:8]) +e4: [1, 2, 3][3] @test(err, code=eval, contains="index out of range [3]", pos=[0:15]) +e5: [1, 2, 3][-1] @test(err, code=eval, contains="invalid index -1", pos=[0:5, 0:15]) +e6: (*[] | {})[1] @test(err, code=eval, contains="index out of range [1]", pos=[0:16]) +e7: [1, 2, 3][3] @test(err, code=eval, contains="index out of range [3]", pos=[0:15]) +e8: [1, 2, 3][-1] @test(err, code=eval, contains="invalid index -1", pos=[0:5, 0:15]) +e9: (*[] | {})[1] @test(err, code=eval, contains="index out of range [1]", pos=[0:16]) + +def: { + a: 1 + #b: 3 +} @test(eq, {a: 1, #b: 3}) +e10: def["b"] @test(err, code=incomplete, contains="undefined field: b", pos=[0:10]) +-- out/compile -- +--- in.cue +{ + a: [ + 2, + ][0] + b: { + foo: "bar" + }["foo"] + c: (*〈0;l〉|{ + "3": 3 + })["3"] + d: (*[]|[ + 1, + ])[0] + l: [] + e1: [ + 2, + ][""] + e2: 2[2] + e3: [][true] + e4: [ + 1, + 2, + 3, + ][3] + e5: [ + 1, + 2, + 3, + ][-1] + e6: (*[]|{})[1] + e7: [ + 1, + 2, + 3, + ][3] + e8: [ + 1, + 2, + 3, + ][-1] + e9: (*[]|{})[1] + def: { + a: 1 + #b: 3 + } + e10: 〈0;def〉["b"] +} diff --git a/internal/core/compile/testdata/sync/resolve/017_disjunctions_of_lists.txtar b/internal/core/compile/testdata/sync/resolve/017_disjunctions_of_lists.txtar new file mode 100644 index 000000000..b73a1d4e0 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/017_disjunctions_of_lists.txtar @@ -0,0 +1,24 @@ +-- in.cue -- +l: [ int, int] | [ string, string] @test(eq, [int, int] | [string, string]) + +l1: ["a", "b"] @test(eq, ["a", "b"]) +l2: l & ["c", "d"] @test(eq, ["c", "d"]) +-- out/compile -- +--- in.cue +{ + l: ([ + int, + int, + ]|[ + string, + string, + ]) + l1: [ + "a", + "b", + ] + l2: (〈0;l〉 & [ + "c", + "d", + ]) +} diff --git a/internal/core/compile/testdata/sync/resolve/018_slice.txtar b/internal/core/compile/testdata/sync/resolve/018_slice.txtar new file mode 100644 index 000000000..394dbe3da --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/018_slice.txtar @@ -0,0 +1,37 @@ +-- in.cue -- +a: [2][0:0] @test(eq, []) +b: [0][1:1] @test(eq, []) +e1: [][1:1] @test(err, code=eval, contains="index 1 out of range", pos=[0:5]) +e2: [0][-1:0] @test(err, code=eval, contains="cannot convert negative number", pos=[0:5]) +e3: [0][1:0] @test(err, code=eval, contains="invalid slice index", pos=[0:5]) +e4: [0][1:2] @test(err, code=eval, contains="index 2 out of range", pos=[0:5]) +e5: 4[1:2] @test(err, code=eval, contains="cannot slice 4", pos=[0:5]) +e6: [2]["":] @test(err, code=eval, contains="cannot use \"\"", pos=[0:5, 0:9]) +e7: [2][:"9"] @test(err, code=eval, contains="cannot use \"9\"", pos=[0:5, 0:10]) +-- out/compile -- +--- in.cue +{ + a: [ + 2, + ][0:0] + b: [ + 0, + ][1:1] + e1: [][1:1] + e2: [ + 0, + ][-1:0] + e3: [ + 0, + ][1:0] + e4: [ + 0, + ][1:2] + e5: 4[1:2] + e6: [ + 2, + ]["":] + e7: [ + 2, + ][:"9"] +} diff --git a/internal/core/compile/testdata/sync/resolve/022_list_unification.txtar b/internal/core/compile/testdata/sync/resolve/022_list_unification.txtar new file mode 100644 index 000000000..bd5d8e10f --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/022_list_unification.txtar @@ -0,0 +1,20 @@ +-- in.cue -- +a: {l: ["foo", v], v: l[1]} @test(eq, {l: ["foo", _], v: _}) +b: a & {l: [_, "bar"]} @test(eq, {l: ["foo", "bar"], v: "bar"}) +-- out/compile -- +--- in.cue +{ + a: { + l: [ + "foo", + 〈1;v〉, + ] + v: 〈0;l〉[1] + } + b: (〈0;a〉 & { + l: [ + _, + "bar", + ] + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/023_correct_error_messages.txtar b/internal/core/compile/testdata/sync/resolve/023_correct_error_messages.txtar new file mode 100644 index 000000000..e1c7404ea --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/023_correct_error_messages.txtar @@ -0,0 +1,8 @@ +-- in.cue -- +a: "a" & 1 @test(err, code=eval, contains="conflicting values", + args=["a", 1], pos=[0:4, 0:10]) +-- out/compile -- +--- in.cue +{ + a: ("a" & 1) +} diff --git a/internal/core/compile/testdata/sync/resolve/024_structs.txtar b/internal/core/compile/testdata/sync/resolve/024_structs.txtar new file mode 100644 index 000000000..2e6485e3b --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/024_structs.txtar @@ -0,0 +1,28 @@ +-- in.cue -- +a: t & {c: 5} @test(eq, {c: 5, d: 15}) // {c:5,d:15} +b: ti & {c: 7} @test(eq, {c: 7, d: 21}) // {c:7,d:21} +t: { + c: number + d: c * 3 @test(err, code=incomplete, contains="non-concrete value number in operand to *", pos=[0:5, -1:5]) +} +ti: t & {c: int} @test(eq, { + c: int + d: _|_ @test(err, code=incomplete, contains="non-concrete value number in operand to *", pos=[5:5 4:5 7:13]) +}) +-- out/compile -- +--- in.cue +{ + a: (〈0;t〉 & { + c: 5 + }) + b: (〈0;ti〉 & { + c: 7 + }) + t: { + c: number + d: (〈0;c〉 * 3) + } + ti: (〈0;t〉 & { + c: int + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/025_definitions.txtar b/internal/core/compile/testdata/sync/resolve/025_definitions.txtar new file mode 100644 index 000000000..ace01afa5 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/025_definitions.txtar @@ -0,0 +1,86 @@ +-- in.cue -- +#Foo: { + field: int + recursive: { + field: string + } + + @test(eq, {field: int, recursive: {field: string}}) + @test(closed) +} + +// Allowed +#Foo1: {field: int} +#Foo1: {field2: string} @test(eq, {field: int, field2: string}) @test(closed) + +foo: #Foo +foo: {feild: 2} @test(err, code=eval, contains="field not allowed", pos=[0:7]) + +foo1: #Foo +foo1: { + field: 2 @test(eq, 2) + recursive: { + feild: 2 @test(err, code=eval, contains="field not allowed", pos=[0:3]) + } +} + +#Bar: { + field: int + {[A=_]: int} + + @test(eq, {field: int, [_]: int}) + @test(closed) +} +bar: #Bar +bar: {feild: 2} @test(eq, {feild: 2, field: int}) + +#Mixed: string +Mixed: string + +mixedRec: {#Mixed: string} +mixedRec: {Mixed: string} @test(eq, {#Mixed: string, Mixed: string}) +-- out/compile -- +--- in.cue +{ + #Foo: { + field: int + recursive: { + field: string + } + } + #Foo1: { + field: int + } + #Foo1: { + field2: string + } + foo: 〈0;#Foo〉 + foo: { + feild: 2 + } + foo1: 〈0;#Foo〉 + foo1: { + field: 2 + recursive: { + feild: 2 + } + } + #Bar: { + field: int + { + [_]: int + } + } + bar: 〈0;#Bar〉 + bar: { + feild: 2 + } + #Mixed: string + Mixed: string + mixedRec: { + #Mixed: string + } + mixedRec: { + Mixed: string + } +} diff --git a/internal/core/compile/testdata/sync/resolve/027_new-style_definitions.txtar b/internal/core/compile/testdata/sync/resolve/027_new-style_definitions.txtar new file mode 100644 index 000000000..989017669 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/027_new-style_definitions.txtar @@ -0,0 +1,30 @@ +-- in.cue -- +#Foo: { + a: 1 + b: int +} @test(eq, {a: 1, b: int}) @test(closed) +"#Foo": #Foo & {b: 1} @test(eq, {b: 1, a: 1}) @test(closed) + +bulk: {[string]: string} & { + #def: 4 // Different namespace, so bulk option does not apply. + _hid: 3 + a: "foo" +} @test(eq, {#def: 4, _hid: 3, a: "foo"}) +-- out/compile -- +--- in.cue +{ + #Foo: { + a: 1 + b: int + } + "#Foo": (〈0;#Foo〉 & { + b: 1 + }) + bulk: ({ + [string]: string + } & { + #def: 4 + _hid: 3 + a: "foo" + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar b/internal/core/compile/testdata/sync/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar new file mode 100644 index 000000000..894dff77f --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar @@ -0,0 +1,68 @@ +-- in.cue -- +#S: { + [string]: {a: int} +} @test(eq, {}) @test(closed) +a: #S & { + v: {b: int} +} @test(err, code=eval, at=v.b, contains="field not allowed", pos=[1:6]) +#Q: { + [string]: {a: int} | {b: int} +} @test(eq, {}) @test(closed) +b: #Q & { + w: {c: int} +} @test(err, code=eval, at=w, contains="field not allowed", pos=[1:6]) +// NOTE: the above test is marked at w, not w.c, because it fails both +// disjunctions. We probably want to record it at c, or at least give a better +// error message. +@test(err:todo, code=eval, at=b.w.c, contains="field not allowed") + +#R: { + [string]: [{a: int}, {b: int}] +} @test(eq, {}) @test(closed) +c: #R & { + w: [{d: int}, ...] +} @test(err, code=eval, at=w.0.d, contains="field not allowed", pos=[1:7]) +-- out/compile -- +--- in.cue +{ + #S: { + [string]: { + a: int + } + } + a: (〈0;#S〉 & { + v: { + b: int + } + }) + #Q: { + [string]: ({ + a: int + }|{ + b: int + }) + } + b: (〈0;#Q〉 & { + w: { + c: int + } + }) + #R: { + [string]: [ + { + a: int + }, + { + b: int + }, + ] + } + c: (〈0;#R〉 & { + w: [ + { + d: int + }, + ..., + ] + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/030_definitions_with_disjunctions.txtar b/internal/core/compile/testdata/sync/resolve/030_definitions_with_disjunctions.txtar new file mode 100644 index 000000000..dfae142ca --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/030_definitions_with_disjunctions.txtar @@ -0,0 +1,40 @@ +-- in.cue -- +#Foo: { + field: int + + {a: 1} | + {b: 2} +} @test(eq, {field: int, a: 1} | {field: int, b: 2}) + +foo: #Foo +foo: {a: 1} @test(eq, {a: 1, field: int}) + +bar: #Foo +bar: {c: 2} @test(err, code=eval, contains="field not allowed", pos=[0:7]) + +baz: #Foo +baz: {b: 2} @test(eq, {b: 2, field: int}) +-- out/compile -- +--- in.cue +{ + #Foo: { + field: int + ({ + a: 1 + }|{ + b: 2 + }) + } + foo: 〈0;#Foo〉 + foo: { + a: 1 + } + bar: 〈0;#Foo〉 + bar: { + c: 2 + } + baz: 〈0;#Foo〉 + baz: { + b: 2 + } +} diff --git a/internal/core/compile/testdata/sync/resolve/031_definitions_with_disjunctions_recurisive.txtar b/internal/core/compile/testdata/sync/resolve/031_definitions_with_disjunctions_recurisive.txtar new file mode 100644 index 000000000..bec9baf94 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/031_definitions_with_disjunctions_recurisive.txtar @@ -0,0 +1,29 @@ +-- in.cue -- +#Foo: { + x: { + field: int + + {a: 1} | + {b: 2} + } + x: c: 3 +} @test(eq, { + x: {field: int, c: 3, a: 1} | {field: int, c: 3, b: 2} +}) +-- out/compile -- +--- in.cue +{ + #Foo: { + x: { + field: int + ({ + a: 1 + }|{ + b: 2 + }) + } + x: { + c: 3 + } + } +} diff --git a/internal/core/compile/testdata/sync/resolve/033_top-level_definition_with_struct_and_disjunction.txtar b/internal/core/compile/testdata/sync/resolve/033_top-level_definition_with_struct_and_disjunction.txtar new file mode 100644 index 000000000..70db58228 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/033_top-level_definition_with_struct_and_disjunction.txtar @@ -0,0 +1,30 @@ +-- in.cue -- +#def: { + Type: string + Text: string + Size: int +} + +#def: { + Type: "B" + Size: 0 +} | { + Type: "A" + Size: 1 +} @test(eq, {Type: "B", Text: string, Size: 0} | {Type: "A", Text: string, Size: 1}) +-- out/compile -- +--- in.cue +{ + #def: { + Type: string + Text: string + Size: int + } + #def: ({ + Type: "B" + Size: 0 + }|{ + Type: "A" + Size: 1 + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/034_closing_structs.txtar b/internal/core/compile/testdata/sync/resolve/034_closing_structs.txtar new file mode 100644 index 000000000..90a1139a6 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/034_closing_structs.txtar @@ -0,0 +1,50 @@ +-- in.cue -- +op: {x: int} @test(eq, {x: int}) // {x: int} +ot: {x: int, ...} @test(eq, {x: int}) // {x: int, ...} +cp: close({x: int}) @test(eq, {x: int}) @test(closed) // closed({x: int}) +ct: close({x: int, ...}) @test(eq, {x: int}) @test(closed) @test(shareID=ctct) @test(allows, string) + +opot: op & ot @test(eq, {x: int}) // {x: int, ...} +otop: ot & op @test(eq, {x: int}) // {x: int, ...} +opcp: op & cp @test(eq, {x: int}) @test(closed) @test(allows=false, string) +cpop: cp & op @test(eq, {x: int}) @test(closed) @test(allows=false, string) +opct: op & ct @test(eq, {x: int}) @test(closed) @test(allows, string) +ctop: ct & op @test(eq, {x: int}) @test(closed) @test(allows, string) +otcp: ot & cp @test(eq, {x: int}) @test(closed) @test(allows, string) @test(allows:todo=false, string) +cpot: cp & ot @test(eq, {x: int}) @test(closed) @test(allows, string) @test(allows:todo=false, string) +otct: ot & ct @test(eq, {x: int}) @test(closed) @test(allows, string) +ctot: ct & ot @test(eq, {x: int}) @test(closed) @test(allows, string) +cpct: cp & ct @test(eq, {x: int}) @test(closed) @test(allows, string) @test(allows:todo=false, string) +ctcp: ct & cp @test(eq, {x: int}) @test(closed) @test(allows, string) @test(allows:todo=false, string) +ctct: ct & ct @test(eq, {x: int}) @test(closed) @test(shareID=ctct) @test(allows, string) +-- out/compile -- +--- in.cue +{ + op: { + x: int + } + ot: { + x: int + ... + } + cp: close({ + x: int + }) + ct: close({ + x: int + ... + }) + opot: (〈0;op〉 & 〈0;ot〉) + otop: (〈0;ot〉 & 〈0;op〉) + opcp: (〈0;op〉 & 〈0;cp〉) + cpop: (〈0;cp〉 & 〈0;op〉) + opct: (〈0;op〉 & 〈0;ct〉) + ctop: (〈0;ct〉 & 〈0;op〉) + otcp: (〈0;ot〉 & 〈0;cp〉) + cpot: (〈0;cp〉 & 〈0;ot〉) + otct: (〈0;ot〉 & 〈0;ct〉) + ctot: (〈0;ct〉 & 〈0;ot〉) + cpct: (〈0;cp〉 & 〈0;ct〉) + ctcp: (〈0;ct〉 & 〈0;cp〉) + ctct: (〈0;ct〉 & 〈0;ct〉) +} diff --git a/internal/core/compile/testdata/sync/resolve/035_excluded_embedding_from_closing.txtar b/internal/core/compile/testdata/sync/resolve/035_excluded_embedding_from_closing.txtar new file mode 100644 index 000000000..07cdaa04e --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/035_excluded_embedding_from_closing.txtar @@ -0,0 +1,45 @@ +-- in.cue -- +#S: { + a: {c: int} + { + c: {d: int} + } + let B = {open: int} + b: B +} @test(eq, { + a: {c: int} + c: {d: int} + b: {open: int} +}) +V: #S & { + c: e: int + b: extra: int +} +@test(err, code=eval, at=V.b.extra, contains="field not allowed", pos=[-2:5]) +@test(err, code=eval, at=V.c.e, contains="field not allowed", pos=[-4:5]) +-- out/compile -- +--- in.cue +{ + #S: { + a: { + c: int + } + { + c: { + d: int + } + } + let B#1 = { + open: int + } + b: 〈0;let B#1〉 + } + V: (〈0;#S〉 & { + c: { + e: int + } + b: { + extra: int + } + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/038_incomplete_comprehensions.txtar b/internal/core/compile/testdata/sync/resolve/038_incomplete_comprehensions.txtar new file mode 100644 index 000000000..b04186487 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/038_incomplete_comprehensions.txtar @@ -0,0 +1,38 @@ +-- in.cue -- +A: { + for v in src { + "\(v)": v + } + src: _ + if true { + baz: "baz" + } + @test(err, code=incomplete, contains="cannot range over src", pos=[1:11]) +} +B: A & { + src: ["foo", "bar"] +} @test(eq, { + src: ["foo", "bar"] + baz: "baz" + foo: "foo" + bar: "bar" +}) +-- out/compile -- +--- in.cue +{ + A: { + for _, v in 〈0;src〉 { + "\(〈1;v〉)": 〈1;v〉 + } + src: _ + if true { + baz: "baz" + } + } + B: (〈0;A〉 & { + src: [ + "foo", + "bar", + ] + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/039_reference_to_root.txtar b/internal/core/compile/testdata/sync/resolve/039_reference_to_root.txtar new file mode 100644 index 000000000..37bb7b38f --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/039_reference_to_root.txtar @@ -0,0 +1,48 @@ +-- in.cue -- +a: {b: int} @test(eq, {b: int}) +c: a & { + b: 100 + d: a.b + 3 // do not resolve as c != a. +} @test(eq, {b: 100, d: _|_ @test(err, + code=incomplete, contains="non-concrete value int in operand to +", pos=[4:5, 1:8])}) +x: { + b: int + c: b + 5 @test(err, code=incomplete, contains="non-concrete value int in operand to +", pos=[0:5, -1:5]) + @test(eq, {b: int, c: _|_}) +} +y: x & {b: 100} @test(eq, {b: 100, c: 105}) // c should resolve to 105 +v: { + b: int + c: v.b + 5 @test(err, code=incomplete, contains="non-concrete value int in operand to +", pos=[0:5, -1:5]) // reference starting from copied node. + @test(eq, {b: int, c: _|_}) +} +w: v & {b: 100} @test(eq, {b: 100, c: _|_}) +wp: v & {b: 100} @test(eq, {b: 100, c: _|_}) +-- out/compile -- +--- in.cue +{ + a: { + b: int + } + c: (〈0;a〉 & { + b: 100 + d: (〈1;a〉.b + 3) + }) + x: { + b: int + c: (〈0;b〉 + 5) + } + y: (〈0;x〉 & { + b: 100 + }) + v: { + b: int + c: (〈1;v〉.b + 5) + } + w: (〈0;v〉 & { + b: 100 + }) + wp: (〈0;v〉 & { + b: 100 + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/040_references_from_template_to_concrete.txtar b/internal/core/compile/testdata/sync/resolve/040_references_from_template_to_concrete.txtar new file mode 100644 index 000000000..a829ef4e8 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/040_references_from_template_to_concrete.txtar @@ -0,0 +1,40 @@ +-- in.cue -- +res: [t] @test(eq, [{ + x: { + a: "XDDDD" + b: str: "DDDD" + c: "X" + } +}]) +@test(shareID=T, at=res[0]) +@test(shareID=T, at=t) +t: [X=string]: { + a: c + b.str + b: str: string + c: "X" +} +t: x: {b: str: "DDDD"} @test(eq, {b: {str: "DDDD"}, a: "XDDDD", c: "X"}) + +-- out/compile -- +--- in.cue +{ + res: [ + 〈1;t〉, + ] + t: { + [string]: { + a: (〈0;c〉 + 〈0;b〉.str) + b: { + str: string + } + c: "X" + } + } + t: { + x: { + b: { + str: "DDDD" + } + } + } +} diff --git a/internal/core/compile/testdata/sync/resolve/043_diamond-shaped_constraints.txtar b/internal/core/compile/testdata/sync/resolve/043_diamond-shaped_constraints.txtar new file mode 100644 index 000000000..0e0b98047 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/043_diamond-shaped_constraints.txtar @@ -0,0 +1,38 @@ +-- in.cue -- +S: { + A: { + a: 1 + } + B: A & { + b: 2 + } + @test(eq, {A: {a: 1}, B: {b: 2, a: 1}}) +} +T: S & {// S == { A: { a:1 }, B: { a:1, b:2 } } + A: { + c: 3 + } + B: { + d: 4 // Combines constraints S.A, S.B, T.A, and T.B // S.B & A + } +} @test(eq, {A: {c: 3, a: 1}, B: {d: 4, b: 2, c: 3, a: 1}}) +-- out/compile -- +--- in.cue +{ + S: { + A: { + a: 1 + } + B: (〈0;A〉 & { + b: 2 + }) + } + T: (〈0;S〉 & { + A: { + c: 3 + } + B: { + d: 4 + } + }) +} diff --git a/internal/core/compile/testdata/sync/resolve/044_field_templates.txtar b/internal/core/compile/testdata/sync/resolve/044_field_templates.txtar new file mode 100644 index 000000000..fc6ff0027 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/044_field_templates.txtar @@ -0,0 +1,57 @@ +-- in.cue -- +a: { + {[name=_]: int} + k: 1 +} @test(eq, {k: 1}) +b: { + {[X=_]: {x: 0, y: *1 | int}} + v: {} + w: {x: 0} +} +b: {[y=_]: {}} @test(eq, { + v: {x: 0, y: *1 | int} + w: {x: 0, y: *1 | int} +}) +c: { + {[Name=_]: {name: Name, y: 1}} + foo: {} + bar: _ +} @test(eq, { + foo: {name: "foo", y: 1} + bar: {name: "bar", y: 1} +}) +-- out/compile -- +--- in.cue +{ + a: { + { + [_]: int + } + k: 1 + } + b: { + { + [_]: { + x: 0 + y: (*1|int) + } + } + v: {} + w: { + x: 0 + } + } + b: { + [_]: {} + } + c: { + { + [_]: { + name: 〈1;-〉 + y: 1 + } + } + foo: {} + bar: _ + } +} diff --git a/internal/core/compile/testdata/sync/resolve/045_range_unification.txtar b/internal/core/compile/testdata/sync/resolve/045_range_unification.txtar new file mode 100644 index 000000000..00d34d4ad --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/045_range_unification.txtar @@ -0,0 +1,85 @@ +-- in.cue -- +// with concrete values +a1: >=1 & <=5 & 3 @test(eq, 3) +a2: >=1 & <=5 & 1 @test(eq, 1) +a3: >=1 & <=5 & 5 @test(eq, 5) +a4: >=1 & <=5 & 6 @test(err, code=eval, contains="invalid value", args=[6], pos=[0:11, 0:17]) +a5: >=1 & <=5 & 0 @test(err, code=eval, contains="invalid value", args=[0], pos=[0:5, 0:17]) + +a6: 3 & >=1 & <=5 @test(eq, 3) +a7: 1 & >=1 & <=5 @test(eq, 1) +a8: 5 & >=1 & <=5 @test(eq, 5) +a9: 6 & >=1 & <=5 @test(err, code=eval, contains="invalid value", args=[6], pos=[0:16, 0:6]) +a10: 0 & >=1 & <=5 @test(err, code=eval, contains="invalid value", args=[0], pos=[0:10, 0:6]) + +// with ranges +b1: >=1 & <=5 & >=1 & <=5 @test(eq, >=1 & <=5) +b2: >=1 & <=5 & >=1 & <=1 @test(eq, >=1 & <=1) +b3: >=1 & <=5 & >=5 & <=5 @test(eq, >=5 & <=5) +b4: >=1 & <=5 & >=2 & <=3 @test(eq, >=2 & <=3) +b5: >=1 & <=5 & >=3 & <=9 @test(eq, >=3 & <=5) +b6: >=1 & <=5 & >=5 & <=9 @test(eq, >=5 & <=5) +b7: >=1 & <=5 & >=6 & <=9 @test(err, code=eval, contains="incompatible number bounds", pos=[0:17, 0:11]) + +b8: >=1 & <=5 & >=1 & <=5 @test(eq, >=1 & <=5) +b9: >=1 & <=1 & >=1 & <=5 @test(eq, >=1 & <=1) +b10: >=5 & <=5 & >=1 & <=5 @test(eq, >=5 & <=5) +b11: >=2 & <=3 & >=1 & <=5 @test(eq, >=2 & <=3) +b12: >=3 & <=9 & >=1 & <=5 @test(eq, >=3 & <=5) +b13: >=5 & <=9 & >=1 & <=5 @test(eq, >=5 & <=5) +b14: >=6 & <=9 & >=1 & <=5 @test(err, code=eval, contains="incompatible number bounds", pos=[0:24, 0:6]) + +// ranges with more general types +c1: int & >=1 & <=5 @test(eq, >=1 & <=5 & int) +c2: >=1 & <=5 & int @test(eq, >=1 & <=5 & int) +c3: string & >=1 & <=5 @test(err, code=eval, contains="conflicting values", args=[string, >=1], pos=[0:5, 0:14]) +c4: >=1 & <=5 & string @test(err, code=eval, contains="conflicting values", args=[string, >=1], pos=[0:5, 0:17]) + +// other types +s1: >="d" & <="z" & "e" @test(eq, "e") +s2: >="d" & <="z" & "ee" @test(eq, "ee") + +n1: number & >=1 & <=2 @test(eq, >=1 & <=2) +n2: int & >=1.1 & <=1.3 @test(err, code=eval, contains="incompatible integer bounds", pos=[0:19, 0:11]) +n3: >=1.0 & <=3.0 & 2 @test(eq, 2) +n4: >=0.0 & <=0.1 & 0.09999 @test(eq, 0.09999) +n5: >=1 & <=5 & 2.5 @test(eq, 2.5) +-- out/compile -- +--- in.cue +{ + a1: ((>=1 & <=5) & 3) + a2: ((>=1 & <=5) & 1) + a3: ((>=1 & <=5) & 5) + a4: ((>=1 & <=5) & 6) + a5: ((>=1 & <=5) & 0) + a6: ((3 & >=1) & <=5) + a7: ((1 & >=1) & <=5) + a8: ((5 & >=1) & <=5) + a9: ((6 & >=1) & <=5) + a10: ((0 & >=1) & <=5) + b1: (((>=1 & <=5) & >=1) & <=5) + b2: (((>=1 & <=5) & >=1) & <=1) + b3: (((>=1 & <=5) & >=5) & <=5) + b4: (((>=1 & <=5) & >=2) & <=3) + b5: (((>=1 & <=5) & >=3) & <=9) + b6: (((>=1 & <=5) & >=5) & <=9) + b7: (((>=1 & <=5) & >=6) & <=9) + b8: (((>=1 & <=5) & >=1) & <=5) + b9: (((>=1 & <=1) & >=1) & <=5) + b10: (((>=5 & <=5) & >=1) & <=5) + b11: (((>=2 & <=3) & >=1) & <=5) + b12: (((>=3 & <=9) & >=1) & <=5) + b13: (((>=5 & <=9) & >=1) & <=5) + b14: (((>=6 & <=9) & >=1) & <=5) + c1: ((int & >=1) & <=5) + c2: ((>=1 & <=5) & int) + c3: ((string & >=1) & <=5) + c4: ((>=1 & <=5) & string) + s1: ((>="d" & <="z") & "e") + s2: ((>="d" & <="z") & "ee") + n1: ((number & >=1) & <=2) + n2: ((int & >=1.1) & <=1.3) + n3: ((>=1.0 & <=3.0) & 2) + n4: ((>=0.0 & <=0.1) & 0.09999) + n5: ((>=1 & <=5) & 2.5) +} diff --git a/internal/core/compile/testdata/sync/resolve/046_predefined_ranges.txtar b/internal/core/compile/testdata/sync/resolve/046_predefined_ranges.txtar new file mode 100644 index 000000000..682860f25 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/046_predefined_ranges.txtar @@ -0,0 +1,24 @@ +#inlinetest:exclude skip — tests the debug printer, not evaluator semantics +-- in.cue -- +k1: int8 +k1: 44 + +k2: int64 +k2: -8_000_000_000 + +s1: int8 +s2: uint16 +s3: float32 +s4: uint +-- out/compile -- +--- in.cue +{ + k1: &(int, >=-128, <=127) + k1: 44 + k2: &(int, >=-9223372036854775808, <=9223372036854775807) + k2: -8000000000 + s1: &(int, >=-128, <=127) + s2: &(int, >=0, <=65535) + s3: &(>=-340282346638528859811704183484516925440, <=340282346638528859811704183484516925440) + s4: &(int, >=0) +} diff --git a/internal/core/compile/testdata/sync/resolve/046_predefined_ranges_error.txtar b/internal/core/compile/testdata/sync/resolve/046_predefined_ranges_error.txtar new file mode 100644 index 000000000..da918c336 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/046_predefined_ranges_error.txtar @@ -0,0 +1,9 @@ +-- in.cue -- +e1: int16 +e1: 100_000 @test(err, code=eval, contains="invalid value 100000", pos=[0:5]) +-- out/compile -- +--- in.cue +{ + e1: &(int, >=-32768, <=32767) + e1: 100000 +} diff --git a/internal/core/compile/testdata/sync/resolve/047_struct_comprehensions.txtar b/internal/core/compile/testdata/sync/resolve/047_struct_comprehensions.txtar new file mode 100644 index 000000000..01a6f9508 --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/047_struct_comprehensions.txtar @@ -0,0 +1,49 @@ +#name: struct comprehensions +#evalPartial +-- in.cue -- +obj: foo: a: "bar" +obj: [Name=string]: { + a: *"dummy" | string + if true { + sub: as: a + } +} + +for k, v in {#def: 1, opt?: 2, _hid: 3, reg: 4} { + "\(k)": v +} +@test(eq, { + obj: foo: { + a: "bar" + sub: as: "bar" + }, + reg: 4 +}) + +-- out/compile -- +--- in.cue +{ + obj: { + foo: { + a: "bar" + } + } + obj: { + [string]: { + a: (*"dummy"|string) + if true { + sub: { + as: 〈2;a〉 + } + } + } + } + for k, v in { + #def: 1 + opt?: 2 + _hid: 3 + reg: 4 + } { + "\(〈1;k〉)": 〈1;v〉 + } +} diff --git a/internal/core/compile/testdata/sync/resolve/048_builtins.txtar b/internal/core/compile/testdata/sync/resolve/048_builtins.txtar new file mode 100644 index 000000000..fa6ec90bd --- /dev/null +++ b/internal/core/compile/testdata/sync/resolve/048_builtins.txtar @@ -0,0 +1,202 @@ +-- in.cue -- +import ( + "list" + "strings" +) + +a1: { + a: and([b, c]) + b: =~"oo" + c: =~"fo" +} @test(eq, { + a: =~"oo" & =~"fo" + b: =~"oo" + c: =~"fo" +}) +a2: a1 & {a: "foo"} @test(eq, {a: "foo", b: =~"oo", c: =~"fo"}) +a3: a1 & {a: "bar"} @test(err, code=eval, + suberr=(code=eval, contains="invalid value", args=["bar", =~"oo"], pos=[-8:5, -9:5, 0:14]), + suberr=(code=eval, contains="invalid value", args=["bar", =~"fo"], pos=[-7:5, -9:5, 0:14])) + +o1: { + a: or([b, c]) + b: string + c: "bar" +} @test(eq, {a: string | "bar", b: string, c: "bar"}) +o2: o1 & {a: "foo"} @test(eq, {a: "foo", b: string, c: "bar"}) +o3: o1 & {a: "foo", b: "baz"} @test(err, code=eval, + suberr=(code=eval, contains="conflicting values", args=["bar", "foo"], pos=[-5:12, -3:5, 0:5, 0:14]), + suberr=(code=eval, contains="conflicting values", args=["baz", "foo"], pos=[-5:9, 0:5, 0:14, 0:24])) + +// Issue #585 +stringListErrors: { + a: { + x: [string, ...string] + result: strings.Join(x, " ") @test(err, code=incomplete, + contains="non-concrete value string for element", pos=[0:11, -1:7]) + } + + b: { + x: [int, ...string] + result: strings.Join(x, " ") @test(err, code=eval, + contains="cannot use value int (int) as string", pos=[0:11, -1:7]) + } + + c: { + x: [] + result: strings.Join(x, int) @test(err, code=eval, + contains="cannot use int (type int) as string in argument 2 to strings.Join", + pos=[0:27]) + } +} + +decimalListErrors: { + a: { + x: [string] + result: list.Avg(x) @test(err, code=eval, + contains="invalid list element", pos=[0:11, -1:7]) + // TODO: allow checking wrapped errors: args=[string, number], + } + + b: { + x: [int, ...string] + result: list.Avg(x) @test(err, code=incomplete, + contains="non-concrete value int for element 0 of number list argument 0", pos=[0:11, -1:7]) + } +} +-- issue3648.cue -- +// Fully finalize values before passing them to builtins. + +// "not properly initialized" error regression in evalv3 involving builtins: +// list.Concat received an unfinalized value when called from a pattern constraint. +// https://cuelang.org/issue/3648 +import "list" + +issue3648: reduced: { + [string]: { + a: list.Concat([b]) + b: [{}] + } + foo: {} + + @test(eq, {foo: {a: [{}], b: [{}]}}) +} +issue3648: full: { + #Redirect: path?: string + + [string]: { + // Note that this bug disappears if the order of the fields below is swapped. + allRedirects: list.Concat([redirects]) + redirects: [...#Redirect] + } + foo: {} + + @test(eq, { + #Redirect: {path?: string} + [string]: { + allRedirects: list.Concat([[]]) + redirects: [] + } + foo: {allRedirects: [], redirects: []} + }) +} +-- out/compile -- +--- in.cue +{ + a1: { + a: and([ + 〈1;b〉, + 〈1;c〉, + ]) + b: =~"oo" + c: =~"fo" + } + a2: (〈0;a1〉 & { + a: "foo" + }) + a3: (〈0;a1〉 & { + a: "bar" + }) + o1: { + a: or([ + 〈1;b〉, + 〈1;c〉, + ]) + b: string + c: "bar" + } + o2: (〈0;o1〉 & { + a: "foo" + }) + o3: (〈0;o1〉 & { + a: "foo" + b: "baz" + }) + stringListErrors: { + a: { + x: [ + string, + ...string, + ] + result: 〈import;strings〉.Join(〈0;x〉, " ") + } + b: { + x: [ + int, + ...string, + ] + result: 〈import;strings〉.Join(〈0;x〉, " ") + } + c: { + x: [] + result: 〈import;strings〉.Join(〈0;x〉, int) + } + } + decimalListErrors: { + a: { + x: [ + string, + ] + result: 〈import;list〉.Avg(〈0;x〉) + } + b: { + x: [ + int, + ...string, + ] + result: 〈import;list〉.Avg(〈0;x〉) + } + } +} +--- issue3648.cue +{ + issue3648: { + reduced: { + [string]: { + a: 〈import;list〉.Concat([ + 〈1;b〉, + ]) + b: [ + {}, + ] + } + foo: {} + } + } + issue3648: { + full: { + #Redirect: { + path?: string + } + [string]: { + allRedirects: 〈import;list〉.Concat([ + 〈1;redirects〉, + ]) + redirects: [ + ...〈2;#Redirect〉, + ] + } + foo: {} + } + } +} diff --git a/internal/core/compile/testdata/sync/scalars/embed.txtar b/internal/core/compile/testdata/sync/scalars/embed.txtar new file mode 100644 index 000000000..966146145 --- /dev/null +++ b/internal/core/compile/testdata/sync/scalars/embed.txtar @@ -0,0 +1,349 @@ +-- in.cue -- +// Issue #739: Tests that scalar values (integers, lists, strings) embedded in +// structs participate correctly in arithmetic, indexing, and built-in function +// calls (list.Concat, strings.Join). Also covers definitions and optional fields +// used alongside embedded scalars, and comprehensions gated on optional presence. +// +// Issue #794: Tests that a hidden field used as a list element inside an embedded +// struct resolves to its concrete value (hidden.issue794: _foo embedded as [_foo]). +import "strings" +import "list" + +intEmbed: { + a1: { + 2 + @test(eq, 2) + } + a2: { + v: { + 3 + #foo: a2.v + 1 + } + w: v + x: v.#foo + @test(eq, { + v: {3, #foo: 4} @test(shareID=a2vw) + w: {3, #foo: 4} @test(shareID=a2vw) + x: 4 + }) + } + a3: a1 + a2.v @test(eq, 5) +} + +listEmbed: { + a1: { + 2 + @test(eq, 2) + } + b3: { + [1, 2] + #foo: 1 + @test(eq, {[1, 2], #foo: 1}) + } + b4: list.Concat([b3, b3]) @test(eq, [1, 2, 1, 2]) + b5: b3[1] @test(eq, 2) + b6: b3[5] @test(err, code=eval, contains="index out of range [5] with length 2", pos=[0:9]) + b7: b4[a1] @test(eq, 1) +} + +stringEmbed: { + s1: { + "foo" + #bar: "bar" + @test(eq, {"foo", #bar: "bar"}) + } + s2: [ s1, {s1.#bar, #baz: 4}] @test(eq, [ + {"foo", #bar: "bar"}, + {"bar", #baz: 4}, + ]) + s3: strings.Join(s2, "--") @test(eq, "foo--bar") +} + +outPattern: { + sum: { + out: #a + #b + #a: int + #b: int + } + used: { + sum & {#a: 1, #b: 3} + @test(eq, { + out: 4 + #a: 1 + #b: 3 + }) + } +} + +arithmetic: { + sum: { + #a + #b + #a: int + #b: int + } + a1: (sum & {_, #a: 1, #b: 3}) + 2 @test(eq, 6) + a2: 2 + (sum & {_, #a: 1, #b: 3}) @test(eq, 6) + a3: 2 + (2 + (sum & {_, #a: 1, #b: 3})) @test(eq, 8) +} + +defCheck: { + a: { + #def: 1 + @test(eq, {#def: 1}) + } + b: a.#def @test(eq, 1) +} + +optionalExists: { + string | { + value?: string + + if value != _|_ { + other: int + } + } + @test(eq, { string } | {value?: string}) +} + +optionalCheck: { + thing: string | { + value?: string + + if value != _|_ { + other: int + } + } + + thing: { + value: "some string" + other: 3 + } @test(eq, { + value: "some string" + other: 3 + }) +} + +hidden: { + issue794: { + _foo: "foo" + [_foo] + @test(eq, { + _foo: "foo" + ["foo"] + }) + } +} + +-- issue2113.cue -- +// Issue #2113: Tests that embedded scalars inside a definition function (#fn with +// an embedded bare value) resolve correctly when the definition is specialized, +// regardless of which field is declared first. The @test(permute) exercises all +// declaration orders to confirm order-independence. +merged: t1: { + @test(permute, count=6) + + #fn: { #in2: _, _ } + #fn: { #in2: c1: string, #in2.c1 } + x: #fn & {#in2: {c1: "V 1"}, _} + @test(eq, { + #fn: { string, #in2: c1: string } + x: { + "V 1" + #in2: {c1: "V 1"} + } + }) +} + +-- issue2163.cue -- +// Issue #2163: Tests that a self-referencing embedded expression — a definition +// that embeds (#Func & {_foo: #in, "buzz"}) + "fiz", where the embedded result +// depends on an inner field — does not panic or produce a spurious error. +selfRefInEmbed: t1: { + #Func: { + #in: _ + _ + } + #fn: #Func + #fn: { + #in: _ + + (#Func & { + _foo: #in + "buzz" + }) + "fiz" + } + + @test(eq, { + #Func: { + _ + #in: _ + } + #fn: { + "buzzfiz" + #in: _ + } + }) +} + +-- out/compile -- +--- in.cue +{ + intEmbed: { + a1: { + 2 + } + a2: { + v: { + 3 + #foo: (〈2;a2〉.v + 1) + } + w: 〈0;v〉 + x: 〈0;v〉.#foo + } + a3: (〈0;a1〉 + 〈0;a2〉.v) + } + listEmbed: { + a1: { + 2 + } + b3: { + [ + 1, + 2, + ] + #foo: 1 + } + b4: 〈import;list〉.Concat([ + 〈1;b3〉, + 〈1;b3〉, + ]) + b5: 〈0;b3〉[1] + b6: 〈0;b3〉[5] + b7: 〈0;b4〉[〈0;a1〉] + } + stringEmbed: { + s1: { + "foo" + #bar: "bar" + } + s2: [ + 〈1;s1〉, + { + 〈2;s1〉.#bar + #baz: 4 + }, + ] + s3: 〈import;strings〉.Join(〈0;s2〉, "--") + } + outPattern: { + sum: { + out: (〈0;#a〉 + 〈0;#b〉) + #a: int + #b: int + } + used: { + (〈1;sum〉 & { + #a: 1 + #b: 3 + }) + } + } + arithmetic: { + sum: { + (〈0;#a〉 + 〈0;#b〉) + #a: int + #b: int + } + a1: ((〈0;sum〉 & { + _ + #a: 1 + #b: 3 + }) + 2) + a2: (2 + (〈0;sum〉 & { + _ + #a: 1 + #b: 3 + })) + a3: (2 + (2 + (〈0;sum〉 & { + _ + #a: 1 + #b: 3 + }))) + } + defCheck: { + a: { + #def: 1 + } + b: 〈0;a〉.#def + } + optionalExists: { + (string|{ + value?: string + if (〈0;value〉 != _|_(explicit error (_|_ literal) in source)) { + other: int + } + }) + } + optionalCheck: { + thing: (string|{ + value?: string + if (〈0;value〉 != _|_(explicit error (_|_ literal) in source)) { + other: int + } + }) + thing: { + value: "some string" + other: 3 + } + } + hidden: { + issue794: { + _foo: "foo" + [ + 〈1;_foo〉, + ] + } + } +} +--- issue2113.cue +{ + merged: { + t1: { + #fn: { + #in2: _ + _ + } + #fn: { + #in2: { + c1: string + } + 〈0;#in2〉.c1 + } + x: (〈0;#fn〉 & { + #in2: { + c1: "V 1" + } + _ + }) + } + } +} +--- issue2163.cue +{ + selfRefInEmbed: { + t1: { + #Func: { + #in: _ + _ + } + #fn: 〈0;#Func〉 + #fn: { + #in: _ + ((〈1;#Func〉 & { + _foo: 〈1;#in〉 + "buzz" + }) + "fiz") + } + } + } +} diff --git a/internal/core/compile/testdata/sync/scalars/embed_bound.txtar b/internal/core/compile/testdata/sync/scalars/embed_bound.txtar new file mode 100644 index 000000000..09cac0c6b --- /dev/null +++ b/internal/core/compile/testdata/sync/scalars/embed_bound.txtar @@ -0,0 +1,28 @@ +-- in.cue -- +// Embedding !=null at file scope should preserve the constraint, +// not collapse to (struct){}. + +a: { + !=null +} @test(eq, !=null) + +// As a field value, !=null is preserved. Verify parity. +b: !=null @test(eq, !=null) + +// !=null as embedding combined with a regular field. +c: { + !=null + x: 1 +} @test(eq, {x: 1}) +-- out/compile -- +--- in.cue +{ + a: { + !=null + } + b: !=null + c: { + !=null + x: 1 + } +} diff --git a/internal/core/compile/testdata/sync/scalars/emptystruct.txtar b/internal/core/compile/testdata/sync/scalars/emptystruct.txtar new file mode 100644 index 000000000..9dfad9b55 --- /dev/null +++ b/internal/core/compile/testdata/sync/scalars/emptystruct.txtar @@ -0,0 +1,195 @@ +// Tests that unifying a struct with an embedded scalar and definition fields +// against a definition (or disjunction of definitions) works correctly. +// The `ellipsis`, `bulk`, and `optional` groups cover open definitions with +// `...`, bulk constraints, and optional fields respectively. The `issue783` +// group covers the original bug: unifying such a struct against a disjunction +// of definitions (`{...} | {string, ...}`) was incorrectly failing or dropping +// disjunction branches. +// https://cuelang.org/issue/783 +-- in.cue -- +elipsis: { + test1: { + string + #foo: "bar" + } + + #Def: { + ... + #foo: string + _ + } + check: test1 & #Def + + @test(eq, { + test1: { + string + #foo: "bar" + } + #Def: { + #foo: string + _ + } + check: { + string + #foo: "bar" + } + }) +} + +bulk: { + test1: { + string + #foo: "bar" + } + + #Def: { + [string]: int + #foo: string + _ + } + check: test1 & #Def @test(eq, { + [string]: int + #foo: "bar" + string + }) @test(closed, hint="could be either") +} + +optional: { + test1: { + string + #foo: "bar" + } + + #Def: { + bar?: int + #foo: string + _ + } + check: test1 & #Def @test(eq, { + string + bar?: int + #foo: "bar" + }) +} + +// Tests that unifying a struct with an embedded scalar and definition fields +// against a definition (or disjunction of definitions) works correctly. +// The `ellipsis`, `bulk`, and `optional` groups cover open definitions with +// `...`, bulk constraints, and optional fields respectively. The `issue783` +// group covers the original bug: unifying such a struct against a disjunction +// of definitions (`{...} | {string, ...}`) was incorrectly failing or dropping +// disjunction branches. +// https://cuelang.org/issue/783 +issue783: { + test1: { + string + #foo: "bar" + } + + test2: { + hello: "world" + #foo: "bar" + } + + #Def1: { + ... + #foo: string + } | { + string + #foo: string + } @test(eq, { + #foo: string + } | { + string + #foo: string + }) + + check1a: test1 & #Def1 @test(eq, { + string + #foo: "bar" + }) + check1b: test2 & #Def1 @test(eq, { + hello: "world" + #foo: "bar" + }) + + #Def2: { + ... + #foo: string + _ + } + check2a: test1 & #Def2 @test(eq, { + string + #foo: "bar" + }) + check2b: test2 & #Def2 @test(eq, { + hello: "world" + #foo: "bar" + }) +} +-- out/compile -- +--- in.cue +{ + elipsis: { + test1: { + string + #foo: "bar" + } + #Def: { + ... + #foo: string + _ + } + check: (〈0;test1〉 & 〈0;#Def〉) + } + bulk: { + test1: { + string + #foo: "bar" + } + #Def: { + [string]: int + #foo: string + _ + } + check: (〈0;test1〉 & 〈0;#Def〉) + } + optional: { + test1: { + string + #foo: "bar" + } + #Def: { + bar?: int + #foo: string + _ + } + check: (〈0;test1〉 & 〈0;#Def〉) + } + issue783: { + test1: { + string + #foo: "bar" + } + test2: { + hello: "world" + #foo: "bar" + } + #Def1: ({ + ... + #foo: string + }|{ + string + #foo: string + }) + check1a: (〈0;test1〉 & 〈0;#Def1〉) + check1b: (〈0;test2〉 & 〈0;#Def1〉) + #Def2: { + ... + #foo: string + _ + } + check2a: (〈0;test1〉 & 〈0;#Def2〉) + check2b: (〈0;test2〉 & 〈0;#Def2〉) + } +} diff --git a/internal/core/compile/testdata/sync/scalars/yield.txtar b/internal/core/compile/testdata/sync/scalars/yield.txtar new file mode 100644 index 000000000..342e89939 --- /dev/null +++ b/internal/core/compile/testdata/sync/scalars/yield.txtar @@ -0,0 +1,55 @@ +// Issue #729 +-- in.cue -- +ifScalar: { + _#cond: true + + if _#cond {5} + @test(eq, { + 5 + _#cond: true + }) +} + +ifScalarConflict: { + _#cond: true + + if _#cond {5} + + "soo" + @test(err, code=eval, contains="conflicting values", args=["soo", 5, string, int], pos=[0:19, 3:2, 3:13, 5:2]) +} + +ifScalarNested: { + _#cond: true + + if _#cond {{{5}}} + + @test(eq, {5, _#cond: true}) +} +-- out/compile -- +--- in.cue +{ + ifScalar: { + _#cond: true + if 〈0;_#cond〉 { + 5 + } + } + ifScalarConflict: { + _#cond: true + if 〈0;_#cond〉 { + 5 + } + "soo" + } + ifScalarNested: { + _#cond: true + if 〈0;_#cond〉 { + { + { + 5 + } + } + } + } +} -- 2.51.2