Skip to content

Remove dead code and stale docs in compiler/ext, common, depends and ml - #8699

Open
cristianoc wants to merge 29 commits into
masterfrom
cristianoc/cleanup-compiler-ext-common-ml
Open

cristianoc wants to merge 29 commits into
masterfrom
cristianoc/cleanup-compiler-ext-common-ml

Conversation

@cristianoc

@cristianoc cristianoc commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #8712.

⚠️ @cknitt: please check one commit before merging

"Remove the unused raw type printer" deletes a debugging aid kept on purpose: Printtyp.raw_type_expr, its helpers and the Btype.print_raw hook. Nothing uses them; only commented-out debug lines did. It is a separate commit, so it can be dropped if the printer is still wanted.

Summary

  • Remove unused constants from Literals. 31 constants in compiler/ext/literals.ml (js_array_ctor, prim, param, the fn_run/method_run family, node_modules, package_json, the .a/.cmo/.cma/ .cmx/.cmxa/.mll/.cmt/.cmti/.d/.gen.js/.gen.tsx suffixes, esmodule, commonjs, unused_attribute, sourcedirs_meta and others) had no reference: no file names them as Literals.x or L.x, and nothing opens Literals.
  • Remove unused functions from ext utility modules. Ext_array (reverse_in_place, filter, filter_map, filter_mapi, range, map2i, is_empty), Ext_list (map_split_opt, map2i, filter_map2, find_def, mem_string, drop), Ext_string (repeat, rindex_opt, lowercase_ascii, unsafe_sub), Ext_buffer.clear, Ext_char.valid_hex, Ext_fmt.invalid_argf, Ext_obj.bt, Ext_pp_scope.print and Hash_set_poly (clear, reset, iter, to_list) had no caller outside their own definitions; with them go the helper rindex_rec_opt and the Ext_char comment about a Char.escaped backport the module does not contain.
  • Remove unused functions from Misc. Misc.map_left_right, list_remove, log2, chop_extensions and Int_literal_converter.int32/int64 had no caller, qualified or through open Misc; typecore.ml uses only Int_literal_converter.int.
  • Remove unused members of Identifiable. Ident is the only Identifiable.Make instance, and nothing uses its Map.disjoint_union, union_right, union_left, union_merge, map_keys, of_set, transpose_keys_and_data(_set) or Tbl.memoize; nothing applies the Pair functor.
  • Remove unused operations from Ordered_hash_map. Ordered_hash_map_local_ident, the only instance, is used through create, add, rank, find_value, iter, length and to_sorted_array (lambda_scc.ml and the ounit hashtbl suite). The clear, reset, mem, fold, elements and choose members of Ordered_hash_map_gen.S had no caller; with them go the gen-level clear, reset, fold, elements, the unused bucket_length and the initial_size field that only reset read.
  • Remove unused operations from the ext map and set functors. No instance of Map_gen.S (Map_int, Map_string, Map_ident, and Handler_map in core) is used through remove or add_list, and nothing calls Map_gen.concat; Map_gen.merge and its min-binding helpers served only remove. No instance of Set_gen.S (Set_int, Set_string, Set_ident) is used through print, so the functor's element print requirement goes too, and nothing calls Set_gen.partition.
  • Fix the cmt_magic_number comment in Config. config.mli described cmt_magic_number with the comment copied from cmi_magic_number ("compiled interface files"); the value ("Caml1999T039") heads the typed-tree files that Cmt_format.save_cmt writes (.cmt, .cmti).
  • Remove the unused Bs_loc.merge. Nothing calls Bs_loc.merge; its private helper is_ghost and the commented-out none/is_ghost declarations go with it. The frontend uses only the Bs_loc.t alias. bs_loc.mli stays: the common library enables warning 70 (missing interface).
  • Fix stale comments in the common library. Js_config documented a browser flag it does not define and kept commented-out declarations of package-info accessors that no longer exist; Ext_log's example called an err function the module does not export (it exports dwarn); Ml_binary's header described Reason AST reading instead of the Parsetree/Parsetree0 conversion it provides.
  • Describe the actual -bs-ast file format in Binary_ast. The write_ast doc described a { magic number; filename; ast } layout, a "-" stdin filename and a fan tool, and pointed to Bsb_depfile_gen; the function writes a length-prefixed dependency block, the source file name and the marshalled AST, and rewatch's get_dep_modules decodes the block. magic_sep_char was exported but used only inside binary_ast.ml.
  • Remove the unused -annot type-annotation dump. Stypes and Annot recorded type annotations for an -annot dump that bsc never enables: Clflags.annotations was never set to true, Stypes.record returned immediately and Stypes.dump had no caller. The scope arguments threaded through Typecore and Typemod.type_structure fed only those records.
  • Remove the unused in-process ppx driver from Ast_mapper. tool_name, apply, run_main, register_function and register (with apply_lazy, extension_of_exn and Ppx_context.update_cookies, which only they used) had no caller: bsc runs ppx binaries as separate processes through cmd_ppx_apply, which uses only the add/drop_ppx_context helpers.
  • Remove unused definitions from the type checker modules. Each removed value had no reference anywhere in the repository (checked with git grep -w over all sources and the modules that open them): Ast_helper with_default_loc and Const.nativeint, Env copy_local and diff, Lambda ref_field_info, Parmatch inactive, Consistbl filter, Tbl print, Pprintast string_of_expression, Predef type_option, Printlambda structured_constant, Printtyp print_items, Subst typexp, Ast_untagged_variants block_type_to_user_visible_string, Record_type_spread t_equals and Asttypes virtual_flag. The helpers only they used go with them. Error_message_utils type_clash_context_maybe_option was the only constructor of MaybeUnwrapOption, so that context and its never-printed hint are removed and the error catalog no longer lists maybe_unwrap_option.res as covering it. Ast_helper0 keeps its copies because it is frozen.
  • Fix stale comments in type checker modules. Variant_runtime named Ast_untagged_variants as re-exporting and deriving the layout; the derivation is in Variant_layout and the open re-exports nothing. Cmt_format_common named a selected Cmt_format implementation; the selected module is Cmt_format_persistence, copied by compiler/ml/dune per profile. Clflags.binary_annotations was labelled -annot; it controls .cmt writing and is cleared by -bs-no-bin-annot. Outcometree described OCaml toplevel hooks; ReScript has no toplevel and prints the trees through Oprint's hooks.
  • Replace Bs_loc.t with Location.t and delete Bs_loc. compiler/common/bs_loc.ml defines only type t = Location.t = {...}, a re-export of Location.t. Its sole users are the signature of Ast_external_process.handle_attributes (.ml and .mli), which now name Location.t directly. The module and its interface are deleted.
  • Remove unused definitions from the ext library. A typed scan of every .cmt in the build (value paths in Texp_ident, resolved through module aliases and includes) finds no use of these outside their own definitions: Literals.debugger (core prints the keyword from Js_dump_lit.debugger); Misc.for_all2, Misc.fst3, Misc.output_to_file_via_temporary; Set_gen.invariant (the sets use the functor's own invariant, which calls Set_gen.check and Set_gen.is_ordered)
  • Remove unused definitions from the ml library. A typed scan of every .cmt in the build (value paths in Texp_ident, resolved through module aliases and includes, plus a token check of the playground sources the default profile does not compile) finds no use of these outside their own definitions: Ast_helper0.with_default_loc; Ast_mapper_from0.map_snd and Ast_mapper_to0.map_snd; Btype.set_name, the only producer of the Cname trail entry; the constructor and its undo case go with it (warning 37 reports it otherwise); Consistbl.source; Depend.weaken_map; Env.summary (keep_only_summary reads the summary field directly); Printtyp.type_sch; Tbl.mem, Tbl.remove (and merge, which only remove called), Tbl.map
  • Record used attributes in a Hash_set.Make instance. Hash_set_poly repeated the remove, add and mem bodies of Hash_set.Make with Hashtbl.hash and ( = ) in place of the functor's hash and equal. Its only compiler user was ml/used_attributes.ml, which now instantiates Hash_set.Make with exactly those two functions for string Asttypes.loc, so key_index, bucket equality and resizing are unchanged. compiler/ext/hash_set_poly.ml and .mli are deleted.
  • Split the last list element with Ext_list.split_at_last. Misc.split_last and Ext_list.split_at_last both return the list without its last element paired with that element. Misc's two callers, Misc.did_you_mean and Includemod.report_error, each call it only on a non-empty list (both match [] first), where the results are equal; the definitions differ only on [] (assert false vs Invalid_argument), which neither caller reaches. Ext_list.split_at_last is the ext list helper with ounit coverage, so both callers use it and Misc.split_last is removed. includemod.ml used Misc only for split_last, so its open Misc goes too.
  • Define Ext_option.map and iter by Stdlib.Option. Misc.may and Misc.may_map are Stdlib.Option.iter and Stdlib.Option.map. Ext_option.iter and Ext_option.map restated the same two matches with the option first. They now call Stdlib.Option.iter and Stdlib.Option.map with the arguments swapped, so all four names share one implementation and keep their argument orders; the ~70 Misc.may/may_map call sites in ml and the Ext_option call sites in core are unchanged.
  • Derive Ml_binary.magic_of_ast0 from magic_of_kind. magic_of_kind and magic_of_ast0 both mapped an AST kind to Config.ast0_impl_magic_number or Config.ast0_intf_magic_number, once for the kind witness (Ml, Mli) and once for the AST value (Impl, Intf). magic_of_kind now holds the mapping and magic_of_ast0 maps Impl to Ml and Intf to Mli through it, so cmd_ppx_apply.ml writes and checks the same magic strings.
  • Narrow ext interfaces to the values other modules use. Ext_pervasives.reraise, Map_gen.fill_array_with_f and fill_array_aux, Warnings.is_error and nerrors, Set_gen.remove_min_elt, Misc.edit_distance, Ext_list.exclude, Ext_ident.is_uppercase_exotic, Ext_string.ends_with_index and concat5 are exported but used only inside their own module. Evidence: a compiler-libs reader over the .cmt files of dune build @check and of dune build --profile browser @check (Texp_ident paths resolved through module aliases and dune's library wrappers) finds no use of them in any other module, and a token check of compiler/jsoo, the platform/playground directories and tests/ounit_tests finds no qualified use. Each one stays used inside its module, so only the interface changes; the edit_distance documentation moves to its definition.
  • Narrow ml interfaces to the values other modules use. These values are exported by compiler/ml interfaces and used by no other module: Ast_helper.default_loc, Ast_mapper.map_opt, Ast_payload.unrecognized_config_record, Bigint_utils.is_neg, is_pos, remove_leading_sign and remove_leading_zeros, Cmt_format.read, read_magic_number and record_deprecated_used, Ctype.sort_row_fields, full_expand, rigidify, all_distinct_vars and is_contractive, Datarepr.constructor_existentials, Depend.make_leaf, make_node and add_signature_binding, Env.add_functor_arg, save_signature_with_imports, crc_units, add_import and report_error, External_arg_spec.empty_label, Includemod.print_coercion, Lambda.lambda_true and lambda_false, Location.error_reporter, Longident.unflatten, Matching.flatten_pattern, Mtype.no_code_needed and no_code_needed_sig, Oprint.parenthesized_ident, Pprintast.expression and core_type, Predef.type_list, path_iterable, path_async_iterable, path_extension_constructor and ident_division_by_zero, Printast.expression and structure, Printlambda.primitive, Printtyp.reset, tree_of_type_scheme, tree_of_module, tree_of_modtype_declaration, type_expansion, prepare_expansion and trace, Printtyped.implementation, String_literal.encode_js_template, Subst.module_declaration, Translmod.report_error, Typecore.check_partial, type_approx, option_some, option_none, extract_option_type, iter_pattern, generalizable and report_error, Typedecl.abstract_type_decl, and Typemod.type_module, check_nongen_schemes, simplify_signature and path_of_module.
  • Narrow Ident's interface to the values other modules use. Ident.unique_name had one user outside ident.ml, the coercion printer in includemod.ml, which is gone. Evidence: a compiler-libs reader over the .cmt files of dune build @check and dune build --profile browser @check (Texp_ident paths resolved through module aliases and dune's library wrappers) finds no use in another module, and a token check of compiler/jsoo, the platform/playground directories and tests/ounit_tests finds none. Ident.output still uses it, so only the interface changes.
  • Name existing functions in compiler internal-error messages. Four invalid_arg/fatal_error strings named functions that do not exist: Ext_list: arr_list_combine_unsafe raised "Ext_list.combine" (no combine in ext_list.ml). The message names arr_list_combine_unsafe; Ext_list: the function was spelled arr_list_filter_map_unasfe while its error said "Ext_list.arr_list_filter_map_unsafe". The function is renamed to arr_list_filter_map_unsafe (private to ext_list.ml, absent from ext_list.mli), so the message names it; Matching: flatten_cases raised "Matching.flatten_case"; Parmatch: record_arg raised "Parmatch.as_record".
  • Name current definitions in ext comments. - hash.ml, hash_set.ml and hash_set_poly.ml kept commented-out bindings to Hash_gen.stats, Hash_set_gen.copy and Hash_set_gen.stats, which are not defined; they are deleted. - ext_string.ml kept a commented check_any_suffix_case calling the undefined check_suffix_case, and a commented extract_until calling the undefined index_rec; extract_until's doc and commented val in the .mli go with it. - literals.ml tied the "create" literal to Caml_exceptions.create; it is used as Primitive_exceptions.create (js_exp_make.ml), which the runtime's Primitive_exceptions.resi exports. - ext_pp_scope.ml compared str_of_ident with Js_dump.ident; the printing function is ident in the same module. It also pointed at test/test_global_print.ml, which is not in the tree. - hash_set_ident_mask.mli documented mask_and_check_all_hit as check_mask.
  • Name current definitions in ml comments. - parmatch.ml and typecore.ml said record fields are sorted by Typecore.type_label_a_list; the sort by lbl_pos is in type_record_elem_list. - typecore.ml said partial_pred is passed to Partial.parmatch; it is passed to Parmatch.check_partial_gadt and Parmatch.check_unused. A "same as Ctype.poly" remark is deleted (Ctype has no poly), as is a commented unify_pat call building a row with the removed row_bound field. Two notes cited res_core.ml:3841 for normalize_for_of_pattern, which is no longer at that line; they now cite the file. - parmatch.ml kept the commented non-GADT exhaustiveness path (exhaust, try_many, combinations, do_check_partial_normal, do_check_fragile_normal, check_partial); the live path is the GADT one, and the commented code is deleted. Prose naming every_satisfiable / every_satisfied now names every_satisfiables. - matching.ml named may_constr_equal and compiled_flattened; the functions are Types.may_equal_constr and compile_flattened. - env.ml said save_signature_with_imports makes imported_unit() return the crc; the function is imports (). - location.ml pointed at a super_error_reporter above; the reporter is default_error_reporter below. - typedtree.mli misspelled Longident.t as Longindent.t. - lambda_traverse.ml named Pervasives.compare; the comparison used is Stdlib.compare. - lambda.mli described main_module_block_size and the flambda middle-end, which this compiler does not have; deleted. - Commented-out code over undefined names is deleted: debug prints over StringSet, PathSet and IdentSet (depend, mtype, translmod), cmt_format.mli's list of vals (is_magic_number, read_signature, ...), ctype's actual_mode guard and correct_abbrev val, external_arg_spec's empty_lit val, and printlambda's field_kind over Pgenval and boxed_integer_name.
  • Remove the unused raw type printer. Printtyp.raw_type_expr printed a type's internal representation. It was installed into Btype.print_raw, and both were reached only from commented-out debug lines in typecore, typedecl, ctype, env and printtyp. The printer, its helpers (raw_list, safe_repr, list_of_memo, print_name), the hook and those commented-out calls are removed. Restore with git revert if the printer is still wanted for debugging.

Test plan

  • dune build
  • dune build @fmt
  • dune build --profile browser @check
  • make
  • make lib
  • no change in the runtime and Belt lib/ outputs
  • make test
  • make test-analysis
  • make test-tools
  • make test-gentype
  • make test-syntax
  • make checkformat
  • npm run check

🤖 Generated with Claude Code

cristianoc and others added 28 commits October 2, 2026 07:36
31 constants in compiler/ext/literals.ml (js_array_ctor, prim, param, the
fn_run/method_run family, node_modules, package_json, the .a/.cmo/.cma/
.cmx/.cmxa/.mll/.cmt/.cmti/.d/.gen.js/.gen.tsx suffixes, esmodule, commonjs,
unused_attribute, sourcedirs_meta and others) had no reference: no file
names them as Literals.x or L.x, and nothing opens Literals.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ext_array (reverse_in_place, filter, filter_map, filter_mapi, range, map2i,
is_empty), Ext_list (map_split_opt, map2i, filter_map2, find_def,
mem_string, drop), Ext_string (repeat, rindex_opt, lowercase_ascii,
unsafe_sub), Ext_buffer.clear, Ext_char.valid_hex, Ext_fmt.invalid_argf,
Ext_obj.bt, Ext_pp_scope.print and Hash_set_poly (clear, reset, iter,
to_list) had no caller outside their own definitions; with them go the
helper rindex_rec_opt and the Ext_char comment about a Char.escaped
backport the module does not contain.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Misc.map_left_right, list_remove, log2, chop_extensions and
Int_literal_converter.int32/int64 had no caller, qualified or through
`open Misc`; typecore.ml uses only Int_literal_converter.int.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ident is the only Identifiable.Make instance, and nothing uses its
Map.disjoint_union, union_right, union_left, union_merge, map_keys, of_set,
transpose_keys_and_data(_set) or Tbl.memoize; nothing applies the Pair
functor.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ordered_hash_map_local_ident, the only instance, is used through create,
add, rank, find_value, iter, length and to_sorted_array (lambda_scc.ml and
the ounit hashtbl suite). The clear, reset, mem, fold, elements and choose
members of Ordered_hash_map_gen.S had no caller; with them go the gen-level
clear, reset, fold, elements, the unused bucket_length and the
initial_size field that only reset read.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No instance of Map_gen.S (Map_int, Map_string, Map_ident, and Handler_map
in core) is used through remove or add_list, and nothing calls
Map_gen.concat; Map_gen.merge and its min-binding helpers served only
remove. No instance of Set_gen.S (Set_int, Set_string, Set_ident) is used
through print, so the functor's element print requirement goes too, and
nothing calls Set_gen.partition.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
config.mli described cmt_magic_number with the comment copied from
cmi_magic_number ("compiled interface files"); the value ("Caml1999T039")
heads the typed-tree files that Cmt_format.save_cmt writes (.cmt, .cmti).

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing calls Bs_loc.merge; its private helper is_ghost and the
commented-out none/is_ghost declarations go with it. The frontend uses
only the Bs_loc.t alias. bs_loc.mli stays: the common library enables
warning 70 (missing interface).

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Js_config documented a browser flag it does not define and kept
commented-out declarations of package-info accessors that no longer
exist; Ext_log's example called an `err` function the module does not
export (it exports dwarn); Ml_binary's header described Reason AST reading
instead of the Parsetree/Parsetree0 conversion it provides.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The write_ast doc described a { magic number; filename; ast } layout, a
"-" stdin filename and a `fan` tool, and pointed to Bsb_depfile_gen; the
function writes a length-prefixed dependency block, the source file name
and the marshalled AST, and rewatch's get_dep_modules decodes the block.
magic_sep_char was exported but used only inside binary_ast.ml.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stypes and Annot recorded type annotations for an -annot dump that bsc never
enables: Clflags.annotations was never set to true, Stypes.record returned
immediately and Stypes.dump had no caller. The scope arguments threaded
through Typecore and Typemod.type_structure fed only those records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
tool_name, apply, run_main, register_function and register (with apply_lazy,
extension_of_exn and Ppx_context.update_cookies, which only they used) had no
caller: bsc runs ppx binaries as separate processes through cmd_ppx_apply,
which uses only the add/drop_ppx_context helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Each removed value had no reference anywhere in the repository (checked with
git grep -w over all sources and the modules that open them): Ast_helper
with_default_loc and Const.nativeint, Env copy_local and diff, Lambda
ref_field_info, Parmatch inactive, Consistbl filter, Tbl print, Pprintast
string_of_expression, Predef type_option, Printlambda structured_constant,
Printtyp print_items, Subst typexp, Ast_untagged_variants
block_type_to_user_visible_string, Record_type_spread t_equals and Asttypes
virtual_flag. The helpers only they used go with them. Error_message_utils
type_clash_context_maybe_option was the only constructor of MaybeUnwrapOption,
so that context and its never-printed hint are removed and the error catalog
no longer lists maybe_unwrap_option.res as covering it. Ast_helper0 keeps its
copies because it is frozen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Variant_runtime named Ast_untagged_variants as re-exporting and deriving the
layout; the derivation is in Variant_layout and the open re-exports nothing.
Cmt_format_common named a selected Cmt_format implementation; the selected
module is Cmt_format_persistence, copied by compiler/ml/dune per profile.
Clflags.binary_annotations was labelled -annot; it controls .cmt writing and
is cleared by -bs-no-bin-annot. Outcometree described OCaml toplevel hooks;
ReScript has no toplevel and prints the trees through Oprint's hooks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
compiler/common/bs_loc.ml defines only `type t = Location.t = {...}`, a
re-export of Location.t. Its sole users are the signature of
Ast_external_process.handle_attributes (.ml and .mli), which now name
Location.t directly. The module and its interface are deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
A typed scan of every .cmt in the build (value paths in Texp_ident,
resolved through module aliases and includes) finds no use of these
outside their own definitions:

- Literals.debugger (core prints the keyword from Js_dump_lit.debugger)
- Misc.for_all2, Misc.fst3, Misc.output_to_file_via_temporary
- Set_gen.invariant (the sets use the functor's own invariant, which
  calls Set_gen.check and Set_gen.is_ordered)

The commented-out `let compare = Set_gen.compare ...` in ext_set.ml names a
function Set_gen does not define; it is deleted too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
A typed scan of every .cmt in the build (value paths in Texp_ident,
resolved through module aliases and includes, plus a token check of the
playground sources the default profile does not compile) finds no use of
these outside their own definitions:

- Ast_helper0.with_default_loc
- Ast_mapper_from0.map_snd and Ast_mapper_to0.map_snd
- Btype.set_name, the only producer of the Cname trail entry; the
  constructor and its undo case go with it (warning 37 reports it
  otherwise)
- Consistbl.source
- Depend.weaken_map
- Env.summary (keep_only_summary reads the summary field directly)
- Printtyp.type_sch
- Tbl.mem, Tbl.remove (and merge, which only remove called), Tbl.map

The commented-out dump_used_attributes in used_attributes.ml calls
Hash_set_poly.iter, which no longer exists; it is deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Hash_set_poly repeated the remove, add and mem bodies of Hash_set.Make with
Hashtbl.hash and ( = ) in place of the functor's hash and equal. Its only
compiler user was ml/used_attributes.ml, which now instantiates
Hash_set.Make with exactly those two functions for string Asttypes.loc, so
key_index, bucket equality and resizing are unchanged.
compiler/ext/hash_set_poly.ml and .mli are deleted.

The three ounit cases for Hash_set_poly go with it; the Id_hash_set case
beside them runs the same add, mem, remove and length sequence through
Hash_set.Make and continues further.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Misc.split_last and Ext_list.split_at_last both return the list without its
last element paired with that element. Misc's two callers,
Misc.did_you_mean and Includemod.report_error, each call it only on a
non-empty list (both match [] first), where the results are equal; the
definitions differ only on [] (assert false vs Invalid_argument), which
neither caller reaches. Ext_list.split_at_last is the ext list helper with
ounit coverage, so both callers use it and Misc.split_last is removed.
includemod.ml used Misc only for split_last, so its open Misc goes too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Misc.may and Misc.may_map are Stdlib.Option.iter and Stdlib.Option.map.
Ext_option.iter and Ext_option.map restated the same two matches with the
option first. They now call Stdlib.Option.iter and Stdlib.Option.map with
the arguments swapped, so all four names share one implementation and keep
their argument orders; the ~70 Misc.may/may_map call sites in ml and the
Ext_option call sites in core are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
magic_of_kind and magic_of_ast0 both mapped an AST kind to
Config.ast0_impl_magic_number or Config.ast0_intf_magic_number, once for
the kind witness (Ml, Mli) and once for the AST value (Impl, Intf).
magic_of_kind now holds the mapping and magic_of_ast0 maps Impl to Ml and
Intf to Mli through it, so cmd_ppx_apply.ml writes and checks the same
magic strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Ext_pervasives.reraise, Map_gen.fill_array_with_f and fill_array_aux,
Warnings.is_error and nerrors, Set_gen.remove_min_elt, Misc.edit_distance,
Ext_list.exclude, Ext_ident.is_uppercase_exotic, Ext_string.ends_with_index
and concat5 are exported but used only inside their own module. Evidence:
a compiler-libs reader over the .cmt files of `dune build @check` and of
`dune build --profile browser @check` (Texp_ident paths resolved through
module aliases and dune's library wrappers) finds no use of them in any
other module, and a token check of compiler/jsoo, the platform/playground
directories and tests/ounit_tests finds no qualified use. Each one stays
used inside its module, so only the interface changes; the edit_distance
documentation moves to its definition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
These values are exported by compiler/ml interfaces and used by no other
module: Ast_helper.default_loc, Ast_mapper.map_opt,
Ast_payload.unrecognized_config_record, Bigint_utils.is_neg, is_pos,
remove_leading_sign and remove_leading_zeros, Cmt_format.read,
read_magic_number and record_deprecated_used, Ctype.sort_row_fields,
full_expand, rigidify, all_distinct_vars and is_contractive,
Datarepr.constructor_existentials, Depend.make_leaf, make_node and
add_signature_binding, Env.add_functor_arg, save_signature_with_imports,
crc_units, add_import and report_error, External_arg_spec.empty_label,
Includemod.print_coercion, Lambda.lambda_true and lambda_false,
Location.error_reporter, Longident.unflatten, Matching.flatten_pattern,
Mtype.no_code_needed and no_code_needed_sig, Oprint.parenthesized_ident,
Pprintast.expression and core_type, Predef.type_list, path_iterable,
path_async_iterable, path_extension_constructor and
ident_division_by_zero, Printast.expression and structure,
Printlambda.primitive, Printtyp.reset, tree_of_type_scheme,
tree_of_module, tree_of_modtype_declaration, type_expansion,
prepare_expansion and trace, Printtyped.implementation,
String_literal.encode_js_template, Subst.module_declaration,
Translmod.report_error, Typecore.check_partial, type_approx, option_some,
option_none, extract_option_type, iter_pattern, generalizable and
report_error, Typedecl.abstract_type_decl, and Typemod.type_module,
check_nongen_schemes, simplify_signature and path_of_module.

Evidence: a compiler-libs reader over the .cmt files of
`dune build @check` and `dune build --profile browser @check`
(Texp_ident paths resolved through module aliases and dune's library
wrappers) finds no use of them in another module, and a token check of
compiler/jsoo, the platform/playground directories and tests/ounit_tests
finds no qualified use.

Most stay used inside their module, so only the interface changes. Four
were used nowhere and are deleted: Includemod.print_coercion (with its
print_list helpers), Mtype.no_code_needed and no_code_needed_sig, and
the Pprintast.expression and core_type wrappers. The `open Format` in
env.mli and typecore.mli served only the removed report_error
declarations. Documentation of the narrowed values with no comment at
their definition moves to the definition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Ident.unique_name had one user outside ident.ml, the coercion printer
in includemod.ml, which is gone. Evidence: a compiler-libs reader over
the .cmt files of `dune build @check` and `dune build --profile browser
@check` (Texp_ident paths resolved through module aliases and dune's
library wrappers) finds no use in another module, and a token check of
compiler/jsoo, the platform/playground directories and tests/ounit_tests
finds none. Ident.output still uses it, so only the interface changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Four invalid_arg/fatal_error strings named functions that do not exist:

- Ext_list: arr_list_combine_unsafe raised "Ext_list.combine" (no
  combine in ext_list.ml). The message names arr_list_combine_unsafe.
- Ext_list: the function was spelled arr_list_filter_map_unasfe while
  its error said "Ext_list.arr_list_filter_map_unsafe". The function is
  renamed to arr_list_filter_map_unsafe (private to ext_list.ml, absent
  from ext_list.mli), so the message names it.
- Matching: flatten_cases raised "Matching.flatten_case".
- Parmatch: record_arg raised "Parmatch.as_record".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
- hash.ml, hash_set.ml and hash_set_poly.ml kept commented-out
  bindings to Hash_gen.stats, Hash_set_gen.copy and
  Hash_set_gen.stats, which are not defined; they are deleted.
- ext_string.ml kept a commented check_any_suffix_case calling the
  undefined check_suffix_case, and a commented extract_until calling the
  undefined index_rec; extract_until's doc and commented val in the
  .mli go with it.
- literals.ml tied the "create" literal to Caml_exceptions.create; it is
  used as Primitive_exceptions.create (js_exp_make.ml), which the
  runtime's Primitive_exceptions.resi exports.
- ext_pp_scope.ml compared str_of_ident with Js_dump.ident; the
  printing function is ident in the same module. It also pointed at
  test/test_global_print.ml, which is not in the tree.
- hash_set_ident_mask.mli documented mask_and_check_all_hit as
  check_mask.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
- parmatch.ml and typecore.ml said record fields are sorted by
  Typecore.type_label_a_list; the sort by lbl_pos is in
  type_record_elem_list.
- typecore.ml said partial_pred is passed to Partial.parmatch; it is
  passed to Parmatch.check_partial_gadt and Parmatch.check_unused.
  A "same as Ctype.poly" remark is deleted (Ctype has no poly), as is a
  commented unify_pat call building a row with the removed row_bound
  field. Two notes cited res_core.ml:3841 for normalize_for_of_pattern,
  which is no longer at that line; they now cite the file.
- parmatch.ml kept the commented non-GADT exhaustiveness path (exhaust,
  try_many, combinations, do_check_partial_normal,
  do_check_fragile_normal, check_partial); the live path is the GADT
  one, and the commented code is deleted. Prose naming
  every_satisfiable / every_satisfied now names every_satisfiables.
- matching.ml named may_constr_equal and compiled_flattened; the
  functions are Types.may_equal_constr and compile_flattened.
- env.ml said save_signature_with_imports makes imported_unit() return
  the crc; the function is imports ().
- location.ml pointed at a super_error_reporter above; the reporter is
  default_error_reporter below.
- typedtree.mli misspelled Longident.t as Longindent.t.
- lambda_traverse.ml named Pervasives.compare; the comparison used is
  Stdlib.compare.
- lambda.mli described main_module_block_size and the flambda
  middle-end, which this compiler does not have; deleted.
- Commented-out code over undefined names is deleted: debug prints
  over StringSet, PathSet and IdentSet (depend, mtype, translmod),
  cmt_format.mli's list of vals (is_magic_number, read_signature, ...),
  ctype's actual_mode guard and correct_abbrev val, external_arg_spec's
  empty_lit val, and printlambda's field_kind over Pgenval and
  boxed_integer_name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Printtyp.raw_type_expr printed a type's internal representation. It was
installed into Btype.print_raw, and both were reached only from
commented-out debug lines in typecore, typedecl, ctype, env and
printtyp. The printer, its helpers (raw_list, safe_repr, list_of_memo,
print_name), the hook and those commented-out calls are removed.
Restore with `git revert` if the printer is still wanted for debugging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
@cristianoc
cristianoc requested a review from cknitt October 2, 2026 06:30
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-02T06:34:23.762233Z afe9555 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: afe955585f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

The first argument to [register] is a symbolic name to be used by
the ppx driver. *)

(** {1 Convenience functions to write mappers} *)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the PPX example after removing register

When Ast_mapper is used as its own module documentation directs (lines 16–47), removing register and run_main makes the sample PPX fail to compile with Unbound value register; the overview also still claims this module handles serialization and command-line forwarding. Either preserve the documented standalone entry point for compatibility or replace the example and overview with the supported external-PPX workflow.

AGENTS.md reference: AGENTS.md:L91-L91

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right: the overview and example still described the standalone register/run_main driver this PR removes. c8d2bec rewrites the ast_mapper.mli overview: the example now applies a mapper directly (test_mapper.structure test_mapper str), and the text describes how bsc runs external -ppx executables through Cmd_ppx_apply, exchanging the marshalled Parsetree0 in the Ml_binary format. It also drops the empty Cookies section. Documentation only, so no test; I checked that the example typechecks against the current Parsetree.

@codecov

codecov Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.84211% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.92%. Comparing base (ece8b14) to head (c8d2bec).
⚠️ Report is 11 commits behind head on master.

Files with missing lines Patch % Lines
compiler/common/ml_binary.ml 50.00% 2 Missing ⚠️
compiler/ext/ext_list.ml 75.00% 1 Missing ⚠️
compiler/ml/matching.ml 0.00% 1 Missing ⚠️
compiler/ml/parmatch.ml 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8699      +/-   ##
==========================================
+ Coverage   78.67%   79.92%   +1.24%     
==========================================
  Files         476      470       -6     
  Lines       64402    63355    -1047     
==========================================
- Hits        50670    50637      -33     
+ Misses      13732    12718    -1014     
Files with missing lines Coverage Δ
compiler/common/js_config.ml 75.00% <ø> (ø)
compiler/depends/binary_ast.ml 100.00% <ø> (ø)
compiler/ext/ext_array.ml 98.97% <ø> (+20.75%) ⬆️
compiler/ext/ext_buffer.ml 97.22% <ø> (+2.62%) ⬆️
compiler/ext/ext_char.ml 33.33% <ø> (+16.66%) ⬆️
compiler/ext/ext_fmt.ml 83.33% <ø> (+11.90%) ⬆️
compiler/ext/ext_map.ml 82.35% <100.00%> (+6.00%) ⬆️
compiler/ext/ext_obj.ml 55.55% <ø> (+11.69%) ⬆️
compiler/ext/ext_option.ml 100.00% <100.00%> (ø)
compiler/ext/ext_pp_scope.ml 100.00% <ø> (+18.51%) ⬆️
... and 56 more

... and 93 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new

pkg-pr-new Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8699

@rescript/belt

npm i https://pkg.pr.new/@rescript/belt@8699

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@8699

@rescript/darwin-x64

npm i https://pkg.pr.new/@rescript/darwin-x64@8699

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@8699

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@8699

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8699

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@8699

commit: c8d2bec

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

The module overview and example referred to the removed standalone
register/run_main entry point. The overview now describes mapper and
default_mapper, gives an example that applies a mapper directly, and
describes how bsc exchanges the marshalled Parsetree0 with external -ppx
executables through Cmd_ppx_apply and Ml_binary. The empty Cookies
section is dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
@cknitt

cknitt commented Oct 3, 2026

Copy link
Copy Markdown
Member

Discussed the removal of the "unused raw type printer" with Codex (see below, shortened a bit). I think we should keep it.


Yes—there is value in keeping it for type-checker debugging. The remaining printers serve a different purpose: they show readable types, while raw_type_expr exposes the internal type graph.

...

The raw printer exposes information that ordinary type printing hides:

  • Node IDs and sharing: repeated nodes print as {id=…}, showing whether two positions share the same inference variable.
  • Generalization levels: each node includes level, useful when debugging escaping variables or incorrect generalization.
  • Internal constructors: distinctions such as Tvar, Tunivar, Tpoly, and Tsubst.
  • Polymorphic-variant state: row tails, closed/fixed flags, and Rpresent/Reither/Rabsent.
  • Abbreviation memo paths: useful when investigating type expansion.

For example, two variables can both render as 'a in separate ordinary printouts while having different identities or levels. Those differences often matter when debugging unification, copying, and scope. See the raw printer.

It does have limitations: it follows Tlink representatives, so it doesn’t preserve the full link topology; some fields are omitted; and its visited-node state is global. It is a useful diagnostic tool, rather than a complete serialization of compiler state.

The other facilities are:

Facility What it prints Where it is used
Printtyp.type_expr, type_sch, type_scheme Readable types, with variable naming and recursive-type handling Compiler diagnostics in typecore, typedecl, and typetexp; annotation output in stypes; a few typed-tree dump fields
Printtyp.tree_of_typexp, tree_of_type_scheme Converts internal types into Outcometree.out_type for rendering or inspection Editor analysis, playground type display, and rescript-tools
Res_outcome_printer Renders outcome trees in ReScript syntax Editor hover/completion through Print_type and Shared; generated interfaces; playground and tools. Its setup also installs the rendering callbacks used by Printtyp
Printtyp.signature, modtype, declaration printers Readable signatures, module types, and declarations Module/type diagnostics; bsc printing a .cmi; interface generation
Printtyped, via -dtypedtree Typed AST structure Compiler pipeline debugging; it doesn’t replace a dump of inference-node IDs, levels, and sharing

...

The Btype.print_raw hook has a separate purpose: it lets lower-level modules invoke the printer without depending directly on Printtyp, which itself depends on Btype and Ctype. Its local callers are commented debugging statements in ctype and env. There is also an uncommented reference in Includemod.print_coercion, but that helper’s external invocation is commented out—so it likewise appears dormant.

My recommendation is to drop the raw-printer removal commit. “No active callers” is expected for a printer enabled through temporary instrumentation. Keeping this relatively small tool preserves a capability the readable printers do not provide. If it is removed, the justification should be that maintainers no longer want to maintain internal graph debugging—not that other type printers already cover it.

@cristianoc

Copy link
Copy Markdown
Collaborator Author

Discussed the removal of the "unused raw type printer" with Codex (see below, shortened a bit). I think we should keep it.


Yes—there is value in keeping it for type-checker debugging. The remaining printers serve a different purpose: they show readable types, while raw_type_expr exposes the internal type graph.

...

The raw printer exposes information that ordinary type printing hides:

  • Node IDs and sharing: repeated nodes print as {id=…}, showing whether two positions share the same inference variable.

  • Generalization levels: each node includes level, useful when debugging escaping variables or incorrect generalization.

  • Internal constructors: distinctions such as Tvar, Tunivar, Tpoly, and Tsubst.

  • Polymorphic-variant state: row tails, closed/fixed flags, and Rpresent/Reither/Rabsent.

  • Abbreviation memo paths: useful when investigating type expansion.

For example, two variables can both render as 'a in separate ordinary printouts while having different identities or levels. Those differences often matter when debugging unification, copying, and scope. See the raw printer.

It does have limitations: it follows Tlink representatives, so it doesn’t preserve the full link topology; some fields are omitted; and its visited-node state is global. It is a useful diagnostic tool, rather than a complete serialization of compiler state.

The other facilities are:

| Facility | What it prints | Where it is used |

|---|---|---|

| Printtyp.type_expr, type_sch, type_scheme | Readable types, with variable naming and recursive-type handling | Compiler diagnostics in typecore, typedecl, and typetexp; annotation output in stypes; a few typed-tree dump fields |

| Printtyp.tree_of_typexp, tree_of_type_scheme | Converts internal types into Outcometree.out_type for rendering or inspection | Editor analysis, playground type display, and rescript-tools |

| Res_outcome_printer | Renders outcome trees in ReScript syntax | Editor hover/completion through Print_type and Shared; generated interfaces; playground and tools. Its setup also installs the rendering callbacks used by Printtyp |

| Printtyp.signature, modtype, declaration printers | Readable signatures, module types, and declarations | Module/type diagnostics; bsc printing a .cmi; interface generation |

| Printtyped, via -dtypedtree | Typed AST structure | Compiler pipeline debugging; it doesn’t replace a dump of inference-node IDs, levels, and sharing |

...

The Btype.print_raw hook has a separate purpose: it lets lower-level modules invoke the printer without depending directly on Printtyp, which itself depends on Btype and Ctype. Its local callers are commented debugging statements in ctype and env. There is also an uncommented reference in Includemod.print_coercion, but that helper’s external invocation is commented out—so it likewise appears dormant.

My recommendation is to drop the raw-printer removal commit. “No active callers” is expected for a printer enabled through temporary instrumentation. Keeping this relatively small tool preserves a capability the readable printers do not provide. If it is removed, the justification should be that maintainers no longer want to maintain internal graph debugging—not that other type printers already cover it.

As I said to keep it we need to add a command line option to turn it on if it does not exist already

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants