From 35d0e094f70d28acb436ec55fd13f034ff7548e4 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 2 Feb 2024 13:36:36 +0100 Subject: [PATCH 01/31] Draft dict pattern matching. Works for this: ``` type myDict = {name?:string, anyOtherField?: int} let tst = (d: myDict) => switch d { | {name:n, something:i} => String.length(n) + i | {name:n} => String.length(n) | {something:i} => i | _ => 0 } ``` --- jscomp/ml/typecore.ml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 57895afe9b..b793bfccce 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -788,6 +788,8 @@ module NameChoice(Name : sig val get_name: t -> string val get_type: t -> type_expr val get_descrs: Env.type_descriptions -> t list + + val set_name: t -> string -> t val unbound_name_error: Env.t -> Longident.t loc -> 'a end) = struct @@ -798,13 +800,19 @@ end) = struct | Tconstr(p, _, _) -> p | _ -> assert false - let lookup_from_type env tpath lid = + let lookup_from_type env tpath (lid : Longident.t loc) : Name.t = let descrs = get_descrs (Env.find_type_descrs tpath env) in Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env); match lid.txt with - Longident.Lident s -> begin + Longident.Lident s_ -> begin + let s = if List.exists (fun nd -> get_name nd = s_) descrs + then s_ + else "anyOtherField" in try - List.find (fun nd -> get_name nd = s) descrs + let x = List.find (fun nd -> get_name nd = s) descrs in + if s = "anyOtherField" + then set_name x s_ + else x with Not_found -> let names = List.map get_name descrs in raise (Error (lid.loc, env, @@ -884,6 +892,14 @@ module Label = NameChoice (struct type t = label_description let type_kind = "record" let get_name lbl = lbl.lbl_name + let set_name lbl name = + let l = + {lbl with + lbl_name = name; + lbl_repres = Record_optional_labels [name]} in + let lbl_all = lbl.lbl_all in + lbl_all.(Array.length lbl_all - 1) <- l; (* assume "anyOtherField" is the last label *) + l let get_type lbl = lbl.lbl_res let get_descrs = snd let unbound_name_error = Typetexp.unbound_label_error @@ -1040,6 +1056,8 @@ module Constructor = NameChoice (struct let type_kind = "variant" let get_name cstr = cstr.cstr_name let get_type cstr = cstr.cstr_res + + let set_name _cstr _name = assert false let get_descrs = fst let unbound_name_error = Typetexp.unbound_constructor_error end) From ed30f68f018e73f109b51a8dcf9b1a63732a517a Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 2 Feb 2024 15:09:49 +0100 Subject: [PATCH 02/31] Avoid mis-firing when a field is legit missing. --- jscomp/ml/typecore.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index b793bfccce..5881c3fcd5 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -805,7 +805,9 @@ end) = struct Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env); match lid.txt with Longident.Lident s_ -> begin - let s = if List.exists (fun nd -> get_name nd = s_) descrs + let s = + if List.exists (fun nd -> get_name nd = s_) descrs + || not (List.exists (fun nd -> get_name nd = "anyOtherField") descrs) then s_ else "anyOtherField" in try From 5b93ca19622881cd500f5f2daf0fb3de705ee37e Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 2 Feb 2024 18:21:20 +0100 Subject: [PATCH 03/31] Make lbl_all mutable. With lbl_all mutable, it can be extended when new fields are used in pattern matching. This handles examples with multiple fields: ``` type myDict = {name?:string, anyOtherField?: int} let tst = (d: myDict) => switch d { | {a:i, b:j} => i + j | _ => 0 } ``` --- jscomp/ml/typecore.ml | 14 ++++++++------ jscomp/ml/types.ml | 2 +- jscomp/ml/types.mli | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 5881c3fcd5..b13075fa58 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -789,7 +789,7 @@ module NameChoice(Name : sig val get_type: t -> type_expr val get_descrs: Env.type_descriptions -> t list - val set_name: t -> string -> t + val add_with_name: t -> string -> t val unbound_name_error: Env.t -> Longident.t loc -> 'a end) = struct @@ -813,7 +813,7 @@ end) = struct try let x = List.find (fun nd -> get_name nd = s) descrs in if s = "anyOtherField" - then set_name x s_ + then add_with_name x s_ else x with Not_found -> let names = List.map get_name descrs in @@ -894,13 +894,15 @@ module Label = NameChoice (struct type t = label_description let type_kind = "record" let get_name lbl = lbl.lbl_name - let set_name lbl name = + let add_with_name lbl name = let l = {lbl with lbl_name = name; + lbl_pos = Array.length lbl.lbl_all; lbl_repres = Record_optional_labels [name]} in - let lbl_all = lbl.lbl_all in - lbl_all.(Array.length lbl_all - 1) <- l; (* assume "anyOtherField" is the last label *) + let lbl_all_list = Array.to_list lbl.lbl_all @ [l] in + let lbl_all = Array.of_list lbl_all_list in + Ext_array.iter lbl_all (fun lbl -> lbl.lbl_all <- lbl_all); l let get_type lbl = lbl.lbl_res let get_descrs = snd @@ -1059,7 +1061,7 @@ module Constructor = NameChoice (struct let get_name cstr = cstr.cstr_name let get_type cstr = cstr.cstr_res - let set_name _cstr _name = assert false + let add_with_name _cstr _name = assert false let get_descrs = fst let unbound_name_error = Typetexp.unbound_constructor_error end) diff --git a/jscomp/ml/types.ml b/jscomp/ml/types.ml index 16923025d2..5b644e831a 100644 --- a/jscomp/ml/types.ml +++ b/jscomp/ml/types.ml @@ -303,7 +303,7 @@ type label_description = lbl_arg: type_expr; (* Type of the argument *) lbl_mut: mutable_flag; (* Is this a mutable field? *) lbl_pos: int; (* Position in block *) - lbl_all: label_description array; (* All the labels in this type *) + mutable lbl_all: label_description array; (* All the labels in this type *) lbl_repres: record_representation; (* Representation for this record *) lbl_private: private_flag; (* Read-only field? *) lbl_loc: Location.t; diff --git a/jscomp/ml/types.mli b/jscomp/ml/types.mli index 52ec4e8c93..b8d43f4461 100644 --- a/jscomp/ml/types.mli +++ b/jscomp/ml/types.mli @@ -449,7 +449,7 @@ type label_description = lbl_arg: type_expr; (* Type of the argument *) lbl_mut: mutable_flag; (* Is this a mutable field? *) lbl_pos: int; (* Position in block *) - lbl_all: label_description array; (* All the labels in this type *) + mutable lbl_all: label_description array; (* All the labels in this type *) lbl_repres: record_representation; (* Representation for this record *) lbl_private: private_flag; (* Read-only field? *) lbl_loc: Location.t; From 011b3bb7a9bc4decf8af8552a17f82b49041aa4d Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Thu, 8 Feb 2024 10:59:51 +0100 Subject: [PATCH 04/31] Add test for the various aspects of first class dicts. --- jscomp/test/FirstClassDicts.js | 69 +++++++++++++++++++++++++++++++++ jscomp/test/FirstClassDicts.res | 33 ++++++++++++++++ jscomp/test/build.ninja | 3 +- 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 jscomp/test/FirstClassDicts.js create mode 100644 jscomp/test/FirstClassDicts.res diff --git a/jscomp/test/FirstClassDicts.js b/jscomp/test/FirstClassDicts.js new file mode 100644 index 0000000000..a4f6f8f2bd --- /dev/null +++ b/jscomp/test/FirstClassDicts.js @@ -0,0 +1,69 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +'use strict'; + + +let test_create = { + name: "hello", + something: 5 +}; + +function test_lookup(d) { + d.something = 10; +} + +let CreateAndLookup = { + test_create: test_create, + test_lookup: test_lookup +}; + +function test_update(d) { + d.something = 10; +} + +let Update = { + test_update: test_update +}; + +function tst1(d) { + let n = d.name; + if (n !== undefined) { + let i = d.something; + if (i !== undefined) { + return n.length + i | 0; + } else { + return n.length; + } + } + let i$1 = d.something; + if (i$1 !== undefined) { + return i$1; + } else { + return 0; + } +} + +function tst2(d) { + if (d.name === undefined) { + return 0; + } + let i = d.a; + if (i === undefined) { + return 0; + } + let j = d.b; + if (j !== undefined) { + return i + j | 0; + } else { + return 0; + } +} + +let PatternMatching = { + tst1: tst1, + tst2: tst2 +}; + +exports.CreateAndLookup = CreateAndLookup; +exports.Update = Update; +exports.PatternMatching = PatternMatching; +/* No side effect */ diff --git a/jscomp/test/FirstClassDicts.res b/jscomp/test/FirstClassDicts.res new file mode 100644 index 0000000000..f7a1bc8651 --- /dev/null +++ b/jscomp/test/FirstClassDicts.res @@ -0,0 +1,33 @@ +module CreateAndLookup = { + type myDict = {name?: string, mutable anyOtherField?: int} + + let test_create: myDict = {name: "hello", something: 5} + + let test_lookup = (d: myDict) => d.something = Some(10) +} + + +module Update = { + type myDict = {name?: string, mutable anyOtherField?: int} + + let test_update = (d: myDict) => d.something = Some(10) +} + + +module PatternMatching = { + type myDict = {name?: string, anyOtherField?: int} + + let tst1 = (d: myDict) => + switch d { + | {name: n, something: i} => String.length(n) + i + | {name: n} => String.length(n) + | {something: i} => i + | _ => 0 + } + + let tst2 = (d: myDict) => + switch d { + | {name: _, a: i, b: j} => i + j + | _ => 0 + } +} diff --git a/jscomp/test/build.ninja b/jscomp/test/build.ninja index 1057a91a41..0eb2e5d5ff 100644 --- a/jscomp/test/build.ninja +++ b/jscomp/test/build.ninja @@ -19,6 +19,7 @@ o test/DotDotDot.cmi test/DotDotDot.cmj : cc test/DotDotDot.res | $bsc others ru o test/EmptyRecord.cmi test/EmptyRecord.cmj : cc test/EmptyRecord.res | $bsc others runtime o test/ExternalArity.cmi test/ExternalArity.cmj : cc test/ExternalArity.res | $bsc others runtime o test/FFI.cmi test/FFI.cmj : cc test/FFI.res | $bsc others runtime +o test/FirstClassDicts.cmi test/FirstClassDicts.cmj : cc test/FirstClassDicts.res | $bsc others runtime o test/Import.cmi test/Import.cmj : cc test/Import.res | $bsc others runtime o test/ImportAttributes.cmi test/ImportAttributes.cmj : cc test/ImportAttributes.res | $bsc others runtime o test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj : cc test/PartialApplicationNoRuntimeCurry.res | $bsc others runtime @@ -623,4 +624,4 @@ o test/update_record_test.cmi test/update_record_test.cmj : cc test/update_recor o test/variant.cmi test/variant.cmj : cc test/variant.res | $bsc others runtime o test/variantsMatching.cmi test/variantsMatching.cmj : cc test/variantsMatching.res | $bsc others runtime o test/webpack_config.cmi test/webpack_config.cmj : cc test/webpack_config.res | $bsc others runtime -o test : phony test/AsInUncurriedExternals.cmi test/AsInUncurriedExternals.cmj test/Coercion.cmi test/Coercion.cmj test/DerivingAccessorsCurried.cmi test/DerivingAccessorsCurried.cmj test/DerivingAccessorsUncurried.cmi test/DerivingAccessorsUncurried.cmj test/DictInference.cmi test/DictInference.cmj test/DictTests.cmi test/DictTests.cmj test/DisambiguateOptionalFields.cmi test/DisambiguateOptionalFields.cmj test/DotDotDot.cmi test/DotDotDot.cmj test/EmptyRecord.cmi test/EmptyRecord.cmj test/ExternalArity.cmi test/ExternalArity.cmj test/FFI.cmi test/FFI.cmj test/Import.cmi test/Import.cmj test/ImportAttributes.cmi test/ImportAttributes.cmj test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj test/RecordCoercion.cmi test/RecordCoercion.cmj test/RecordOrObject.cmi test/RecordOrObject.cmj test/SafePromises.cmi test/SafePromises.cmj test/UncurriedAlways.cmi test/UncurriedAlways.cmj test/UncurriedExternals.cmi test/UncurriedExternals.cmj test/UncurriedPervasives.cmi test/UncurriedPervasives.cmj test/UntaggedVariants.cmi test/UntaggedVariants.cmj test/VariantCoercion.cmi test/VariantCoercion.cmj test/VariantPatternMatchingSpreads.cmi test/VariantPatternMatchingSpreads.cmj test/VariantPatternMatchingSpreadsWithPayloads.cmi test/VariantPatternMatchingSpreadsWithPayloads.cmj test/VariantSpreads.cmi test/VariantSpreads.cmj test/a.cmi test/a.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_default_value_test.cmi test/alias_default_value_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/as_inline_record_test.cmi test/as_inline_record_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_await.cmi test/async_await.cmj test/async_inline.cmi test/async_inline.cmj test/async_inside_loop.cmi test/async_inside_loop.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_float_ntest.cmi test/belt_float_ntest.cmj test/belt_hashmap_ntest.cmi test/belt_hashmap_ntest.cmj test/belt_hashset_int_ntest.cmi test/belt_hashset_int_ntest.cmj test/belt_int_ntest.cmi test/belt_int_ntest.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_list_ntest.cmi test/belt_list_ntest.cmj test/belt_mapint_ntest.cmi test/belt_mapint_ntest.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/belt_sortarray_ntest.cmi test/belt_sortarray_ntest.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/bigint_test.cmi test/bigint_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/caml_compare_bigint_test.cmi test/caml_compare_bigint_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/directives.cmi test/directives.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exotic_labels_test.cmi test/exotic_labels_test.cmj test/exponentiation_precedence_test.cmi test/exponentiation_precedence_test.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/external_ppx2.cmi test/external_ppx2.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/function_directives.cmi test/function_directives.cmj test/function_directives_no_inline.cmi test/function_directives_no_inline.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_4931_allow.cmi test/gpr_4931_allow.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_5280_optimize_test.cmi test/gpr_5280_optimize_test.cmj test/gpr_5557.cmi test/gpr_5557.cmj test/gpr_5753.cmi test/gpr_5753.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_7012_test.cmi test/gpr_7012_test.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/ignore_test.cmi test/ignore_test.cmj test/ignore_uncurry_attribute.cmi test/ignore_uncurry_attribute.cmj test/import2.cmi test/import2.cmj test/import_external.cmi test/import_external.cmj test/import_side_effect.cmi test/import_side_effect.cmj test/import_side_effect_free.cmi test/import_side_effect_free.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_condition_with_pattern_matching.cmi test/inline_condition_with_pattern_matching.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/jsxv4_newtype.cmi test/jsxv4_newtype.cmj test/keep_uncurry_attribute.cmi test/keep_uncurry_attribute.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_test.cmi test/list_test.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/mario_game.cmi test/mario_game.cmj test/meth_annotation.cmi test/meth_annotation.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_assert.cmi test/node_assert.cmj test/node_path_test.cmi test/node_path_test.cmj test/node_test.cmi test/node_test.cmj test/node_test_util.cmi test/node_test_util.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/offset.cmi test/offset.cmj test/omit_trailing_undefined_in_external_calls.cmi test/omit_trailing_undefined_in_external_calls.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/queue_402.cmi test/queue_402.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_array_test.cmi test/rec_array_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/recmodule.cmi test/recmodule.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_type_spread.cmi test/record_type_spread.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_annotation.cmi test/set_annotation.cmj test/set_gen.cmi test/set_gen.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect2.cmi test/side_effect2.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_constant_compare.cmi test/string_constant_compare.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/switch_string.cmi test/switch_string.cmj test/tagged_template_test.cmi test/tagged_template_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/template.cmi test/template.cmj test/test2.cmi test/test2.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unknown.cmi test/test_unknown.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type-coercion-free-vars.cmi test/type-coercion-free-vars.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_crash.cmi test/unboxed_crash.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurried_cast.cmi test/uncurried_cast.cmj test/uncurried_default.args.cmi test/uncurried_default.args.cmj test/uncurried_pipe.cmi test/uncurried_pipe.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/update_record_test.cmi test/update_record_test.cmj test/variant.cmi test/variant.cmj test/variantsMatching.cmi test/variantsMatching.cmj test/webpack_config.cmi test/webpack_config.cmj +o test : phony test/AsInUncurriedExternals.cmi test/AsInUncurriedExternals.cmj test/Coercion.cmi test/Coercion.cmj test/DerivingAccessorsCurried.cmi test/DerivingAccessorsCurried.cmj test/DerivingAccessorsUncurried.cmi test/DerivingAccessorsUncurried.cmj test/DictInference.cmi test/DictInference.cmj test/DictTests.cmi test/DictTests.cmj test/DisambiguateOptionalFields.cmi test/DisambiguateOptionalFields.cmj test/DotDotDot.cmi test/DotDotDot.cmj test/EmptyRecord.cmi test/EmptyRecord.cmj test/ExternalArity.cmi test/ExternalArity.cmj test/FFI.cmi test/FFI.cmj test/FirstClassDicts.cmi test/FirstClassDicts.cmj test/Import.cmi test/Import.cmj test/ImportAttributes.cmi test/ImportAttributes.cmj test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj test/RecordCoercion.cmi test/RecordCoercion.cmj test/RecordOrObject.cmi test/RecordOrObject.cmj test/SafePromises.cmi test/SafePromises.cmj test/UncurriedAlways.cmi test/UncurriedAlways.cmj test/UncurriedExternals.cmi test/UncurriedExternals.cmj test/UncurriedPervasives.cmi test/UncurriedPervasives.cmj test/UntaggedVariants.cmi test/UntaggedVariants.cmj test/VariantCoercion.cmi test/VariantCoercion.cmj test/VariantPatternMatchingSpreads.cmi test/VariantPatternMatchingSpreads.cmj test/VariantPatternMatchingSpreadsWithPayloads.cmi test/VariantPatternMatchingSpreadsWithPayloads.cmj test/VariantSpreads.cmi test/VariantSpreads.cmj test/a.cmi test/a.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_default_value_test.cmi test/alias_default_value_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/as_inline_record_test.cmi test/as_inline_record_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_await.cmi test/async_await.cmj test/async_inline.cmi test/async_inline.cmj test/async_inside_loop.cmi test/async_inside_loop.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_float_ntest.cmi test/belt_float_ntest.cmj test/belt_hashmap_ntest.cmi test/belt_hashmap_ntest.cmj test/belt_hashset_int_ntest.cmi test/belt_hashset_int_ntest.cmj test/belt_int_ntest.cmi test/belt_int_ntest.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_list_ntest.cmi test/belt_list_ntest.cmj test/belt_mapint_ntest.cmi test/belt_mapint_ntest.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/belt_sortarray_ntest.cmi test/belt_sortarray_ntest.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/bigint_test.cmi test/bigint_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/caml_compare_bigint_test.cmi test/caml_compare_bigint_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/directives.cmi test/directives.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exotic_labels_test.cmi test/exotic_labels_test.cmj test/exponentiation_precedence_test.cmi test/exponentiation_precedence_test.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/external_ppx2.cmi test/external_ppx2.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/function_directives.cmi test/function_directives.cmj test/function_directives_no_inline.cmi test/function_directives_no_inline.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_4931_allow.cmi test/gpr_4931_allow.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_5280_optimize_test.cmi test/gpr_5280_optimize_test.cmj test/gpr_5557.cmi test/gpr_5557.cmj test/gpr_5753.cmi test/gpr_5753.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_7012_test.cmi test/gpr_7012_test.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/ignore_test.cmi test/ignore_test.cmj test/ignore_uncurry_attribute.cmi test/ignore_uncurry_attribute.cmj test/import2.cmi test/import2.cmj test/import_external.cmi test/import_external.cmj test/import_side_effect.cmi test/import_side_effect.cmj test/import_side_effect_free.cmi test/import_side_effect_free.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_condition_with_pattern_matching.cmi test/inline_condition_with_pattern_matching.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/jsxv4_newtype.cmi test/jsxv4_newtype.cmj test/keep_uncurry_attribute.cmi test/keep_uncurry_attribute.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_test.cmi test/list_test.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/mario_game.cmi test/mario_game.cmj test/meth_annotation.cmi test/meth_annotation.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_assert.cmi test/node_assert.cmj test/node_path_test.cmi test/node_path_test.cmj test/node_test.cmi test/node_test.cmj test/node_test_util.cmi test/node_test_util.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/offset.cmi test/offset.cmj test/omit_trailing_undefined_in_external_calls.cmi test/omit_trailing_undefined_in_external_calls.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/queue_402.cmi test/queue_402.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_array_test.cmi test/rec_array_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/recmodule.cmi test/recmodule.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_type_spread.cmi test/record_type_spread.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_annotation.cmi test/set_annotation.cmj test/set_gen.cmi test/set_gen.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect2.cmi test/side_effect2.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_constant_compare.cmi test/string_constant_compare.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/switch_string.cmi test/switch_string.cmj test/tagged_template_test.cmi test/tagged_template_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/template.cmi test/template.cmj test/test2.cmi test/test2.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unknown.cmi test/test_unknown.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type-coercion-free-vars.cmi test/type-coercion-free-vars.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_crash.cmi test/unboxed_crash.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurried_cast.cmi test/uncurried_cast.cmj test/uncurried_default.args.cmi test/uncurried_default.args.cmj test/uncurried_pipe.cmi test/uncurried_pipe.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/update_record_test.cmi test/update_record_test.cmj test/variant.cmi test/variant.cmj test/variantsMatching.cmi test/variantsMatching.cmj test/webpack_config.cmi test/webpack_config.cmj From a4e809a00b77f43bfb218dffbfbe5a48c19fca84 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Thu, 8 Feb 2024 11:02:40 +0100 Subject: [PATCH 05/31] update tests --- jscomp/test/FirstClassDicts.js | 12 ++++++------ jscomp/test/FirstClassDicts.res | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/jscomp/test/FirstClassDicts.js b/jscomp/test/FirstClassDicts.js index a4f6f8f2bd..f639b0503e 100644 --- a/jscomp/test/FirstClassDicts.js +++ b/jscomp/test/FirstClassDicts.js @@ -2,17 +2,17 @@ 'use strict'; -let test_create = { +function test_lookup(d) { + return d.something; +} + +let CreateAndLookup_test_create = { name: "hello", something: 5 }; -function test_lookup(d) { - d.something = 10; -} - let CreateAndLookup = { - test_create: test_create, + test_create: CreateAndLookup_test_create, test_lookup: test_lookup }; diff --git a/jscomp/test/FirstClassDicts.res b/jscomp/test/FirstClassDicts.res index f7a1bc8651..43e6088168 100644 --- a/jscomp/test/FirstClassDicts.res +++ b/jscomp/test/FirstClassDicts.res @@ -1,9 +1,9 @@ module CreateAndLookup = { - type myDict = {name?: string, mutable anyOtherField?: int} + type myDict = {name?: string, anyOtherField?: int} let test_create: myDict = {name: "hello", something: 5} - let test_lookup = (d: myDict) => d.something = Some(10) + let test_lookup = (d: myDict) : option => d.something } From 1a079a4d82c5b0e88abaddcb1c598b0eebb2f687 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 29 Sep 2024 17:32:07 +0200 Subject: [PATCH 06/31] make builtin dict type be a record with anyOtherField catch all --- jscomp/ml/predef.ml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/jscomp/ml/predef.ml b/jscomp/ml/predef.ml index c1fcd5ad3d..1c05b13cee 100644 --- a/jscomp/ml/predef.ml +++ b/jscomp/ml/predef.ml @@ -112,6 +112,8 @@ and ident_failure = ident_create_predef_exn "Failure" and ident_ok = ident_create_predef_exn "Ok" and ident_error = ident_create_predef_exn "Error" +and ident_anyOtherField = ident_create "anyOtherField" + and ident_js_error = ident_create_predef_exn "JsError" and ident_not_found = ident_create_predef_exn "Not_found" @@ -221,7 +223,16 @@ let common_initial_env add_type add_extension empty_env = {decl_abstr with type_params = [tvar]; type_arity = 1; - type_variance = [Variance.full]} + type_variance = [Variance.full]; + type_kind = + Type_record ([ + {ld_id = ident_anyOtherField; + ld_attributes = [(Location.mknoloc "res.optional", Parsetree.PStr [])]; + ld_loc = Location.none; + ld_mutable = Immutable; (* TODO(dict-pattern-matching) Should probably be mutable? *) + ld_type = newgenty (Tconstr (path_option, [tvar], ref Mnil)); + }], Record_optional_labels [Ident.name ident_anyOtherField]); + } and decl_uncurried = let tvar1, tvar2 = newgenvar(), newgenvar() in {decl_abstr with From 9c4c091bf898ab5b19524df2a104c754d20874bc Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 29 Sep 2024 17:51:51 +0200 Subject: [PATCH 07/31] make typechecker account for res.dictPattern attribute to infer record pattern as dict pattern match when the type is not already known --- .../expected/dict_pattern_inference.res.expected | 12 ++++++++++++ .../fixtures/dict_pattern_inference.res | 5 +++++ jscomp/ml/dicts.ml | 5 +++++ jscomp/ml/typecore.ml | 12 ++++++++++-- jscomp/test/DictTests.js | 14 ++++++++++++++ jscomp/test/DictTests.res | 8 ++++++++ 6 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected create mode 100644 jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res create mode 100644 jscomp/ml/dicts.ml diff --git a/jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected b/jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected new file mode 100644 index 0000000000..7eaf8a0832 --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/dict_pattern_inference.res:3:36-42 + + 1 │ let foo = dict => + 2 │ switch dict { + 3 │ | @res.dictPattern {one: 1, two: "hello"} => Js.log("one") + 4 │ | _ => Js.log("not one") + 5 │ } + + This pattern matches values of type string + but a pattern was expected which matches values of type int \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res new file mode 100644 index 0000000000..99f5e16166 --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res @@ -0,0 +1,5 @@ +let foo = dict => + switch dict { + | @res.dictPattern {one: 1, two: "hello"} => Js.log("one") + | _ => Js.log("not one") + } diff --git a/jscomp/ml/dicts.ml b/jscomp/ml/dicts.ml new file mode 100644 index 0000000000..7fc38a198f --- /dev/null +++ b/jscomp/ml/dicts.ml @@ -0,0 +1,5 @@ +let has_dict_pattern_attribute attrs = + attrs + |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> + txt = "res.dictPattern") + |> Option.is_some \ No newline at end of file diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index b13075fa58..2f06d145b3 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -1370,12 +1370,20 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env | _ -> k None end | Ppat_record(lid_sp_list, closed) -> - let opath, record_ty = + let has_dict_pattern_attr = Dicts.has_dict_pattern_attribute sp.ppat_attributes in + let opath, record_ty = ( + match (has_dict_pattern_attr, expected_ty.desc) with + | (true, Tvar _) -> + (* When this is a dict pattern and we don't have an actual expected type yet, + infer the type as a dict with a new type variable. This let us hook into the + existing inference mechanism for records in dict pattern matching too. *) + (Some (Predef.path_dict, Predef.path_dict), newgenty (Tconstr (Predef.path_dict, [newvar ()], ref Mnil))) + | _ -> try let (p0, p, _, _) = extract_concrete_record !env expected_ty in Some (p0, p), expected_ty with Not_found -> None, newvar () - in + ) in let get_jsx_component_error_info = get_jsx_component_error_info ~extract_concrete_typedecl opath !env record_ty in let process_optional_label (ld, pat) = let exp_optional_attr = check_optional_attr !env ld pat.ppat_attributes pat.ppat_loc in diff --git a/jscomp/test/DictTests.js b/jscomp/test/DictTests.js index 8228a11d00..b5367fe999 100644 --- a/jscomp/test/DictTests.js +++ b/jscomp/test/DictTests.js @@ -17,10 +17,24 @@ let intDict = { three: 3 }; +function foo(dict) { + let match = dict.one; + if (match === 1) { + console.log("one"); + } else { + console.log("not one"); + } +} + +let PatternMatching = { + foo: foo +}; + let three = 3; exports.someString = someString; exports.createdDict = createdDict; exports.three = three; exports.intDict = intDict; +exports.PatternMatching = PatternMatching; /* No side effect */ diff --git a/jscomp/test/DictTests.res b/jscomp/test/DictTests.res index abf0bad193..b4784a828f 100644 --- a/jscomp/test/DictTests.res +++ b/jscomp/test/DictTests.res @@ -14,3 +14,11 @@ let intDict = dict{ "two": 2, "three": three, } + +module PatternMatching = { + let foo = dict => + switch dict { + | @res.dictPattern {one: 1} => Js.log("one") + | _ => Js.log("not one") + } +} From 09f07f251f0d315806292121d0336891e24da945 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 29 Sep 2024 18:05:14 +0200 Subject: [PATCH 08/31] format --- jscomp/test/FirstClassDicts.res | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jscomp/test/FirstClassDicts.res b/jscomp/test/FirstClassDicts.res index 43e6088168..4c635c845a 100644 --- a/jscomp/test/FirstClassDicts.res +++ b/jscomp/test/FirstClassDicts.res @@ -3,17 +3,15 @@ module CreateAndLookup = { let test_create: myDict = {name: "hello", something: 5} - let test_lookup = (d: myDict) : option => d.something + let test_lookup = (d: myDict): option => d.something } - module Update = { type myDict = {name?: string, mutable anyOtherField?: int} let test_update = (d: myDict) => d.something = Some(10) } - module PatternMatching = { type myDict = {name?: string, anyOtherField?: int} From 35a6dadc6a481b31ae8a5aa9f2a221c36153d2e8 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 11:45:40 +0200 Subject: [PATCH 09/31] add some tests, and disallow direct record field access on dicts --- ...pattern_inference_constrained.res.expected | 30 +++++++++++++++++++ ...ict_record_style_field_access.res.expected | 9 ++++++ .../dict_pattern_inference_constrained.res | 7 +++++ .../dict_record_style_field_access.res | 5 ++++ jscomp/ml/dicts.ml | 8 ++++- jscomp/ml/predef.ml | 9 +++--- jscomp/ml/typecore.ml | 11 +++++-- jscomp/ml/typecore.mli | 1 + jscomp/test/DictInference.res | 2 ++ jscomp/test/DictTests.js | 14 +++++++-- jscomp/test/DictTests.res | 14 +++++++-- 11 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected create mode 100644 jscomp/build_tests/super_errors/expected/dict_record_style_field_access.res.expected create mode 100644 jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res create mode 100644 jscomp/build_tests/super_errors/fixtures/dict_record_style_field_access.res diff --git a/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected b/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected new file mode 100644 index 0000000000..a1ba01a48d --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected @@ -0,0 +1,30 @@ + + Warning number 9 + /.../fixtures/dict_pattern_inference_constrained.res:3:22-29 + + 1 │ let foo = dict => + 2 │ switch dict { + 3 │ | @res.dictPattern {one: 1} => + 4 │ let _: dict = dict + 5 │ Js.log("one") + + the following labels are not bound in this record pattern: anyOtherField +Either bind these labels explicitly or add ', _' to the pattern. + + + We've found a bug for you! + /.../fixtures/dict_pattern_inference_constrained.res:4:27-30 + + 2 ┆ switch dict { + 3 ┆ | @res.dictPattern {one: 1} => + 4 ┆ let _: dict = dict + 5 ┆ Js.log("one") + 6 ┆ | _ => Js.log("not one") + + This has type: dict + But it's expected to have type: dict + + The incompatible parts: + int vs string + + You can convert int to string with Belt.Int.toString. \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/expected/dict_record_style_field_access.res.expected b/jscomp/build_tests/super_errors/expected/dict_record_style_field_access.res.expected new file mode 100644 index 0000000000..f9bcfc32dc --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/dict_record_style_field_access.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/dict_record_style_field_access.res:5:20-23 + + 3 │ } + 4 │ + 5 │ let x = stringDict.name + + Direct field access on a dict is not supported. Use Dict.get instead. \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res new file mode 100644 index 0000000000..b090126c61 --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res @@ -0,0 +1,7 @@ +let foo = dict => + switch dict { + | @res.dictPattern {one: 1} => + let _: dict = dict + Js.log("one") + | _ => Js.log("not one") + } diff --git a/jscomp/build_tests/super_errors/fixtures/dict_record_style_field_access.res b/jscomp/build_tests/super_errors/fixtures/dict_record_style_field_access.res new file mode 100644 index 0000000000..af20f04b3c --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/dict_record_style_field_access.res @@ -0,0 +1,5 @@ +let stringDict = dict{ + "name": "hello", +} + +let x = stringDict.name \ No newline at end of file diff --git a/jscomp/ml/dicts.ml b/jscomp/ml/dicts.ml index 7fc38a198f..a34b7c70fb 100644 --- a/jscomp/ml/dicts.ml +++ b/jscomp/ml/dicts.ml @@ -2,4 +2,10 @@ let has_dict_pattern_attribute attrs = attrs |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> txt = "res.dictPattern") - |> Option.is_some \ No newline at end of file + |> Option.is_some + +let has_dict_attribute attrs = + attrs + |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> + txt = "res.dict") + |> Option.is_some \ No newline at end of file diff --git a/jscomp/ml/predef.ml b/jscomp/ml/predef.ml index 1c05b13cee..2592a14766 100644 --- a/jscomp/ml/predef.ml +++ b/jscomp/ml/predef.ml @@ -221,17 +221,18 @@ let common_initial_env add_type add_extension empty_env = and decl_dict = let tvar = newgenvar() in {decl_abstr with + type_attributes = [(Location.mknoloc "res.dict", Parsetree.PStr [])]; type_params = [tvar]; type_arity = 1; type_variance = [Variance.full]; - type_kind = - Type_record ([ - {ld_id = ident_anyOtherField; + type_kind = Type_record ([{ + ld_id = ident_anyOtherField; ld_attributes = [(Location.mknoloc "res.optional", Parsetree.PStr [])]; ld_loc = Location.none; ld_mutable = Immutable; (* TODO(dict-pattern-matching) Should probably be mutable? *) ld_type = newgenty (Tconstr (path_option, [tvar], ref Mnil)); - }], Record_optional_labels [Ident.name ident_anyOtherField]); + }], + Record_optional_labels [Ident.name ident_anyOtherField]); } and decl_uncurried = let tvar1, tvar2 = newgenvar(), newgenvar() in diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 2f06d145b3..3b40e21059 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -75,6 +75,7 @@ type error = | Uncurried_arity_mismatch of type_expr * int * int | Field_not_optional of string * type_expr | Type_params_not_supported of Longident.t + | Field_access_on_dict_type exception Error of Location.t * Env.t * error exception Error_forward of Location.error @@ -3013,8 +3014,12 @@ and type_label_access env srecord lid = let ty_exp = record.exp_type in let opath = try - let (p0, p, _, _) = extract_concrete_record env ty_exp in - Some(p0, p) + match extract_concrete_typedecl env ty_exp with + | (p0, _, {type_attributes}) + when Path.same p0 Predef.path_dict && Dicts.has_dict_attribute type_attributes -> + raise(Error(lid.loc, env, Field_access_on_dict_type)) + | (p0, p, {type_kind=Type_record _}) -> Some(p0, p) + | _ -> None with Not_found -> None in let labels = Typetexp.find_all_labels env lid.loc lid.txt in @@ -4131,6 +4136,8 @@ let report_error env ppf = function type_expr typ | Type_params_not_supported lid -> fprintf ppf "The type %a@ has type parameters, but type parameters is not supported here." longident lid + | Field_access_on_dict_type -> + fprintf ppf "Direct field access on a dict is not supported. Use Dict.get instead." let super_report_error_no_wrap_printing_env = report_error diff --git a/jscomp/ml/typecore.mli b/jscomp/ml/typecore.mli index d159b101c7..47d17a4336 100644 --- a/jscomp/ml/typecore.mli +++ b/jscomp/ml/typecore.mli @@ -108,6 +108,7 @@ type error = | Uncurried_arity_mismatch of type_expr * int * int | Field_not_optional of string * type_expr | Type_params_not_supported of Longident.t + | Field_access_on_dict_type exception Error of Location.t * Env.t * error exception Error_forward of Location.error diff --git a/jscomp/test/DictInference.res b/jscomp/test/DictInference.res index cabae911e5..a267ae2e6e 100644 --- a/jscomp/test/DictInference.res +++ b/jscomp/test/DictInference.res @@ -2,3 +2,5 @@ let dict = Js.Dict.empty() dict->Js.Dict.set("someKey1", 1) dict->Js.Dict.set("someKey2", 2) let asArray = dict->Js.Dict.values + +let _: dict = dict diff --git a/jscomp/test/DictTests.js b/jscomp/test/DictTests.js index b5367fe999..48b048847d 100644 --- a/jscomp/test/DictTests.js +++ b/jscomp/test/DictTests.js @@ -17,7 +17,16 @@ let intDict = { three: 3 }; -function foo(dict) { +function inferDictByPattern(dict) { + let match = dict.one; + if (match === 1) { + console.log("one"); + } else { + console.log("not one"); + } +} + +function constrainedAsDict(dict) { let match = dict.one; if (match === 1) { console.log("one"); @@ -27,7 +36,8 @@ function foo(dict) { } let PatternMatching = { - foo: foo + inferDictByPattern: inferDictByPattern, + constrainedAsDict: constrainedAsDict }; let three = 3; diff --git a/jscomp/test/DictTests.res b/jscomp/test/DictTests.res index b4784a828f..4ab90dd134 100644 --- a/jscomp/test/DictTests.res +++ b/jscomp/test/DictTests.res @@ -16,9 +16,19 @@ let intDict = dict{ } module PatternMatching = { - let foo = dict => + let inferDictByPattern = dict => switch dict { - | @res.dictPattern {one: 1} => Js.log("one") + | @res.dictPattern {one: 1} => + let _d: dict = dict + Js.log("one") + | _ => Js.log("not one") + } + + let constrainedAsDict = (dict: dict) => + switch dict { + | @res.dictPattern {one: 1} => + let _d: dict = dict + Js.log("one") | _ => Js.log("not one") } } From a2d09fa6e7be18b3c3a9ab55ed1dbff949c54e63 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 12:04:32 +0200 Subject: [PATCH 10/31] make code path handling the magic record field for dicts just work on the predefined dict --- .../dict_magic_field_on_non_dict.res.expected | 13 +++++++ .../fixtures/dict_magic_field_on_non_dict.res | 8 +++++ jscomp/ml/predef.ml | 2 +- jscomp/ml/typecore.ml | 35 +++++++++++++------ 4 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 jscomp/build_tests/super_errors/expected/dict_magic_field_on_non_dict.res.expected create mode 100644 jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res diff --git a/jscomp/build_tests/super_errors/expected/dict_magic_field_on_non_dict.res.expected b/jscomp/build_tests/super_errors/expected/dict_magic_field_on_non_dict.res.expected new file mode 100644 index 0000000000..05d88219c2 --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/dict_magic_field_on_non_dict.res.expected @@ -0,0 +1,13 @@ + + We've found a bug for you! + /.../fixtures/dict_magic_field_on_non_dict.res:5:6-23 + + 3 │ let foo = (fakeDict: fakeDict<'a>) => { + 4 │ switch fakeDict { + 5 │ | {someUndefinedField: 1} => Js.log("one") + 6 │ | _ => Js.log("not one") + 7 │ } + + The field someUndefinedField does not belong to type fakeDict + + This record pattern is expected to have type fakeDict<'a> \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res b/jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res new file mode 100644 index 0000000000..2af6937040 --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res @@ -0,0 +1,8 @@ +type fakeDict<'t> = {anyOtherField?: 't} + +let foo = (fakeDict: fakeDict<'a>) => { + switch fakeDict { + | {someUndefinedField: 1} => Js.log("one") + | _ => Js.log("not one") + } +} diff --git a/jscomp/ml/predef.ml b/jscomp/ml/predef.ml index 2592a14766..9fc710ebe0 100644 --- a/jscomp/ml/predef.ml +++ b/jscomp/ml/predef.ml @@ -227,7 +227,7 @@ let common_initial_env add_type add_extension empty_env = type_variance = [Variance.full]; type_kind = Type_record ([{ ld_id = ident_anyOtherField; - ld_attributes = [(Location.mknoloc "res.optional", Parsetree.PStr [])]; + ld_attributes = [(Location.mknoloc "res.optional", Parsetree.PStr []); (Location.mknoloc "res.dictMagicField", Parsetree.PStr [])]; ld_loc = Location.none; ld_mutable = Immutable; (* TODO(dict-pattern-matching) Should probably be mutable? *) ld_type = newgenty (Tconstr (path_option, [tvar], ref Mnil)); diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 3b40e21059..eb1b438c05 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -804,18 +804,31 @@ end) = struct let lookup_from_type env tpath (lid : Longident.t loc) : Name.t = let descrs = get_descrs (Env.find_type_descrs tpath env) in Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env); - match lid.txt with - Longident.Lident s_ -> begin - let s = - if List.exists (fun nd -> get_name nd = s_) descrs - || not (List.exists (fun nd -> get_name nd = "anyOtherField") descrs) - then s_ - else "anyOtherField" in + (* TODO(dict-pattern-matching): also lookup the actual definition and check for @res.dict? *) + let is_dict = Path.same tpath Predef.path_dict in + if is_dict then ( + match lid.txt with + Longident.Lident s_ -> begin + let s = + if List.exists (fun nd -> get_name nd = s_) descrs + || not (List.exists (fun nd -> get_name nd = "anyOtherField") descrs) + then s_ + else "anyOtherField" in + try + let x = List.find (fun nd -> get_name nd = s) descrs in + if s = "anyOtherField" + then add_with_name x s_ + else x + with Not_found -> + let names = List.map get_name descrs in + raise (Error (lid.loc, env, + Wrong_name ("", newvar (), type_kind, tpath, s, names))) + end + | _ -> raise Not_found) + else match lid.txt with + Longident.Lident s -> begin try - let x = List.find (fun nd -> get_name nd = s) descrs in - if s = "anyOtherField" - then add_with_name x s_ - else x + List.find (fun nd -> get_name nd = s) descrs with Not_found -> let names = List.map get_name descrs in raise (Error (lid.loc, env, From f783d20a844fd749e9d2abf37585baab53a84071 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 12:07:00 +0200 Subject: [PATCH 11/31] remove now irrelevant test since we reduced scope to just focus on dicts in the first iteration, not record-with-some-and-some-unknown-properties --- jscomp/test/FirstClassDicts.res | 31 ------------------------------- jscomp/test/build.ninja | 3 +-- 2 files changed, 1 insertion(+), 33 deletions(-) delete mode 100644 jscomp/test/FirstClassDicts.res diff --git a/jscomp/test/FirstClassDicts.res b/jscomp/test/FirstClassDicts.res deleted file mode 100644 index 4c635c845a..0000000000 --- a/jscomp/test/FirstClassDicts.res +++ /dev/null @@ -1,31 +0,0 @@ -module CreateAndLookup = { - type myDict = {name?: string, anyOtherField?: int} - - let test_create: myDict = {name: "hello", something: 5} - - let test_lookup = (d: myDict): option => d.something -} - -module Update = { - type myDict = {name?: string, mutable anyOtherField?: int} - - let test_update = (d: myDict) => d.something = Some(10) -} - -module PatternMatching = { - type myDict = {name?: string, anyOtherField?: int} - - let tst1 = (d: myDict) => - switch d { - | {name: n, something: i} => String.length(n) + i - | {name: n} => String.length(n) - | {something: i} => i - | _ => 0 - } - - let tst2 = (d: myDict) => - switch d { - | {name: _, a: i, b: j} => i + j - | _ => 0 - } -} diff --git a/jscomp/test/build.ninja b/jscomp/test/build.ninja index 0eb2e5d5ff..1057a91a41 100644 --- a/jscomp/test/build.ninja +++ b/jscomp/test/build.ninja @@ -19,7 +19,6 @@ o test/DotDotDot.cmi test/DotDotDot.cmj : cc test/DotDotDot.res | $bsc others ru o test/EmptyRecord.cmi test/EmptyRecord.cmj : cc test/EmptyRecord.res | $bsc others runtime o test/ExternalArity.cmi test/ExternalArity.cmj : cc test/ExternalArity.res | $bsc others runtime o test/FFI.cmi test/FFI.cmj : cc test/FFI.res | $bsc others runtime -o test/FirstClassDicts.cmi test/FirstClassDicts.cmj : cc test/FirstClassDicts.res | $bsc others runtime o test/Import.cmi test/Import.cmj : cc test/Import.res | $bsc others runtime o test/ImportAttributes.cmi test/ImportAttributes.cmj : cc test/ImportAttributes.res | $bsc others runtime o test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj : cc test/PartialApplicationNoRuntimeCurry.res | $bsc others runtime @@ -624,4 +623,4 @@ o test/update_record_test.cmi test/update_record_test.cmj : cc test/update_recor o test/variant.cmi test/variant.cmj : cc test/variant.res | $bsc others runtime o test/variantsMatching.cmi test/variantsMatching.cmj : cc test/variantsMatching.res | $bsc others runtime o test/webpack_config.cmi test/webpack_config.cmj : cc test/webpack_config.res | $bsc others runtime -o test : phony test/AsInUncurriedExternals.cmi test/AsInUncurriedExternals.cmj test/Coercion.cmi test/Coercion.cmj test/DerivingAccessorsCurried.cmi test/DerivingAccessorsCurried.cmj test/DerivingAccessorsUncurried.cmi test/DerivingAccessorsUncurried.cmj test/DictInference.cmi test/DictInference.cmj test/DictTests.cmi test/DictTests.cmj test/DisambiguateOptionalFields.cmi test/DisambiguateOptionalFields.cmj test/DotDotDot.cmi test/DotDotDot.cmj test/EmptyRecord.cmi test/EmptyRecord.cmj test/ExternalArity.cmi test/ExternalArity.cmj test/FFI.cmi test/FFI.cmj test/FirstClassDicts.cmi test/FirstClassDicts.cmj test/Import.cmi test/Import.cmj test/ImportAttributes.cmi test/ImportAttributes.cmj test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj test/RecordCoercion.cmi test/RecordCoercion.cmj test/RecordOrObject.cmi test/RecordOrObject.cmj test/SafePromises.cmi test/SafePromises.cmj test/UncurriedAlways.cmi test/UncurriedAlways.cmj test/UncurriedExternals.cmi test/UncurriedExternals.cmj test/UncurriedPervasives.cmi test/UncurriedPervasives.cmj test/UntaggedVariants.cmi test/UntaggedVariants.cmj test/VariantCoercion.cmi test/VariantCoercion.cmj test/VariantPatternMatchingSpreads.cmi test/VariantPatternMatchingSpreads.cmj test/VariantPatternMatchingSpreadsWithPayloads.cmi test/VariantPatternMatchingSpreadsWithPayloads.cmj test/VariantSpreads.cmi test/VariantSpreads.cmj test/a.cmi test/a.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_default_value_test.cmi test/alias_default_value_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/as_inline_record_test.cmi test/as_inline_record_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_await.cmi test/async_await.cmj test/async_inline.cmi test/async_inline.cmj test/async_inside_loop.cmi test/async_inside_loop.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_float_ntest.cmi test/belt_float_ntest.cmj test/belt_hashmap_ntest.cmi test/belt_hashmap_ntest.cmj test/belt_hashset_int_ntest.cmi test/belt_hashset_int_ntest.cmj test/belt_int_ntest.cmi test/belt_int_ntest.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_list_ntest.cmi test/belt_list_ntest.cmj test/belt_mapint_ntest.cmi test/belt_mapint_ntest.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/belt_sortarray_ntest.cmi test/belt_sortarray_ntest.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/bigint_test.cmi test/bigint_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/caml_compare_bigint_test.cmi test/caml_compare_bigint_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/directives.cmi test/directives.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exotic_labels_test.cmi test/exotic_labels_test.cmj test/exponentiation_precedence_test.cmi test/exponentiation_precedence_test.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/external_ppx2.cmi test/external_ppx2.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/function_directives.cmi test/function_directives.cmj test/function_directives_no_inline.cmi test/function_directives_no_inline.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_4931_allow.cmi test/gpr_4931_allow.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_5280_optimize_test.cmi test/gpr_5280_optimize_test.cmj test/gpr_5557.cmi test/gpr_5557.cmj test/gpr_5753.cmi test/gpr_5753.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_7012_test.cmi test/gpr_7012_test.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/ignore_test.cmi test/ignore_test.cmj test/ignore_uncurry_attribute.cmi test/ignore_uncurry_attribute.cmj test/import2.cmi test/import2.cmj test/import_external.cmi test/import_external.cmj test/import_side_effect.cmi test/import_side_effect.cmj test/import_side_effect_free.cmi test/import_side_effect_free.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_condition_with_pattern_matching.cmi test/inline_condition_with_pattern_matching.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/jsxv4_newtype.cmi test/jsxv4_newtype.cmj test/keep_uncurry_attribute.cmi test/keep_uncurry_attribute.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_test.cmi test/list_test.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/mario_game.cmi test/mario_game.cmj test/meth_annotation.cmi test/meth_annotation.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_assert.cmi test/node_assert.cmj test/node_path_test.cmi test/node_path_test.cmj test/node_test.cmi test/node_test.cmj test/node_test_util.cmi test/node_test_util.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/offset.cmi test/offset.cmj test/omit_trailing_undefined_in_external_calls.cmi test/omit_trailing_undefined_in_external_calls.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/queue_402.cmi test/queue_402.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_array_test.cmi test/rec_array_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/recmodule.cmi test/recmodule.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_type_spread.cmi test/record_type_spread.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_annotation.cmi test/set_annotation.cmj test/set_gen.cmi test/set_gen.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect2.cmi test/side_effect2.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_constant_compare.cmi test/string_constant_compare.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/switch_string.cmi test/switch_string.cmj test/tagged_template_test.cmi test/tagged_template_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/template.cmi test/template.cmj test/test2.cmi test/test2.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unknown.cmi test/test_unknown.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type-coercion-free-vars.cmi test/type-coercion-free-vars.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_crash.cmi test/unboxed_crash.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurried_cast.cmi test/uncurried_cast.cmj test/uncurried_default.args.cmi test/uncurried_default.args.cmj test/uncurried_pipe.cmi test/uncurried_pipe.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/update_record_test.cmi test/update_record_test.cmj test/variant.cmi test/variant.cmj test/variantsMatching.cmi test/variantsMatching.cmj test/webpack_config.cmi test/webpack_config.cmj +o test : phony test/AsInUncurriedExternals.cmi test/AsInUncurriedExternals.cmj test/Coercion.cmi test/Coercion.cmj test/DerivingAccessorsCurried.cmi test/DerivingAccessorsCurried.cmj test/DerivingAccessorsUncurried.cmi test/DerivingAccessorsUncurried.cmj test/DictInference.cmi test/DictInference.cmj test/DictTests.cmi test/DictTests.cmj test/DisambiguateOptionalFields.cmi test/DisambiguateOptionalFields.cmj test/DotDotDot.cmi test/DotDotDot.cmj test/EmptyRecord.cmi test/EmptyRecord.cmj test/ExternalArity.cmi test/ExternalArity.cmj test/FFI.cmi test/FFI.cmj test/Import.cmi test/Import.cmj test/ImportAttributes.cmi test/ImportAttributes.cmj test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj test/RecordCoercion.cmi test/RecordCoercion.cmj test/RecordOrObject.cmi test/RecordOrObject.cmj test/SafePromises.cmi test/SafePromises.cmj test/UncurriedAlways.cmi test/UncurriedAlways.cmj test/UncurriedExternals.cmi test/UncurriedExternals.cmj test/UncurriedPervasives.cmi test/UncurriedPervasives.cmj test/UntaggedVariants.cmi test/UntaggedVariants.cmj test/VariantCoercion.cmi test/VariantCoercion.cmj test/VariantPatternMatchingSpreads.cmi test/VariantPatternMatchingSpreads.cmj test/VariantPatternMatchingSpreadsWithPayloads.cmi test/VariantPatternMatchingSpreadsWithPayloads.cmj test/VariantSpreads.cmi test/VariantSpreads.cmj test/a.cmi test/a.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_default_value_test.cmi test/alias_default_value_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/as_inline_record_test.cmi test/as_inline_record_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_await.cmi test/async_await.cmj test/async_inline.cmi test/async_inline.cmj test/async_inside_loop.cmi test/async_inside_loop.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_float_ntest.cmi test/belt_float_ntest.cmj test/belt_hashmap_ntest.cmi test/belt_hashmap_ntest.cmj test/belt_hashset_int_ntest.cmi test/belt_hashset_int_ntest.cmj test/belt_int_ntest.cmi test/belt_int_ntest.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_list_ntest.cmi test/belt_list_ntest.cmj test/belt_mapint_ntest.cmi test/belt_mapint_ntest.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/belt_sortarray_ntest.cmi test/belt_sortarray_ntest.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/bigint_test.cmi test/bigint_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/caml_compare_bigint_test.cmi test/caml_compare_bigint_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/directives.cmi test/directives.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exotic_labels_test.cmi test/exotic_labels_test.cmj test/exponentiation_precedence_test.cmi test/exponentiation_precedence_test.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/external_ppx2.cmi test/external_ppx2.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/function_directives.cmi test/function_directives.cmj test/function_directives_no_inline.cmi test/function_directives_no_inline.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_4931_allow.cmi test/gpr_4931_allow.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_5280_optimize_test.cmi test/gpr_5280_optimize_test.cmj test/gpr_5557.cmi test/gpr_5557.cmj test/gpr_5753.cmi test/gpr_5753.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_7012_test.cmi test/gpr_7012_test.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/ignore_test.cmi test/ignore_test.cmj test/ignore_uncurry_attribute.cmi test/ignore_uncurry_attribute.cmj test/import2.cmi test/import2.cmj test/import_external.cmi test/import_external.cmj test/import_side_effect.cmi test/import_side_effect.cmj test/import_side_effect_free.cmi test/import_side_effect_free.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_condition_with_pattern_matching.cmi test/inline_condition_with_pattern_matching.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/jsxv4_newtype.cmi test/jsxv4_newtype.cmj test/keep_uncurry_attribute.cmi test/keep_uncurry_attribute.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_test.cmi test/list_test.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/mario_game.cmi test/mario_game.cmj test/meth_annotation.cmi test/meth_annotation.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_assert.cmi test/node_assert.cmj test/node_path_test.cmi test/node_path_test.cmj test/node_test.cmi test/node_test.cmj test/node_test_util.cmi test/node_test_util.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/offset.cmi test/offset.cmj test/omit_trailing_undefined_in_external_calls.cmi test/omit_trailing_undefined_in_external_calls.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/queue_402.cmi test/queue_402.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_array_test.cmi test/rec_array_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/recmodule.cmi test/recmodule.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_type_spread.cmi test/record_type_spread.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_annotation.cmi test/set_annotation.cmj test/set_gen.cmi test/set_gen.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect2.cmi test/side_effect2.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_constant_compare.cmi test/string_constant_compare.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/switch_string.cmi test/switch_string.cmj test/tagged_template_test.cmi test/tagged_template_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/template.cmi test/template.cmj test/test2.cmi test/test2.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unknown.cmi test/test_unknown.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type-coercion-free-vars.cmi test/type-coercion-free-vars.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_crash.cmi test/unboxed_crash.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurried_cast.cmi test/uncurried_cast.cmj test/uncurried_default.args.cmi test/uncurried_default.args.cmj test/uncurried_pipe.cmi test/uncurried_pipe.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/update_record_test.cmi test/update_record_test.cmj test/variant.cmi test/variant.cmj test/variantsMatching.cmi test/variantsMatching.cmj test/webpack_config.cmi test/webpack_config.cmj From f134c621e0fb3fc51e69c553f8ffc8991ee10340 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 12:09:07 +0200 Subject: [PATCH 12/31] remove lingering file --- jscomp/test/FirstClassDicts.js | 69 ---------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 jscomp/test/FirstClassDicts.js diff --git a/jscomp/test/FirstClassDicts.js b/jscomp/test/FirstClassDicts.js deleted file mode 100644 index f639b0503e..0000000000 --- a/jscomp/test/FirstClassDicts.js +++ /dev/null @@ -1,69 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -'use strict'; - - -function test_lookup(d) { - return d.something; -} - -let CreateAndLookup_test_create = { - name: "hello", - something: 5 -}; - -let CreateAndLookup = { - test_create: CreateAndLookup_test_create, - test_lookup: test_lookup -}; - -function test_update(d) { - d.something = 10; -} - -let Update = { - test_update: test_update -}; - -function tst1(d) { - let n = d.name; - if (n !== undefined) { - let i = d.something; - if (i !== undefined) { - return n.length + i | 0; - } else { - return n.length; - } - } - let i$1 = d.something; - if (i$1 !== undefined) { - return i$1; - } else { - return 0; - } -} - -function tst2(d) { - if (d.name === undefined) { - return 0; - } - let i = d.a; - if (i === undefined) { - return 0; - } - let j = d.b; - if (j !== undefined) { - return i + j | 0; - } else { - return 0; - } -} - -let PatternMatching = { - tst1: tst1, - tst2: tst2 -}; - -exports.CreateAndLookup = CreateAndLookup; -exports.Update = Update; -exports.PatternMatching = PatternMatching; -/* No side effect */ From b1ebde4587aa17f53de1920ad5970578802104c6 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 12:10:19 +0200 Subject: [PATCH 13/31] format --- jscomp/ml/dicts.ml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/jscomp/ml/dicts.ml b/jscomp/ml/dicts.ml index a34b7c70fb..aae10a8065 100644 --- a/jscomp/ml/dicts.ml +++ b/jscomp/ml/dicts.ml @@ -1,11 +1,10 @@ let has_dict_pattern_attribute attrs = attrs |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> - txt = "res.dictPattern") + txt = "res.dictPattern") |> Option.is_some let has_dict_attribute attrs = - attrs - |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> - txt = "res.dict") - |> Option.is_some \ No newline at end of file + attrs + |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> txt = "res.dict") + |> Option.is_some \ No newline at end of file From 651084740463f472a928467b3954fc7f935e322c Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 12:13:40 +0200 Subject: [PATCH 14/31] make sure coercion is disallowed for dicts --- .../super_errors/expected/dict_coercion.res.expected | 10 ++++++++++ .../super_errors/fixtures/dict_coercion.res | 7 +++++++ 2 files changed, 17 insertions(+) create mode 100644 jscomp/build_tests/super_errors/expected/dict_coercion.res.expected create mode 100644 jscomp/build_tests/super_errors/fixtures/dict_coercion.res diff --git a/jscomp/build_tests/super_errors/expected/dict_coercion.res.expected b/jscomp/build_tests/super_errors/expected/dict_coercion.res.expected new file mode 100644 index 0000000000..c0f20c4fd2 --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/dict_coercion.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/dict_coercion.res:7:10-30 + + 5 │ type fakeDict<'t> = {anyOtherField?: 't} + 6 │ + 7 │ let d = (dict :> fakeDict) + 8 │ + + Type Js.Dict.t = dict is not a subtype of fakeDict \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/fixtures/dict_coercion.res b/jscomp/build_tests/super_errors/fixtures/dict_coercion.res new file mode 100644 index 0000000000..a1a70178a0 --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/dict_coercion.res @@ -0,0 +1,7 @@ +let dict = Js.Dict.empty() +dict->Js.Dict.set("someKey1", 1) +dict->Js.Dict.set("someKey2", 2) + +type fakeDict<'t> = {anyOtherField?: 't} + +let d = (dict :> fakeDict) From 4073eb087594757db44eccf4da585f0c32d8fbbe Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 12:19:02 +0200 Subject: [PATCH 15/31] add internal test making sure dict labels dont stack --- jscomp/test/DictInternalRepresentation.js | 25 +++++++++++++++++++++ jscomp/test/DictInternalRepresentation.res | 26 ++++++++++++++++++++++ jscomp/test/build.ninja | 3 ++- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 jscomp/test/DictInternalRepresentation.js create mode 100644 jscomp/test/DictInternalRepresentation.res diff --git a/jscomp/test/DictInternalRepresentation.js b/jscomp/test/DictInternalRepresentation.js new file mode 100644 index 0000000000..54a2143c61 --- /dev/null +++ b/jscomp/test/DictInternalRepresentation.js @@ -0,0 +1,25 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +'use strict'; + + +let stringDict = { + first: "hello" +}; + +let intDict = { + first: 1 +}; + +function foo() { + let first = stringDict.first; + let first$1 = first !== undefined ? first + "2" : "hello"; + console.log(first$1); + let first$2 = intDict.first; + let second = first$2 !== undefined ? first$2 + 2 | 0 : 1; + console.log(second); +} + +exports.stringDict = stringDict; +exports.intDict = intDict; +exports.foo = foo; +/* No side effect */ diff --git a/jscomp/test/DictInternalRepresentation.res b/jscomp/test/DictInternalRepresentation.res new file mode 100644 index 0000000000..bc3a940fea --- /dev/null +++ b/jscomp/test/DictInternalRepresentation.res @@ -0,0 +1,26 @@ +// Make sure labels matched don't "stick" on the builtin dict type +let stringDict = dict{ + "first": "hello", +} + +let intDict = dict{ + "first": 1, +} + +let foo = () => { + let first = switch stringDict { + | @res.dictPattern {first} => first ++ "2" + | _ => "hello" + } + Js.log(first) + let second = switch intDict { + | @res.dictPattern {first} => first + 2 + | _ => 1 + } + Js.log(second) + let third = switch stringDict { + | @res.dictPattern {first} => first ++ "2" + | _ => "hello" + } + Js.log(third) +} diff --git a/jscomp/test/build.ninja b/jscomp/test/build.ninja index 1057a91a41..db4def6feb 100644 --- a/jscomp/test/build.ninja +++ b/jscomp/test/build.ninja @@ -13,6 +13,7 @@ o test/Coercion.cmi test/Coercion.cmj : cc test/Coercion.res | $bsc others runti o test/DerivingAccessorsCurried.cmi test/DerivingAccessorsCurried.cmj : cc test/DerivingAccessorsCurried.res | $bsc others runtime o test/DerivingAccessorsUncurried.cmi test/DerivingAccessorsUncurried.cmj : cc test/DerivingAccessorsUncurried.res | $bsc others runtime o test/DictInference.cmi test/DictInference.cmj : cc test/DictInference.res | $bsc others runtime +o test/DictInternalRepresentation.cmi test/DictInternalRepresentation.cmj : cc test/DictInternalRepresentation.res | $bsc others runtime o test/DictTests.cmi test/DictTests.cmj : cc test/DictTests.res | $bsc others runtime o test/DisambiguateOptionalFields.cmi test/DisambiguateOptionalFields.cmj : cc test/DisambiguateOptionalFields.res | $bsc others runtime o test/DotDotDot.cmi test/DotDotDot.cmj : cc test/DotDotDot.res | $bsc others runtime @@ -623,4 +624,4 @@ o test/update_record_test.cmi test/update_record_test.cmj : cc test/update_recor o test/variant.cmi test/variant.cmj : cc test/variant.res | $bsc others runtime o test/variantsMatching.cmi test/variantsMatching.cmj : cc test/variantsMatching.res | $bsc others runtime o test/webpack_config.cmi test/webpack_config.cmj : cc test/webpack_config.res | $bsc others runtime -o test : phony test/AsInUncurriedExternals.cmi test/AsInUncurriedExternals.cmj test/Coercion.cmi test/Coercion.cmj test/DerivingAccessorsCurried.cmi test/DerivingAccessorsCurried.cmj test/DerivingAccessorsUncurried.cmi test/DerivingAccessorsUncurried.cmj test/DictInference.cmi test/DictInference.cmj test/DictTests.cmi test/DictTests.cmj test/DisambiguateOptionalFields.cmi test/DisambiguateOptionalFields.cmj test/DotDotDot.cmi test/DotDotDot.cmj test/EmptyRecord.cmi test/EmptyRecord.cmj test/ExternalArity.cmi test/ExternalArity.cmj test/FFI.cmi test/FFI.cmj test/Import.cmi test/Import.cmj test/ImportAttributes.cmi test/ImportAttributes.cmj test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj test/RecordCoercion.cmi test/RecordCoercion.cmj test/RecordOrObject.cmi test/RecordOrObject.cmj test/SafePromises.cmi test/SafePromises.cmj test/UncurriedAlways.cmi test/UncurriedAlways.cmj test/UncurriedExternals.cmi test/UncurriedExternals.cmj test/UncurriedPervasives.cmi test/UncurriedPervasives.cmj test/UntaggedVariants.cmi test/UntaggedVariants.cmj test/VariantCoercion.cmi test/VariantCoercion.cmj test/VariantPatternMatchingSpreads.cmi test/VariantPatternMatchingSpreads.cmj test/VariantPatternMatchingSpreadsWithPayloads.cmi test/VariantPatternMatchingSpreadsWithPayloads.cmj test/VariantSpreads.cmi test/VariantSpreads.cmj test/a.cmi test/a.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_default_value_test.cmi test/alias_default_value_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/as_inline_record_test.cmi test/as_inline_record_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_await.cmi test/async_await.cmj test/async_inline.cmi test/async_inline.cmj test/async_inside_loop.cmi test/async_inside_loop.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_float_ntest.cmi test/belt_float_ntest.cmj test/belt_hashmap_ntest.cmi test/belt_hashmap_ntest.cmj test/belt_hashset_int_ntest.cmi test/belt_hashset_int_ntest.cmj test/belt_int_ntest.cmi test/belt_int_ntest.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_list_ntest.cmi test/belt_list_ntest.cmj test/belt_mapint_ntest.cmi test/belt_mapint_ntest.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/belt_sortarray_ntest.cmi test/belt_sortarray_ntest.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/bigint_test.cmi test/bigint_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/caml_compare_bigint_test.cmi test/caml_compare_bigint_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/directives.cmi test/directives.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exotic_labels_test.cmi test/exotic_labels_test.cmj test/exponentiation_precedence_test.cmi test/exponentiation_precedence_test.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/external_ppx2.cmi test/external_ppx2.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/function_directives.cmi test/function_directives.cmj test/function_directives_no_inline.cmi test/function_directives_no_inline.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_4931_allow.cmi test/gpr_4931_allow.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_5280_optimize_test.cmi test/gpr_5280_optimize_test.cmj test/gpr_5557.cmi test/gpr_5557.cmj test/gpr_5753.cmi test/gpr_5753.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_7012_test.cmi test/gpr_7012_test.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/ignore_test.cmi test/ignore_test.cmj test/ignore_uncurry_attribute.cmi test/ignore_uncurry_attribute.cmj test/import2.cmi test/import2.cmj test/import_external.cmi test/import_external.cmj test/import_side_effect.cmi test/import_side_effect.cmj test/import_side_effect_free.cmi test/import_side_effect_free.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_condition_with_pattern_matching.cmi test/inline_condition_with_pattern_matching.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/jsxv4_newtype.cmi test/jsxv4_newtype.cmj test/keep_uncurry_attribute.cmi test/keep_uncurry_attribute.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_test.cmi test/list_test.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/mario_game.cmi test/mario_game.cmj test/meth_annotation.cmi test/meth_annotation.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_assert.cmi test/node_assert.cmj test/node_path_test.cmi test/node_path_test.cmj test/node_test.cmi test/node_test.cmj test/node_test_util.cmi test/node_test_util.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/offset.cmi test/offset.cmj test/omit_trailing_undefined_in_external_calls.cmi test/omit_trailing_undefined_in_external_calls.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/queue_402.cmi test/queue_402.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_array_test.cmi test/rec_array_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/recmodule.cmi test/recmodule.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_type_spread.cmi test/record_type_spread.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_annotation.cmi test/set_annotation.cmj test/set_gen.cmi test/set_gen.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect2.cmi test/side_effect2.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_constant_compare.cmi test/string_constant_compare.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/switch_string.cmi test/switch_string.cmj test/tagged_template_test.cmi test/tagged_template_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/template.cmi test/template.cmj test/test2.cmi test/test2.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unknown.cmi test/test_unknown.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type-coercion-free-vars.cmi test/type-coercion-free-vars.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_crash.cmi test/unboxed_crash.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurried_cast.cmi test/uncurried_cast.cmj test/uncurried_default.args.cmi test/uncurried_default.args.cmj test/uncurried_pipe.cmi test/uncurried_pipe.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/update_record_test.cmi test/update_record_test.cmj test/variant.cmi test/variant.cmj test/variantsMatching.cmi test/variantsMatching.cmj test/webpack_config.cmi test/webpack_config.cmj +o test : phony test/AsInUncurriedExternals.cmi test/AsInUncurriedExternals.cmj test/Coercion.cmi test/Coercion.cmj test/DerivingAccessorsCurried.cmi test/DerivingAccessorsCurried.cmj test/DerivingAccessorsUncurried.cmi test/DerivingAccessorsUncurried.cmj test/DictInference.cmi test/DictInference.cmj test/DictInternalRepresentation.cmi test/DictInternalRepresentation.cmj test/DictTests.cmi test/DictTests.cmj test/DisambiguateOptionalFields.cmi test/DisambiguateOptionalFields.cmj test/DotDotDot.cmi test/DotDotDot.cmj test/EmptyRecord.cmi test/EmptyRecord.cmj test/ExternalArity.cmi test/ExternalArity.cmj test/FFI.cmi test/FFI.cmj test/Import.cmi test/Import.cmj test/ImportAttributes.cmi test/ImportAttributes.cmj test/PartialApplicationNoRuntimeCurry.cmi test/PartialApplicationNoRuntimeCurry.cmj test/RecordCoercion.cmi test/RecordCoercion.cmj test/RecordOrObject.cmi test/RecordOrObject.cmj test/SafePromises.cmi test/SafePromises.cmj test/UncurriedAlways.cmi test/UncurriedAlways.cmj test/UncurriedExternals.cmi test/UncurriedExternals.cmj test/UncurriedPervasives.cmi test/UncurriedPervasives.cmj test/UntaggedVariants.cmi test/UntaggedVariants.cmj test/VariantCoercion.cmi test/VariantCoercion.cmj test/VariantPatternMatchingSpreads.cmi test/VariantPatternMatchingSpreads.cmj test/VariantPatternMatchingSpreadsWithPayloads.cmi test/VariantPatternMatchingSpreadsWithPayloads.cmj test/VariantSpreads.cmi test/VariantSpreads.cmj test/a.cmi test/a.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_default_value_test.cmi test/alias_default_value_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/as_inline_record_test.cmi test/as_inline_record_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_await.cmi test/async_await.cmj test/async_inline.cmi test/async_inline.cmj test/async_inside_loop.cmi test/async_inside_loop.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_float_ntest.cmi test/belt_float_ntest.cmj test/belt_hashmap_ntest.cmi test/belt_hashmap_ntest.cmj test/belt_hashset_int_ntest.cmi test/belt_hashset_int_ntest.cmj test/belt_int_ntest.cmi test/belt_int_ntest.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_list_ntest.cmi test/belt_list_ntest.cmj test/belt_mapint_ntest.cmi test/belt_mapint_ntest.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/belt_sortarray_ntest.cmi test/belt_sortarray_ntest.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/bigint_test.cmi test/bigint_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/caml_compare_bigint_test.cmi test/caml_compare_bigint_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/directives.cmi test/directives.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exotic_labels_test.cmi test/exotic_labels_test.cmj test/exponentiation_precedence_test.cmi test/exponentiation_precedence_test.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/external_ppx2.cmi test/external_ppx2.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/function_directives.cmi test/function_directives.cmj test/function_directives_no_inline.cmi test/function_directives_no_inline.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_4931_allow.cmi test/gpr_4931_allow.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_5280_optimize_test.cmi test/gpr_5280_optimize_test.cmj test/gpr_5557.cmi test/gpr_5557.cmj test/gpr_5753.cmi test/gpr_5753.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_7012_test.cmi test/gpr_7012_test.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/ignore_test.cmi test/ignore_test.cmj test/ignore_uncurry_attribute.cmi test/ignore_uncurry_attribute.cmj test/import2.cmi test/import2.cmj test/import_external.cmi test/import_external.cmj test/import_side_effect.cmi test/import_side_effect.cmj test/import_side_effect_free.cmi test/import_side_effect_free.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_condition_with_pattern_matching.cmi test/inline_condition_with_pattern_matching.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/jsxv4_newtype.cmi test/jsxv4_newtype.cmj test/keep_uncurry_attribute.cmi test/keep_uncurry_attribute.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_test.cmi test/list_test.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/mario_game.cmi test/mario_game.cmj test/meth_annotation.cmi test/meth_annotation.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_assert.cmi test/node_assert.cmj test/node_path_test.cmi test/node_path_test.cmj test/node_test.cmi test/node_test.cmj test/node_test_util.cmi test/node_test_util.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/offset.cmi test/offset.cmj test/omit_trailing_undefined_in_external_calls.cmi test/omit_trailing_undefined_in_external_calls.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/queue_402.cmi test/queue_402.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_array_test.cmi test/rec_array_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/recmodule.cmi test/recmodule.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_type_spread.cmi test/record_type_spread.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_annotation.cmi test/set_annotation.cmj test/set_gen.cmi test/set_gen.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect2.cmi test/side_effect2.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_constant_compare.cmi test/string_constant_compare.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/switch_string.cmi test/switch_string.cmj test/tagged_template_test.cmi test/tagged_template_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/template.cmi test/template.cmj test/test2.cmi test/test2.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unknown.cmi test/test_unknown.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type-coercion-free-vars.cmi test/type-coercion-free-vars.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_crash.cmi test/unboxed_crash.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurried_cast.cmi test/uncurried_cast.cmj test/uncurried_default.args.cmi test/uncurried_default.args.cmj test/uncurried_pipe.cmi test/uncurried_pipe.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/update_record_test.cmi test/update_record_test.cmj test/variant.cmi test/variant.cmj test/variantsMatching.cmi test/variantsMatching.cmj test/webpack_config.cmi test/webpack_config.cmj From 768814f892d8489a58431b794601f09138e2c68c Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 14:33:34 +0200 Subject: [PATCH 16/31] add more fields to test --- jscomp/test/DictInternalRepresentation.js | 3 +++ jscomp/test/DictTests.js | 15 ++++++++++++++- jscomp/test/DictTests.res | 7 ++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/jscomp/test/DictInternalRepresentation.js b/jscomp/test/DictInternalRepresentation.js index 54a2143c61..641a311cdb 100644 --- a/jscomp/test/DictInternalRepresentation.js +++ b/jscomp/test/DictInternalRepresentation.js @@ -17,6 +17,9 @@ function foo() { let first$2 = intDict.first; let second = first$2 !== undefined ? first$2 + 2 | 0 : 1; console.log(second); + let first$3 = stringDict.first; + let third = first$3 !== undefined ? first$3 + "2" : "hello"; + console.log(third); } exports.stringDict = stringDict; diff --git a/jscomp/test/DictTests.js b/jscomp/test/DictTests.js index 48b048847d..5d9df63325 100644 --- a/jscomp/test/DictTests.js +++ b/jscomp/test/DictTests.js @@ -20,7 +20,20 @@ let intDict = { function inferDictByPattern(dict) { let match = dict.one; if (match === 1) { - console.log("one"); + let match$1 = dict.three; + if (match$1 === 3) { + let match$2 = dict.four; + if (match$2 === 4) { + dict["five"] = 5; + return; + } + + } + + } + let match$3 = dict.two; + if (match$3 === 1) { + console.log("two"); } else { console.log("not one"); } diff --git a/jscomp/test/DictTests.res b/jscomp/test/DictTests.res index 4ab90dd134..0cf8cd843b 100644 --- a/jscomp/test/DictTests.res +++ b/jscomp/test/DictTests.res @@ -18,9 +18,10 @@ let intDict = dict{ module PatternMatching = { let inferDictByPattern = dict => switch dict { - | @res.dictPattern {one: 1} => - let _d: dict = dict - Js.log("one") + | @res.dictPattern {one: 1, three: 3, four: 4} => + // Make sure that the dict is of correct type + dict->Js.Dict.set("five", 5) + | @res.dictPattern {two: 1} => Js.log("two") | _ => Js.log("not one") } From 828b01c82722fa29f78c36e255f9163fdb65077f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 15:37:58 +0200 Subject: [PATCH 17/31] comment + rename file --- jscomp/ml/{dicts.ml => dict_type_helpers.ml} | 0 jscomp/ml/typecore.ml | 8 ++++++-- 2 files changed, 6 insertions(+), 2 deletions(-) rename jscomp/ml/{dicts.ml => dict_type_helpers.ml} (100%) diff --git a/jscomp/ml/dicts.ml b/jscomp/ml/dict_type_helpers.ml similarity index 100% rename from jscomp/ml/dicts.ml rename to jscomp/ml/dict_type_helpers.ml diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index eb1b438c05..f0cfc41b97 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -1384,7 +1384,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env | _ -> k None end | Ppat_record(lid_sp_list, closed) -> - let has_dict_pattern_attr = Dicts.has_dict_pattern_attribute sp.ppat_attributes in + let has_dict_pattern_attr = Dict_type_helpers.has_dict_pattern_attribute sp.ppat_attributes in let opath, record_ty = ( match (has_dict_pattern_attr, expected_ty.desc) with | (true, Tvar _) -> @@ -3029,7 +3029,11 @@ and type_label_access env srecord lid = try match extract_concrete_typedecl env ty_exp with | (p0, _, {type_attributes}) - when Path.same p0 Predef.path_dict && Dicts.has_dict_attribute type_attributes -> + when Path.same p0 Predef.path_dict && Dict_type_helpers.has_dict_attribute type_attributes -> + (* Cover the case when trying to direct field access on a dict, e.g. `someDict.name`. + We need to disallow this because the fact that a dict is represented as a single field + record internally is just an implementation detail, and not intended to be exposed to + the user.*) raise(Error(lid.loc, env, Field_access_on_dict_type)) | (p0, p, {type_kind=Type_record _}) -> Some(p0, p) | _ -> None From 821bd2d64731fe1e3c77071112f3178e76789940 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 15:54:55 +0200 Subject: [PATCH 18/31] share a few definitions --- .../expected/dict_coercion.res.expected | 2 +- ...ict_pattern_inference_constrained.res.expected | 2 +- .../super_errors/fixtures/dict_coercion.res | 2 +- .../fixtures/dict_magic_field_on_non_dict.res | 2 +- jscomp/ml/dict_type_helpers.ml | 12 ++++++++++-- jscomp/ml/predef.ml | 15 ++++++++++----- jscomp/ml/typecore.ml | 6 +++--- 7 files changed, 27 insertions(+), 14 deletions(-) diff --git a/jscomp/build_tests/super_errors/expected/dict_coercion.res.expected b/jscomp/build_tests/super_errors/expected/dict_coercion.res.expected index c0f20c4fd2..5e7889860a 100644 --- a/jscomp/build_tests/super_errors/expected/dict_coercion.res.expected +++ b/jscomp/build_tests/super_errors/expected/dict_coercion.res.expected @@ -2,7 +2,7 @@ We've found a bug for you! /.../fixtures/dict_coercion.res:7:10-30 - 5 │ type fakeDict<'t> = {anyOtherField?: 't} + 5 │ type fakeDict<'t> = {dictValuesType?: 't} 6 │ 7 │ let d = (dict :> fakeDict) 8 │ diff --git a/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected b/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected index a1ba01a48d..a5caf992a8 100644 --- a/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected +++ b/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected @@ -8,7 +8,7 @@ 4 │ let _: dict = dict 5 │ Js.log("one") - the following labels are not bound in this record pattern: anyOtherField + the following labels are not bound in this record pattern: dictValuesType Either bind these labels explicitly or add ', _' to the pattern. diff --git a/jscomp/build_tests/super_errors/fixtures/dict_coercion.res b/jscomp/build_tests/super_errors/fixtures/dict_coercion.res index a1a70178a0..b58fe32d9a 100644 --- a/jscomp/build_tests/super_errors/fixtures/dict_coercion.res +++ b/jscomp/build_tests/super_errors/fixtures/dict_coercion.res @@ -2,6 +2,6 @@ let dict = Js.Dict.empty() dict->Js.Dict.set("someKey1", 1) dict->Js.Dict.set("someKey2", 2) -type fakeDict<'t> = {anyOtherField?: 't} +type fakeDict<'t> = {dictValuesType?: 't} let d = (dict :> fakeDict) diff --git a/jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res b/jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res index 2af6937040..5f3e978589 100644 --- a/jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res +++ b/jscomp/build_tests/super_errors/fixtures/dict_magic_field_on_non_dict.res @@ -1,4 +1,4 @@ -type fakeDict<'t> = {anyOtherField?: 't} +type fakeDict<'t> = {dictValuesType?: 't} let foo = (fakeDict: fakeDict<'a>) => { switch fakeDict { diff --git a/jscomp/ml/dict_type_helpers.ml b/jscomp/ml/dict_type_helpers.ml index aae10a8065..322722fb33 100644 --- a/jscomp/ml/dict_type_helpers.ml +++ b/jscomp/ml/dict_type_helpers.ml @@ -1,3 +1,5 @@ +let dict_magic_field_name = "dictValuesType" + let has_dict_pattern_attribute attrs = attrs |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> @@ -6,5 +8,11 @@ let has_dict_pattern_attribute attrs = let has_dict_attribute attrs = attrs - |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> txt = "res.dict") - |> Option.is_some \ No newline at end of file + |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> txt = "res.$dict") + |> Option.is_some + +let dict_attr : Parsetree.attribute = + (Location.mknoloc "res.$dict", Parsetree.PStr []) + +let dict_magic_field_attr : Parsetree.attribute = + (Location.mknoloc "res.$dictMagicField", Parsetree.PStr []) diff --git a/jscomp/ml/predef.ml b/jscomp/ml/predef.ml index 9fc710ebe0..1abf024876 100644 --- a/jscomp/ml/predef.ml +++ b/jscomp/ml/predef.ml @@ -112,7 +112,7 @@ and ident_failure = ident_create_predef_exn "Failure" and ident_ok = ident_create_predef_exn "Ok" and ident_error = ident_create_predef_exn "Error" -and ident_anyOtherField = ident_create "anyOtherField" +and ident_dict_magic_field_name = ident_create Dict_type_helpers.dict_magic_field_name and ident_js_error = ident_create_predef_exn "JsError" and ident_not_found = ident_create_predef_exn "Not_found" @@ -220,19 +220,24 @@ let common_initial_env add_type add_extension empty_env = type_variance = [Variance.covariant; Variance.covariant]} and decl_dict = let tvar = newgenvar() in + (* Dicts are implented as a as a single "magic" field record. This magic field + is then leveraged to be able to piggy back on the existing record pattern + matching mechanism. So, this definition is import for the dict pattern + matching functionality, but not something intended to be exposed to the + user. *) {decl_abstr with - type_attributes = [(Location.mknoloc "res.dict", Parsetree.PStr [])]; + type_attributes = [Dict_type_helpers.dict_attr]; type_params = [tvar]; type_arity = 1; type_variance = [Variance.full]; type_kind = Type_record ([{ - ld_id = ident_anyOtherField; - ld_attributes = [(Location.mknoloc "res.optional", Parsetree.PStr []); (Location.mknoloc "res.dictMagicField", Parsetree.PStr [])]; + ld_id = ident_dict_magic_field_name; + ld_attributes = [(Location.mknoloc "res.optional", Parsetree.PStr []); Dict_type_helpers.dict_magic_field_attr]; ld_loc = Location.none; ld_mutable = Immutable; (* TODO(dict-pattern-matching) Should probably be mutable? *) ld_type = newgenty (Tconstr (path_option, [tvar], ref Mnil)); }], - Record_optional_labels [Ident.name ident_anyOtherField]); + Record_optional_labels [Ident.name ident_dict_magic_field_name]); } and decl_uncurried = let tvar1, tvar2 = newgenvar(), newgenvar() in diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index f0cfc41b97..3d8f1eb316 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -811,12 +811,12 @@ end) = struct Longident.Lident s_ -> begin let s = if List.exists (fun nd -> get_name nd = s_) descrs - || not (List.exists (fun nd -> get_name nd = "anyOtherField") descrs) + || not (List.exists (fun nd -> get_name nd = Dict_type_helpers.dict_magic_field_name) descrs) then s_ - else "anyOtherField" in + else Dict_type_helpers.dict_magic_field_name in try let x = List.find (fun nd -> get_name nd = s) descrs in - if s = "anyOtherField" + if s = Dict_type_helpers.dict_magic_field_name then add_with_name x s_ else x with Not_found -> From ae1ff05fcd13a2726c933f6b3583fc36595bd33d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 19:53:14 +0200 Subject: [PATCH 19/31] no need to check tvar --- .../dict_pattern_regular_record.res.expected | 25 +++++++++++++++++++ .../fixtures/dict_pattern_regular_record.res | 7 ++++++ jscomp/ml/typecore.ml | 5 ++-- 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected create mode 100644 jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res diff --git a/jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected b/jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected new file mode 100644 index 0000000000..d5d2d77763 --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected @@ -0,0 +1,25 @@ + + Warning number 9 + /.../fixtures/dict_pattern_regular_record.res:5:22-33 + + 3 │ let constrainedAsDict = (dict: x) => + 4 │ switch dict { + 5 │ | @res.dictPattern {one: "one"} => Js.log("one") + 6 │ | _ => Js.log("not one") + 7 │ } + + the following labels are not bound in this record pattern: dictValuesType +Either bind these labels explicitly or add ', _' to the pattern. + + + We've found a bug for you! + /.../fixtures/dict_pattern_regular_record.res:5:22-33 + + 3 │ let constrainedAsDict = (dict: x) => + 4 │ switch dict { + 5 │ | @res.dictPattern {one: "one"} => Js.log("one") + 6 │ | _ => Js.log("not one") + 7 │ } + + This pattern matches values of type dict + but a pattern was expected which matches values of type x \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res b/jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res new file mode 100644 index 0000000000..2fe964eaef --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res @@ -0,0 +1,7 @@ +type x = {one: int} + +let constrainedAsDict = (dict: x) => + switch dict { + | @res.dictPattern {one: "one"} => Js.log("one") + | _ => Js.log("not one") + } diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 3d8f1eb316..4b076eb597 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -1386,13 +1386,12 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env | Ppat_record(lid_sp_list, closed) -> let has_dict_pattern_attr = Dict_type_helpers.has_dict_pattern_attribute sp.ppat_attributes in let opath, record_ty = ( - match (has_dict_pattern_attr, expected_ty.desc) with - | (true, Tvar _) -> + if has_dict_pattern_attr then ( (* When this is a dict pattern and we don't have an actual expected type yet, infer the type as a dict with a new type variable. This let us hook into the existing inference mechanism for records in dict pattern matching too. *) (Some (Predef.path_dict, Predef.path_dict), newgenty (Tconstr (Predef.path_dict, [newvar ()], ref Mnil))) - | _ -> + ) else try let (p0, p, _, _) = extract_concrete_record !env expected_ty in Some (p0, p), expected_ty From c5587710600dbf0a86761584b2dddaf499fa30c2 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 20:02:13 +0200 Subject: [PATCH 20/31] remove comment --- jscomp/ml/predef.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jscomp/ml/predef.ml b/jscomp/ml/predef.ml index 1abf024876..327144401b 100644 --- a/jscomp/ml/predef.ml +++ b/jscomp/ml/predef.ml @@ -234,7 +234,7 @@ let common_initial_env add_type add_extension empty_env = ld_id = ident_dict_magic_field_name; ld_attributes = [(Location.mknoloc "res.optional", Parsetree.PStr []); Dict_type_helpers.dict_magic_field_attr]; ld_loc = Location.none; - ld_mutable = Immutable; (* TODO(dict-pattern-matching) Should probably be mutable? *) + ld_mutable = Immutable; ld_type = newgenty (Tconstr (path_option, [tvar], ref Mnil)); }], Record_optional_labels [Ident.name ident_dict_magic_field_name]); From f91c04cb1e7f19c1e34a7efafff7767d1fab572f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 20:10:25 +0200 Subject: [PATCH 21/31] add more comments --- jscomp/ml/typecore.ml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 4b076eb597..3bc0ab7f92 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -804,9 +804,14 @@ end) = struct let lookup_from_type env tpath (lid : Longident.t loc) : Name.t = let descrs = get_descrs (Env.find_type_descrs tpath env) in Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env); - (* TODO(dict-pattern-matching): also lookup the actual definition and check for @res.dict? *) let is_dict = Path.same tpath Predef.path_dict in if is_dict then ( + (* [dict] Dicts are implented as a record with a single "magic" field. This magic field is + used to track the dict value type, and any label lookup on the dict record type + will give that single value type back. This is how we can piggy back on the record + pattern matching mechanism. + + The code below handles directing any label lookup to the magic field. *) match lid.txt with Longident.Lident s_ -> begin let s = @@ -908,7 +913,11 @@ module Label = NameChoice (struct type t = label_description let type_kind = "record" let get_name lbl = lbl.lbl_name + let add_with_name lbl name = + (* [dict] This is used in dicts and shouldn't be used anywhere else. + It adds a new field to an existing record type, to "fool" the pattern + matching into thinking the label exists. *) let l = {lbl with lbl_name = name; @@ -1387,9 +1396,10 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env let has_dict_pattern_attr = Dict_type_helpers.has_dict_pattern_attribute sp.ppat_attributes in let opath, record_ty = ( if has_dict_pattern_attr then ( - (* When this is a dict pattern and we don't have an actual expected type yet, - infer the type as a dict with a new type variable. This let us hook into the - existing inference mechanism for records in dict pattern matching too. *) + (* [dict] If this is a dict pattern match we know we should force the record type + as the dict record type with a fresh type variable. This fixes so that dicts + can still be inferred properly from just pattern usage. Without this little + tweak, the inference would not work properly. *) (Some (Predef.path_dict, Predef.path_dict), newgenty (Tconstr (Predef.path_dict, [newvar ()], ref Mnil))) ) else try @@ -3029,10 +3039,10 @@ and type_label_access env srecord lid = match extract_concrete_typedecl env ty_exp with | (p0, _, {type_attributes}) when Path.same p0 Predef.path_dict && Dict_type_helpers.has_dict_attribute type_attributes -> - (* Cover the case when trying to direct field access on a dict, e.g. `someDict.name`. + (* [dict] Cover the case when trying to direct field access on a dict, e.g. `someDict.name`. We need to disallow this because the fact that a dict is represented as a single field record internally is just an implementation detail, and not intended to be exposed to - the user.*) + the user. *) raise(Error(lid.loc, env, Field_access_on_dict_type)) | (p0, p, {type_kind=Type_record _}) -> Some(p0, p) | _ -> None From 00dd136cdc190c3f68e110e0fdcee80565085e3c Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 21:32:11 +0200 Subject: [PATCH 22/31] syntax support --- .../dict_pattern_inference.res.expected | 4 +- ...pattern_inference_constrained.res.expected | 15 +----- .../dict_pattern_regular_record.res.expected | 17 +------ .../fixtures/dict_pattern_inference.res | 2 +- .../dict_pattern_inference_constrained.res | 2 +- .../fixtures/dict_pattern_regular_record.res | 2 +- jscomp/syntax/src/res_core.ml | 26 ++++++++++ jscomp/syntax/src/res_parsetree_viewer.ml | 8 ++- jscomp/syntax/src/res_parsetree_viewer.mli | 1 + jscomp/syntax/src/res_printer.ml | 49 +++++++++++++++++++ .../tests/parsing/grammar/pattern/dict.res | 10 ++++ .../grammar/pattern/expected/dict.res.txt | 10 ++++ jscomp/syntax/tests/printer/pattern/dict.res | 10 ++++ .../printer/pattern/expected/dict.res.txt | 11 +++++ jscomp/test/DictInternalRepresentation.res | 6 +-- jscomp/test/DictTests.res | 6 +-- 16 files changed, 138 insertions(+), 41 deletions(-) create mode 100644 jscomp/syntax/tests/parsing/grammar/pattern/dict.res create mode 100644 jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt create mode 100644 jscomp/syntax/tests/printer/pattern/dict.res create mode 100644 jscomp/syntax/tests/printer/pattern/expected/dict.res.txt diff --git a/jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected b/jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected index 7eaf8a0832..eb2a546da9 100644 --- a/jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected +++ b/jscomp/build_tests/super_errors/expected/dict_pattern_inference.res.expected @@ -1,10 +1,10 @@ We've found a bug for you! - /.../fixtures/dict_pattern_inference.res:3:36-42 + /.../fixtures/dict_pattern_inference.res:3:27-33 1 │ let foo = dict => 2 │ switch dict { - 3 │ | @res.dictPattern {one: 1, two: "hello"} => Js.log("one") + 3 │ | dict{"one": 1, "two": "hello"} => Js.log("one") 4 │ | _ => Js.log("not one") 5 │ } diff --git a/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected b/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected index a5caf992a8..ce340c0ae9 100644 --- a/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected +++ b/jscomp/build_tests/super_errors/expected/dict_pattern_inference_constrained.res.expected @@ -1,22 +1,9 @@ - Warning number 9 - /.../fixtures/dict_pattern_inference_constrained.res:3:22-29 - - 1 │ let foo = dict => - 2 │ switch dict { - 3 │ | @res.dictPattern {one: 1} => - 4 │ let _: dict = dict - 5 │ Js.log("one") - - the following labels are not bound in this record pattern: dictValuesType -Either bind these labels explicitly or add ', _' to the pattern. - - We've found a bug for you! /.../fixtures/dict_pattern_inference_constrained.res:4:27-30 2 ┆ switch dict { - 3 ┆ | @res.dictPattern {one: 1} => + 3 ┆ | dict{"one": 1} => 4 ┆ let _: dict = dict 5 ┆ Js.log("one") 6 ┆ | _ => Js.log("not one") diff --git a/jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected b/jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected index d5d2d77763..69b1bb9e15 100644 --- a/jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected +++ b/jscomp/build_tests/super_errors/expected/dict_pattern_regular_record.res.expected @@ -1,23 +1,10 @@ - Warning number 9 - /.../fixtures/dict_pattern_regular_record.res:5:22-33 - - 3 │ let constrainedAsDict = (dict: x) => - 4 │ switch dict { - 5 │ | @res.dictPattern {one: "one"} => Js.log("one") - 6 │ | _ => Js.log("not one") - 7 │ } - - the following labels are not bound in this record pattern: dictValuesType -Either bind these labels explicitly or add ', _' to the pattern. - - We've found a bug for you! - /.../fixtures/dict_pattern_regular_record.res:5:22-33 + /.../fixtures/dict_pattern_regular_record.res:5:5-22 3 │ let constrainedAsDict = (dict: x) => 4 │ switch dict { - 5 │ | @res.dictPattern {one: "one"} => Js.log("one") + 5 │ | dict{"one": "one"} => Js.log("one") 6 │ | _ => Js.log("not one") 7 │ } diff --git a/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res index 99f5e16166..b2b9e66b34 100644 --- a/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res +++ b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference.res @@ -1,5 +1,5 @@ let foo = dict => switch dict { - | @res.dictPattern {one: 1, two: "hello"} => Js.log("one") + | dict{"one": 1, "two": "hello"} => Js.log("one") | _ => Js.log("not one") } diff --git a/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res index b090126c61..36b315487e 100644 --- a/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res +++ b/jscomp/build_tests/super_errors/fixtures/dict_pattern_inference_constrained.res @@ -1,6 +1,6 @@ let foo = dict => switch dict { - | @res.dictPattern {one: 1} => + | dict{"one": 1} => let _: dict = dict Js.log("one") | _ => Js.log("not one") diff --git a/jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res b/jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res index 2fe964eaef..c5caecc489 100644 --- a/jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res +++ b/jscomp/build_tests/super_errors/fixtures/dict_pattern_regular_record.res @@ -2,6 +2,6 @@ type x = {one: int} let constrainedAsDict = (dict: x) => switch dict { - | @res.dictPattern {one: "one"} => Js.log("one") + | dict{"one": "one"} => Js.log("one") | _ => Js.log("not one") } diff --git a/jscomp/syntax/src/res_core.ml b/jscomp/syntax/src/res_core.ml index 08910341c6..a4779d7b90 100644 --- a/jscomp/syntax/src/res_core.ml +++ b/jscomp/syntax/src/res_core.ml @@ -1127,6 +1127,9 @@ let rec parse_pattern ?(alias = true) ?(or_ = true) p = | List -> Parser.next p; parse_list_pattern ~start_pos ~attrs p + | Dict -> + Parser.next p; + parse_dict_pattern ~start_pos ~attrs p | Module -> parse_module_pattern ~attrs p | Percent -> let extension = parse_extension p in @@ -1397,6 +1400,29 @@ and parse_list_pattern ~start_pos ~attrs p = let pat = make_list_pattern loc patterns None in {pat with ppat_loc = loc; ppat_attributes = attrs} +and parse_dict_pattern_row p = + match p.Parser.token with + | String s -> + let loc = mk_loc p.start_pos p.end_pos in + Parser.next p; + let fieldName = Location.mkloc (Longident.Lident s) loc in + Parser.expect Colon p; + let optional = parse_optional_label p in + let pat = parse_pattern p in + Some (fieldName, make_pattern_optional ~optional pat) + | _ -> None + +and parse_dict_pattern ~start_pos ~attrs (p : Parser.t) = + let fields = + parse_comma_delimited_region p ~grammar:DictRows ~closing:Rbrace + ~f:parse_dict_pattern_row + in + Parser.expect Rbrace p; + let loc = mk_loc start_pos p.prev_end_pos in + Ast_helper.Pat.record ~loc + ~attrs:((Location.mknoloc "res.dictPattern", PStr []) :: attrs) + fields Open + and parse_array_pattern ~attrs p = let start_pos = p.start_pos in Parser.expect Lbracket p; diff --git a/jscomp/syntax/src/res_parsetree_viewer.ml b/jscomp/syntax/src/res_parsetree_viewer.ml index 9edb373b1f..0b3b0ae857 100644 --- a/jscomp/syntax/src/res_parsetree_viewer.ml +++ b/jscomp/syntax/src/res_parsetree_viewer.ml @@ -105,6 +105,12 @@ let has_res_pat_variant_spread_attribute attrs = | _ -> false) attrs +let has_dict_pattern_attribute attrs = + attrs + |> List.find_opt (fun (({txt}, _) : Parsetree.attribute) -> + txt = "res.dictPattern") + |> Option.is_some + let collect_array_expressions expr = match expr.pexp_desc with | Pexp_array exprs -> (exprs, None) @@ -228,7 +234,7 @@ let filter_parsing_attrs attrs = ( "res.arity" | "res.braces" | "ns.braces" | "res.iflet" | "res.namedArgLoc" | "res.optional" | "res.ternary" | "res.async" | "res.await" | "res.template" | "res.taggedTemplate" - | "res.patVariantSpread" ); + | "res.patVariantSpread" | "res.dictPattern" ); }, _ ) -> false diff --git a/jscomp/syntax/src/res_parsetree_viewer.mli b/jscomp/syntax/src/res_parsetree_viewer.mli index e84691dd25..56e68a307b 100644 --- a/jscomp/syntax/src/res_parsetree_viewer.mli +++ b/jscomp/syntax/src/res_parsetree_viewer.mli @@ -28,6 +28,7 @@ val process_function_attributes : val has_await_attribute : Parsetree.attributes -> bool val has_res_pat_variant_spread_attribute : Parsetree.attributes -> bool +val has_dict_pattern_attribute : Parsetree.attributes -> bool type if_condition_kind = | If of Parsetree.expression diff --git a/jscomp/syntax/src/res_printer.ml b/jscomp/syntax/src/res_printer.ml index 507ed42034..e7c5356161 100644 --- a/jscomp/syntax/src/res_printer.ml +++ b/jscomp/syntax/src/res_printer.ml @@ -2416,6 +2416,25 @@ and print_pattern ~state (p : Parsetree.pattern) cmt_tbl = Doc.concat [Doc.text "..."; print_ident_path ident cmt_tbl] | Ppat_type ident -> Doc.concat [Doc.text "#..."; print_ident_path ident cmt_tbl] + | Ppat_record (rows, _) + when ParsetreeViewer.has_dict_pattern_attribute p.ppat_attributes -> + Doc.concat + [ + Doc.text "dict{"; + Doc.indent + (Doc.concat + [ + Doc.soft_line; + Doc.join + ~sep:(Doc.concat [Doc.text ","; Doc.line]) + (List.map + (fun row -> print_pattern_dict_row ~state row cmt_tbl) + rows); + ]); + Doc.if_breaks (Doc.text ",") Doc.nil; + Doc.soft_line; + Doc.rbrace; + ] | Ppat_record (rows, open_flag) -> Doc.group (Doc.concat @@ -2582,6 +2601,36 @@ and print_pattern_record_row ~state row cmt_tbl = in print_comments doc cmt_tbl loc_for_comments +and print_pattern_dict_row ~state + (row : Longident.t Location.loc * Parsetree.pattern) cmt_tbl = + match row with + | longident, pattern -> + let loc_for_comments = + {longident.loc with loc_end = pattern.ppat_loc.loc_end} + in + let rhs_doc = + let doc = print_pattern ~state pattern cmt_tbl in + let doc = + if Parens.pattern_record_row_rhs pattern then add_parens doc else doc + in + Doc.concat [print_optional_label pattern.ppat_attributes; doc] + in + let lbl_doc = + Doc.concat [Doc.text "\""; print_longident longident.txt; Doc.text "\""] + in + let doc = + Doc.group + (Doc.concat + [ + lbl_doc; + Doc.text ":"; + (if ParsetreeViewer.is_huggable_pattern pattern then + Doc.concat [Doc.space; rhs_doc] + else Doc.indent (Doc.concat [Doc.line; rhs_doc])); + ]) + in + print_comments doc cmt_tbl loc_for_comments + and print_expression_with_comments ~state expr cmt_tbl : Doc.t = let doc = print_expression ~state expr cmt_tbl in print_comments doc cmt_tbl expr.Parsetree.pexp_loc diff --git a/jscomp/syntax/tests/parsing/grammar/pattern/dict.res b/jscomp/syntax/tests/parsing/grammar/pattern/dict.res new file mode 100644 index 0000000000..dbee869239 --- /dev/null +++ b/jscomp/syntax/tests/parsing/grammar/pattern/dict.res @@ -0,0 +1,10 @@ +let someDict = dict{ + "one": "one", +} + +let dict{"one": ?one} = someDict + +let foo = () => switch someDict { +| dict{"one": "one"} => Js.log("one") +| _ => Js.log("not one") +} \ No newline at end of file diff --git a/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt b/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt new file mode 100644 index 0000000000..f3678bf8a2 --- /dev/null +++ b/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt @@ -0,0 +1,10 @@ +let someDict = Primitive_dict.make [|("one", {js|one|js})|] +let (({ one = ((one)[@res.optional ]);_})[@res.dictPattern ]) = someDict +let foo = + ((Function$ + (fun () -> + match someDict with + | (({ one = {js|one|js};_})[@res.dictPattern ]) -> + Js.log {js|one|js} + | _ -> Js.log {js|not one|js})) + [@res.arity 1]) \ No newline at end of file diff --git a/jscomp/syntax/tests/printer/pattern/dict.res b/jscomp/syntax/tests/printer/pattern/dict.res new file mode 100644 index 0000000000..dbee869239 --- /dev/null +++ b/jscomp/syntax/tests/printer/pattern/dict.res @@ -0,0 +1,10 @@ +let someDict = dict{ + "one": "one", +} + +let dict{"one": ?one} = someDict + +let foo = () => switch someDict { +| dict{"one": "one"} => Js.log("one") +| _ => Js.log("not one") +} \ No newline at end of file diff --git a/jscomp/syntax/tests/printer/pattern/expected/dict.res.txt b/jscomp/syntax/tests/printer/pattern/expected/dict.res.txt new file mode 100644 index 0000000000..8fea002783 --- /dev/null +++ b/jscomp/syntax/tests/printer/pattern/expected/dict.res.txt @@ -0,0 +1,11 @@ +let someDict = dict{ + "one": "one", +} + +let dict{"one": ?one} = someDict + +let foo = () => + switch someDict { + | dict{"one": "one"} => Js.log("one") + | _ => Js.log("not one") + } diff --git a/jscomp/test/DictInternalRepresentation.res b/jscomp/test/DictInternalRepresentation.res index bc3a940fea..a7ba45b640 100644 --- a/jscomp/test/DictInternalRepresentation.res +++ b/jscomp/test/DictInternalRepresentation.res @@ -9,17 +9,17 @@ let intDict = dict{ let foo = () => { let first = switch stringDict { - | @res.dictPattern {first} => first ++ "2" + | dict{"first": first} => first ++ "2" | _ => "hello" } Js.log(first) let second = switch intDict { - | @res.dictPattern {first} => first + 2 + | dict{"first": first} => first + 2 | _ => 1 } Js.log(second) let third = switch stringDict { - | @res.dictPattern {first} => first ++ "2" + | dict{"first": first} => first ++ "2" | _ => "hello" } Js.log(third) diff --git a/jscomp/test/DictTests.res b/jscomp/test/DictTests.res index 0cf8cd843b..e1d2523cac 100644 --- a/jscomp/test/DictTests.res +++ b/jscomp/test/DictTests.res @@ -18,16 +18,16 @@ let intDict = dict{ module PatternMatching = { let inferDictByPattern = dict => switch dict { - | @res.dictPattern {one: 1, three: 3, four: 4} => + | dict{"one": 1, "three": 3, "four": 4} => // Make sure that the dict is of correct type dict->Js.Dict.set("five", 5) - | @res.dictPattern {two: 1} => Js.log("two") + | dict{"two": 1} => Js.log("two") | _ => Js.log("not one") } let constrainedAsDict = (dict: dict) => switch dict { - | @res.dictPattern {one: 1} => + | dict{"one": 1} => let _d: dict = dict Js.log("one") | _ => Js.log("not one") From db294378d5d9a5da0c2ae921bc3b7ca9a7496129 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 30 Sep 2024 21:38:25 +0200 Subject: [PATCH 23/31] cleanup --- jscomp/syntax/src/res_printer.ml | 51 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/jscomp/syntax/src/res_printer.ml b/jscomp/syntax/src/res_printer.ml index e7c5356161..0c53e9cc00 100644 --- a/jscomp/syntax/src/res_printer.ml +++ b/jscomp/syntax/src/res_printer.ml @@ -2602,34 +2602,33 @@ and print_pattern_record_row ~state row cmt_tbl = print_comments doc cmt_tbl loc_for_comments and print_pattern_dict_row ~state - (row : Longident.t Location.loc * Parsetree.pattern) cmt_tbl = - match row with - | longident, pattern -> - let loc_for_comments = - {longident.loc with loc_end = pattern.ppat_loc.loc_end} - in - let rhs_doc = - let doc = print_pattern ~state pattern cmt_tbl in - let doc = - if Parens.pattern_record_row_rhs pattern then add_parens doc else doc - in - Doc.concat [print_optional_label pattern.ppat_attributes; doc] - in - let lbl_doc = - Doc.concat [Doc.text "\""; print_longident longident.txt; Doc.text "\""] - in + ((longident, pattern) : Longident.t Location.loc * Parsetree.pattern) + cmt_tbl = + let loc_for_comments = + {longident.loc with loc_end = pattern.ppat_loc.loc_end} + in + let rhs_doc = + let doc = print_pattern ~state pattern cmt_tbl in let doc = - Doc.group - (Doc.concat - [ - lbl_doc; - Doc.text ":"; - (if ParsetreeViewer.is_huggable_pattern pattern then - Doc.concat [Doc.space; rhs_doc] - else Doc.indent (Doc.concat [Doc.line; rhs_doc])); - ]) + if Parens.pattern_record_row_rhs pattern then add_parens doc else doc in - print_comments doc cmt_tbl loc_for_comments + Doc.concat [print_optional_label pattern.ppat_attributes; doc] + in + let lbl_doc = + Doc.concat [Doc.text "\""; print_longident longident.txt; Doc.text "\""] + in + let doc = + Doc.group + (Doc.concat + [ + lbl_doc; + Doc.text ":"; + (if ParsetreeViewer.is_huggable_pattern pattern then + Doc.concat [Doc.space; rhs_doc] + else Doc.indent (Doc.concat [Doc.line; rhs_doc])); + ]) + in + print_comments doc cmt_tbl loc_for_comments and print_expression_with_comments ~state expr cmt_tbl : Doc.t = let doc = print_expression ~state expr cmt_tbl in From d4df2f80c62dc0c62ece89d72154b90c44f7a02d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 1 Oct 2024 07:41:42 +0200 Subject: [PATCH 24/31] add broken dict pattern parsing test --- .../tests/parsing/grammar/pattern/dict.res | 41 ++++++++++++++++- .../grammar/pattern/expected/dict.res.txt | 46 +++++++++++++++---- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/jscomp/syntax/tests/parsing/grammar/pattern/dict.res b/jscomp/syntax/tests/parsing/grammar/pattern/dict.res index dbee869239..cd938eaac5 100644 --- a/jscomp/syntax/tests/parsing/grammar/pattern/dict.res +++ b/jscomp/syntax/tests/parsing/grammar/pattern/dict.res @@ -1,5 +1,5 @@ let someDict = dict{ - "one": "one", + "one": "one", } let dict{"one": ?one} = someDict @@ -7,4 +7,41 @@ let dict{"one": ?one} = someDict let foo = () => switch someDict { | dict{"one": "one"} => Js.log("one") | _ => Js.log("not one") -} \ No newline at end of file +} + +@unboxed +type rec json = + | Boolean(bool) + | @as(null) Null + | String(string) + | Number(float) + | Object(dict) + | Array(array) + +type user = { + name: string, + age?: float, +} + +let decodeUser = (json: json): option => { + switch json { + | Object(dict{ + "name": String(name), + "age": ageJson + }) => + Some({ + name, + age: ?switch ageJson { + | Number(age) => Some(age) + | _ => + /* Invalid age JSON type */ + None + }, + }) + | _ => + Js.log("Not an object.") + None + } +} + +Js.log(decodeUser(jsonParse(`{"name": "John", "age": 30}`))) \ No newline at end of file diff --git a/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt b/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt index f3678bf8a2..0fc54b10c2 100644 --- a/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt +++ b/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt @@ -1,10 +1,36 @@ -let someDict = Primitive_dict.make [|("one", {js|one|js})|] -let (({ one = ((one)[@res.optional ]);_})[@res.dictPattern ]) = someDict -let foo = - ((Function$ - (fun () -> - match someDict with - | (({ one = {js|one|js};_})[@res.dictPattern ]) -> - Js.log {js|one|js} - | _ -> Js.log {js|not one|js})) - [@res.arity 1]) \ No newline at end of file + + Syntax error! + tests/parsing/grammar/pattern/dict.res:28:12-16 + + 26 │ let decodeUser = (json: json): option => { + 27 │ switch json { + 28 │ | Object(dict{ + 29 │ "name": String(name), + 30 │ "age": ageJson + + Did you forget a `)` here? + + + Syntax error! + tests/parsing/grammar/pattern/dict.res:31:6 + + 29 ┆ "name": String(name), + 30 ┆ "age": ageJson + 31 ┆ }) => + 32 ┆ Some({ + 33 ┆ name, + + I'm not sure what to parse here when looking at ")". + + + Syntax error! + tests/parsing/grammar/pattern/dict.res:41:3 + + 39 ┆ }, + 40 ┆ }) + 41 ┆ | _ => + 42 ┆ Js.log("Not an object.") + 43 ┆ None + + I'm not sure what to parse here when looking at "|". + From 01132d3948829a9c7f9949608c4006c2b633d1c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Tue, 1 Oct 2024 16:35:27 +0200 Subject: [PATCH 25/31] fix pattern matching of dict --- jscomp/syntax/src/res_grammar.ml | 6 +- .../grammar/pattern/expected/dict.res.txt | 77 ++++++++++--------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/jscomp/syntax/src/res_grammar.ml b/jscomp/syntax/src/res_grammar.ml index 7e06e79c2e..35a5a498da 100644 --- a/jscomp/syntax/src/res_grammar.ml +++ b/jscomp/syntax/src/res_grammar.ml @@ -131,7 +131,7 @@ let is_signature_item_start = function let is_atomic_pattern_start = function | Token.Int _ | String _ | Codepoint _ | Backtick | Lparen | Lbracket | Lbrace - | Underscore | Lident _ | Uident _ | List | Exception | Percent -> + | Underscore | Lident _ | Uident _ | List | Dict | Exception | Percent -> true | _ -> false @@ -170,8 +170,8 @@ let is_structure_item_start = function let is_pattern_start = function | Token.Int _ | Float _ | String _ | Codepoint _ | Backtick | True | False - | Minus | Plus | Lparen | Lbracket | Lbrace | List | Underscore | Lident _ - | Uident _ | Hash | Exception | Percent | Module | At -> + | Minus | Plus | Lparen | Lbracket | Lbrace | List | Dict | Underscore + | Lident _ | Uident _ | Hash | Exception | Percent | Module | At -> true | _ -> false diff --git a/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt b/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt index 0fc54b10c2..752fce10ed 100644 --- a/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt +++ b/jscomp/syntax/tests/parsing/grammar/pattern/expected/dict.res.txt @@ -1,36 +1,41 @@ - - Syntax error! - tests/parsing/grammar/pattern/dict.res:28:12-16 - - 26 │ let decodeUser = (json: json): option => { - 27 │ switch json { - 28 │ | Object(dict{ - 29 │ "name": String(name), - 30 │ "age": ageJson - - Did you forget a `)` here? - - - Syntax error! - tests/parsing/grammar/pattern/dict.res:31:6 - - 29 ┆ "name": String(name), - 30 ┆ "age": ageJson - 31 ┆ }) => - 32 ┆ Some({ - 33 ┆ name, - - I'm not sure what to parse here when looking at ")". - - - Syntax error! - tests/parsing/grammar/pattern/dict.res:41:3 - - 39 ┆ }, - 40 ┆ }) - 41 ┆ | _ => - 42 ┆ Js.log("Not an object.") - 43 ┆ None - - I'm not sure what to parse here when looking at "|". - +let someDict = Primitive_dict.make [|("one", {js|one|js})|] +let (({ one = ((one)[@res.optional ]);_})[@res.dictPattern ]) = someDict +let foo = + ((Function$ + (fun () -> + match someDict with + | (({ one = {js|one|js};_})[@res.dictPattern ]) -> + Js.log {js|one|js} + | _ -> Js.log {js|not one|js})) + [@res.arity 1]) +type json = + | Boolean of bool + | Null [@as null] + | String of string + | Number of float + | Object of json dict + | Array of t array [@@unboxed ] +type nonrec user = { + name: string ; + age: float [@res.optional ]} +let decodeUser = + ((Function$ + (fun (json : json) -> + (((match json with + | Object + (({ name = String name; age = ageJson;_})[@res.dictPattern ]) + -> + Some + { + name; + age = + (((match ageJson with + | Number age -> Some age + | _ -> None))[@res.optional ]) + } + | _ -> (Js.log {js|Not an object.|js}; None)) + [@res.braces ]) : user option))) + [@res.arity 1]) +;;Js.log + (decodeUser + (jsonParse (({js|{"name": "John", "age": 30}|js})[@res.template ]))) \ No newline at end of file From 849d95094f78410cbb8dccfa6b5a2b75e9abb306 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 1 Oct 2024 21:15:41 +0200 Subject: [PATCH 26/31] comments and changelog --- CHANGELOG.md | 38 ++++++++++++++++++---------------- jscomp/ml/dict_type_helpers.ml | 30 +++++++++++++++++++++++++++ jscomp/ml/predef.ml | 13 +++++++----- jscomp/ml/typecore.ml | 2 +- 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d9da7b13..bd9d17e556 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,8 @@ - Use FORCE_COLOR environmental variable to force colorized output https://github.com/rescript-lang/rescript-compiler/pull/7033 - Allow spreads of variants in patterns (`| ...someVariant as v => `) when the variant spread is a subtype of the variant matched on. https://github.com/rescript-lang/rescript-compiler/pull/6721 -- Fix the issue where dynamic imports are not working for function-defined externals. https://github.com/rescript-lang/rescript-compiler/pull/7060 +- Fix the issue where dynamic imports are not working for function-defined externals. https://github.com/rescript-lang/rescript-compiler/pull/7060 +- Allow pattern matching on dicts. `switch someDict { | dict{"one": 1} => Js.log("one is one") }` https://github.com/rescript-lang/rescript-compiler/pull/7059 #### :bug: Bug fix @@ -316,7 +317,7 @@ #### :rocket: New Feature -- Experimental support of tagged template literals, e.g. ```sql`select * from ${table}```. https://github.com/rescript-lang/rescript-compiler/pull/6250 +- Experimental support of tagged template literals, e.g. `` sql`select * from ${table} ``. https://github.com/rescript-lang/rescript-compiler/pull/6250 - Experimental support for generic/custom JSX transforms. https://github.com/rescript-lang/rescript-compiler/pull/6565 - `dict` is now a builtin type. https://github.com/rescript-lang/rescript-compiler/pull/6590 @@ -496,7 +497,7 @@ No changes compared to rc.9. #### :boom: Breaking Change -- Stop mangling object field names. If you had objects with field names containing "__" or leading "_", they won't be mangled in the compiled JavaScript and represented as it is without changes. https://github.com/rescript-lang/rescript-compiler/pull/6354 +- Stop mangling object field names. If you had objects with field names containing "\__" or leading "_", they won't be mangled in the compiled JavaScript and represented as it is without changes. https://github.com/rescript-lang/rescript-compiler/pull/6354 #### :bug: Bug Fix @@ -551,7 +552,7 @@ No changes compared to rc.9. #### :rocket: New Feature -- Introduced a new `%ffi` extension (*experimental* - not for production use!) that provides a more robust mechanism for JavaScript function interoperation by considering function arity in type constraints. This enhancement improves safety when dealing with JavaScript functions by enforcing type constraints based on the arity of the function. https://github.com/rescript-lang/rescript-compiler/pull/6251 +- Introduced a new `%ffi` extension (_experimental_ - not for production use!) that provides a more robust mechanism for JavaScript function interoperation by considering function arity in type constraints. This enhancement improves safety when dealing with JavaScript functions by enforcing type constraints based on the arity of the function. https://github.com/rescript-lang/rescript-compiler/pull/6251 - Extended untagged variants with function types. https://github.com/rescript-lang/rescript-compiler/pull/6279 #### :boom: Breaking Change @@ -629,14 +630,14 @@ No changes compared to rc.9. #### :bug: Bug Fix -- Fix broken formatting in uncurried mode for functions with _ placeholder args. https://github.com/rescript-lang/rescript-compiler/pull/6148 +- Fix broken formatting in uncurried mode for functions with \_ placeholder args. https://github.com/rescript-lang/rescript-compiler/pull/6148 - Fix issue where spreading record types with optional labels would not have their labels preserved as optional. https://github.com/rescript-lang/rescript-compiler/pull/6154 - Fix error location to be the type with the spreads when spreading record types with duplicate labels. https://github.com/rescript-lang/rescript-compiler/pull/6157 - Disable warning on `@inline` attibute on uncurried functions. https://github.com/rescript-lang/rescript-compiler/pull/6152 - Support doc comments on arguments of function types. https://github.com/rescript-lang/rescript-compiler/pull/6161 - Fix issue with record type coercion and unboxed. https://github.com/rescript-lang/rescript-compiler/issues/6158 - Fixed subtype checking for record types with "@as" attributes: The subtype relationship now takes into account the compatibility of "@as" attributes between corresponding fields, ensuring correctness in runtime representation. - https://github.com/rescript-lang/rescript-compiler/issues/6158 + https://github.com/rescript-lang/rescript-compiler/issues/6158 - Emit directive above header comment. https://github.com/rescript-lang/rescript-compiler/pull/6172 - Add error message to private extension. https://github.com/rescript-lang/rescript-compiler/pull/6175 @@ -665,7 +666,6 @@ No changes compared to rc.9. - Special case generation of uncurried functions with 1 argument of unit type so they don't take a parameter. https://github.com/rescript-lang/rescript-compiler/pull/6131 - # 11.0.0-alpha.1 #### :rocket: Main New Feature @@ -676,16 +676,16 @@ No changes compared to rc.9. #### :rocket: New Feature - Add support for uncurried mode: a mode where everything is considered uncurried, whether with or without the `.`. This can be turned on with `@@uncurried` locally in a file. For project-level configuration in `bsconfig.json`, there's a boolean config `"uncurried"`, which propagates to dependencies, to turn on uncurried mode. -Since there's no syntax for partial application in this new mode, introduce `@res.partial foo(x)` to express partial application. This is temporary and will later have some surface syntax. -Make uncurried functions a subtype of curried functions, and allow application for uncurried functions. -The `make` function of components is generated as an uncurried function. -Use best effort to determine the config when formatting a file. -https://github.com/rescript-lang/rescript-compiler/pull/5968 https://github.com/rescript-lang/rescript-compiler/pull/6080 https://github.com/rescript-lang/rescript-compiler/pull/6086 https://github.com/rescript-lang/rescript-compiler/pull/6087 + Since there's no syntax for partial application in this new mode, introduce `@res.partial foo(x)` to express partial application. This is temporary and will later have some surface syntax. + Make uncurried functions a subtype of curried functions, and allow application for uncurried functions. + The `make` function of components is generated as an uncurried function. + Use best effort to determine the config when formatting a file. + https://github.com/rescript-lang/rescript-compiler/pull/5968 https://github.com/rescript-lang/rescript-compiler/pull/6080 https://github.com/rescript-lang/rescript-compiler/pull/6086 https://github.com/rescript-lang/rescript-compiler/pull/6087 - Customization of runtime representation of variants. This is work in progress. E.g. some restrictions on the input. See comments of the form "TODO: put restriction on the variant definitions allowed, to make sure this never happens". https://github.com/rescript-lang/rescript-compiler/pull/6095 - Introduce untagged variants https://github.com/rescript-lang/rescript-compiler/pull/6103 - Add support for unary uncurried pipe in uncurried mode https://github.com/rescript-lang/rescript-compiler/pull/5804 - Add support for partial application of uncurried functions: with uncurried application one can provide a -subset of the arguments, and return a curried type with the remaining ones https://github.com/rescript-lang/rescript-compiler/pull/5805 + subset of the arguments, and return a curried type with the remaining ones https://github.com/rescript-lang/rescript-compiler/pull/5805 - Add support for uncurried externals https://github.com/rescript-lang/rescript-compiler/pull/5815 https://github.com/rescript-lang/rescript-compiler/pull/5819 https://github.com/rescript-lang/rescript-compiler/pull/5830 https://github.com/rescript-lang/rescript-compiler/pull/5894 - Parser/Printer: unify uncurried functions of arity 0, and of arity 1 taking unit. There's now only arity 1 in the source language. https://github.com/rescript-lang/rescript-compiler/pull/5825 - Add support for default arguments in uncurried functions https://github.com/rescript-lang/rescript-compiler/pull/5835 @@ -707,12 +707,12 @@ subset of the arguments, and return a curried type with the remaining ones https - `rescript convert ` - Remove obsolete built-in project templates and the "rescript init" functionality. This is replaced by [create-rescript-app](https://github.com/rescript-lang/create-rescript-app) which is maintained separately. - Do not attempt to build ReScript from source on npm postinstall for platforms without prebuilt binaries anymore. -- Made pinned dependencies transitive: if *a* is a pinned dependency of *b* and *b* is a pinned dependency of *c*, then *a* is implicitly a pinned dependency of *c*. This change is only breaking if your build process assumes non-transitivity. +- Made pinned dependencies transitive: if _a_ is a pinned dependency of _b_ and _b_ is a pinned dependency of _c_, then _a_ is implicitly a pinned dependency of _c_. This change is only breaking if your build process assumes non-transitivity. - Curried after uncurried is not fused anymore: `(. x) => y => 3` is not equivalent to `(. x, y) => 3` anymore. It's instead equivalent to `(. x) => { y => 3 }`. -Also, `(. int) => string => bool` is not equivalen to `(. int, string) => bool` anymore. -These are only breaking changes for unformatted code. + Also, `(. int) => string => bool` is not equivalen to `(. int, string) => bool` anymore. + These are only breaking changes for unformatted code. - Exponentiation operator `**` is now right-associative. `2. ** 3. ** 2.` now compile to `Math.pow(2, Math.pow(3, 2))` and not anymore `Math.pow(Math.pow(2, 3), 2)`. Parentheses can be used to change precedence. -- Remove unsafe ``` j`$(a)$(b)` ``` interpolation deprecated in compiler version 10 https://github.com/rescript-lang/rescript-compiler/pull/6068 +- Remove unsafe `` j`$(a)$(b)` `` interpolation deprecated in compiler version 10 https://github.com/rescript-lang/rescript-compiler/pull/6068 - Remove deprecated module `Printexc` - `@deriving(jsConverter)` not supported anymore for variant types https://github.com/rescript-lang/rescript-compiler/pull/6088 - New representation for variants, where the tag is a string instead of a number. https://github.com/rescript-lang/rescript-compiler/pull/6088 @@ -761,19 +761,21 @@ These are only breaking changes for unformatted code. # 10.1.4 #### :bug: Bug Fix + - Fix implementation of directives https://github.com/rescript-lang/rescript-compiler/pull/6052 - Fix issue if the `lib` dir is included in the sources of bsconfig.json https://github.com/rescript-lang/rescript-compiler/pull/6055 - Fix issue with string escape in pattern match https://github.com/rescript-lang/rescript-compiler/pull/6062 - Fix issue with literal comparison of string constants https://github.com/rescript-lang/rescript-compiler/pull/6065 #### :rocket: New Feature + - Add support for toplevel `await` https://github.com/rescript-lang/rescript-compiler/pull/6054 #### :nail_care: Polish - Better error message for extension point https://github.com/rescript-lang/rescript-compiler/pull/6057 - Improve format check help https://github.com/rescript-lang/rescript-compiler/pull/6056 -- Deprecate unsafe ``` j`$(a)$(b)` ``` interpolation: use string templates ``` `${a}${b}` ``` instead https://github.com/rescript-lang/rescript-compiler/pull/6067 +- Deprecate unsafe `` j`$(a)$(b)` `` interpolation: use string templates `` `${a}${b}` `` instead https://github.com/rescript-lang/rescript-compiler/pull/6067 # 10.1.3 diff --git a/jscomp/ml/dict_type_helpers.ml b/jscomp/ml/dict_type_helpers.ml index 322722fb33..75a41142f6 100644 --- a/jscomp/ml/dict_type_helpers.ml +++ b/jscomp/ml/dict_type_helpers.ml @@ -1,3 +1,33 @@ +(* + An overview of the implementation of dicts in ReScript: + ### What is a dict? + Dicts are effectively an object with unknown fields, but a single known type of the values it holds. + + ### How are they implemented? + Dicts in ReScript are implemented as predefined record type, with a single (magic) field that holds + the type of the dict's values. This field is called `dictValuesType`, and is just an implementation + detail - it's never actually exposed to the user, just used internally. + + The compiler will route any label lookup on the dict record type to the magic field, which creates a + record with unknown keys, but of a single type. + + The reason for this seemingly convoluted implementation is that it allows us to piggyback on the + existing record pattern matching mechanism, which means we get pattern matching on dicts for free. + + ### Modifications to the type checker + We've made a few smaller modifications to the type checker to support this implementation: + + - We've added a new predefined type `dict` that is a record with a single field called `dictValuesType`. + This type is used to represent the type of the values in a dict. + - We've modified the type checker to recognize `dict` patterns, and route them to the predefined `dict` type. + This allows us to get full inference for dicts in patterns. + + ### Syntax + There's first class syntax support for dicts, both as expressions and as patterns. + A dict pattern is treated as a record pattern in the compiler and syntax, with an attriubute `@res.dictPattern` + attached to it. This attribute is used to tell the compiler that the pattern is a dict pattern, and is what + triggers the compiler to treat the dict record type differently to regular record types. + *) let dict_magic_field_name = "dictValuesType" let has_dict_pattern_attribute attrs = diff --git a/jscomp/ml/predef.ml b/jscomp/ml/predef.ml index 327144401b..3b1fba7add 100644 --- a/jscomp/ml/predef.ml +++ b/jscomp/ml/predef.ml @@ -220,11 +220,14 @@ let common_initial_env add_type add_extension empty_env = type_variance = [Variance.covariant; Variance.covariant]} and decl_dict = let tvar = newgenvar() in - (* Dicts are implented as a as a single "magic" field record. This magic field - is then leveraged to be able to piggy back on the existing record pattern - matching mechanism. So, this definition is import for the dict pattern - matching functionality, but not something intended to be exposed to the - user. *) + (* Dicts are implemented as a single "magic" field record. This magic field + is the medium through which we can piggy back on the existing record pattern + matching mechanism. We do this by letting the compiler route any label lookup + for the dict record type to the magic field, which has the type of the values + of the dict. + + So, this definition is important for the dict pattern matching functionality, + but not something intended to be exposed to the user. *) {decl_abstr with type_attributes = [Dict_type_helpers.dict_attr]; type_params = [tvar]; diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 3bc0ab7f92..56092fc7e2 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -806,7 +806,7 @@ end) = struct Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env); let is_dict = Path.same tpath Predef.path_dict in if is_dict then ( - (* [dict] Dicts are implented as a record with a single "magic" field. This magic field is + (* [dict] Dicts are implemented as a record with a single "magic" field. This magic field is used to track the dict value type, and any label lookup on the dict record type will give that single value type back. This is how we can piggy back on the record pattern matching mechanism. From c082baa61b38633f5048eee6221b7b164982b206 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 1 Oct 2024 21:23:37 +0200 Subject: [PATCH 27/31] a few more comment tests --- jscomp/syntax/tests/printer/pattern/dict.res | 49 +++++++++++++++++-- .../printer/pattern/expected/dict.res.txt | 44 +++++++++++++++-- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/jscomp/syntax/tests/printer/pattern/dict.res b/jscomp/syntax/tests/printer/pattern/dict.res index dbee869239..7bd4ee0bf5 100644 --- a/jscomp/syntax/tests/printer/pattern/dict.res +++ b/jscomp/syntax/tests/printer/pattern/dict.res @@ -1,10 +1,49 @@ let someDict = dict{ - "one": "one", + "one": "one", } let dict{"one": ?one} = someDict -let foo = () => switch someDict { -| dict{"one": "one"} => Js.log("one") -| _ => Js.log("not one") -} \ No newline at end of file +let foo = () => { + let _ = switch someDict { + // Comment here + | dict{ + // Comment above the pattern + "one": + // Comment right in the pattern + "one", + } => + Js.log("one") + | _ => Js.log("not one") + } + + let _ = switch someDict { + | dict{ + // foo + "one": "one", + // bar + "twoooooooooo": 2, + // baz + "three": 3, + "fooooour": 4, + "fiiiive": 5, + } => + Js.log("one") + | _ => Js.log("not one") + } + + let _ = switch someDict { + | dict{ + /* foo */ + /* baz */ "one": "one", + /* bar */ + /* baz */ "twoooooooooo": 2, + /* baz */ + /* baz */ "three": 3, + "fooooour": 4, + "fiiiive": 5, + } => + Js.log("one") + | _ => Js.log("not one") + } +} diff --git a/jscomp/syntax/tests/printer/pattern/expected/dict.res.txt b/jscomp/syntax/tests/printer/pattern/expected/dict.res.txt index 8fea002783..7bd4ee0bf5 100644 --- a/jscomp/syntax/tests/printer/pattern/expected/dict.res.txt +++ b/jscomp/syntax/tests/printer/pattern/expected/dict.res.txt @@ -4,8 +4,46 @@ let someDict = dict{ let dict{"one": ?one} = someDict -let foo = () => - switch someDict { - | dict{"one": "one"} => Js.log("one") +let foo = () => { + let _ = switch someDict { + // Comment here + | dict{ + // Comment above the pattern + "one": + // Comment right in the pattern + "one", + } => + Js.log("one") | _ => Js.log("not one") } + + let _ = switch someDict { + | dict{ + // foo + "one": "one", + // bar + "twoooooooooo": 2, + // baz + "three": 3, + "fooooour": 4, + "fiiiive": 5, + } => + Js.log("one") + | _ => Js.log("not one") + } + + let _ = switch someDict { + | dict{ + /* foo */ + /* baz */ "one": "one", + /* bar */ + /* baz */ "twoooooooooo": 2, + /* baz */ + /* baz */ "three": 3, + "fooooour": 4, + "fiiiive": 5, + } => + Js.log("one") + | _ => Js.log("not one") + } +} From 9fa2193348c8485a65629d1e0fd087a9631362ed Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 1 Oct 2024 21:38:32 +0200 Subject: [PATCH 28/31] undo changelog formatting --- CHANGELOG.md | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd9d17e556..cb04f07a3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ - Use FORCE_COLOR environmental variable to force colorized output https://github.com/rescript-lang/rescript-compiler/pull/7033 - Allow spreads of variants in patterns (`| ...someVariant as v => `) when the variant spread is a subtype of the variant matched on. https://github.com/rescript-lang/rescript-compiler/pull/6721 -- Fix the issue where dynamic imports are not working for function-defined externals. https://github.com/rescript-lang/rescript-compiler/pull/7060 +- Fix the issue where dynamic imports are not working for function-defined externals. https://github.com/rescript-lang/rescript-compiler/pull/7060 - Allow pattern matching on dicts. `switch someDict { | dict{"one": 1} => Js.log("one is one") }` https://github.com/rescript-lang/rescript-compiler/pull/7059 #### :bug: Bug fix @@ -317,7 +317,7 @@ #### :rocket: New Feature -- Experimental support of tagged template literals, e.g. `` sql`select * from ${table} ``. https://github.com/rescript-lang/rescript-compiler/pull/6250 +- Experimental support of tagged template literals, e.g. ```sql`select * from ${table}```. https://github.com/rescript-lang/rescript-compiler/pull/6250 - Experimental support for generic/custom JSX transforms. https://github.com/rescript-lang/rescript-compiler/pull/6565 - `dict` is now a builtin type. https://github.com/rescript-lang/rescript-compiler/pull/6590 @@ -497,7 +497,7 @@ No changes compared to rc.9. #### :boom: Breaking Change -- Stop mangling object field names. If you had objects with field names containing "\__" or leading "_", they won't be mangled in the compiled JavaScript and represented as it is without changes. https://github.com/rescript-lang/rescript-compiler/pull/6354 +- Stop mangling object field names. If you had objects with field names containing "__" or leading "_", they won't be mangled in the compiled JavaScript and represented as it is without changes. https://github.com/rescript-lang/rescript-compiler/pull/6354 #### :bug: Bug Fix @@ -552,7 +552,7 @@ No changes compared to rc.9. #### :rocket: New Feature -- Introduced a new `%ffi` extension (_experimental_ - not for production use!) that provides a more robust mechanism for JavaScript function interoperation by considering function arity in type constraints. This enhancement improves safety when dealing with JavaScript functions by enforcing type constraints based on the arity of the function. https://github.com/rescript-lang/rescript-compiler/pull/6251 +- Introduced a new `%ffi` extension (*experimental* - not for production use!) that provides a more robust mechanism for JavaScript function interoperation by considering function arity in type constraints. This enhancement improves safety when dealing with JavaScript functions by enforcing type constraints based on the arity of the function. https://github.com/rescript-lang/rescript-compiler/pull/6251 - Extended untagged variants with function types. https://github.com/rescript-lang/rescript-compiler/pull/6279 #### :boom: Breaking Change @@ -630,14 +630,14 @@ No changes compared to rc.9. #### :bug: Bug Fix -- Fix broken formatting in uncurried mode for functions with \_ placeholder args. https://github.com/rescript-lang/rescript-compiler/pull/6148 +- Fix broken formatting in uncurried mode for functions with _ placeholder args. https://github.com/rescript-lang/rescript-compiler/pull/6148 - Fix issue where spreading record types with optional labels would not have their labels preserved as optional. https://github.com/rescript-lang/rescript-compiler/pull/6154 - Fix error location to be the type with the spreads when spreading record types with duplicate labels. https://github.com/rescript-lang/rescript-compiler/pull/6157 - Disable warning on `@inline` attibute on uncurried functions. https://github.com/rescript-lang/rescript-compiler/pull/6152 - Support doc comments on arguments of function types. https://github.com/rescript-lang/rescript-compiler/pull/6161 - Fix issue with record type coercion and unboxed. https://github.com/rescript-lang/rescript-compiler/issues/6158 - Fixed subtype checking for record types with "@as" attributes: The subtype relationship now takes into account the compatibility of "@as" attributes between corresponding fields, ensuring correctness in runtime representation. - https://github.com/rescript-lang/rescript-compiler/issues/6158 + https://github.com/rescript-lang/rescript-compiler/issues/6158 - Emit directive above header comment. https://github.com/rescript-lang/rescript-compiler/pull/6172 - Add error message to private extension. https://github.com/rescript-lang/rescript-compiler/pull/6175 @@ -666,6 +666,7 @@ No changes compared to rc.9. - Special case generation of uncurried functions with 1 argument of unit type so they don't take a parameter. https://github.com/rescript-lang/rescript-compiler/pull/6131 + # 11.0.0-alpha.1 #### :rocket: Main New Feature @@ -676,16 +677,16 @@ No changes compared to rc.9. #### :rocket: New Feature - Add support for uncurried mode: a mode where everything is considered uncurried, whether with or without the `.`. This can be turned on with `@@uncurried` locally in a file. For project-level configuration in `bsconfig.json`, there's a boolean config `"uncurried"`, which propagates to dependencies, to turn on uncurried mode. - Since there's no syntax for partial application in this new mode, introduce `@res.partial foo(x)` to express partial application. This is temporary and will later have some surface syntax. - Make uncurried functions a subtype of curried functions, and allow application for uncurried functions. - The `make` function of components is generated as an uncurried function. - Use best effort to determine the config when formatting a file. - https://github.com/rescript-lang/rescript-compiler/pull/5968 https://github.com/rescript-lang/rescript-compiler/pull/6080 https://github.com/rescript-lang/rescript-compiler/pull/6086 https://github.com/rescript-lang/rescript-compiler/pull/6087 +Since there's no syntax for partial application in this new mode, introduce `@res.partial foo(x)` to express partial application. This is temporary and will later have some surface syntax. +Make uncurried functions a subtype of curried functions, and allow application for uncurried functions. +The `make` function of components is generated as an uncurried function. +Use best effort to determine the config when formatting a file. +https://github.com/rescript-lang/rescript-compiler/pull/5968 https://github.com/rescript-lang/rescript-compiler/pull/6080 https://github.com/rescript-lang/rescript-compiler/pull/6086 https://github.com/rescript-lang/rescript-compiler/pull/6087 - Customization of runtime representation of variants. This is work in progress. E.g. some restrictions on the input. See comments of the form "TODO: put restriction on the variant definitions allowed, to make sure this never happens". https://github.com/rescript-lang/rescript-compiler/pull/6095 - Introduce untagged variants https://github.com/rescript-lang/rescript-compiler/pull/6103 - Add support for unary uncurried pipe in uncurried mode https://github.com/rescript-lang/rescript-compiler/pull/5804 - Add support for partial application of uncurried functions: with uncurried application one can provide a - subset of the arguments, and return a curried type with the remaining ones https://github.com/rescript-lang/rescript-compiler/pull/5805 +subset of the arguments, and return a curried type with the remaining ones https://github.com/rescript-lang/rescript-compiler/pull/5805 - Add support for uncurried externals https://github.com/rescript-lang/rescript-compiler/pull/5815 https://github.com/rescript-lang/rescript-compiler/pull/5819 https://github.com/rescript-lang/rescript-compiler/pull/5830 https://github.com/rescript-lang/rescript-compiler/pull/5894 - Parser/Printer: unify uncurried functions of arity 0, and of arity 1 taking unit. There's now only arity 1 in the source language. https://github.com/rescript-lang/rescript-compiler/pull/5825 - Add support for default arguments in uncurried functions https://github.com/rescript-lang/rescript-compiler/pull/5835 @@ -707,12 +708,12 @@ No changes compared to rc.9. - `rescript convert ` - Remove obsolete built-in project templates and the "rescript init" functionality. This is replaced by [create-rescript-app](https://github.com/rescript-lang/create-rescript-app) which is maintained separately. - Do not attempt to build ReScript from source on npm postinstall for platforms without prebuilt binaries anymore. -- Made pinned dependencies transitive: if _a_ is a pinned dependency of _b_ and _b_ is a pinned dependency of _c_, then _a_ is implicitly a pinned dependency of _c_. This change is only breaking if your build process assumes non-transitivity. +- Made pinned dependencies transitive: if *a* is a pinned dependency of *b* and *b* is a pinned dependency of *c*, then *a* is implicitly a pinned dependency of *c*. This change is only breaking if your build process assumes non-transitivity. - Curried after uncurried is not fused anymore: `(. x) => y => 3` is not equivalent to `(. x, y) => 3` anymore. It's instead equivalent to `(. x) => { y => 3 }`. - Also, `(. int) => string => bool` is not equivalen to `(. int, string) => bool` anymore. - These are only breaking changes for unformatted code. +Also, `(. int) => string => bool` is not equivalen to `(. int, string) => bool` anymore. +These are only breaking changes for unformatted code. - Exponentiation operator `**` is now right-associative. `2. ** 3. ** 2.` now compile to `Math.pow(2, Math.pow(3, 2))` and not anymore `Math.pow(Math.pow(2, 3), 2)`. Parentheses can be used to change precedence. -- Remove unsafe `` j`$(a)$(b)` `` interpolation deprecated in compiler version 10 https://github.com/rescript-lang/rescript-compiler/pull/6068 +- Remove unsafe ``` j`$(a)$(b)` ``` interpolation deprecated in compiler version 10 https://github.com/rescript-lang/rescript-compiler/pull/6068 - Remove deprecated module `Printexc` - `@deriving(jsConverter)` not supported anymore for variant types https://github.com/rescript-lang/rescript-compiler/pull/6088 - New representation for variants, where the tag is a string instead of a number. https://github.com/rescript-lang/rescript-compiler/pull/6088 @@ -761,21 +762,19 @@ No changes compared to rc.9. # 10.1.4 #### :bug: Bug Fix - - Fix implementation of directives https://github.com/rescript-lang/rescript-compiler/pull/6052 - Fix issue if the `lib` dir is included in the sources of bsconfig.json https://github.com/rescript-lang/rescript-compiler/pull/6055 - Fix issue with string escape in pattern match https://github.com/rescript-lang/rescript-compiler/pull/6062 - Fix issue with literal comparison of string constants https://github.com/rescript-lang/rescript-compiler/pull/6065 #### :rocket: New Feature - - Add support for toplevel `await` https://github.com/rescript-lang/rescript-compiler/pull/6054 #### :nail_care: Polish - Better error message for extension point https://github.com/rescript-lang/rescript-compiler/pull/6057 - Improve format check help https://github.com/rescript-lang/rescript-compiler/pull/6056 -- Deprecate unsafe `` j`$(a)$(b)` `` interpolation: use string templates `` `${a}${b}` `` instead https://github.com/rescript-lang/rescript-compiler/pull/6067 +- Deprecate unsafe ``` j`$(a)$(b)` ``` interpolation: use string templates ``` `${a}${b}` ``` instead https://github.com/rescript-lang/rescript-compiler/pull/6067 # 10.1.3 From 81b11ecad17febb9e4529559fc7ba441cf92a7ec Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 2 Oct 2024 13:32:37 +0200 Subject: [PATCH 29/31] fixes --- jscomp/ml/dict_type_helpers.ml | 5 +++-- jscomp/ml/typecore.ml | 29 ++++++++++------------------- jscomp/ml/types.ml | 2 +- jscomp/ml/types.mli | 3 +-- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/jscomp/ml/dict_type_helpers.ml b/jscomp/ml/dict_type_helpers.ml index 75a41142f6..0f5a807b3d 100644 --- a/jscomp/ml/dict_type_helpers.ml +++ b/jscomp/ml/dict_type_helpers.ml @@ -5,8 +5,9 @@ ### How are they implemented? Dicts in ReScript are implemented as predefined record type, with a single (magic) field that holds - the type of the dict's values. This field is called `dictValuesType`, and is just an implementation - detail - it's never actually exposed to the user, just used internally. + the type of the dict's values. This field is called `dictValuesType`, and it represent every possible + key in the dict. It's just an implementation detail - it's never actually exposed to the user, just + used internally. The compiler will route any label lookup on the dict record type to the magic field, which creates a record with unknown keys, but of a single type. diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 56092fc7e2..4611ba069a 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -790,7 +790,7 @@ module NameChoice(Name : sig val get_type: t -> type_expr val get_descrs: Env.type_descriptions -> t list - val add_with_name: t -> string -> t + val unsafe_do_not_use_add_with_name: t -> string -> t val unbound_name_error: Env.t -> Longident.t loc -> 'a end) = struct @@ -804,14 +804,8 @@ end) = struct let lookup_from_type env tpath (lid : Longident.t loc) : Name.t = let descrs = get_descrs (Env.find_type_descrs tpath env) in Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env); - let is_dict = Path.same tpath Predef.path_dict in - if is_dict then ( - (* [dict] Dicts are implemented as a record with a single "magic" field. This magic field is - used to track the dict value type, and any label lookup on the dict record type - will give that single value type back. This is how we can piggy back on the record - pattern matching mechanism. - - The code below handles directing any label lookup to the magic field. *) + if Path.same tpath Predef.path_dict then ( + (* [dict] Handle directing any label lookup to the magic dict field. *) match lid.txt with Longident.Lident s_ -> begin let s = @@ -822,7 +816,7 @@ end) = struct try let x = List.find (fun nd -> get_name nd = s) descrs in if s = Dict_type_helpers.dict_magic_field_name - then add_with_name x s_ + then unsafe_do_not_use_add_with_name x s_ else x with Not_found -> let names = List.map get_name descrs in @@ -914,7 +908,7 @@ module Label = NameChoice (struct let type_kind = "record" let get_name lbl = lbl.lbl_name - let add_with_name lbl name = + let unsafe_do_not_use_add_with_name lbl name = (* [dict] This is used in dicts and shouldn't be used anywhere else. It adds a new field to an existing record type, to "fool" the pattern matching into thinking the label exists. *) @@ -1084,7 +1078,7 @@ module Constructor = NameChoice (struct let get_name cstr = cstr.cstr_name let get_type cstr = cstr.cstr_res - let add_with_name _cstr _name = assert false + let unsafe_do_not_use_add_with_name _cstr _name = assert false let get_descrs = fst let unbound_name_error = Typetexp.unbound_constructor_error end) @@ -1396,10 +1390,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env let has_dict_pattern_attr = Dict_type_helpers.has_dict_pattern_attribute sp.ppat_attributes in let opath, record_ty = ( if has_dict_pattern_attr then ( - (* [dict] If this is a dict pattern match we know we should force the record type - as the dict record type with a fresh type variable. This fixes so that dicts - can still be inferred properly from just pattern usage. Without this little - tweak, the inference would not work properly. *) + (* [dict] Make sure dict patterns are inferred as actual dicts *) (Some (Predef.path_dict, Predef.path_dict), newgenty (Tconstr (Predef.path_dict, [newvar ()], ref Mnil))) ) else try @@ -3040,9 +3031,9 @@ and type_label_access env srecord lid = | (p0, _, {type_attributes}) when Path.same p0 Predef.path_dict && Dict_type_helpers.has_dict_attribute type_attributes -> (* [dict] Cover the case when trying to direct field access on a dict, e.g. `someDict.name`. - We need to disallow this because the fact that a dict is represented as a single field - record internally is just an implementation detail, and not intended to be exposed to - the user. *) + We need to disallow this because the fact that a dict is represented as a single magic + field record internally is just an implementation detail, and not intended to be exposed + to the user. *) raise(Error(lid.loc, env, Field_access_on_dict_type)) | (p0, p, {type_kind=Type_record _}) -> Some(p0, p) | _ -> None diff --git a/jscomp/ml/types.ml b/jscomp/ml/types.ml index 5b644e831a..3ec0bd46af 100644 --- a/jscomp/ml/types.ml +++ b/jscomp/ml/types.ml @@ -303,7 +303,7 @@ type label_description = lbl_arg: type_expr; (* Type of the argument *) lbl_mut: mutable_flag; (* Is this a mutable field? *) lbl_pos: int; (* Position in block *) - mutable lbl_all: label_description array; (* All the labels in this type *) + mutable lbl_all: label_description array; (* All the labels in this type. This is mutable only because of a specific feature related to dicts, and should not be mutated elsewhere. *) lbl_repres: record_representation; (* Representation for this record *) lbl_private: private_flag; (* Read-only field? *) lbl_loc: Location.t; diff --git a/jscomp/ml/types.mli b/jscomp/ml/types.mli index b8d43f4461..c7e8f48f82 100644 --- a/jscomp/ml/types.mli +++ b/jscomp/ml/types.mli @@ -449,8 +449,7 @@ type label_description = lbl_arg: type_expr; (* Type of the argument *) lbl_mut: mutable_flag; (* Is this a mutable field? *) lbl_pos: int; (* Position in block *) - mutable lbl_all: label_description array; (* All the labels in this type *) - lbl_repres: record_representation; (* Representation for this record *) + mutable lbl_all: label_description array; (* All the labels in this type. This is mutable only because of a specific feature related to dicts, and should not be mutated elsewhere. *) lbl_repres: record_representation; (* Representation for this record *) lbl_private: private_flag; (* Read-only field? *) lbl_loc: Location.t; lbl_attributes: Parsetree.attributes; From 02c12f1b701858de20469b860f9f08663debe052 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 2 Oct 2024 13:47:14 +0200 Subject: [PATCH 30/31] simplify --- jscomp/ml/typecore.ml | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 4611ba069a..e818e0ac89 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -790,7 +790,7 @@ module NameChoice(Name : sig val get_type: t -> type_expr val get_descrs: Env.type_descriptions -> t list - val unsafe_do_not_use_add_with_name: t -> string -> t + val unsafe_do_not_use__add_with_name: t -> string -> t val unbound_name_error: Env.t -> Longident.t loc -> 'a end) = struct @@ -807,21 +807,9 @@ end) = struct if Path.same tpath Predef.path_dict then ( (* [dict] Handle directing any label lookup to the magic dict field. *) match lid.txt with - Longident.Lident s_ -> begin - let s = - if List.exists (fun nd -> get_name nd = s_) descrs - || not (List.exists (fun nd -> get_name nd = Dict_type_helpers.dict_magic_field_name) descrs) - then s_ - else Dict_type_helpers.dict_magic_field_name in - try - let x = List.find (fun nd -> get_name nd = s) descrs in - if s = Dict_type_helpers.dict_magic_field_name - then unsafe_do_not_use_add_with_name x s_ - else x - with Not_found -> - let names = List.map get_name descrs in - raise (Error (lid.loc, env, - Wrong_name ("", newvar (), type_kind, tpath, s, names))) + Longident.Lident s -> begin + let x = List.find (fun nd -> get_name nd = Dict_type_helpers.dict_magic_field_name) descrs in + unsafe_do_not_use__add_with_name x s end | _ -> raise Not_found) else match lid.txt with @@ -908,7 +896,7 @@ module Label = NameChoice (struct let type_kind = "record" let get_name lbl = lbl.lbl_name - let unsafe_do_not_use_add_with_name lbl name = + let unsafe_do_not_use__add_with_name lbl name = (* [dict] This is used in dicts and shouldn't be used anywhere else. It adds a new field to an existing record type, to "fool" the pattern matching into thinking the label exists. *) @@ -1078,7 +1066,7 @@ module Constructor = NameChoice (struct let get_name cstr = cstr.cstr_name let get_type cstr = cstr.cstr_res - let unsafe_do_not_use_add_with_name _cstr _name = assert false + let unsafe_do_not_use__add_with_name _cstr _name = assert false let get_descrs = fst let unbound_name_error = Typetexp.unbound_constructor_error end) From 3d42ed039c7ca5e9392ae332f523877f7b0b9bac Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 2 Oct 2024 14:02:16 +0200 Subject: [PATCH 31/31] add live attribute suppressing dead code analysis for dicts since they can't be statically analysed for unused fields --- jscomp/ml/predef.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jscomp/ml/predef.ml b/jscomp/ml/predef.ml index 3b1fba7add..38760e67d8 100644 --- a/jscomp/ml/predef.ml +++ b/jscomp/ml/predef.ml @@ -229,7 +229,7 @@ let common_initial_env add_type add_extension empty_env = So, this definition is important for the dict pattern matching functionality, but not something intended to be exposed to the user. *) {decl_abstr with - type_attributes = [Dict_type_helpers.dict_attr]; + type_attributes = [Dict_type_helpers.dict_attr; (Location.mknoloc "live", Parsetree.PStr [])]; type_params = [tvar]; type_arity = 1; type_variance = [Variance.full];