136 lines
12 KiB
HTML
136 lines
12 KiB
HTML
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Overview"><title>self_cell - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-42caa33d.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="self_cell" data-themes="" data-resource-suffix="" data-rustdoc-version="1.84.0 (9fc6b4312 2025-01-07)" data-channel="1.84.0" data-search-js="search-92e6798f.js" data-settings-js="settings-0f613d39.js" ><script src="../static.files/storage-59e33391.js"></script><script defer src="../crates.js"></script><script defer src="../static.files/main-5f194d8c.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-893ab5e7.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc mod crate"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../self_cell/index.html">self_<wbr>cell</a><span class="version">1.1.0</span></h2></div><div class="sidebar-elems"><ul class="block"><li><a id="all-types" href="all.html">All Items</a></li></ul><section id="rustdoc-toc"><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#overview" title="Overview">Overview</a><ul><li><a href="#fast-compile-times" title="Fast compile times">Fast compile times</a></li><li><a href="#a-motivating-use-case" title="A motivating use case">A motivating use case</a></li><li><a href="#min-required-rustc-version" title="Min required rustc version">Min required rustc version</a></li></ul></li></ul><h3><a href="#macros">Crate Items</a></h3><ul class="block"><li><a href="#macros" title="Macros">Macros</a></li><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><h1>Crate <span>self_cell</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../src/self_cell/lib.rs.html#1-677">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><h2 id="overview"><a class="doc-anchor" href="#overview">§</a>Overview</h2>
|
||
<p><code>self_cell</code> provides one macro-rules macro: <a href="macro.self_cell.html" title="macro self_cell::self_cell"><code>self_cell</code></a>. With this macro
|
||
you can create self-referential structs that are safe-to-use in stable Rust,
|
||
without leaking the struct internal lifetime.</p>
|
||
<p>In a nutshell, the API looks <em>roughly</em> like this:</p>
|
||
|
||
<div class="example-wrap ignore"><a href="#" class="tooltip" title="This example is not tested">ⓘ</a><pre class="rust rust-example-rendered"><code><span class="comment">// User code:
|
||
|
||
</span><span class="macro">self_cell!</span>(
|
||
<span class="kw">struct </span>NewStructName {
|
||
owner: Owner,
|
||
|
||
<span class="attr">#[covariant]
|
||
</span>dependent: Dependent,
|
||
}
|
||
|
||
<span class="kw">impl </span>{Debug}
|
||
);
|
||
|
||
<span class="comment">// Generated by macro:
|
||
|
||
</span><span class="kw">struct </span>NewStructName(...);
|
||
|
||
<span class="kw">impl </span>NewStructName {
|
||
<span class="kw">fn </span>new(
|
||
owner: Owner,
|
||
dependent_builder: <span class="kw">impl for</span><<span class="lifetime">'a</span>> ::core::ops::FnOnce(<span class="kw-2">&</span><span class="lifetime">'a </span>Owner) -> Dependent<<span class="lifetime">'a</span>>
|
||
) -> NewStructName { ... }
|
||
<span class="kw">fn </span>borrow_owner<<span class="lifetime">'a</span>>(<span class="kw-2">&</span><span class="lifetime">'a </span><span class="self">self</span>) -> <span class="kw-2">&</span><span class="lifetime">'a </span>Owner { ... }
|
||
<span class="kw">fn </span>borrow_dependent<<span class="lifetime">'a</span>>(<span class="kw-2">&</span><span class="lifetime">'a </span><span class="self">self</span>) -> <span class="kw-2">&</span><span class="lifetime">'a </span>Dependent<<span class="lifetime">'a</span>> { ... }
|
||
[...]
|
||
<span class="comment">// See the macro level documentation for a list of all generated functions,
|
||
// section "Generated API".
|
||
</span>}
|
||
|
||
<span class="kw">impl </span>Debug <span class="kw">for </span>NewStructName { ... }</code></pre></div>
|
||
<p>Self-referential structs are currently not supported with safe vanilla Rust.
|
||
The only reasonable safe alternative is to have the user juggle 2 separate
|
||
data structures which is a mess. The library solution ouroboros is expensive
|
||
to compile due to its use of procedural macros.</p>
|
||
<p>This alternative is <code>no_std</code>, uses no proc-macros, some self contained
|
||
unsafe and works on stable Rust, and is miri tested. With a total of less
|
||
than 300 lines of implementation code, which consists mostly of type and
|
||
trait implementations, this crate aims to be a good minimal solution to the
|
||
problem of self-referential structs.</p>
|
||
<p>It has undergone <a href="https://users.rust-lang.org/t/experimental-safe-to-use-proc-macro-free-self-referential-structs-in-stable-rust/52775">community code
|
||
review</a>
|
||
from experienced Rust users.</p>
|
||
<h4 id="fast-compile-times"><a class="doc-anchor" href="#fast-compile-times">§</a>Fast compile times</h4><div class="example-wrap"><pre class="language-txt"><code>$ rm -rf target && cargo +nightly build -Z timings
|
||
|
||
Compiling self_cell v0.7.0
|
||
Completed self_cell v0.7.0 in 0.2s</code></pre></div>
|
||
<p>Because it does <strong>not</strong> use proc-macros, and has 0 dependencies
|
||
compile-times are fast.</p>
|
||
<p>Measurements done on a slow laptop.</p>
|
||
<h4 id="a-motivating-use-case"><a class="doc-anchor" href="#a-motivating-use-case">§</a>A motivating use case</h4>
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>self_cell::self_cell;
|
||
|
||
<span class="attr">#[derive(Debug, Eq, PartialEq)]
|
||
</span><span class="kw">struct </span>Ast<<span class="lifetime">'a</span>>(<span class="kw">pub </span>Vec<<span class="kw-2">&</span><span class="lifetime">'a </span>str>);
|
||
|
||
<span class="macro">self_cell!</span>(
|
||
<span class="kw">struct </span>AstCell {
|
||
owner: String,
|
||
|
||
<span class="attr">#[covariant]
|
||
</span>dependent: Ast,
|
||
}
|
||
|
||
<span class="kw">impl </span>{Debug, Eq, PartialEq}
|
||
);
|
||
|
||
<span class="kw">fn </span>build_ast_cell(code: <span class="kw-2">&</span>str) -> AstCell {
|
||
<span class="comment">// Create owning String on stack.
|
||
</span><span class="kw">let </span>pre_processed_code = code.trim().to_string();
|
||
|
||
<span class="comment">// Move String into AstCell, then build Ast inplace.
|
||
</span>AstCell::new(
|
||
pre_processed_code,
|
||
|code| Ast(code.split(<span class="string">' '</span>).filter(|word| word.len() > <span class="number">1</span>).collect())
|
||
)
|
||
}
|
||
|
||
<span class="kw">fn </span>main() {
|
||
<span class="kw">let </span>ast_cell = build_ast_cell(<span class="string">"fox = cat + dog"</span>);
|
||
|
||
<span class="macro">println!</span>(<span class="string">"ast_cell -> {:?}"</span>, <span class="kw-2">&</span>ast_cell);
|
||
<span class="macro">println!</span>(<span class="string">"ast_cell.borrow_owner() -> {:?}"</span>, ast_cell.borrow_owner());
|
||
<span class="macro">println!</span>(<span class="string">"ast_cell.borrow_dependent().0[1] -> {:?}"</span>, ast_cell.borrow_dependent().<span class="number">0</span>[<span class="number">1</span>]);
|
||
}</code></pre></div>
|
||
<div class="example-wrap"><pre class="language-txt"><code>$ cargo run
|
||
|
||
ast_cell -> AstCell { owner: "fox = cat + dog", dependent: Ast(["fox", "cat", "dog"]) }
|
||
ast_cell.borrow_owner() -> "fox = cat + dog"
|
||
ast_cell.borrow_dependent().0[1] -> "cat"</code></pre></div>
|
||
<p>There is no way in safe Rust to have an API like <code>build_ast_cell</code>, as soon
|
||
as <code>Ast</code> depends on stack variables like <code>pre_processed_code</code> you can’t
|
||
return the value out of the function anymore. You could move the
|
||
pre-processing into the caller but that gets ugly quickly because you can’t
|
||
encapsulate things anymore. Note this is a somewhat niche use case,
|
||
self-referential structs should only be used when there is no good
|
||
alternative.</p>
|
||
<p>Under the hood, it heap allocates a struct which it initializes first by
|
||
moving the owner value to it and then using the reference to this now
|
||
Pin/Immovable owner to construct the dependent inplace next to it. This
|
||
makes it safe to move the generated SelfCell but you have to pay for the
|
||
heap allocation.</p>
|
||
<p>See the documentation for <a href="macro.self_cell.html" title="macro self_cell::self_cell"><code>self_cell</code></a> to dive further into the details.</p>
|
||
<p>Or take a look at the advanced examples:</p>
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/Voultapher/self_cell/tree/main/examples/fallible_dependent_construction">Example how to handle dependent construction that can
|
||
fail</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/Voultapher/self_cell/tree/main/examples/lazy_ast">How to build a lazy AST with
|
||
self_cell</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/Voultapher/self_cell/tree/main/examples/mut_ref_to_owner_in_builder">How to handle dependents that take a mutable reference</a> see also <a href="struct.MutBorrow.html" title="struct self_cell::MutBorrow"><code>MutBorrow</code></a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://github.com/Voultapher/self_cell/tree/main/examples/owner_with_lifetime">How to use an owner type with
|
||
lifetime</a></p>
|
||
</li>
|
||
</ul>
|
||
<h4 id="min-required-rustc-version"><a class="doc-anchor" href="#min-required-rustc-version">§</a>Min required rustc version</h4>
|
||
<p>By default the minimum required rustc version is 1.51.</p>
|
||
<p>There is an optional feature you can enable called “old_rust” that enables
|
||
support down to rustc version 1.36. However this requires polyfilling std
|
||
library functionality for older rustc with technically UB versions. Testing
|
||
does not show older rustc versions (ab)using this. Use at your own risk.</p>
|
||
<p>The minimum versions are a best effor and may change with any new major
|
||
release.</p>
|
||
</div></details><h2 id="macros" class="section-header">Macros<a href="#macros" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="macro" href="macro.self_cell.html" title="macro self_cell::self_cell">self_<wbr>cell</a></div><div class="desc docblock-short">This macro declares a new struct of <code>$StructName</code> and implements traits
|
||
based on <code>$AutomaticDerive</code>.</div></li></ul><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="struct" href="struct.MutBorrow.html" title="struct self_cell::MutBorrow">MutBorrow</a></div><div class="desc docblock-short">Wrapper type that allows creating a self-referential type that hold a mutable borrow <code>&mut T</code>.</div></li></ul></section></div></main></body></html> |