Repository navigation
Conversation
Changelog🏠 Internal
Semantic Diff11 commits · Full page Remove dead compiler, build system and test code found by reanalyzeebb9114 · cknitt + Claude · Nov 02, 2026, 20:58 UTC Running reanalyze's dead code analysis over the native and browser (playground) builds reports values, constructors and fields that nothing uses: unused exports of Ext_list, Request_local, Misc.Color, Ast_literal, Ast_fixed_arg, Ast_helper and Ctype, Ast_helper0 builders, the narrowed Typedtree_iter.Make_iterator signature, Lam_id_kind's MutableBlock, Exception and boxed Undefined (with Lambda's Pis_undefined and Js_exp_make.is_undef, which only they produced), Bsc_args actions, Includecore.Field_arity, the hash_string_int primitive and its C stub, two rewatch exception aliases that were only matched, and unused ounit helpers. Fields of serialized formats (.cmi/.cmt) and the frozen parsetree0 stay. Remove dead editor analysis code and reanalyze's write-only file depse75f00a · cknitt + Claude · Nov 02, 2026, 20:58 UTC Reanalyze finds unused code in the editor analysis and in reanalyze itself: the Reactive.Registry/Scheduler exports, Shared_types helpers, Completion fields type_arg_context and data (with the parameters that only filled them), package.dependencies, Server.let*, the never-produced Circular issue, and record fields of the reactive pipeline that nothing reads. Two reactive collections, file_deps_map and files, were computed but never consumed; they were the only readers of the per-file File_deps builder, so that module and its ~file_deps/~add_file_reference plumbing go as well. package.rescript_version stays: the ve+ test directives set it. Remove unused fields of the .cmi and .cmt formats17cf05b · cknitt + Claude · Nov 03, 2026, 06:40 UTC Reanalyze finds fields of the serialized formats that nothing reads: cmt_comments, cmt_sourcefile, cmt_builddir, cmt_loadpath, cmt_initial_env, cmt_imports and cmt_use_summaries of Cmt_format, deprecated_used.deprecated_text, Types.label_description.lbl_attributes, Typedtree.extension_constructor.ext_name, Primitive.prim_alloc, and the never-built Env_constraints summary. v13 has a new .cmi/.cmt version anyway, and the release bumps the magic numbers. The initial environment only fed cmt_initial_env, so save_cmt and Typemod.save_signature no longer take it. Remove optional arguments that no caller passes2c8c04d · cknitt + Claude · Nov 03, 2026, 07:21 UTC Reanalyze reports optional parameters that are never supplied. The largest group is ?comment in Js_exp_make and Js_stmt_make: only three producers remain (the The rest are parameters whose default is always taken, such as Location.errorf's ?sub and ?if_highlight, Ctype.free_vars' ?env (with the request-local really_closed it set), Js_implementation's ?outputprefix, Bsc_args.parse_exn's ?finish, and Ast_helper builders' ?runtime_tag, ?runtime_name, ?default and ?suffix. The default is now used directly. Make optional arguments that every caller supplies mandatory8955cbd · cknitt + Claude · Nov 03, 2026, 07:40 UTC Reanalyze reports optional parameters that no call omits. They become labelled arguments, so a default that is never taken no longer suggests otherwise: mostly ~loc and ~attrs of the Ast_helper0 builders used by the frozen-AST mappers (the mk functions included where all builders now pass both), plus a few others such as Location.pp_ksprintf ~before, Parmatch.do_check_partial ~pred and Type_utils.filter_pipeable_functions ~target_type_id, whose None branches were unreachable. Remove the last dead code and mark fields reanalyze cannot see as live47ab359 · cknitt + Claude · Nov 03, 2026, 08:03 UTC The remaining reanalyze findings outside the frozen parsetree0: - Dead, removed: the playground's int_unsafe_blit; package.rescript_version with Packages.get_rescript_version, the RESCRIPT_VERSION lookup and the ve+/ve- analysis test directives that only set it; and the default enter_expression of Typedtree_iter, which every iterator overrides (Default_iterator_argument now implements IteratorArgumentDefaults, IteratorArgument without enter_expression). - Live, annotated with [ Also give the playground's Cmt_format_persistence.save_cmt the signature without the initial environment, which the .cmt field removal missed: the call was a partial application, harmless only because the playground writes no .cmt. Add make dead-code to run reanalyze's dead code analysis4cfd3fc · cknitt + Claude · Nov 03, 2026, 08:03 UTC scripts/dead_code.sh builds the native and the browser (playground) profiles and runs reanalyze over both, so uses in either count, and fails on any finding. Vendored flow_parser and the frozen parsetree0 are suppressed. It needs a reanalyze with rescript-lang/reanalyze#224, given as REANALYZE. Give platform variants distinct source names and mark forward-ref hooks livebe4ea2c · cknitt + Claude · Nov 03, 2026, 19:05 UTC The native and playground variants of a platform module were copied to the same name, so their .cmt locations shared one source path and reanalyze could not tell their declarations apart (it now warns about that). The copy rules use copy#, whose line directive makes locations name platform/native/... or platform/playground/... instead. type_open_, default_error_reporter and record_deprecated_used are called through forward references (Typecore.type_open, error_reporter, Cmt_utils.record_deprecated_used) with optional arguments reanalyze cannot trace, so they are marked [ Remove code left unused by in-memory build file writes7fd9bad · cknitt + Claude · Nov 04, 2026, 06:11 UTC Since #9170 writes build files through Build_file_store, nothing writes or reads them through channels any more. make dead-code reported: - Misc.output_to_bin_file_directly, Ext_buffer.output_buffer and Cmi_format.read_cmi_channel: never used; removed. - File_util.read_build_file: used only inside File_util; no longer exported. - Compiler_process.run_requests: its ?poll and ?on_complete are never passed (the only caller is a test); removed, like the other never-passed optional arguments. Remove code that recent master changes left unused09cd097 · cknitt + Claude · Nov 06, 2026, 20:48 UTC After rebasing onto master (Rust rewatch removal, flat lib/rescript), master's new code still matched Lambda.Pis_undefined, which this branch removes as never produced, and make dead-code reported: - Js_exp_make.of_block ?e, and the test helpers' module_ ?interface and publish ?has_interface: never passed; removed. - Cmi_format.input_cmi and Build_session.iter_package_plans: never used. - Package_plan.t.source_files: never read; removed with its two writes. The two Pis_undefined arms (Lambda, Lam_analysis) go. Keep the color palette, iterator entry points and Mod.mk as live98faffc · cknitt + Claude · Nov 06, 2026, 21:01 UTC The first commit removed what no code used today, including parts of general APIs that new code is likely to need. These come back, marked [ - Misc.Color: the full ANSI palette (Black, Green, Blue, White) and background colors (BG), exported again so OCaml's unused-constructor warning does not fire. - Typedtree_iter.Make_iterator: iter_structure, iter_signature, iter_signature_item, iter_module_type and iter_pattern. - Ast_helper.Mod.mk: the builder the other Mod builders specialize. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #9173 +/- ##
==========================================
+ Coverage 81.74% 81.92% +0.18%
==========================================
Files 457 456 -1
Lines 65713 65471 -242
==========================================
- Hits 53715 53636 -79
+ Misses 11998 11835 -163
🚀 New features to boost your workflow:
|
rescript
@rescript/belt
@rescript/darwin-arm64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
|
Developer playground preview: https://rescript-lang.github.io/rescript/dev-playground/?version=pr-9173 |
c4bb502 to
fe3dfd9
Compare
|
@codex review |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Running reanalyze's dead code analysis over the native and browser (playground) builds reports values, constructors and fields that nothing uses: unused exports of Ext_list, Request_local, Misc.Color, Ast_literal, Ast_fixed_arg, Ast_helper and Ctype, Ast_helper0 builders, the narrowed Typedtree_iter.Make_iterator signature, Lam_id_kind's MutableBlock, Exception and boxed Undefined (with Lambda's Pis_undefined and Js_exp_make.is_undef, which only they produced), Bsc_args actions, Includecore.Field_arity, the hash_string_int primitive and its C stub, two rewatch exception aliases that were only matched, and unused ounit helpers. Fields of serialized formats (.cmi/.cmt) and the frozen parsetree0 stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
Reanalyze finds unused code in the editor analysis and in reanalyze itself: the Reactive.Registry/Scheduler exports, Shared_types helpers, Completion fields type_arg_context and data (with the parameters that only filled them), package.dependencies, Server.let*, the never-produced Circular issue, and record fields of the reactive pipeline that nothing reads. Two reactive collections, file_deps_map and files, were computed but never consumed; they were the only readers of the per-file File_deps builder, so that module and its ~file_deps/~add_file_reference plumbing go as well. package.rescript_version stays: the ve+ test directives set it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
Reanalyze finds fields of the serialized formats that nothing reads: cmt_comments, cmt_sourcefile, cmt_builddir, cmt_loadpath, cmt_initial_env, cmt_imports and cmt_use_summaries of Cmt_format, deprecated_used.deprecated_text, Types.label_description.lbl_attributes, Typedtree.extension_constructor.ext_name, Primitive.prim_alloc, and the never-built Env_constraints summary. v13 has a new .cmi/.cmt version anyway, and the release bumps the magic numbers. The initial environment only fed cmt_initial_env, so save_cmt and Typemod.save_signature no longer take it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
Reanalyze reports optional parameters that are never supplied. The largest group is ?comment in Js_exp_make and Js_stmt_make: only three producers remain (the @__PURE__ annotation on exception creation and the [] and assert_false hints on constants) plus the builders that forward to them, so the generated JavaScript is unchanged. The comment of a tuple field access was always None, so Lambda.str_of_field_info goes too. The rest are parameters whose default is always taken, such as Location.errorf's ?sub and ?if_highlight, Ctype.free_vars' ?env (with the request-local really_closed it set), Js_implementation's ?outputprefix, Bsc_args.parse_exn's ?finish, and Ast_helper builders' ?runtime_tag, ?runtime_name, ?default and ?suffix. The default is now used directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
Reanalyze reports optional parameters that no call omits. They become labelled arguments, so a default that is never taken no longer suggests otherwise: mostly ~loc and ~attrs of the Ast_helper0 builders used by the frozen-AST mappers (the mk functions included where all builders now pass both), plus a few others such as Location.pp_ksprintf ~before, Parmatch.do_check_partial ~pred and Type_utils.filter_pipeable_functions ~target_type_id, whose None branches were unreachable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
The remaining reanalyze findings outside the frozen parsetree0: - Dead, removed: the playground's int_unsafe_blit; package.rescript_version with Packages.get_rescript_version, the RESCRIPT_VERSION lookup and the ve+/ve- analysis test directives that only set it; and the default enter_expression of Typedtree_iter, which every iterator overrides (Default_iterator_argument now implements IteratorArgumentDefaults, IteratorArgument without enter_expression). - Live, annotated with [@@LiVe] and a comment: Watch_snapshot's file and dependency and Run_config.snapshot, whose fields are only read by structural equality, and Platform_windows.command, read through Platform.command on Windows only. Also give the playground's Cmt_format_persistence.save_cmt the signature without the initial environment, which the .cmt field removal missed: the call was a partial application, harmless only because the playground writes no .cmt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
scripts/dead_code.sh builds the native and the browser (playground) profiles and runs reanalyze over both, so uses in either count, and fails on any finding. Vendored flow_parser and the frozen parsetree0 are suppressed. It needs a reanalyze with rescript-lang/reanalyze#224, given as REANALYZE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
…ks live The native and playground variants of a platform module were copied to the same name, so their .cmt locations shared one source path and reanalyze could not tell their declarations apart (it now warns about that). The copy rules use copy#, whose line directive makes locations name platform/native/... or platform/playground/... instead. type_open_, default_error_reporter and record_deprecated_used are called through forward references (Typecore.type_open, error_reporter, Cmt_utils.record_deprecated_used) with optional arguments reanalyze cannot trace, so they are marked [@LiVe] with a comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
Since #9170 writes build files through Build_file_store, nothing writes or reads them through channels any more. make dead-code reported: - Misc.output_to_bin_file_directly, Ext_buffer.output_buffer and Cmi_format.read_cmi_channel: never used; removed. - File_util.read_build_file: used only inside File_util; no longer exported. - Compiler_process.run_requests: its ?poll and ?on_complete are never passed (the only caller is a test); removed, like the other never-passed optional arguments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
After rebasing onto master (Rust rewatch removal, flat lib/rescript), master's new code still matched Lambda.Pis_undefined, which this branch removes as never produced, and make dead-code reported: - Js_exp_make.of_block ?e, and the test helpers' module_ ?interface and publish ?has_interface: never passed; removed. - Cmi_format.input_cmi and Build_session.iter_package_plans: never used. - Package_plan.t.source_files: never read; removed with its two writes. The two Pis_undefined arms (Lambda, Lam_analysis) go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
The first commit removed what no code used today, including parts of general APIs that new code is likely to need. These come back, marked [@@LiVe] with a comment so the dead-code check accepts them: - Misc.Color: the full ANSI palette (Black, Green, Blue, White) and background colors (BG), exported again so OCaml's unused-constructor warning does not fire. - Typedtree_iter.Make_iterator: iter_structure, iter_signature, iter_signature_item, iter_module_type and iter_pattern. - Ast_helper.Mod.mk: the builder the other Mod builders specialize. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel <ck@cca.io>
9ba9825 to
98faffc
Compare
✅ Compiler benchmarksAllocated wordsIn total: 456,989,425 → 456,745,704 (-0.05%).
72 more changes
InstructionsIn total: 10,226,962,471 → 10,228,138,954 (+0.01%).
Pull request 98faffc compared with base bf35764 in this run. |
Removes the dead code that reanalyze's dead-code analysis finds in the OCaml sources, and adds
make dead-codeto check for it. The analysis runs over both the native and the browser (playground) build, so uses in either count. The vendoredcompiler/flow_parseris left to the rest of the stack (#9267, #9208).What goes
Ext_list.concat_appendandRequest_local.set.Misc.Color'sansi_of_style_l,stylesanddefault_stylesexports. They're still used insideMisc; the color palette itself stays, see "Kept" below.Ast_literalvalues.Ast_fixed_arg.of_payload/to_expression.Ast_helper.Jsx_component.to_attribute.Ctype.apply.Ast_helper0builders for OCaml-only constructs (new_,setinstvar,override,lazy_, extensionrebind).Lam_id_kind'sMutableBlock/Exception/boxedUndefined, which nothing produces. With them goLambda.Pis_undefinedandJs_exp_make.is_undef, which only they produced.Bsc_argsactions,Includecore.Field_arity(an error never raised), and thehash_string_intprimitive with its C stub.int_unsafe_blit, andTypedtree_iter's defaultenter_expression, which every iterator overrides.Build_session.iter_package_plans, the never-readPackage_plan.t.source_files, and theFile_util.read_build_fileexport.package.dependencies, the never-producedCircularissue, and never-read fields of the reactive pipeline.package.rescript_version, with its^ve+/^ve-analysis-test directive.file_deps_map,files) that were computed but never consumed. They were the only readers of theFile_depsbuilder, so that write-only tracking goes too..cmi/.cmtfields:Cmt_format.cmt_infosfields nobody reads (cmt_comments,cmt_sourcefile,cmt_builddir,cmt_loadpath,cmt_initial_env,cmt_imports,cmt_use_summaries).Cmt_utils.deprecated_text,Types.lbl_attributes,Typedtree.ext_name,Primitive.prim_allocandEnv.Env_constraints.Misc.output_to_bin_file_directly,Ext_buffer.output_buffer,Cmi_format.read_cmi_channelandCmi_format.input_cmi.?commentinJs_exp_make/Js_stmt_make. Only the@__PURE__annotation on exception creation and the/* [] */andassert_falsehints still produce comments, so the generated JS is unchanged.Location.errorf ?sub ?if_highlight,Ctype.free_vars ?env,Js_implementation ?outputprefix,Js_exp_make.of_block ?e,Compiler_process.run_requests ?poll ?on_complete.~loc/~attrsof theAst_helper0builders.Nonebranch was unreachable (Location.pp_ksprintf ~before,Parmatch.do_check_partial ~pred, …).Kept, marked
[@@live]with a commentWatch_snapshot.file/dependencyandRun_config.snapshot, whose fields are only read by structural equality.Platform_windows.command, read on Windows only. On other platforms the file is only type-checked in the tests.Typemod.type_open_,Location.default_error_reporter) andCmt_format_common.record_deprecated_used.Misc.Color, including background colorsTypedtree_iter.Make_iteratorentry points (iter_structure,iter_signature,iter_signature_item,iter_module_type,iter_pattern)Ast_helper.Mod.mkThe platform variants of
compiler/{core,ext,ml}are now copied withcopy#, so the native and playground copies have distinct source positions and reanalyze doesn't merge their declarations.Running it:
make dead-codescripts/dead_code.shbuilds the native and browser profiles and runs reanalyze over both. It fails on any finding, and currently reports 0 issues.opam install reanalyze). The script usesreanalyze.exefromPATH, orREANALYZE=path/to/reanalyze.exe.What the check deliberately doesn't report:
parsetree0.ml, whose constructors only PPXs build.compiler/flow_parser. Remove dead code from the vendored Flow parser #9208 narrows that to its AST.🤖 Generated with Claude Code
https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT