{
  "@context": "https://schema.org",
  "@id": "https://aggr.aymericbeaumet.com/items/lobste-rs/2026-09-29-pining-for-arc-downcasting-in-rust/#webpage",
  "@type": [
    "WebPage",
    "ArchiveComponent"
  ],
  "articleBody": "In the course of writing my [build driver](https://git.sr.ht/~polywolf/driver), I came across a bit of an unusual problem, for which I made a bit of an usual solution. I think the solution is interesting and would like to talk about it, but to understand anything we must first understand the problem at hand.\n\n## Consider The Case Of The Humble Concurrent Cache\n\nSuppose we have some expensive function we'd like to put a cache in front of. Furthermore, suppose we'd like to access this cache from multiple threads. A simple example follows ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=cf4e4af4e40d6895d16d12779f395fa0)):\n\n```rust\nenum JSON {\n    F64(f64),\n    String(String),\n    Vec(Vec<JSON>),\n    Object(HashMap<String, JSON>),\n}\n\nstruct Proxy {\n    client: HTTPClient,\n    cache: RWLock<HashMap<String, JSON>>,\n}\n\nimpl Proxy {\n    fn get(&self, key: &str) -> JSON {\n        // 1.\n        {\n            let cache = self.cache.read().unwrap();\n            if let Some(value) = cache.get(key) {\n                return value.clone();\n            }\n        }\n\n        // 2.\n        let value = self.client.get(key);\n        {\n            let mut cache = self.cache.write().unwrap();\n            cache.insert(key.to_string(), value.clone());\n        }\n        value\n    }\n}\n```\n\nThis code has an \"early exit\" path (1) where it returns a value from the cache if it's present, and a \"late exit\" path (2) where it calls the expensive function, then inserts the resulting value into the cache.\n\nPlease ignore the many, many obvious problems with this implementation[^1]. Instead, let's focus on the one problem that bothers me the most: there's fair bit of `.clone()` action going on here!\n\nTechnically, it's just one `.clone()` per call: one on early exit to take value out of the cache, and one on late exit to put value into the cache. But if those values are big/tree-shaped/otherwise expensive to clone, this cost can dominate, minimizing the savings conferred by a cache. In my code, I found this to be the case, so we gotta do something about it.\n\n## Let's Get Rid Of The Clones?\n\nAssume that, with the way we use this data, read-only access is more than enough. Shared references are read-only & cheap to `Copy`, so using those instead of `.clone()`-ing the entire value seems good. If some later part of the code really needs to take ownership, we can just `.clone()` there, saving time in the average case. So, we'd like to change the signature for `get()` to be:\n\n```rust\nimpl Proxy {\n    fn get<'a, 'b>(&'a self, url: &'b str) -> &'a JSON { ... }\n}\n```\n\nBut we can't do this!! Because our cache is behind a mutex, the only way we can get references to its contents is thru temporary handles. Those handles, while live, hold a lock on the cache, plus they only live for the body of the function, a not for all of `'a`. Even if we *could* return one of those handles, that'd be equivalent to holding the lock outside the function, which is very bad. Locks should only be held for VERY SHORT amounts of time unless ur into that sorta thing next month ;)\n\n## Let's Make The Clones Cheaper\n\nSo, no references. What other types can we use? What we want is something with all the following properties:\n\n1. It allows for read access to our data. That is, it allows us to get an `&JSON` somehow.\n2. It has no lifetime parameters (`'a`, the only lifetime we have access to, is too long).\n3. It is cheap to `.clone()`, even if the underlying value is *not* cheap to `.clone()`.\n\nThese requirements hint we should probably still be looking for some sort of pointer... Among standard library types, we have the following options[^2]:\n\n- [Raw pointers](https://doc.rust-lang.org/std/primitive.pointer.html): `*const JSON`\n- [Reference-counted pointers](https://doc.rust-lang.org/std/rc/index.html): `Rc<JSON>`\n- [Atomically-reference-counted pointers](https://doc.rust-lang.org/std/sync/struct.Arc.html): `Arc<JSON>`\n\nLike any good Rustacean, we care a lot about safety & concurrency, so `Arc` is the obvious pick here :3 Modifying the example to use it is straightforward ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f3e3821009472761d2297690f6262e17)):\n\n```rust\nstruct Proxy {\n    client: HTTPClient,\n    cache: RWLock<HashMap<String, Arc<JSON>>>, // new!\n}\n\nimpl Proxy {\n    fn get(&self, url: &str) -> Arc<JSON> { // new!\n        {\n            let cache = self.cache.read().unwrap();\n            if let Some(value) = cache.get(url) {\n                return value.clone();\n            }\n        }\n\n        let value = Arc::new(self.client.get(url)); // new!\n        {\n            let mut cache = self.cache.write().unwrap();\n            cache.insert(url.to_string(), value.clone());\n        }\n        value\n    }\n}\n```\n\nOther than the three lines with `Arc` added to them, this implementation looks the exact same as before. But now our clones are cheaper, so we're happy, yay!!\n\n## So What's This About Downcasting?\n\nI hope the above section convinced you having an `Arc` \"owned value that acts like a reference\" is both normal to want & possible to achieve. Switching gears a bit, I'd like to discuss an interesting shortcoming with them: they don't fit into Rust's type system very well.\n\nSupposed we know for a fact that certain `JSON` values are strings, and we're only interested in the `JSON::String` variant of them. With an owned value or a shared reference, we can just pattern-match to \"downcast\" from a `JSON` to a `String`, or a `&JSON` to a `&String`.\n\n```rust\nimpl JSON {\n    fn to_str(self) -> Option<String> {\n        match self {\n            Self::String(s) => Some(s),\n            _ => None,\n        }\n    }\n    \n    fn as_str(&self) -> Option<&String> {\n        match self {\n            Self::String(s) => Some(s),\n            _ => None,\n        }\n    }\n}\n```\n\nBut if we have an `Arc<JSON>`, we can't get another `Arc<String>` the same way!\n\n```rust\nimpl JSON {\n    fn doesnt_exist(value: Arc<JSON>) -> Option<Arc<String>> {\n        match value.deref() {\n            Self::String(s) => Some(s), // compile error!\n            _ => None,\n        }\n    }\n}\n```\n\nThis is because `value.deref()` creates a reference to `value`, whose lifetime will end as soon as the function is over, because we don't return it, only a pointer somewhere inside it. The machinery for `Arc` only works if it has access to the original pointer, not any derived pointers. So if we wanted to return an `Arc<String>`, we'd need to `.clone()` out of the `Arc<JSON>`, which is what we've been trying to avoid this whole time.\n\nHowever! We don't necessarily *need* a full `Arc<String>`! We'd be perfectly happy returning some other type, perhaps implementing `Deref<Target = String>`, so long as it still gives us those \"owned value that acts like a reference\" properties. If only we could extend the lifetime of `value`, perhaps by returning it alongside a reference to its contents, packaged together to implement `Deref` like we want...\n\n## Tying The Two Together With Evil Lesbian Shibari\n\nOur goal is some return type that looks like:\n\n```\n               ,-----------------------+---------------------.\nval: owned --> | contents: *const JSON | refcnt: AtomicUsize |\n               `-----------------------+---------------------'\n                                     |\n          /--------------------------/\n          V\n        ,------------------+--------------+------------+------------.\n        | JSON::String tag | buf: *mut u8 | len: usize | cap: usize |\n        `------------------+--------------+------------+------------'\n                             ^          |\n                             |          |\nptr: ref --------------------/          |\n                                        V\n                                      ,---+---+---+---.\n                                      |'A'|'C'|'A'|'B'|\n                                      `---+---+---+---'\n```\n\nThat is, we want some `val` showing us how to get to the main value we care about, and then some pointer `ptr` into the memory `val` references. Then, as long as we keep those tied together, we know `ptr` will still be valid, because `val` is still alive, because we own `val`.\n\nA first attempt at writing this reveals an immediate issue[^3]\n\n```rust\nstruct Ref<V, T> {\n    val: V,\n    ptr: &T, // What's the lifetime here?\n}\n```\n\nWe can't express `ptr` as a reference, because there's no obvious lifetime to attach it to. Without a way to spell \"lifetime of the containing struct\" in Rust, it looks like we're going to need a raw pointer instead. But what if.....\n\n```rust\nstruct Ref<V, T: 'static> {\n    val: V,\n    ptr: &'static T,\n}\n\nimpl<T, V: Deref<Target = T>> {\n    fn new(val: V) -> Self {\n        let ptr: &T = val.deref();\n        Self {\n            // This is the easiest way to do lifetime extension\n            // SAFETY: hm?\n            ptr: unsafe { std::mem::transmute(ptr) },\n            val,\n        }\n    }\n}\n```\n\nWhoa!! That's scary!!! Are they even allowed to hold hands like that...?\n\nIt's true this is exceedingly unsafe if users could extract that `ptr: &'static T` separately from the `val: V` it points into (`val`'s lifetime isn't `'static`!). But we could also just... not allow that, keeping them tied together always, providing access only via `Deref` implementation:\n\n```rust\nimpl<V, T> Deref for Ref<V, T> {\n    type Target = T;\n    fn deref(&self) -> &T {\n        self.ptr\n    }\n}\n```\n\nBecause the *effective* lifetime for which `ptr` can be accessed is a subset of the *actual* lifetime for which `val` lives, I believe we've properly rules-lawyered Rust's reference aliasing rules into submission. Or have we...\n\nOh noes... ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=52455c2042bd9bc26f1bbbb8a239f9a4))\n\n```rust\nstruct SimpleWrapper<T>(T);\n\nimpl<T> Deref for SimpleWrapper<T> {\n    type Target = T;\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nfn main() {\n    let r = Ref::new(SimpleWrapper(x));\n    // Check what's stored vs what should be returned\n    let ptr = r.ptr as *const i32 as usize;\n    let actual_ptr = r.val.deref() as *const i32 as usize;\n    println!(\"ptr: {ptr:x} actual_ptr {actual_ptr:x}\");\n}\n```\n\nRunning this, I got `ptr: 7fff85189b5c actual_ptr 7fff85189b88`. These are in fact different pointers!!! Turns out I messed up my earlier rules-lawyering: The act of moving `val` into `Ref::new()`, taking the `.deref()` on that stack frame, and then moving it back out to the parent stack frame invalidates `ptr`[^3]. Lifetimes exist precisely to prevent bugs like this, and our extension trick was foiled. Lesson learned! Guess we'll do this the hard way...\n\n## Ensure Address Stability With This One Simple Trick!\n\nTo fix our datastructure, we'll want a guarantee that each `.deref()` will give us the same pointer, even if move the container around. For this, we MUST NOT be able to move the `val: V` out of its location once we wrap it. Fortunately, Rust has a type exactly for this usecase!\n\nahem. anyways. Unfortunately, `Pin` is very hard to use, to the point I found a flaw in my initial implementation[^4] while writing this :( Still, the docs are *really* good, and we can pretty easily follow their example to make [a self-referential struct](https://doc.rust-lang.org/std/pin/index.html#a-self-referential-struct):\n\n```rust\nstruct MustPin<V> {\n    val: V,\n    _pin: PhantomPinned,\n}\nstruct PinRef<V, T> {\n    val: Pin<Arc<MustPin<V>>>,\n    // MUST point into [`val`].\n    ptr: *const T,\n}\n\nimpl<V> MustPin<V> {\n    fn new(val: V) -> Pin<Arc<Self>> {\n        Arc::pin(Self {\n            val,\n            _pin: PhantomPinned,\n        })\n    }\n}\n\nimpl<V> PinRef<V, V> {\n    fn new(val: Pin<Arc<MustPin<V>>>) -> Self {\n        let ptr = &raw const val.val;\n        Self { val, ptr }\n    }\n}\n```\n\nComparing this to the example in the docs:\n\n1. We use `*const T` instead of `NonNull<T>` because the latter is more like a `*mut T`, and we don't need all that power.\n2. We don't need `MaybeUninit` because we solve the \"knot-tying\" trick in a different way: we create the pinned data first, and then store a pointer into it out-of-line. This is still fine because of pin guarantees.\n3. We still need `PhantomPinned` because if we have `Pin<Arc<V>>` where `V: Unpin`, all bets are off, literally every pin guarantee goes out the window.\n\n`Deref` is simple like before, just with a pointer instead of a reference:\n\n```rust\nimpl<V, T> Deref for PinRef<V, T> {\n    type Target = T;\n    fn deref(&self) -> &Self::Target {\n        // SAFETY: by construction and pin guarantees, the pointer is still valid.\n        unsafe { &*self.ptr }\n    }\n}\n```\n\nNow, finally, we're all set up for the big reveal: how are we going to downcast these things?\n\n## She Downcast On My `Pin` 'Til I `Arc`\n\nOur rule for `ptr` is that it MUST point somewhere valid inside `val`. That's all we can assume, and that's what we have to uphold while doing our downcasts. Fortunately, we can use Rust's type-checking for \"standard\" downcasts to our advantage!\n\n```rust\nimpl<V, T> PinRef<V, T> {\n    fn project<U>(self, f: impl for<'a> FnOnce(&'a T) -> &'a U) -> PinRef<V, U> {\n        let Self { val, ptr } = self;\n        // SAFETY: by validity of `ptr` and `f`\n        let ptr = unsafe { f(&*ptr) as *const U };\n        PinRef { val, ptr }\n    }\n}\n```\n\nStating this signature more in more math-y terms, for those unfamiliar with Rust's syntax:\n\n$\\begin{gathered} \\text{PinRef} : (\\text{Type}, \\text{Type}) \\rightarrow \\text{Type}\\\\ \\forall\\ V,T,U : \\text{Type}.\\\\ \\text{project} : \\text{PinRef}(V,T) \\rightarrow (\\forall(a: \\text{Lifetime}).\\ \\&'a T \\rightarrow \\&'aU) \\rightarrow \\text{PinRef}(V,U) \\end{gathered}$\n\nHow we should interpret this is: If we can go from a `&T` to a `&U` for an *arbitrary* lifetime `'a`, that means `*U` is a fixed offset from `*T`[^5]. So, because `ptr` has a fixed address (it was derived from the pinned `val`), so will the output of `f`. Other pin guarantees like \"`val` will always remain valid at that address while it's pinned\" help too.\n\nIf I were a real type theorist, I would have pulled out some sort of commutative diagram and drawn a bunch of arrows, or perhaps even written down some inference rules, but alas, I cannot even abstract over monads... Anyways this argument works for what we originally wanted too:\n\n```rust\nimpl<V, T> PinRef<V, T> {\n    fn filter_project<U>(\n        self,\n        f: impl for<'a> FnOnce(&'a T) -> Option<&'a U>,\n    ) -> Option<PinRef<V, U>> {\n        let Self { val, ptr } = self;\n        // SAFETY: by validity of `ptr`, `f`\n        let ptr = unsafe { f(&*ptr)? as *const U };\n        Some(PinRef { val, ptr })\n    }\n    \n    fn try_project<U, E>(\n        self,\n        f: impl for<'a> FnOnce(&'a T) -> Result<&'a U, E>,\n    ) -> Result<PinRef<V, U>, E> {\n        let Self { val, ptr } = self;\n        // SAFETY: by validity of `ptr`, `f`\n        let ptr = unsafe { f(&*ptr)? as *const U };\n        Ok(PinRef { val, ptr })\n    }\n}\n```\n\nYou see that??? We did the thing!! To celebrate, here's a full example using the original JSON projections ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=9ba8b6f27dc48afb065a2923023fb1da)):\n\n```rust\nfn print(s: impl Deref<Target = str>) {\n    println!(\"{}\", s.deref())\n}\n\nfn main() {\n    let v = std::sync::Arc::pin(JSON::String(String::from(\"hello, world!\")));\n    let v = PinRef::new(v);\n    let s = v.filter_project(JSON::as_str).unwrap();\n    print(s.clone());\n    print(s);\n}\n```\n\nAll that remains in our original example is to replace all the plain `Arc<JSON>` with `Pin<Arc<MustPin<JSON>>>` (wow what a mouthful), make a `Clone` implementation, account for `?Sized` types, etc. etc. This post is long enough as it is so I've omitted that, but if you want, you can find the full details in my [repository](https://git.sr.ht/~polywolf/driver/tree/cb9ee31e272f24311981a41f979d82f31f39f61f/item/packages/pin-downcast/src/pin_ref.rs). I might release this as a standalone crate if I feel like it, but this might still be riddled with UB I missed so maybe not (:\n\nAnyways!! Hope you learned something, until next time~\n\n[^1]: In increasing order of badness: too much string typing, no error handling, concurrent requests can race and end up doing extra work. Probably others I'm missing too. The solution to that last one is simultaneously very interesting & very boring, [read the code yourself if you want](https://git.sr.ht/~polywolf/driver/tree/3e0e9250a6657f9e5ed977ecdd08f3550e06f68b/item/packages/driver-db/src/database.rs#L150-270).\n\n[^2]: I'm only covering options from the Rust standard library for simplicity, but garbage-collected pointers from [`dumpster`](https://crates.io/crates/dumpster) or arena pointers from [`slotmap`](https://crates.io/crates/slotmap) can also be good ideas.\n\n[^3]: You might be thinking, \"why not `struct Ref<V, T> { val: Arc<V>, ptr: &'static T}`?\" and unfortunately a refutation is much more complex, and this example is more illustrative of why we need `Pin` later. Suffice to say, even though `Arc` on its own gives address stability in practice, Rust's type system doesn't enforce that it will [4](https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/#fn-other-idea).\n\n[^4]: I previously thought `struct PinRef<V, T> { val: Pin<Arc<V>>, ptr: &'static T }` was enough, but turns out that's entirely insufficient due to the presence of `Unpin`. [↩2](https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/#fnref-other-idea-2)\n\n[^5]: \"Arbitrary\" is key here. Means we can't do `fn project<'a, U>(self, f: impl FnOnce(&'a T) -> &'a U) -> PinRef<V, U>`, because `'a` is bound too early, which would allow us to choose a smaller lifetime, letting us project things w/ interior mutability, which is bad. Wish I could formalize this better but I've thought about it really really hard and haven't been able to come up with a counterexample to my main function so I hope no one else will either.\n",
  "authors": [
    "wolfgirl.dev by polywolf"
  ],
  "captured_at": "2026-10-01T06:33:51.242437607+00:00",
  "category": "news",
  "content_html": "<p>In the course of writing my <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://git.sr.ht/~polywolf/driver\">build driver</a>, I came across a bit of an unusual problem, for which I made a bit of an usual solution. I think the solution is interesting and would like to talk about it, but to understand anything we must first understand the problem at hand.</p>\n<h2>Consider The Case Of The Humble Concurrent Cache</h2>\n<p>Suppose we have some expensive function we'd like to put a cache in front of. Furthermore, suppose we'd like to access this cache from multiple threads. A simple example follows (<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2024&amp;gist=cf4e4af4e40d6895d16d12779f395fa0\">playground link</a>):</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-enum syntax-rust\"><span class=\"syntax-storage syntax-type syntax-enum syntax-rust\">enum</span> <span class=\"syntax-entity syntax-name syntax-enum syntax-rust\">JSON</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-constant syntax-other syntax-rust\">F64</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-storage syntax-type syntax-rust\">f64</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n    <span class=\"syntax-support syntax-type syntax-rust\">String</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-support syntax-type syntax-rust\">String</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n    <span class=\"syntax-support syntax-type syntax-rust\">Vec</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-meta syntax-generic syntax-rust\">Vec<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>JSON<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n    Object<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-meta syntax-generic syntax-rust\">HashMap<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>String, JSON<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-storage syntax-type syntax-struct syntax-rust\">struct</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-entity syntax-name syntax-struct syntax-rust\">Proxy</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">client</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> HTTPClient,\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">cache</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-meta syntax-generic syntax-rust\">RWLock<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">HashMap<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>String, JSON<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span>,\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">Proxy</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">get</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span>, <span class=\"syntax-variable syntax-parameter syntax-rust\">key</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-type syntax-rust\">str</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> JSON</span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> 1.\n</span>        <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-storage syntax-type syntax-rust\">let</span> cache <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span>.cache.<span class=\"syntax-support syntax-function syntax-rust\">read</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>.<span class=\"syntax-support syntax-function syntax-rust\">unwrap</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n            <span class=\"syntax-keyword syntax-control syntax-rust\">if</span> <span class=\"syntax-storage syntax-type syntax-rust\">let</span> <span class=\"syntax-support syntax-type syntax-rust\">Some</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>value</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> cache.<span class=\"syntax-support syntax-function syntax-rust\">get</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>key</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n                <span class=\"syntax-keyword syntax-control syntax-rust\">return</span> value.<span class=\"syntax-support syntax-function syntax-rust\">clone</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n            </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n\n        <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> 2.\n</span>        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> value <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span>.client.<span class=\"syntax-support syntax-function syntax-rust\">get</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>key</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-storage syntax-type syntax-rust\">let</span> <span class=\"syntax-storage syntax-modifier syntax-rust\">mut</span> cache <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span>.cache.<span class=\"syntax-support syntax-function syntax-rust\">write</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>.<span class=\"syntax-support syntax-function syntax-rust\">unwrap</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n            cache.<span class=\"syntax-support syntax-function syntax-rust\">insert</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>key.<span class=\"syntax-support syntax-function syntax-rust\">to_string</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> value.<span class=\"syntax-support syntax-function syntax-rust\">clone</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n        value\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>This code has an &quot;early exit&quot; path (1) where it returns a value from the cache if it's present, and a &quot;late exit&quot; path (2) where it calls the expensive function, then inserts the resulting value into the cache.</p>\n<p>Please ignore the many, many obvious problems with this implementation<sup class=\"footnote-ref\"><a href=\"#fn-1\" id=\"fnref-1\" data-footnote-ref>1</a></sup>. Instead, let's focus on the one problem that bothers me the most: there's fair bit of <code>.clone()</code> action going on here!</p>\n<p>Technically, it's just one <code>.clone()</code> per call: one on early exit to take value out of the cache, and one on late exit to put value into the cache. But if those values are big/tree-shaped/otherwise expensive to clone, this cost can dominate, minimizing the savings conferred by a cache. In my code, I found this to be the case, so we gotta do something about it.</p>\n<h2>Let's Get Rid Of The Clones?</h2>\n<p>Assume that, with the way we use this data, read-only access is more than enough. Shared references are read-only &amp; cheap to <code>Copy</code>, so using those instead of <code>.clone()</code>-ing the entire value seems good. If some later part of the code really needs to take ownership, we can just <code>.clone()</code> there, saving time in the average case. So, we'd like to change the signature for <code>get()</code> to be:</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">Proxy</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">get</span></span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span>, <span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;b</span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span> <span class=\"syntax-variable syntax-parameter syntax-rust\">self</span>, <span class=\"syntax-variable syntax-parameter syntax-rust\">url</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;b</span> <span class=\"syntax-storage syntax-type syntax-rust\">str</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span> JSON</span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">...</span> </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>But we can't do this!! Because our cache is behind a mutex, the only way we can get references to its contents is thru temporary handles. Those handles, while live, hold a lock on the cache, plus they only live for the body of the function, a not for all of <code>'a</code>. Even if we <em>could</em> return one of those handles, that'd be equivalent to holding the lock outside the function, which is very bad. Locks should only be held for VERY SHORT amounts of time unless ur into that sorta thing next month ;)</p>\n<h2>Let's Make The Clones Cheaper</h2>\n<p>So, no references. What other types can we use? What we want is something with all the following properties:</p>\n<ol>\n<li>It allows for read access to our data. That is, it allows us to get an <code>&amp;JSON</code> somehow.</li>\n<li>It has no lifetime parameters (<code>'a</code>, the only lifetime we have access to, is too long).</li>\n<li>It is cheap to <code>.clone()</code>, even if the underlying value is <em>not</em> cheap to <code>.clone()</code>.</li>\n</ol>\n<p>These requirements hint we should probably still be looking for some sort of pointer... Among standard library types, we have the following options<sup class=\"footnote-ref\"><a href=\"#fn-2\" id=\"fnref-2\" data-footnote-ref>2</a></sup>:</p>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://doc.rust-lang.org/std/primitive.pointer.html\">Raw pointers</a>: <code>*const JSON</code></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://doc.rust-lang.org/std/rc/index.html\">Reference-counted pointers</a>: <code>Rc&lt;JSON&gt;</code></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://doc.rust-lang.org/std/sync/struct.Arc.html\">Atomically-reference-counted pointers</a>: <code>Arc&lt;JSON&gt;</code></li>\n</ul>\n<p>Like any good Rustacean, we care a lot about safety &amp; concurrency, so <code>Arc</code> is the obvious pick here :3 Modifying the example to use it is straightforward (<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2024&amp;gist=f3e3821009472761d2297690f6262e17\">playground link</a>):</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-storage syntax-type syntax-struct syntax-rust\">struct</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-entity syntax-name syntax-struct syntax-rust\">Proxy</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">client</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> HTTPClient,\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">cache</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-meta syntax-generic syntax-rust\">RWLock<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">HashMap<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>String, <span class=\"syntax-meta syntax-generic syntax-rust\">Arc<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>JSON<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span>, <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> new!\n</span></span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">Proxy</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">get</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span>, <span class=\"syntax-variable syntax-parameter syntax-rust\">url</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-type syntax-rust\">str</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Arc<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>JSON<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> new!\n</span>        <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-storage syntax-type syntax-rust\">let</span> cache <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span>.cache.<span class=\"syntax-support syntax-function syntax-rust\">read</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>.<span class=\"syntax-support syntax-function syntax-rust\">unwrap</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n            <span class=\"syntax-keyword syntax-control syntax-rust\">if</span> <span class=\"syntax-storage syntax-type syntax-rust\">let</span> <span class=\"syntax-support syntax-type syntax-rust\">Some</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>value</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> cache.<span class=\"syntax-support syntax-function syntax-rust\">get</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>url</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n                <span class=\"syntax-keyword syntax-control syntax-rust\">return</span> value.<span class=\"syntax-support syntax-function syntax-rust\">clone</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n            </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n\n        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> value <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-meta syntax-path syntax-rust\">Arc<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>new<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-language syntax-rust\">self</span>.client.<span class=\"syntax-support syntax-function syntax-rust\">get</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>url</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> new!\n</span>        <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-storage syntax-type syntax-rust\">let</span> <span class=\"syntax-storage syntax-modifier syntax-rust\">mut</span> cache <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span>.cache.<span class=\"syntax-support syntax-function syntax-rust\">write</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>.<span class=\"syntax-support syntax-function syntax-rust\">unwrap</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n            cache.<span class=\"syntax-support syntax-function syntax-rust\">insert</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>url.<span class=\"syntax-support syntax-function syntax-rust\">to_string</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> value.<span class=\"syntax-support syntax-function syntax-rust\">clone</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n        value\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>Other than the three lines with <code>Arc</code> added to them, this implementation looks the exact same as before. But now our clones are cheaper, so we're happy, yay!!</p>\n<h2>So What's This About Downcasting?</h2>\n<p>I hope the above section convinced you having an <code>Arc</code> &quot;owned value that acts like a reference&quot; is both normal to want &amp; possible to achieve. Switching gears a bit, I'd like to discuss an interesting shortcoming with them: they don't fit into Rust's type system very well.</p>\n<p>Supposed we know for a fact that certain <code>JSON</code> values are strings, and we're only interested in the <code>JSON::String</code> variant of them. With an owned value or a shared reference, we can just pattern-match to &quot;downcast&quot; from a <code>JSON</code> to a <code>String</code>, or a <code>&amp;JSON</code> to a <code>&amp;String</code>.</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">JSON</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">to_str</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Option<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>String<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-keyword syntax-control syntax-rust\">match</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-storage syntax-type syntax-rust\">Self</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>String<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=&gt;</span> <span class=\"syntax-support syntax-type syntax-rust\">Some</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n            <span class=\"syntax-keyword syntax-operator syntax-rust\">_</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=&gt;</span> <span class=\"syntax-support syntax-type syntax-rust\">None</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n    \n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">as_str</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Option<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span>String<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-keyword syntax-control syntax-rust\">match</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-storage syntax-type syntax-rust\">Self</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>String<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=&gt;</span> <span class=\"syntax-support syntax-type syntax-rust\">Some</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n            <span class=\"syntax-keyword syntax-operator syntax-rust\">_</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=&gt;</span> <span class=\"syntax-support syntax-type syntax-rust\">None</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>But if we have an <code>Arc&lt;JSON&gt;</code>, we can't get another <code>Arc&lt;String&gt;</code> the same way!</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">JSON</span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">doesnt_exist</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-parameter syntax-rust\">value</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Arc<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>JSON<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Option<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">Arc<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>String<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-keyword syntax-control syntax-rust\">match</span> value.<span class=\"syntax-support syntax-function syntax-rust\">deref</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-storage syntax-type syntax-rust\">Self</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>String<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=&gt;</span> <span class=\"syntax-support syntax-type syntax-rust\">Some</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> compile error!\n</span>            <span class=\"syntax-keyword syntax-operator syntax-rust\">_</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=&gt;</span> <span class=\"syntax-support syntax-type syntax-rust\">None</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>This is because <code>value.deref()</code> creates a reference to <code>value</code>, whose lifetime will end as soon as the function is over, because we don't return it, only a pointer somewhere inside it. The machinery for <code>Arc</code> only works if it has access to the original pointer, not any derived pointers. So if we wanted to return an <code>Arc&lt;String&gt;</code>, we'd need to <code>.clone()</code> out of the <code>Arc&lt;JSON&gt;</code>, which is what we've been trying to avoid this whole time.</p>\n<p>However! We don't necessarily <em>need</em> a full <code>Arc&lt;String&gt;</code>! We'd be perfectly happy returning some other type, perhaps implementing <code>Deref&lt;Target = String&gt;</code>, so long as it still gives us those &quot;owned value that acts like a reference&quot; properties. If only we could extend the lifetime of <code>value</code>, perhaps by returning it alongside a reference to its contents, packaged together to implement <code>Deref</code> like we want...</p>\n<h2>Tying The Two Together With Evil Lesbian Shibari</h2>\n<p>Our goal is some return type that looks like:</p>\n<pre><code><span class=\"code-snippet\">               ,-----------------------+---------------------.\nval: owned --&gt; | contents: *const JSON | refcnt: AtomicUsize |\n               `-----------------------+---------------------&#39;\n                                     |\n          /--------------------------/\n          V\n        ,------------------+--------------+------------+------------.\n        | JSON::String tag | buf: *mut u8 | len: usize | cap: usize |\n        `------------------+--------------+------------+------------&#39;\n                             ^          |\n                             |          |\nptr: ref --------------------/          |\n                                        V\n                                      ,---+---+---+---.\n                                      |&#39;A&#39;|&#39;C&#39;|&#39;A&#39;|&#39;B&#39;|\n                                      `---+---+---+---&#39;\n</span></code></pre>\n<p>That is, we want some <code>val</code> showing us how to get to the main value we care about, and then some pointer <code>ptr</code> into the memory <code>val</code> references. Then, as long as we keep those tied together, we know <code>ptr</code> will still be valid, because <code>val</code> is still alive, because we own <code>val</code>.</p>\n<p>A first attempt at writing this reveals an immediate issue<sup class=\"footnote-ref\"><a href=\"#fn-3\" id=\"fnref-3\" data-footnote-ref>3</a></sup></p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-storage syntax-type syntax-struct syntax-rust\">struct</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-entity syntax-name syntax-struct syntax-rust\">Ref</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span></span><span class=\"syntax-meta syntax-struct syntax-rust\"> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">val</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> V,\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">ptr</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span>T, <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> What&#39;s the lifetime here?\n</span></span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>We can't express <code>ptr</code> as a reference, because there's no obvious lifetime to attach it to. Without a way to spell &quot;lifetime of the containing struct&quot; in Rust, it looks like we're going to need a raw pointer instead. But what if.....</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-storage syntax-type syntax-struct syntax-rust\">struct</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-entity syntax-name syntax-struct syntax-rust\">Ref</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;static</span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span></span><span class=\"syntax-meta syntax-struct syntax-rust\"> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">val</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> V,\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">ptr</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;static</span> T,\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>T, V<span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Deref<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>Target = T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">new</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-parameter syntax-rust\">val</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> V</span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-storage syntax-type syntax-rust\">Self</span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> ptr<span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span>T <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> val.<span class=\"syntax-support syntax-function syntax-rust\">deref</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-storage syntax-type syntax-rust\">Self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> This is the easiest way to do lifetime extension\n</span>            <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> SAFETY: hm?\n</span>            ptr<span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-storage syntax-modifier syntax-rust\">unsafe</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> <span class=\"syntax-meta syntax-path syntax-rust\">std<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span><span class=\"syntax-meta syntax-path syntax-rust\">mem<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>transmute<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>ptr</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n            val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>Whoa!! That's scary!!! Are they even allowed to hold hands like that...?</p>\n<p>It's true this is exceedingly unsafe if users could extract that <code>ptr: &amp;'static T</code> separately from the <code>val: V</code> it points into (<code>val</code>'s lifetime isn't <code>'static</code>!). But we could also just... not allow that, keeping them tied together always, providing access only via <code>Deref</code> implementation:</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> Deref <span class=\"syntax-keyword syntax-other syntax-rust\">for</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> <span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">Ref</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-storage syntax-type syntax-type syntax-rust\">type</span> <span class=\"syntax-entity syntax-name syntax-type syntax-rust\">Target</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> T<span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">deref</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span>T</span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-variable syntax-language syntax-rust\">self</span>.ptr\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>Because the <em>effective</em> lifetime for which <code>ptr</code> can be accessed is a subset of the <em>actual</em> lifetime for which <code>val</code> lives, I believe we've properly rules-lawyered Rust's reference aliasing rules into submission. Or have we...</p>\n<p>Oh noes... (<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2024&amp;gist=52455c2042bd9bc26f1bbbb8a239f9a4\">playground link</a>)</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-storage syntax-type syntax-struct syntax-rust\">struct</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-entity syntax-name syntax-struct syntax-rust\">SimpleWrapper</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span></span><span class=\"syntax-meta syntax-struct syntax-rust\"></span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>T</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n\n<span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> Deref <span class=\"syntax-keyword syntax-other syntax-rust\">for</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> <span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">SimpleWrapper</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-storage syntax-type syntax-type syntax-rust\">type</span> <span class=\"syntax-entity syntax-name syntax-type syntax-rust\">Target</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> T<span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">deref</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-storage syntax-type syntax-rust\"><span class=\"syntax-storage syntax-type syntax-rust\">Self</span><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span></span>Target</span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-variable syntax-language syntax-rust\">self</span>.<span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-rust\">0</span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">main</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-storage syntax-type syntax-rust\">let</span> r <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-meta syntax-path syntax-rust\">Ref<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>new<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>SimpleWrapper<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>x</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> Check what&#39;s stored vs what should be returned\n</span>    <span class=\"syntax-storage syntax-type syntax-rust\">let</span> ptr <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> r.ptr <span class=\"syntax-keyword syntax-operator syntax-rust\">as</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">*</span><span class=\"syntax-storage syntax-type syntax-rust\">const</span> <span class=\"syntax-storage syntax-type syntax-rust\">i32</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">as</span> <span class=\"syntax-storage syntax-type syntax-rust\">usize</span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-storage syntax-type syntax-rust\">let</span> actual_ptr <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> r.val.<span class=\"syntax-support syntax-function syntax-rust\">deref</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">as</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">*</span><span class=\"syntax-storage syntax-type syntax-rust\">const</span> <span class=\"syntax-storage syntax-type syntax-rust\">i32</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">as</span> <span class=\"syntax-storage syntax-type syntax-rust\">usize</span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-support syntax-macro syntax-rust\">println!</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-string syntax-quoted syntax-double syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-rust\">&quot;</span>ptr: <span class=\"syntax-constant syntax-other syntax-placeholder syntax-rust\">{ptr:x}</span> actual_ptr <span class=\"syntax-constant syntax-other syntax-placeholder syntax-rust\">{actual_ptr:x}</span><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-rust\">&quot;</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>Running this, I got <code>ptr: 7fff85189b5c actual_ptr 7fff85189b88</code>. These are in fact different pointers!!! Turns out I messed up my earlier rules-lawyering: The act of moving <code>val</code> into <code>Ref::new()</code>, taking the <code>.deref()</code> on that stack frame, and then moving it back out to the parent stack frame invalidates <code>ptr</code><sup class=\"footnote-ref\"><a href=\"#fn-3\" id=\"fnref-3-2\" data-footnote-ref>3</a></sup>. Lifetimes exist precisely to prevent bugs like this, and our extension trick was foiled. Lesson learned! Guess we'll do this the hard way...</p>\n<h2>Ensure Address Stability With This One Simple Trick!</h2>\n<p>To fix our datastructure, we'll want a guarantee that each <code>.deref()</code> will give us the same pointer, even if move the container around. For this, we MUST NOT be able to move the <code>val: V</code> out of its location once we wrap it. Fortunately, Rust has a type exactly for this usecase!</p>\n<p>ahem. anyways. Unfortunately, <code>Pin</code> is very hard to use, to the point I found a flaw in my initial implementation<sup class=\"footnote-ref\"><a href=\"#fn-4\" id=\"fnref-4\" data-footnote-ref>4</a></sup> while writing this :( Still, the docs are <em>really</em> good, and we can pretty easily follow their example to make <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://doc.rust-lang.org/std/pin/index.html#a-self-referential-struct\">a self-referential struct</a>:</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-storage syntax-type syntax-struct syntax-rust\">struct</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-entity syntax-name syntax-struct syntax-rust\">MustPin</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span></span><span class=\"syntax-meta syntax-struct syntax-rust\"> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">val</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> V,\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">_pin</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> PhantomPinned,\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n<span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-storage syntax-type syntax-struct syntax-rust\">struct</span> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-entity syntax-name syntax-struct syntax-rust\">PinRef</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span></span><span class=\"syntax-meta syntax-struct syntax-rust\"> </span><span class=\"syntax-meta syntax-struct syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">val</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Pin<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">Arc<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">MustPin<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span>,\n    <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> MUST point into [`val`].\n</span>    <span class=\"syntax-variable syntax-other syntax-member syntax-rust\">ptr</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> *const T,\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> <span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">MustPin</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">new</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-parameter syntax-rust\">val</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> V</span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Pin<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">Arc<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-storage syntax-type syntax-rust\">Self</span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-meta syntax-path syntax-rust\">Arc<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>pin<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-storage syntax-type syntax-rust\">Self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n            val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n            _pin<span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> PhantomPinned<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span>\n        </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> <span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">PinRef</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, V<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">new</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-parameter syntax-rust\">val</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Pin<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">Arc<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">MustPin<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-storage syntax-type syntax-rust\">Self</span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> ptr <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span>raw <span class=\"syntax-storage syntax-type syntax-rust\">const</span> val.val<span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-storage syntax-type syntax-rust\">Self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>Comparing this to the example in the docs:</p>\n<ol>\n<li>We use <code>*const T</code> instead of <code>NonNull&lt;T&gt;</code> because the latter is more like a <code>*mut T</code>, and we don't need all that power.</li>\n<li>We don't need <code>MaybeUninit</code> because we solve the &quot;knot-tying&quot; trick in a different way: we create the pinned data first, and then store a pointer into it out-of-line. This is still fine because of pin guarantees.</li>\n<li>We still need <code>PhantomPinned</code> because if we have <code>Pin&lt;Arc&lt;V&gt;&gt;</code> where <code>V: Unpin</code>, all bets are off, literally every pin guarantee goes out the window.</li>\n</ol>\n<p><code>Deref</code> is simple like before, just with a pointer instead of a reference:</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> Deref <span class=\"syntax-keyword syntax-other syntax-rust\">for</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> <span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">PinRef</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-storage syntax-type syntax-type syntax-rust\">type</span> <span class=\"syntax-entity syntax-name syntax-type syntax-rust\">Target</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> T<span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">deref</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-storage syntax-type syntax-rust\"><span class=\"syntax-storage syntax-type syntax-rust\">Self</span><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span></span>Target</span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> SAFETY: by construction and pin guarantees, the pointer is still valid.\n</span>        <span class=\"syntax-storage syntax-modifier syntax-rust\">unsafe</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-keyword syntax-operator syntax-rust\">*</span><span class=\"syntax-variable syntax-language syntax-rust\">self</span>.ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>Now, finally, we're all set up for the big reveal: how are we going to downcast these things?</p>\n<h2>She Downcast On My <code>Pin</code> 'Til I <code>Arc</code></h2>\n<p>Our rule for <code>ptr</code> is that it MUST point somewhere valid inside <code>val</code>. That's all we can assume, and that's what we have to uphold while doing our downcasts. Fortunately, we can use Rust's type-checking for &quot;standard&quot; downcasts to our advantage!</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> <span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">PinRef</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">project</span></span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>U<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-parameter syntax-rust\">self</span>, <span class=\"syntax-variable syntax-parameter syntax-rust\">f</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> impl <span class=\"syntax-meta syntax-generic syntax-rust\">for<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> FnOnce<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\">&amp;&#39;<span class=\"syntax-variable syntax-parameter syntax-rust\">a</span> <span class=\"syntax-variable syntax-parameter syntax-rust\">T</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> -&gt; <span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span> U</span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">PinRef<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, U<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> <span class=\"syntax-storage syntax-type syntax-rust\">Self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> SAFETY: by validity of `ptr` and `f`\n</span>        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> ptr <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-storage syntax-modifier syntax-rust\">unsafe</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> <span class=\"syntax-support syntax-function syntax-rust\">f</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-keyword syntax-operator syntax-rust\">*</span>ptr</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">as</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">*</span><span class=\"syntax-storage syntax-type syntax-rust\">const</span> U </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        PinRef <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>Stating this signature more in more math-y terms, for those unfamiliar with Rust's syntax:</p>\n<p><span class=\"math\">PinRef : (Type, Type) → Type ∀ V,T,U : Type. project : PinRef(V,T) → (∀(a: Lifetime). ′a T → ′aU) → PinRef(V,U)</span></p>\n<p>How we should interpret this is: If we can go from a <code>&amp;T</code> to a <code>&amp;U</code> for an <em>arbitrary</em> lifetime <code>'a</code>, that means <code>*U</code> is a fixed offset from <code>*T</code><sup class=\"footnote-ref\"><a href=\"#fn-5\" id=\"fnref-5\" data-footnote-ref>5</a></sup>. So, because <code>ptr</code> has a fixed address (it was derived from the pinned <code>val</code>), so will the output of <code>f</code>. Other pin guarantees like &quot;<code>val</code> will always remain valid at that address while it's pinned&quot; help too.</p>\n<p>If I were a real type theorist, I would have pulled out some sort of commutative diagram and drawn a bunch of arrows, or perhaps even written down some inference rules, but alas, I cannot even abstract over monads... Anyways this argument works for what we originally wanted too:</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-storage syntax-type syntax-impl syntax-rust\">impl</span></span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-impl syntax-rust\"> <span class=\"syntax-entity syntax-name syntax-impl syntax-rust\">PinRef</span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, T<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> </span><span class=\"syntax-meta syntax-impl syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">filter_project</span></span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>U<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span>\n        <span class=\"syntax-variable syntax-parameter syntax-rust\">self</span>,\n        <span class=\"syntax-variable syntax-parameter syntax-rust\">f</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> impl <span class=\"syntax-meta syntax-generic syntax-rust\">for<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> FnOnce<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\">&amp;&#39;<span class=\"syntax-variable syntax-parameter syntax-rust\">a</span> <span class=\"syntax-variable syntax-parameter syntax-rust\">T</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> -&gt; <span class=\"syntax-meta syntax-generic syntax-rust\">Option<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span> U<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span>,\n    </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Option<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">PinRef<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, U<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> <span class=\"syntax-storage syntax-type syntax-rust\">Self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> SAFETY: by validity of `ptr`, `f`\n</span>        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> ptr <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-storage syntax-modifier syntax-rust\">unsafe</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> <span class=\"syntax-support syntax-function syntax-rust\">f</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-keyword syntax-operator syntax-rust\">*</span>ptr</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-keyword syntax-operator syntax-rust\">?</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">as</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">*</span><span class=\"syntax-storage syntax-type syntax-rust\">const</span> U </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-support syntax-type syntax-rust\">Some</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>PinRef <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n    \n    <span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">try_project</span></span><span class=\"syntax-meta syntax-generic syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>U, E<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span>\n        <span class=\"syntax-variable syntax-parameter syntax-rust\">self</span>,\n        <span class=\"syntax-variable syntax-parameter syntax-rust\">f</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> impl <span class=\"syntax-meta syntax-generic syntax-rust\">for<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span> FnOnce<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\">&amp;&#39;<span class=\"syntax-variable syntax-parameter syntax-rust\">a</span> <span class=\"syntax-variable syntax-parameter syntax-rust\">T</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span> -&gt; <span class=\"syntax-meta syntax-generic syntax-rust\">Result<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-storage syntax-modifier syntax-lifetime syntax-rust\">&#39;a</span> U, E<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span>,\n    </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> <span class=\"syntax-meta syntax-function syntax-return-type syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">-&gt;</span> <span class=\"syntax-meta syntax-generic syntax-rust\">Result<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span><span class=\"syntax-meta syntax-generic syntax-rust\">PinRef<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>V, U<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span>, E<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> <span class=\"syntax-storage syntax-type syntax-rust\">Self</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span> <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-variable syntax-language syntax-rust\">self</span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-comment syntax-line syntax-double-slash syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-rust\">//</span> SAFETY: by validity of `ptr`, `f`\n</span>        <span class=\"syntax-storage syntax-type syntax-rust\">let</span> ptr <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-storage syntax-modifier syntax-rust\">unsafe</span> <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> <span class=\"syntax-support syntax-function syntax-rust\">f</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-keyword syntax-operator syntax-rust\">&amp;</span><span class=\"syntax-keyword syntax-operator syntax-rust\">*</span>ptr</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-keyword syntax-operator syntax-rust\">?</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">as</span> <span class=\"syntax-keyword syntax-operator syntax-rust\">*</span><span class=\"syntax-storage syntax-type syntax-rust\">const</span> U </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n        <span class=\"syntax-support syntax-type syntax-rust\">Ok</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>PinRef <span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span> val<span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> ptr </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>\n    </span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>You see that??? We did the thing!! To celebrate, here's a full example using the original JSON projections (<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2024&amp;gist=9ba8b6f27dc48afb065a2923023fb1da\">playground link</a>):</p>\n<pre><code class=\"language-rust\"><span class=\"code-snippet\" data-language=\"Rust\"><span class=\"syntax-source syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">print</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span><span class=\"syntax-variable syntax-parameter syntax-rust\">s</span><span class=\"syntax-punctuation syntax-separator syntax-rust\">:</span> impl <span class=\"syntax-meta syntax-generic syntax-rust\">Deref<span class=\"syntax-punctuation syntax-definition syntax-generic syntax-begin syntax-rust\">&lt;</span>Target = <span class=\"syntax-storage syntax-type syntax-rust\">str</span><span class=\"syntax-punctuation syntax-definition syntax-generic syntax-end syntax-rust\">&gt;</span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-support syntax-macro syntax-rust\">println!</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-string syntax-quoted syntax-double syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-rust\">&quot;</span><span class=\"syntax-constant syntax-other syntax-placeholder syntax-rust\">{}</span><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-rust\">&quot;</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-separator syntax-rust\">,</span> s.<span class=\"syntax-support syntax-function syntax-rust\">deref</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n\n<span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-storage syntax-type syntax-function syntax-rust\">fn</span> </span><span class=\"syntax-entity syntax-name syntax-function syntax-rust\">main</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-function syntax-parameters syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-rust\">)</span></span></span></span><span class=\"syntax-meta syntax-function syntax-rust\"> </span><span class=\"syntax-meta syntax-function syntax-rust\"><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-rust\">{</span>\n    <span class=\"syntax-storage syntax-type syntax-rust\">let</span> v <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-meta syntax-path syntax-rust\">std<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span><span class=\"syntax-meta syntax-path syntax-rust\">sync<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span><span class=\"syntax-meta syntax-path syntax-rust\">Arc<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>pin<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-constant syntax-other syntax-rust\">JSON</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>String<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-support syntax-type syntax-rust\">String</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>from<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-string syntax-quoted syntax-double syntax-rust\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-rust\">&quot;</span>hello, world!<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-rust\">&quot;</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-storage syntax-type syntax-rust\">let</span> v <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> <span class=\"syntax-meta syntax-path syntax-rust\">PinRef<span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>new<span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>v</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-storage syntax-type syntax-rust\">let</span> s <span class=\"syntax-keyword syntax-operator syntax-rust\">=</span> v.<span class=\"syntax-support syntax-function syntax-rust\">filter_project</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span><span class=\"syntax-constant syntax-other syntax-rust\">JSON</span><span class=\"syntax-meta syntax-path syntax-rust\"><span class=\"syntax-punctuation syntax-accessor syntax-rust\">::</span></span>as_str</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span>.<span class=\"syntax-support syntax-function syntax-rust\">unwrap</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-support syntax-function syntax-rust\">print</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s.<span class=\"syntax-support syntax-function syntax-rust\">clone</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span></span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n    <span class=\"syntax-support syntax-function syntax-rust\">print</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-rust\">(</span>s</span><span class=\"syntax-meta syntax-group syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-rust\">)</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rust\">;</span>\n</span><span class=\"syntax-meta syntax-block syntax-rust\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-rust\">}</span></span></span>\n</span></span></code></pre>\n<p>All that remains in our original example is to replace all the plain <code>Arc&lt;JSON&gt;</code> with <code>Pin&lt;Arc&lt;MustPin&lt;JSON&gt;&gt;&gt;</code> (wow what a mouthful), make a <code>Clone</code> implementation, account for <code>?Sized</code> types, etc. etc. This post is long enough as it is so I've omitted that, but if you want, you can find the full details in my <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://git.sr.ht/~polywolf/driver/tree/cb9ee31e272f24311981a41f979d82f31f39f61f/item/packages/pin-downcast/src/pin_ref.rs\">repository</a>. I might release this as a standalone crate if I feel like it, but this might still be riddled with UB I missed so maybe not (:</p>\n<p>Anyways!! Hope you learned something, until next time~</p>\n<section class=\"footnotes\" data-footnotes>\n<ol>\n<li id=\"fn-1\">\n<p>In increasing order of badness: too much string typing, no error handling, concurrent requests can race and end up doing extra work. Probably others I'm missing too. The solution to that last one is simultaneously very interesting &amp; very boring, <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://git.sr.ht/~polywolf/driver/tree/3e0e9250a6657f9e5ed977ecdd08f3550e06f68b/item/packages/driver-db/src/database.rs#L150-270\">read the code yourself if you want</a>. <a href=\"#fnref-1\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"1\" aria-label=\"Back to reference 1\">↩</a></p>\n</li>\n<li id=\"fn-2\">\n<p>I'm only covering options from the Rust standard library for simplicity, but garbage-collected pointers from <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://crates.io/crates/dumpster\"><code>dumpster</code></a> or arena pointers from <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://crates.io/crates/slotmap\"><code>slotmap</code></a> can also be good ideas. <a href=\"#fnref-2\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"2\" aria-label=\"Back to reference 2\">↩</a></p>\n</li>\n<li id=\"fn-3\">\n<p>You might be thinking, &quot;why not <code>struct Ref&lt;V, T&gt; { val: Arc&lt;V&gt;, ptr: &amp;'static T}</code>?&quot; and unfortunately a refutation is much more complex, and this example is more illustrative of why we need <code>Pin</code> later. Suffice to say, even though <code>Arc</code> on its own gives address stability in practice, Rust's type system doesn't enforce that it will <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/#fn-other-idea\">4</a>. <a href=\"#fnref-3\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"3\" aria-label=\"Back to reference 3\">↩</a> <a href=\"#fnref-3-2\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"3-2\" aria-label=\"Back to reference 3-2\">↩<sup class=\"footnote-ref\">2</sup></a></p>\n</li>\n<li id=\"fn-4\">\n<p>I previously thought <code>struct PinRef&lt;V, T&gt; { val: Pin&lt;Arc&lt;V&gt;&gt;, ptr: &amp;'static T }</code> was enough, but turns out that's entirely insufficient due to the presence of <code>Unpin</code>. <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/#fnref-other-idea-2\">↩2</a> <a href=\"#fnref-4\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"4\" aria-label=\"Back to reference 4\">↩</a></p>\n</li>\n<li id=\"fn-5\">\n<p>&quot;Arbitrary&quot; is key here. Means we can't do <code>fn project&lt;'a, U&gt;(self, f: impl FnOnce(&amp;'a T) -&gt; &amp;'a U) -&gt; PinRef&lt;V, U&gt;</code>, because <code>'a</code> is bound too early, which would allow us to choose a smaller lifetime, letting us project things w/ interior mutability, which is bad. Wish I could formalize this better but I've thought about it really really hard and haven't been able to come up with a counterexample to my main function so I hope no one else will either. <a href=\"#fnref-5\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"5\" aria-label=\"Back to reference 5\">↩</a></p>\n</li>\n</ol>\n</section>\n",
  "content_markdown": "In the course of writing my [build driver](https://git.sr.ht/~polywolf/driver), I came across a bit of an unusual problem, for which I made a bit of an usual solution. I think the solution is interesting and would like to talk about it, but to understand anything we must first understand the problem at hand.\n\n## Consider The Case Of The Humble Concurrent Cache\n\nSuppose we have some expensive function we'd like to put a cache in front of. Furthermore, suppose we'd like to access this cache from multiple threads. A simple example follows ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=cf4e4af4e40d6895d16d12779f395fa0)):\n\n```rust\nenum JSON {\n    F64(f64),\n    String(String),\n    Vec(Vec<JSON>),\n    Object(HashMap<String, JSON>),\n}\n\nstruct Proxy {\n    client: HTTPClient,\n    cache: RWLock<HashMap<String, JSON>>,\n}\n\nimpl Proxy {\n    fn get(&self, key: &str) -> JSON {\n        // 1.\n        {\n            let cache = self.cache.read().unwrap();\n            if let Some(value) = cache.get(key) {\n                return value.clone();\n            }\n        }\n\n        // 2.\n        let value = self.client.get(key);\n        {\n            let mut cache = self.cache.write().unwrap();\n            cache.insert(key.to_string(), value.clone());\n        }\n        value\n    }\n}\n```\n\nThis code has an \"early exit\" path (1) where it returns a value from the cache if it's present, and a \"late exit\" path (2) where it calls the expensive function, then inserts the resulting value into the cache.\n\nPlease ignore the many, many obvious problems with this implementation[^1]. Instead, let's focus on the one problem that bothers me the most: there's fair bit of `.clone()` action going on here!\n\nTechnically, it's just one `.clone()` per call: one on early exit to take value out of the cache, and one on late exit to put value into the cache. But if those values are big/tree-shaped/otherwise expensive to clone, this cost can dominate, minimizing the savings conferred by a cache. In my code, I found this to be the case, so we gotta do something about it.\n\n## Let's Get Rid Of The Clones?\n\nAssume that, with the way we use this data, read-only access is more than enough. Shared references are read-only & cheap to `Copy`, so using those instead of `.clone()`-ing the entire value seems good. If some later part of the code really needs to take ownership, we can just `.clone()` there, saving time in the average case. So, we'd like to change the signature for `get()` to be:\n\n```rust\nimpl Proxy {\n    fn get<'a, 'b>(&'a self, url: &'b str) -> &'a JSON { ... }\n}\n```\n\nBut we can't do this!! Because our cache is behind a mutex, the only way we can get references to its contents is thru temporary handles. Those handles, while live, hold a lock on the cache, plus they only live for the body of the function, a not for all of `'a`. Even if we *could* return one of those handles, that'd be equivalent to holding the lock outside the function, which is very bad. Locks should only be held for VERY SHORT amounts of time unless ur into that sorta thing next month ;)\n\n## Let's Make The Clones Cheaper\n\nSo, no references. What other types can we use? What we want is something with all the following properties:\n\n1. It allows for read access to our data. That is, it allows us to get an `&JSON` somehow.\n2. It has no lifetime parameters (`'a`, the only lifetime we have access to, is too long).\n3. It is cheap to `.clone()`, even if the underlying value is *not* cheap to `.clone()`.\n\nThese requirements hint we should probably still be looking for some sort of pointer... Among standard library types, we have the following options[^2]:\n\n- [Raw pointers](https://doc.rust-lang.org/std/primitive.pointer.html): `*const JSON`\n- [Reference-counted pointers](https://doc.rust-lang.org/std/rc/index.html): `Rc<JSON>`\n- [Atomically-reference-counted pointers](https://doc.rust-lang.org/std/sync/struct.Arc.html): `Arc<JSON>`\n\nLike any good Rustacean, we care a lot about safety & concurrency, so `Arc` is the obvious pick here :3 Modifying the example to use it is straightforward ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f3e3821009472761d2297690f6262e17)):\n\n```rust\nstruct Proxy {\n    client: HTTPClient,\n    cache: RWLock<HashMap<String, Arc<JSON>>>, // new!\n}\n\nimpl Proxy {\n    fn get(&self, url: &str) -> Arc<JSON> { // new!\n        {\n            let cache = self.cache.read().unwrap();\n            if let Some(value) = cache.get(url) {\n                return value.clone();\n            }\n        }\n\n        let value = Arc::new(self.client.get(url)); // new!\n        {\n            let mut cache = self.cache.write().unwrap();\n            cache.insert(url.to_string(), value.clone());\n        }\n        value\n    }\n}\n```\n\nOther than the three lines with `Arc` added to them, this implementation looks the exact same as before. But now our clones are cheaper, so we're happy, yay!!\n\n## So What's This About Downcasting?\n\nI hope the above section convinced you having an `Arc` \"owned value that acts like a reference\" is both normal to want & possible to achieve. Switching gears a bit, I'd like to discuss an interesting shortcoming with them: they don't fit into Rust's type system very well.\n\nSupposed we know for a fact that certain `JSON` values are strings, and we're only interested in the `JSON::String` variant of them. With an owned value or a shared reference, we can just pattern-match to \"downcast\" from a `JSON` to a `String`, or a `&JSON` to a `&String`.\n\n```rust\nimpl JSON {\n    fn to_str(self) -> Option<String> {\n        match self {\n            Self::String(s) => Some(s),\n            _ => None,\n        }\n    }\n    \n    fn as_str(&self) -> Option<&String> {\n        match self {\n            Self::String(s) => Some(s),\n            _ => None,\n        }\n    }\n}\n```\n\nBut if we have an `Arc<JSON>`, we can't get another `Arc<String>` the same way!\n\n```rust\nimpl JSON {\n    fn doesnt_exist(value: Arc<JSON>) -> Option<Arc<String>> {\n        match value.deref() {\n            Self::String(s) => Some(s), // compile error!\n            _ => None,\n        }\n    }\n}\n```\n\nThis is because `value.deref()` creates a reference to `value`, whose lifetime will end as soon as the function is over, because we don't return it, only a pointer somewhere inside it. The machinery for `Arc` only works if it has access to the original pointer, not any derived pointers. So if we wanted to return an `Arc<String>`, we'd need to `.clone()` out of the `Arc<JSON>`, which is what we've been trying to avoid this whole time.\n\nHowever! We don't necessarily *need* a full `Arc<String>`! We'd be perfectly happy returning some other type, perhaps implementing `Deref<Target = String>`, so long as it still gives us those \"owned value that acts like a reference\" properties. If only we could extend the lifetime of `value`, perhaps by returning it alongside a reference to its contents, packaged together to implement `Deref` like we want...\n\n## Tying The Two Together With Evil Lesbian Shibari\n\nOur goal is some return type that looks like:\n\n```\n               ,-----------------------+---------------------.\nval: owned --> | contents: *const JSON | refcnt: AtomicUsize |\n               `-----------------------+---------------------'\n                                     |\n          /--------------------------/\n          V\n        ,------------------+--------------+------------+------------.\n        | JSON::String tag | buf: *mut u8 | len: usize | cap: usize |\n        `------------------+--------------+------------+------------'\n                             ^          |\n                             |          |\nptr: ref --------------------/          |\n                                        V\n                                      ,---+---+---+---.\n                                      |'A'|'C'|'A'|'B'|\n                                      `---+---+---+---'\n```\n\nThat is, we want some `val` showing us how to get to the main value we care about, and then some pointer `ptr` into the memory `val` references. Then, as long as we keep those tied together, we know `ptr` will still be valid, because `val` is still alive, because we own `val`.\n\nA first attempt at writing this reveals an immediate issue[^3]\n\n```rust\nstruct Ref<V, T> {\n    val: V,\n    ptr: &T, // What's the lifetime here?\n}\n```\n\nWe can't express `ptr` as a reference, because there's no obvious lifetime to attach it to. Without a way to spell \"lifetime of the containing struct\" in Rust, it looks like we're going to need a raw pointer instead. But what if.....\n\n```rust\nstruct Ref<V, T: 'static> {\n    val: V,\n    ptr: &'static T,\n}\n\nimpl<T, V: Deref<Target = T>> {\n    fn new(val: V) -> Self {\n        let ptr: &T = val.deref();\n        Self {\n            // This is the easiest way to do lifetime extension\n            // SAFETY: hm?\n            ptr: unsafe { std::mem::transmute(ptr) },\n            val,\n        }\n    }\n}\n```\n\nWhoa!! That's scary!!! Are they even allowed to hold hands like that...?\n\nIt's true this is exceedingly unsafe if users could extract that `ptr: &'static T` separately from the `val: V` it points into (`val`'s lifetime isn't `'static`!). But we could also just... not allow that, keeping them tied together always, providing access only via `Deref` implementation:\n\n```rust\nimpl<V, T> Deref for Ref<V, T> {\n    type Target = T;\n    fn deref(&self) -> &T {\n        self.ptr\n    }\n}\n```\n\nBecause the *effective* lifetime for which `ptr` can be accessed is a subset of the *actual* lifetime for which `val` lives, I believe we've properly rules-lawyered Rust's reference aliasing rules into submission. Or have we...\n\nOh noes... ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=52455c2042bd9bc26f1bbbb8a239f9a4))\n\n```rust\nstruct SimpleWrapper<T>(T);\n\nimpl<T> Deref for SimpleWrapper<T> {\n    type Target = T;\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nfn main() {\n    let r = Ref::new(SimpleWrapper(x));\n    // Check what's stored vs what should be returned\n    let ptr = r.ptr as *const i32 as usize;\n    let actual_ptr = r.val.deref() as *const i32 as usize;\n    println!(\"ptr: {ptr:x} actual_ptr {actual_ptr:x}\");\n}\n```\n\nRunning this, I got `ptr: 7fff85189b5c actual_ptr 7fff85189b88`. These are in fact different pointers!!! Turns out I messed up my earlier rules-lawyering: The act of moving `val` into `Ref::new()`, taking the `.deref()` on that stack frame, and then moving it back out to the parent stack frame invalidates `ptr`[^3]. Lifetimes exist precisely to prevent bugs like this, and our extension trick was foiled. Lesson learned! Guess we'll do this the hard way...\n\n## Ensure Address Stability With This One Simple Trick!\n\nTo fix our datastructure, we'll want a guarantee that each `.deref()` will give us the same pointer, even if move the container around. For this, we MUST NOT be able to move the `val: V` out of its location once we wrap it. Fortunately, Rust has a type exactly for this usecase!\n\nahem. anyways. Unfortunately, `Pin` is very hard to use, to the point I found a flaw in my initial implementation[^4] while writing this :( Still, the docs are *really* good, and we can pretty easily follow their example to make [a self-referential struct](https://doc.rust-lang.org/std/pin/index.html#a-self-referential-struct):\n\n```rust\nstruct MustPin<V> {\n    val: V,\n    _pin: PhantomPinned,\n}\nstruct PinRef<V, T> {\n    val: Pin<Arc<MustPin<V>>>,\n    // MUST point into [`val`].\n    ptr: *const T,\n}\n\nimpl<V> MustPin<V> {\n    fn new(val: V) -> Pin<Arc<Self>> {\n        Arc::pin(Self {\n            val,\n            _pin: PhantomPinned,\n        })\n    }\n}\n\nimpl<V> PinRef<V, V> {\n    fn new(val: Pin<Arc<MustPin<V>>>) -> Self {\n        let ptr = &raw const val.val;\n        Self { val, ptr }\n    }\n}\n```\n\nComparing this to the example in the docs:\n\n1. We use `*const T` instead of `NonNull<T>` because the latter is more like a `*mut T`, and we don't need all that power.\n2. We don't need `MaybeUninit` because we solve the \"knot-tying\" trick in a different way: we create the pinned data first, and then store a pointer into it out-of-line. This is still fine because of pin guarantees.\n3. We still need `PhantomPinned` because if we have `Pin<Arc<V>>` where `V: Unpin`, all bets are off, literally every pin guarantee goes out the window.\n\n`Deref` is simple like before, just with a pointer instead of a reference:\n\n```rust\nimpl<V, T> Deref for PinRef<V, T> {\n    type Target = T;\n    fn deref(&self) -> &Self::Target {\n        // SAFETY: by construction and pin guarantees, the pointer is still valid.\n        unsafe { &*self.ptr }\n    }\n}\n```\n\nNow, finally, we're all set up for the big reveal: how are we going to downcast these things?\n\n## She Downcast On My `Pin` 'Til I `Arc`\n\nOur rule for `ptr` is that it MUST point somewhere valid inside `val`. That's all we can assume, and that's what we have to uphold while doing our downcasts. Fortunately, we can use Rust's type-checking for \"standard\" downcasts to our advantage!\n\n```rust\nimpl<V, T> PinRef<V, T> {\n    fn project<U>(self, f: impl for<'a> FnOnce(&'a T) -> &'a U) -> PinRef<V, U> {\n        let Self { val, ptr } = self;\n        // SAFETY: by validity of `ptr` and `f`\n        let ptr = unsafe { f(&*ptr) as *const U };\n        PinRef { val, ptr }\n    }\n}\n```\n\nStating this signature more in more math-y terms, for those unfamiliar with Rust's syntax:\n\n$\\begin{gathered} \\text{PinRef} : (\\text{Type}, \\text{Type}) \\rightarrow \\text{Type}\\\\ \\forall\\ V,T,U : \\text{Type}.\\\\ \\text{project} : \\text{PinRef}(V,T) \\rightarrow (\\forall(a: \\text{Lifetime}).\\ \\&'a T \\rightarrow \\&'aU) \\rightarrow \\text{PinRef}(V,U) \\end{gathered}$\n\nHow we should interpret this is: If we can go from a `&T` to a `&U` for an *arbitrary* lifetime `'a`, that means `*U` is a fixed offset from `*T`[^5]. So, because `ptr` has a fixed address (it was derived from the pinned `val`), so will the output of `f`. Other pin guarantees like \"`val` will always remain valid at that address while it's pinned\" help too.\n\nIf I were a real type theorist, I would have pulled out some sort of commutative diagram and drawn a bunch of arrows, or perhaps even written down some inference rules, but alas, I cannot even abstract over monads... Anyways this argument works for what we originally wanted too:\n\n```rust\nimpl<V, T> PinRef<V, T> {\n    fn filter_project<U>(\n        self,\n        f: impl for<'a> FnOnce(&'a T) -> Option<&'a U>,\n    ) -> Option<PinRef<V, U>> {\n        let Self { val, ptr } = self;\n        // SAFETY: by validity of `ptr`, `f`\n        let ptr = unsafe { f(&*ptr)? as *const U };\n        Some(PinRef { val, ptr })\n    }\n    \n    fn try_project<U, E>(\n        self,\n        f: impl for<'a> FnOnce(&'a T) -> Result<&'a U, E>,\n    ) -> Result<PinRef<V, U>, E> {\n        let Self { val, ptr } = self;\n        // SAFETY: by validity of `ptr`, `f`\n        let ptr = unsafe { f(&*ptr)? as *const U };\n        Ok(PinRef { val, ptr })\n    }\n}\n```\n\nYou see that??? We did the thing!! To celebrate, here's a full example using the original JSON projections ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=9ba8b6f27dc48afb065a2923023fb1da)):\n\n```rust\nfn print(s: impl Deref<Target = str>) {\n    println!(\"{}\", s.deref())\n}\n\nfn main() {\n    let v = std::sync::Arc::pin(JSON::String(String::from(\"hello, world!\")));\n    let v = PinRef::new(v);\n    let s = v.filter_project(JSON::as_str).unwrap();\n    print(s.clone());\n    print(s);\n}\n```\n\nAll that remains in our original example is to replace all the plain `Arc<JSON>` with `Pin<Arc<MustPin<JSON>>>` (wow what a mouthful), make a `Clone` implementation, account for `?Sized` types, etc. etc. This post is long enough as it is so I've omitted that, but if you want, you can find the full details in my [repository](https://git.sr.ht/~polywolf/driver/tree/cb9ee31e272f24311981a41f979d82f31f39f61f/item/packages/pin-downcast/src/pin_ref.rs). I might release this as a standalone crate if I feel like it, but this might still be riddled with UB I missed so maybe not (:\n\nAnyways!! Hope you learned something, until next time~\n\n[^1]: In increasing order of badness: too much string typing, no error handling, concurrent requests can race and end up doing extra work. Probably others I'm missing too. The solution to that last one is simultaneously very interesting & very boring, [read the code yourself if you want](https://git.sr.ht/~polywolf/driver/tree/3e0e9250a6657f9e5ed977ecdd08f3550e06f68b/item/packages/driver-db/src/database.rs#L150-270).\n\n[^2]: I'm only covering options from the Rust standard library for simplicity, but garbage-collected pointers from [`dumpster`](https://crates.io/crates/dumpster) or arena pointers from [`slotmap`](https://crates.io/crates/slotmap) can also be good ideas.\n\n[^3]: You might be thinking, \"why not `struct Ref<V, T> { val: Arc<V>, ptr: &'static T}`?\" and unfortunately a refutation is much more complex, and this example is more illustrative of why we need `Pin` later. Suffice to say, even though `Arc` on its own gives address stability in practice, Rust's type system doesn't enforce that it will [4](https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/#fn-other-idea).\n\n[^4]: I previously thought `struct PinRef<V, T> { val: Pin<Arc<V>>, ptr: &'static T }` was enough, but turns out that's entirely insufficient due to the presence of `Unpin`. [↩2](https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/#fnref-other-idea-2)\n\n[^5]: \"Arbitrary\" is key here. Means we can't do `fn project<'a, U>(self, f: impl FnOnce(&'a T) -> &'a U) -> PinRef<V, U>`, because `'a` is bound too early, which would allow us to choose a smaller lifetime, letting us project things w/ interior mutability, which is bad. Wish I could formalize this better but I've thought about it really really hard and haven't been able to come up with a counterexample to my main function so I hope no one else will either.\n",
  "dateCreated": "2026-10-01T06:33:51.242437607+00:00",
  "date_created": "2026-09-29T15:35:14+00:00",
  "date_modified": "2026-09-29T15:35:14+00:00",
  "date_published": "2026-09-29T15:35:14+00:00",
  "description": "Comments",
  "external_url": "https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/",
  "git": {
    "commit": "ebb0941c5c06a2ab2377342d607535262a3e969e",
    "path": "items/lobste-rs/2026/09/2026-09-29-pining-for-arc-downcasting-in-rust.md",
    "permalink": "https://github.com/aymericbeaumet/aggr-instance/blob/ebb0941c5c06a2ab2377342d607535262a3e969e/items/lobste-rs/2026/09/2026-09-29-pining-for-arc-downcasting-in-rust.md"
  },
  "id": "urn:aggr:item:7364ac0546a231036aebeb40297fea333ca893e3",
  "isBasedOn": {
    "@id": "https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/"
  },
  "mainEntity": {
    "@id": "https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/",
    "@type": "CreativeWork",
    "archivedAt": {
      "@id": "https://aggr.aymericbeaumet.com/items/lobste-rs/2026-09-29-pining-for-arc-downcasting-in-rust/#webpage"
    },
    "author": [
      {
        "@type": "Person",
        "name": "wolfgirl.dev by polywolf"
      }
    ],
    "dateModified": "2026-09-29T15:35:14+00:00",
    "datePublished": "2026-09-29T15:35:14+00:00",
    "headline": "Pining for Arc Downcasting in Rust",
    "timeRequired": "PT12M",
    "url": "https://wolfgirl.dev/blog/2026-09-29-pining-for-arc-downcasting-in-rust/",
    "wordCount": 2499
  },
  "name": "Archived snapshot: Pining for Arc Downcasting in Rust",
  "preview": null,
  "reading_minutes": 12,
  "replicated_at": null,
  "source": "lobste-rs",
  "source_name": "Lobsters: Top Stories of the Past Week",
  "summary": "Comments",
  "tags": [
    "rust"
  ],
  "temporalCoverage": "2026-10-01T06:33:51.242437607+00:00",
  "title": "Pining for Arc Downcasting in Rust",
  "url": "https://aggr.aymericbeaumet.com/items/lobste-rs/2026-09-29-pining-for-arc-downcasting-in-rust/",
  "word_count": 2499
}