{"id":28489569,"url":"https://github.com/cark/cark-ref-counted","last_synced_at":"2025-07-02T04:31:09.232Z","repository":{"id":63066703,"uuid":"563673567","full_name":"cark/cark-ref-counted","owner":"cark","description":"Generic reference counted smart pointers","archived":false,"fork":false,"pushed_at":"2022-11-12T01:32:31.000Z","size":28,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-08T06:42:06.868Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/cark.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}},"created_at":"2022-11-09T04:49:05.000Z","updated_at":"2023-01-21T16:55:50.000Z","dependencies_parsed_at":"2022-11-12T05:15:18.383Z","dependency_job_id":null,"html_url":"https://github.com/cark/cark-ref-counted","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cark/cark-ref-counted","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cark%2Fcark-ref-counted","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cark%2Fcark-ref-counted/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cark%2Fcark-ref-counted/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cark%2Fcark-ref-counted/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cark","download_url":"https://codeload.github.com/cark/cark-ref-counted/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cark%2Fcark-ref-counted/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263074397,"owners_count":23409755,"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":"2025-06-08T06:37:04.215Z","updated_at":"2025-07-02T04:31:09.219Z","avatar_url":"https://github.com/cark.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cark-ref-counted\n\n## cark-ref-counted\n\nA [GATs](https://blog.rust-lang.org/2022/10/28/gats-stabilization.html) powered abstraction for reference counted smart pointers.\n\n### What is it for\n\nYour library needs some kind of a reference counted pointer, but you want to leave the choice between [Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html) and [Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html) to the library user.\n\n### Show me the code\n\n```rust\nuse cark_ref_counted::*;\n\n// My library struct\nstruct Foo\u003cR: RefCountFamily\u003e {\n    name: R::Pointer\u003cString\u003e,\n}\n\nimpl\u003cR: RefCountFamily\u003e Foo\u003cR\u003e {\n    fn name(\u0026self) -\u003e \u0026str {\n        \u0026self.name\n    }\n    fn new(name: \u0026str) -\u003e Self {\n        Self {\n            // we wrap the string in some ref counted pointer\n            name: R::new(name.to_owned()),\n        }\n    }\n}\n\n// RcMark indicates which kind of reference counted\n// pointer we want this time\nlet foo = Foo::\u003cRcMark\u003e::new(\"John Doe\");\nassert_eq!(foo.name(), \"John Doe\");\n```\n\n### Some issues are remaining\n\n##### Ergonomics\n\nThere are some places where the type inference needs a little bit of help.\n\n```rust\nfn wrap\u003cR: RefCountFamily\u003e(value: i32) -\u003e R::Pointer\u003ci32\u003e {\n    R::new(value)\n}\n\n// Rc doesn't need help\nlet _a: Rc\u003ci32\u003e = Rc::new(1);\n\n// Type inference doesn't understand which Mark we're using\n// let _a: Rc\u003ci32\u003e = wrap(1);\n\n// So we need to specify it\nlet _a: Rc\u003ci32\u003e = wrap::\u003cRcMark\u003e(1);\n```\n\n##### Closures\n\nRust closures have a great deal of magic attached to them. Wrapping these will require the use of the [coerce_unsized nightly feature](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html).\n\n```rust\n#![feature(coerce_unsized)]\nuse std::ops::CoerceUnsized;\n\n// Inside a type that needs dyn Fn\nstruct Foo\u003cMark: RefCountFamily\u003e(Mark::Pointer\u003cdyn Fn(i32) -\u003e i32\u003e);\n\nimpl\u003cMark: RefCountFamily\u003e Foo\u003cMark\u003e {\n    // the c parmeter has to be generic here because it wouldn't be Sized\n    fn wrap\u003cT: Fn(i32) -\u003e i32 + 'static\u003e(c: T) -\u003e Self\n    where\n        Mark::Pointer\u003cT\u003e: CoerceUnsized\u003cMark::Pointer\u003cdyn Fn(i32) -\u003e i32\u003e\u003e,\n    {\n        // This cannot be done without the coerce_unsized nightly feature\n        // which has to be declared right here, because we cannot assume anything\n        // about the c parameter, other than it's a closure.\n        Self(Mark::new(c))\n    }\n}\nlet _a = Foo::\u003cRcMark\u003e::wrap(|a| a + 1).0;\n\n```\n\nWe obviously would prefer not to use a nightly feature here. It seems to me that the issue\nis not really with GATs but rather with the way rust closures are implemented.\n\nThe tentative conclusion to my experiments was that no amount of wrapping would allow this library to alleviate the issue by itself. At some point the closure needs to be passed as a generic parameter, and if we want it to be understood as implementing CoerceUnsized, it needs to be specified right there.\n\nA shot in the dark: Maybe would it be possible for the std team to implement CoerceUnsized for all `Rc\u003cFn\u003c...\u003e\u003e` to `Rc\u003cdyn Fn\u003c...\u003e\u003e`? And for `Arc` too. While this would still leave an open question for implementers of other reference counted types, the ergonomics would be greatly improved for this use case.\n\n### Thanks\n\n- Reddit user [Eh2406](https://www.reddit.com/user/Eh2406) for pushing.\n- Rust programming language forum user [semicoleon](https://users.rust-lang.org/u/semicoleon) for pointing me toward the CoerceUnsized trait.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcark%2Fcark-ref-counted","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcark%2Fcark-ref-counted","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcark%2Fcark-ref-counted/lists"}