{"id":18016903,"url":"https://github.com/fitzgen/safe-gc","last_synced_at":"2025-04-09T18:18:53.813Z","repository":{"id":220087962,"uuid":"750721328","full_name":"fitzgen/safe-gc","owner":"fitzgen","description":"A garbage collection library for Rust with zero unsafe code","archived":false,"fork":false,"pushed_at":"2024-07-15T22:07:56.000Z","size":45,"stargazers_count":111,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-09T18:18:48.371Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://docs.rs/safe-gc","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fitzgen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-31T07:24:35.000Z","updated_at":"2025-03-25T14:02:35.000Z","dependencies_parsed_at":"2024-10-30T05:05:12.895Z","dependency_job_id":null,"html_url":"https://github.com/fitzgen/safe-gc","commit_stats":null,"previous_names":["fitzgen/safe-gc"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fitzgen%2Fsafe-gc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fitzgen%2Fsafe-gc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fitzgen%2Fsafe-gc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fitzgen%2Fsafe-gc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fitzgen","download_url":"https://codeload.github.com/fitzgen/safe-gc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248085325,"owners_count":21045139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-30T04:19:38.929Z","updated_at":"2025-04-09T18:18:53.793Z","avatar_url":"https://github.com/fitzgen.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003e\u003ccode\u003esafe-gc\u003c/code\u003e\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eA garbage collection library for Rust without any \u003ccode\u003eunsafe\u003c/code\u003e code\u003c/strong\u003e\u003c/p\u003e\n  \u003cp\u003e\n    \u003ca href=\"https://github.com/fitzgen/safe-gc/actions/workflows/rust.yml\"\u003e\u003cimg src=\"https://github.com/fitzgen/safe-gc/actions/workflows/rust.yml/badge.svg\" alt=\"build status\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://docs.rs/safe-gc\"\u003e\u003cimg src=\"https://docs.rs/safe-gc/badge.svg\" alt=\"Documentation Status\" /\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## About\n\n`safe-gc` implements a garbage collection library for Rust with zero `unsafe`\ncode and zero dependencies. It even has a `forbid(unsafe_code)` directive at the\ntop!\n\nAdditional features:\n\n* Allows constructing and collecting arbitrary heap graphs, including cycles. It\n  doesn't impose any ownership hierarchy, or anything like that, to the shapes\n  of references between GC-managed objects within the heap.\n\n* Leverages Rust's ownership and borrowing in its API: if you have an `\u0026mut\n  Heap`, you can get mutable access to objects in the heap. It doesn't, for\n  example, force everything in the heap into `RefCell`s, or only give out shared\n  references to GC-managed objects, or similar.\n\n* Allows constructing multiple, separate GC heaps that can be independently\n  collected.\n\n* Allows allocating any number of heterogeneous types within the heap. For\n  example, you can allocate both `Cons` and `Tree` objects within the\n  heap. Heaps are *not* constrained to only a single, uniform `T` type of GC\n  objects.\n\n* Footgun-free GC object finalization with Rust's regular, old `Drop` trait. No\n  worries about accidentally deref'ing pointers to GC objects the collector has\n  already reclaimed or resurrecting objects it was about to reclaim.\n\n`safe-gc` is not, however, a particularly high-performance garbage collector.\n\n## Usage\n\n* Define types managed by the GC.\n\n* Define references from within one GC type to another GC type with `Gc\u003cT\u003e`.\n\n* Implement `Trace` for your GC-managed types.\n\n* Create one or more `Heap`s.\n\n* Allocate objects in your `Heap`s.\n\n* Hold onto GC roots with `Root\u003cT\u003e`.\n\n* Let the garbage collector reclaim unreachable objects!\n\n## Example\n\n```rust\nuse safe_gc::{Collector, Gc, Heap, Trace};\n\n// Define a GC-managed tree of `T` values.\nstruct Tree\u003cT: Trace\u003e {\n    value: Gc\u003cT\u003e,\n\n    // A cyclic parent pointer.\n    parent: Option\u003cGc\u003cTree\u003cT\u003e\u003e\u003e,\n\n    // Left and right subtrees.\n    left: Option\u003cGc\u003cTree\u003cT\u003e\u003e\u003e,\n    right: Option\u003cGc\u003cTree\u003cT\u003e\u003e\u003e,\n}\n\n// Report each of the GC references within a `Tree` to the\n// collector.\n//\n// See the `Trace` docs for more details.\nimpl\u003cT: Trace\u003e Trace for Tree\u003cT\u003e {\n    fn trace(\u0026self, collector: \u0026mut Collector) {\n        collector.edge(self.value);\n        if let Some(parent) = self.parent {\n            collector.edge(parent);\n        }\n        if let Some(left) = self.left {\n            collector.edge(left);\n        }\n        if let Some(right) = self.right {\n            collector.edge(right);\n        }\n    }\n}\n\n// Another GC type!\nstruct Cat {\n    cuteness: u32,\n    cat_tree: Option\u003cGc\u003cTree\u003cCat\u003e\u003e\u003e,\n}\n\nimpl Trace for Cat {\n    fn trace(\u0026self, collector: \u0026mut Collector) {\n        if let Some(tree) = self.cat_tree {\n            collector.edge(tree);\n        }\n    }\n}\n\n// Create a new GC heap!\nlet mut heap = Heap::new();\n\n// Allocate some objects in the heap!\nlet momo = heap.alloc(Cat {\n    cuteness: u32::MAX,\n    cat_tree: None,\n});\nlet tree = heap.alloc(Tree {\n    value: momo.unrooted(),\n    parent: None,\n    left: None,\n    right: None,\n});\n\n// Create a bunch of garbage! Who cares!\nfor _ in 0..100 {\n    let _ = heap.alloc(Tree {\n        value: momo.unrooted(),\n        parent: None,\n        left: None,\n        right: None,\n    });\n}\n\n// Read data from objects in the heap!\nlet cuteness = heap[\u0026momo].cuteness;\nassert_eq!(cuteness, u32::MAX);\n\n// Mutate objects in the heap!\nheap[\u0026momo].cat_tree = Some(tree.into());\n\n// Garbage collections will happen automatically, as necessary, but you can also\n// force a collection, if you want!\nheap.gc();\n```\n\n## Why?\n\n`safe-gc` is certainly a point in the design space of garbage-collection\nlibraries in Rust. One could even argue it is an interesting -- and maybe even\nuseful? -- point in the design space!\n\nAlso, it was fun!\n\nAt the very least, you don't have to wonder about the correctness of any\n`unsafe` code in here, because there isn't any. As long as the Rust language and\nits standard library are sound, this crate is too.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffitzgen%2Fsafe-gc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffitzgen%2Fsafe-gc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffitzgen%2Fsafe-gc/lists"}