Skip to content

feat(assembly): add LinkMode::Analysis to keep resolved modules on a static cycle - #3535

Open
huitseeker wants to merge 3 commits into
nextfrom
feat/link-analysis-mode
Open

feat(assembly): add LinkMode::Analysis to keep resolved modules on a static cycle#3535
huitseeker wants to merge 3 commits into
nextfrom
feat/link-analysis-mode

Conversation

@huitseeker

Copy link
Copy Markdown
Collaborator

Closes #3457.

The linker rolls back resolved modules and returns an error when the call graph has a static cycle. Assembly needs that: MAST is built callees-to-callers, so a cycle blocks it. Lint analysis doesn't build MAST, and the rollback throws away the resolved graph it needs.

LinkMode::Analysis makes the cycle check nonfatal. Resolved modules and call edges are committed, and the cycle is returned with its procedure paths. Strict mode is unchanged and still rolls back on failure. Unresolved imports, unresolved calls, and failed rewrites stay fatal in both modes.

New public API:

  • LinkMode { Strict, Analysis } (Strict is the default)
  • Linker::link_analysis(roots, support) -> Result<LinkAnalysis, LinkerError>
  • LinkAnalysis { module_indices, cycle } with has_cycle(); cycle holds fully-qualified procedure paths

The call graph stays committed in analysis mode, so topological_sort_from_root still flags the cycle and its callers, while procedures that don't reach it lift normally.

@huitseeker
huitseeker force-pushed the feat/link-analysis-mode branch from 73123ad to 0ec552a Compare August 6, 2026 18:23
@huitseeker
huitseeker marked this pull request as ready for review August 6, 2026 18:23
@huitseeker huitseeker closed this Aug 6, 2026
@huitseeker huitseeker reopened this Aug 6, 2026
…cycle (#3457)

`Linker::link_and_rewrite` resolves imports and calls, then rejects any
static cycle in the call graph by rolling back and returning an error.
Assembly needs that check because MAST procedures must be built from
callees to callers, so a static cycle blocks MAST generation.

Lint analysis does not build MAST. It wants to skip the cycle and its
callers and keep analyzing the rest of the project, so rolling back
throws away exactly the work it needs.

Add `LinkMode::Analysis`. In this mode the final cycle check is
nonfatal: the resolved modules and call edges are committed, and the
cycle is returned in the new `LinkAnalysis` result as a nonfatal
diagnostic with its fully-qualified procedure paths.

`LinkMode::Strict` (the default) is unchanged: it still rejects a cycle
before MAST is built and rolls back all changes on failure. Unresolved
imports, unresolved calls, and failed rewrites remain fatal errors in
both modes; only the cycle check is nonfatal in analysis mode.

The new `Linker::link_analysis` entry point returns the linked module
indices together with the cycle diagnostic, and leaves the call graph
committed so callers can detect both the cycle and every caller that
depends on it (via `Linker::topological_sort_from_root`) while still
lifting procedures outside that set.
@huitseeker
huitseeker force-pushed the feat/link-analysis-mode branch from 0ec552a to 41c62ff Compare August 7, 2026 13:40
The `LinkMode` doc comment linked to the private `Linker::link_and_rewrite`,
which trips `rustdoc::private_intra_doc_links` under `-D warnings` in the
CI doc build. Point the intra-doc link at the public `Linker::link` entry
point that drives the same strict-mode cycle check.
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.

Keep resolved MASM modules when the call graph has a cycle

1 participant