-
Notifications
You must be signed in to change notification settings - Fork 473
docs(reanalyze): add DCE refactor plan #8043
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
rescript
@rescript/darwin-arm64
@rescript/darwin-x64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
|
I don't see an explicit mention of monorepos or npm/yarn/pnpm workspaces. In this context "dependencies" only refer to other files, but there is still the missing use case when one has shared code like this: where the root "workspaces": [
"common",
"mobile",
"web"
]and the root "dependencies": [
"common",
"mobile",
"web",
]And "dependencies": []Whereas both "dependencies": [
"common"
]And we want DCE to mark stuff as dead that is part of This needs to be an option to configure because when e.g. developing a library with tests, I might have tests dependent on the main package, but not 100 % coverage. The knowledge about package manager monorepos is mostly in Also tagging @nojaf and @DZakh who are users of bun and pnpm monorepos. |
This is a behavior preserving refactor. |
- Introduce BindingContext in DeadValue to track the current binding location during dead-code traversal, so binding context is explicit and locally encapsulated. - Introduce ReportingContext in DeadCommon to track, per file, the end position of the last reported value when deciding whether to suppress nested warnings. - Replace addValueReference_state with addValueReference ~binding, so value-reference bookkeeping is driven by an explicit binding location rather than a threaded analysis state. - Update dead-code value and exception handling to use the new addValueReference API. - Refresh DEADCODE_REFACTOR_PLAN.md to mark these state-localisation steps as completed and to narrow the remaining follow-up to making the binding context fully pure. - Verified with make test-analysis that behaviour and expected outputs remain unchanged.
- Remove BindingContext module wrapper (was just forwarding to Current) - Remove Current module entirely (unnecessary abstraction) - Simplify to pass Location.t directly instead of record type - Remove unused max_value_pos_end field - Refactor traverseStructure to use pure functional mapper creation - Update DEADCODE_REFACTOR_PLAN.md to mark task 4.3 as complete This eliminates ~40 lines of wrapper code and makes the binding state tracking pure and simpler to understand.
The original plan was too granular with many 'add scaffolding but don't use it yet' tasks. This rewrite focuses on: - Problem-first structure: each task solves a real architectural issue - Combined related changes: no pointless intermediate states - Clear value propositions: why each task matters - Testable success criteria: how we know it worked - Realistic effort estimates Reduces 14 fine-grained tasks down to 10 focused tasks that each leave the codebase measurably better. Signed-off-by: Cursor AI <cursor@cursor.com>
Replace global config reads with explicit ~config parameter threading throughout the DCE analysis pipeline. This makes the analysis pure and testable with different configurations. ## Changes ### New module - DceConfig: Encapsulates DCE configuration (cli + run config) - DceConfig.current() captures global state once - All analysis functions now take explicit ~config parameter ### DCE Analysis (fully pure - no global reads) - DeadCode: threads config to all Dead* modules - DeadValue: replaced ~15 !Cli.debug reads with config.cli.debug - DeadType: replaced ~7 !Cli.debug reads with config.cli.debug - DeadOptionalArgs: takes ~config, passes to Log_.warning - DeadModules: uses config.run.transitive - DeadCommon: threads config through reporting pipeline - WriteDeadAnnotations: uses config.cli.write/json - ProcessDeadAnnotations: uses config.cli.live_names/live_paths ### Logging infrastructure - Log_.warning: now requires ~config (no optional) - Log_.logIssue: now requires ~config (no optional) - Log_.Stats.report: now requires ~config (no optional) - Consistent API - no conditional logic on Some/None ### Non-DCE analyses (call DceConfig.current() at use sites) - Exception: 4 call sites updated - Arnold: 7 call sites updated - TODO: Thread config through these for full purity ### Other - Common.ml: removed unused lineAnnotationStr field - Reanalyze: single DceConfig.current() call at entry point - DEADCODE_REFACTOR_PLAN.md: updated Task 2, added verification task ## Impact ✅ DCE analysis is now pure - takes explicit config, no global reads ✅ All config parameters required (zero 'config option' types) ✅ Can run analysis with different configs without mutating globals ✅ All tests pass - no regressions ## Remaining Work (Task 2) - Thread config through Exception/Arnold to eliminate DceConfig.current() - Verify zero DceConfig.current() calls in analysis code Signed-off-by: Cursor AI <ai@cursor.com> Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
- Replace DceConfig.current() and !Common.Cli.debug with explicit config parameter - Thread config through Arnold.ml functions (Stats, ExtendFunctionTable, CheckExpressionWellFormed, Compile, Eval) - Thread config through Exception.ml functions (Event.combine, Checks.doCheck/doChecks, traverseAst) - Update Reanalyze.ml to pass config to all analysis functions - Improves testability and eliminates global state dependencies
This PR introduces a planning document for refactoring the reanalyze dead code analysis into a pure, order-independent pipeline.
There are no behavioural changes in this PR: it only adds documentation to coordinate subsequent work on the dead code analysis pipeline.