Memory 2: cycle detection investigation + Type::can_form_cycle foundation#402
Merged
Conversation
A foundation primitive for any future cycle collector. Returns true if a runtime value of the given static type could possibly participate in a reference cycle under ilo's current memory model. Today every well-typed value classifies as cycle-incapable: records are immutable after construction, lists and maps mutate via copy-on-share, closures capture by value. The classifier exists as a regression surface so that if a future PR adds a cycle-forming construct (field assignment, ref cells, by-reference captures) the answer for the relevant type will flip and the test suite will say so. Defaults to true wherever information is missing (Any, Fn, unknown Named): marking a cycle-capable type clean would leak; marking a clean type capable only costs unnecessary scanning if and when a collector ever exists. 12 tests cover primitives, nested wrappers, records of primitives, records with Any / Fn fields, self-referential records, mutually recursive records, and lists of records.
Reference doc covering ilo's reference-counting model and the structural reasons cycles are unreachable today. Records are immutable after construction, container mutation goes through copy-on-share (Arc::make_mut, OP_RECCOPY), closures capture by value, and there is no field-assignment expression. Lists the surface changes that would close the cycle gap, and points at Type::can_form_cycle as the foundation a future cycle collector would plug into. Context: the memory-2 brief asks for incremental cycle detection and type-based pruning on a detector that does not exist. These notes keep that finding alongside the model itself, so anyone picking the work up later starts from accurate priors.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Investigation pass on the memory-2 brief (zero-gap-specs/briefs/memory/2-cycle-detection-brief.md). The brief asks for two optimisations to ilo's runtime cycle detector: incremental detection and type-based pruning of immutable types.
ilo does not currently have a cycle detector, and the surface language is structurally cycle-free. Records are immutable after construction. List/map "mutation" goes through
Arc::make_mut(interpreter) or fresh-allocation copy-on-share (OP_RECCOPY/OP_RECNEW_EMPTYin the VM). Closures capture by value. There is no field-assignment expression. Refcounts always drain through normal drop chains.That makes the brief's two deliverables non-applicable as written: there is no detector to make incremental, and no scanning to prune. The brief's underlying intent (foundation for the day ilo grows a mutation primitive that closes the cycle gap) lands here as a static classifier with a regression-surface test suite.
Time-box: 3 hours against a 1-2 month brief, as requested.
What's in the diff
Commit 1:
add Type::can_form_cycle classifier(src/ast/mod.rs)impl Type { pub fn can_form_cycle<F>(&self, resolve_record: &F) -> bool ... }trueif a runtime value of the given static type could possibly participate in a reference cycle.true(cycle-capable) whenever information is missing (Any, Fn, unknown Named). Sound bias: marking a clean type capable only costs unnecessary scanning if and when a collector is added; the reverse would leak.Commit 2:
docs: memory model notes and cycle freedom(MEMORY-MODEL.md)What landed vs what is deferred
--features craneliftgreenCHANGELOG.mdentrySuggested follow-up: retire or rewrite the memory-2 brief to reflect the actual memory model. The investigation notes in
MEMORY-MODEL.mdare written so that work can drop straight in.Test plan
cargo fmt --checkcleancargo clippy --lib --tests -- -D warningscleancargo test --release --features craneliftgreen (3192 lib + full suite)can_form_cycletests passDoc sync
No user-visible surface change: no new builtin, no new flag, no semantic change. SPEC.md / ai.txt / SKILL.md / site untouched per the workflow's "internal refactors / perf with no surface-area change" carve-out. The classifier is a future-collector hook, no current call sites.
Follow-ups
Type::can_form_cycleinto the allocator and add the Bacon-Rajan-style detector behind it.