<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged rust-lang</title>
<link>https://coderlegion.com/tag/rust-lang</link>
<description>Powered by Question2Answer</description>
<item>
<title> New Rust Tutorial: Structured Logging with tracing</title>
<link>https://coderlegion.com/7598/new-rust-tutorial-structured-logging-with-tracing</link>
<description>&lt;p&gt;For this week’s Rust update, I released a new episode of Fearless in Rust focusing on production-ready logging with tracing.&lt;/p&gt;
&lt;p&gt;This video shows how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;set up flexible log layers&lt;/li&gt;
&lt;li&gt;output compact or JSON logs&lt;/li&gt;
&lt;li&gt;attach fields like source_id for request tracing&lt;/li&gt;
&lt;li&gt;use TraceLayer to auto-log HTTP traffic&lt;/li&gt;
&lt;li&gt;apply #[instrument] to clean up debugging&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;▶️ &lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/UBxHiPFMg0M&quot;&gt;https://youtu.be/UBxHiPFMg0M&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Great for anyone building API services or distributed systems in Rust.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/7598/new-rust-tutorial-structured-logging-with-tracing</guid>
<pubDate>Fri, 21 Nov 2025 11:32:59 +0000</pubDate>
</item>
<item>
<title>Runtime-initialized variables in Rust</title>
<link>https://coderlegion.com/3235/runtime-initialized-variables-in-rust</link>
<description>&lt;p&gt;Rust offers different ways to initialize &lt;strong&gt;compile time-initialized&lt;/strong&gt; variables. Recently, I had to create a runtime-initialized variable: existing approaches don't work in this case. I want to describe multiple ways to achieve it in this post.&lt;/p&gt;
&lt;h3 id=&quot;constants&quot;&gt;Constants&lt;/h3&gt;
&lt;p&gt;The Rust language allows you to create constants. Two keywords are available: &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;static&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&amp;gt;Sometimes a certain value is used many times throughout a program, and it can become inconvenient to copy it over and over. What’s more, it’s not always possible or desirable to make it a variable that gets carried around to each function that needs it. In these cases, the &lt;code&gt;const&lt;/code&gt; keyword provides a convenient alternative to code duplication:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;gt;&lt;code&gt;`&lt;/code&gt;rust&lt;br&gt;
&amp;gt;const THING: u32 = 0xABAD1DEA;&lt;/p&gt;
&lt;p&gt;&amp;gt;let foo = 123 + THING;&lt;br&gt;
&amp;gt;&lt;code&gt;`&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;gt;-- &lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/std/keyword.const.html&quot;&gt;Keyword const&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;gt;A static item is a value which is valid for the entire duration of your program (a &lt;code&gt;'static&lt;/code&gt; lifetime).&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;gt;On the surface, &lt;code&gt;static&lt;/code&gt; items seem very similar to &lt;code&gt;const&lt;/code&gt;: both contain a value, both require type annotations and both can only be initialized with constant functions and values. However, &lt;code&gt;static&lt;/code&gt; are notably different in that they represent a location in memory. That means that you can have references to &lt;code&gt;static&lt;/code&gt; items and potentially even modify them, making them essentially global variables.&lt;/p&gt;
&lt;p&gt;&amp;gt;Static items do not call &lt;code&gt;drop&lt;/code&gt; at the end of the program.&lt;/p&gt;
&lt;p&gt;&amp;gt;There are two types of &lt;code&gt;static&lt;/code&gt; items: those declared in association with the &lt;code&gt;mut&lt;/code&gt; keyword and those without.&lt;/p&gt;
&lt;p&gt;&amp;gt;-- &lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/std/keyword.static.html&quot;&gt;Keyword static&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;None of the above work with &lt;code&gt;struct&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I stand corrected: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.reddit.com/r/rust/comments/1l0uwzy/comment/mvgghb0/&quot;&gt;https://www.reddit.com/r/rust/comments/1l0uwzy/comment/mvgghb0/&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;const REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r&quot;^WAREHOUSE__(?&amp;lt;index&amp;gt;\d)__ENDPOINT.*&quot;).unwrap();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Trying to compile the previous line returns the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error[E0015]: cannot call non-const fn `regex::Regex::new` in constants
  |
6 | const REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r&quot;^WAREHOUSE__(?&amp;lt;index&amp;gt;\d)__ENDPOINT.*&quot;).unwrap();
  |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: calls in constants are limited to constant functions, tuple structs and tuple variants
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same happens with if we change &lt;code&gt;const&lt;/code&gt; to &lt;code&gt;static&lt;/code&gt;. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error[E0015]: cannot call non-const fn `regex::Regex::new` in statics
 --&amp;gt; src/config.rs:6:43
  |
6 | static REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r&quot;^WAREHOUSE__(?&amp;lt;index&amp;gt;\d)__ENDPOINT.*&quot;).unwrap();
  |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: calls in statics are limited to constant functions, tuple structs and tuple variants
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need a &lt;strong&gt;runtime-initialized&lt;/strong&gt; variable for the &lt;code&gt;struct&lt;/code&gt;. Neither &lt;code&gt;const&lt;/code&gt; nor &lt;code&gt;lazy&lt;/code&gt; work; time to search for something else.&lt;/p&gt;
&lt;h3 id=&quot;the-lazy-static-crate&quot;&gt;The &lt;code&gt;lazy_static&lt;/code&gt; crate&lt;/h3&gt;
&lt;p&gt;When you need something, there's a high chance somebody required it before. If lucky, they created a crate for it. Case in point, the &lt;code&gt;lazy_static&lt;/code&gt; crate provides a solution.&lt;/p&gt;
&lt;p&gt;&amp;gt;A macro for declaring lazily evaluated statics in Rust.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;gt;Using this macro, it is possible to have statics that require code to be executed at runtime in order to be initialized. This includes anything requiring heap allocations, like vectors or hash maps, as well as anything that requires non-const function calls to be computed.&lt;/p&gt;
&lt;p&gt;&amp;gt;-- &lt;a rel=&quot;nofollow&quot; href=&quot;https://crates.io/crates/lazy_static&quot;&gt;lazy_static crate&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The usage is straightforward: we wrap the &lt;code&gt;static&lt;/code&gt; declaration in a macro.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;lazy_static! {
    static ref REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r&quot;^WAREHOUSE__(?&amp;lt;index&amp;gt;\d)__ENDPOINT.*&quot;).unwrap();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We achieved what we wanted to. Yet, we can do better.&lt;/p&gt;
&lt;h3 id=&quot;lazylock-for-the-win&quot;&gt;&lt;code&gt;LazyLock&lt;/code&gt; for the win&lt;/h3&gt;
&lt;p&gt;Rust 1.80 adds &lt;code&gt;LazyLock&lt;/code&gt;. &lt;code&gt;LazyLock&lt;/code&gt; is a built-in exact replacement for the &lt;code&gt;lazy_static&lt;/code&gt; macro.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=15390373099004456590&quot; alt=&quot;https://x.com/13erbse/status/1816491350235173228&quot;&gt;&lt;/p&gt;
&lt;p&gt;The documentation of &lt;code&gt;LazyLock&lt;/code&gt; is straightforward:&lt;/p&gt;
&lt;p&gt;&amp;gt;&lt;code&gt;pub struct LazyLock&amp;lt;T, F = fn() -&amp;gt; T&amp;gt; { /* private fields */ }&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;gt;A value which is initialized on the first access.&lt;/p&gt;
&lt;p&gt;&amp;gt;This type is a thread-safe LazyCell, and can be used in statics. Since initialization may be called from multiple threads, any dereferencing call will block the calling thread if another initialization routine is currently running.&lt;/p&gt;
&lt;p&gt;&amp;gt;-- &lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/beta/std/sync/struct.LazyLock.html&quot;&gt;LazyLock&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At this point, we can use it directly:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;static REGEXP_WAREHOUSE_ENDPOINT: LazyLock&amp;lt;Regex&amp;gt; =
        LazyLock::new(|| Regex::new(r&quot;^WAREHOUSE__(?&amp;lt;index&amp;gt;\d)__ENDPOINT.*&quot;).unwrap());
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;oncelock&quot;&gt;&lt;code&gt;OnceLock&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;As an alternative, one can use &lt;code&gt;OnceLock&lt;/code&gt; from Rust 1.70.&lt;/p&gt;
&lt;p&gt;&amp;gt;&lt;code&gt;pub struct OnceLock&amp;lt;T&amp;gt; { /* private fields */ }&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;gt;A synchronization primitive which can nominally be written to only once.&lt;/p&gt;
&lt;p&gt;&amp;gt;This type is a thread-safe &lt;code&gt;OnceCell&lt;/code&gt;, and can be used in statics. In many simple cases, you can use &lt;code&gt;LazyLock&amp;lt;T, F&amp;gt;&lt;/code&gt; instead to get the benefits of this type with less effort: &lt;code&gt;LazyLock&amp;lt;T, F&amp;gt;&lt;/code&gt; &quot;looks like&quot; &lt;code&gt;&amp;amp;T&lt;/code&gt; because it initializes with &lt;code&gt;F&lt;/code&gt; on deref! Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock doesn’t allow additional inputs to its function after you call &lt;code&gt;LazyLock::new(|| ...)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&amp;gt;-- &lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html&quot;&gt;OnceLock&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Usage is quite different:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;static REGEXP_WAREHOUSE_ENDPOINT: OnceLock&amp;lt;Regex&amp;gt; = OnceLock::new();       //1

let endpoint = REGEXP_WAREHOUSE_ENDPOINT.get_or_init(
        || Regex::new(r&quot;^WAREHOUSE__(?P&amp;lt;index&amp;gt;\d+)__ENDPOINT$&quot;).unwrap()); //2

endpoint.find(&quot;whatever&quot;).is_some()                                        //3
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Create the &lt;code&gt;OnceLock&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Get or initialize the variable&lt;/li&gt;
&lt;li&gt;Use the variable&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;In this post, we described several options to create lazy-initialized variables. Before, we had to rely on the &lt;code&gt;lazy_static&lt;/code&gt; crate. With Rust 1.80, we can replace it with &lt;code&gt;LazyLock&lt;/code&gt;. If you need additional input after the &lt;code&gt;LazyLock::new()&lt;/code&gt;, &lt;code&gt;OnceLock&lt;/code&gt; is your friend.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To go further:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/std/keyword.const.html&quot;&gt;Keyword const&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.rs/lazy_static/latest/lazy_static/&quot;&gt;lazy_static crate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/beta/std/sync/struct.LazyLock.html&quot;&gt;Struct LazyLock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html&quot;&gt;Struct OnceLock&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Originally published at &lt;a rel=&quot;nofollow&quot; href=&quot;https://blog.frankel.ch/lazy-initialized-vars-rust/&quot;&gt;A Java Geek&lt;/a&gt; on June 1&lt;sup&gt;st&lt;/sup&gt;, 2025&lt;/em&gt;&lt;/p&gt;
</description>
<category>Backend Dev</category>
<guid isPermaLink="true">https://coderlegion.com/3235/runtime-initialized-variables-in-rust</guid>
<pubDate>Thu, 05 Jun 2025 07:03:35 +0000</pubDate>
</item>
<item>
<title>High-cardinality values for build flags in Rust</title>
<link>https://coderlegion.com/1880/high-cardinality-values-for-build-flags-in-rust</link>
<description>&lt;p&gt;While working on my &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ajavageek/wasm-kubernetes&quot;&gt;demo&lt;/a&gt; on WebAssembly and Kubernetes, I wanted to create three different binaries based on the same code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Native: compile the Rust code to regular native code as a baseline&lt;/li&gt;
&lt;li&gt;Embed: compile to WebAssembly and use the WasmEdge runtime image as the base Docker image&lt;/li&gt;
&lt;li&gt;Runtime: compile to WebAssembly, use a base &lt;code&gt;scratch&lt;/code&gt; image as my base image, and set the runtime when running the code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code itself is an HTTP server that offers a single endpoint. For the sake of the demo, I wanted it to return the flavour of the underlying image.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl localhost:3000/get

{&quot;source&quot;: &quot;native&quot;, &quot;data&quot;: {}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The idea is to have a single codebase that I can compile to native or WebAssembly. I solved this requirement by using a &lt;code&gt;cfg&lt;/code&gt; compile flag.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#[cfg(flavor = &quot;native&quot;)]
const FLAVOR: &amp;amp;str = &quot;native&quot;;

#[cfg(flavor = &quot;embed&quot;)]
const FLAVOR: &amp;amp;str = &quot;embed&quot;;

#[cfg(flavor = &quot;runtime&quot;)]
const FLAVOR: &amp;amp;str = &quot;runtime&quot;;

// Use FLAVOR later in the returned HTTP response
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my case, I can live with three different values. But what if I had to deal with a high cardinality, say, fifteen? It would be quite a bore to define them manually. I searched for a solution and found Build Scripts.&lt;/p&gt;
&lt;p&gt;&amp;gt;Some packages need to compile third-party non-Rust code, for example C libraries. Other packages need to link to C libraries which can either be located on the system or possibly need to be built from source. Others still need facilities for functionality such as code generation before building (think parser generators).&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;gt;Cargo does not aim to replace other tools that are well-optimized for these tasks, but it does integrate with them with custom build scripts. Placing a file named &lt;code&gt;build.rs&lt;/code&gt; in the root of a package will cause Cargo to compile that script and execute it just before building the package.&lt;/p&gt;
&lt;p&gt;&amp;gt;-- &lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/cargo/reference/build-scripts.html&quot;&gt;Build Scripts&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let's try with a simple &lt;code&gt;build.script&lt;/code&gt; at the root of the crate:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn main() {
    println!(&quot;Hello from build script!&quot;);
}

cargo build

Compiling high-cardinality-cfg-compile v0.1.0 (/Users/nico/projects/private/high-cardinality-cfg-compile)
 Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There isn't any log–nothing seems to happen. The documentation reveals the reason:&lt;/p&gt;
&lt;p&gt;&amp;gt;The output of the script is hidden from the terminal during normal compilation.&lt;br&gt;
&amp;gt;If you would like to see the output directly in your terminal, invoke Cargo as &quot;very verbose&quot; with the &lt;code&gt;-vv&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;Let's compile again with the verbose flag:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cargo build --vv
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output is what we expect:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
[high-cardinality-cfg-compile 0.1.0] Hello from build script!
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now is the time to do something useful: I'll use the build script to replace the hard-coded constants above. For that, I'll generate a Rust code file that contains the value passed for flavor.&lt;/p&gt;
&lt;p&gt;Note the &lt;strong&gt;build script runs before compilation&lt;/strong&gt;. Hence, it doesn't have access to the &lt;code&gt;cfg&lt;/code&gt; flags. Instead, I'll pass the value as a &lt;code&gt;Cargo.toml&lt;/code&gt; package metadata key value.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[package.metadata]
flavor = &quot;foobar&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our build script to read the &lt;code&gt;Cargo.toml&lt;/code&gt; metadata, we need to add a build dependency:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[build-dependencies]
cargo_metadata = &quot;0.19.1&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code is straightforward:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn main() {
    let metadata = MetadataCommand::new()                                         //1
        .exec()
        .expect(&quot;Failed to fetch cargo metadata&quot;);

    let package = metadata.root_package().expect(&quot;No root package found&quot;);        //2

    let flavor = package                                                          //3
        .metadata
        .get(&quot;flavor&quot;)
        .and_then(|f| f.as_str())
        .expect(&quot;flavor is not set in Cargo.toml under [package.metadata]&quot;);

    let dest_path = Path::new(&quot;src&quot;).join(&quot;flavor.rs&quot;);                           //4

    fs::write(&amp;amp;dest_path, format!(&quot;pub const FLAVOR: &amp;amp;str = \&quot;{}\&quot;;\n&quot;, flavor))  //5
        .expect(&quot;Failed to write flavor.rs&quot;);

    println!(&quot;cargo:rerun-if-changed=Cargo.toml&quot;);
    println!(&quot;cargo:warning=FLAVOR written to {}&quot;, dest_path.display());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Get the metadata&lt;/li&gt;
&lt;li&gt;Get the package where we want to create the new file&lt;/li&gt;
&lt;li&gt;Read the flavor value&lt;/li&gt;
&lt;li&gt;Reference &lt;code&gt;src/flavor.rs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Write &lt;code&gt;pub const FLAVOR: &amp;amp;str = &amp;lt;flavor&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On the code side, we only need to use the &lt;code&gt;FLAVOR&lt;/code&gt; const from the &lt;code&gt;flavor&lt;/code&gt; module:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mod flavor;

fn main() {
    println!(&quot;Hello from flavor {}&quot;, flavor::FLAVOR);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running the program outputs the flavor configured in the &lt;code&gt;Cargo.toml&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cargo run

Hello from flavor foobar
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this, I've shown how to use high-cardinality build parameters from the package metadata. I could have achieved the same with environment variables, but I wanted to learn about the &lt;code&gt;metadata&lt;/code&gt; section of the &lt;code&gt;Cargo.toml&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;build.rs&lt;/code&gt; file is a handy trick for achieving goals that aren't possible with regular Cargo features.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To go further:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/cargo/reference/build-scripts.html&quot;&gt;Build Scripts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Originally published at &lt;a rel=&quot;nofollow&quot; href=&quot;https://blog.frankel.ch/high-cardinality-values-build-flags-rust/&quot;&gt;A Java Geek&lt;/a&gt; on April 13&lt;sup&gt;th&lt;/sup&gt;, 2025&lt;/em&gt;&lt;/p&gt;
</description>
<category>Java</category>
<guid isPermaLink="true">https://coderlegion.com/1880/high-cardinality-values-for-build-flags-in-rust</guid>
<pubDate>Thu, 17 Apr 2025 08:10:37 +0000</pubDate>
</item>
<item>
<title>Mastering Borrow Checking in Rust: The Key to Safe and Efficient Memory Management</title>
<link>https://coderlegion.com/504/mastering-borrow-checking-in-rust-the-key-to-safe-and-efficient-memory-management</link>
<description>&lt;p&gt;As a developer, you have probably wrestled with memory management challenges: from the dreaded &lt;code&gt;null&lt;/code&gt; pointer dereferences to elusive &lt;em&gt;race&lt;/em&gt; conditions in concurrent code. &lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://rust-lang.org&quot;&gt;Rust&lt;/a&gt;, with its groundbreaking approach to safety and performance, offers a solution: &lt;strong&gt;borrow checking&lt;/strong&gt;. This unique feature enforces strict ownership and borrowing rules, eliminating common memory errors at compile time without relying on garbage collection.&lt;/p&gt;
&lt;p&gt;In this post, I’ll break down the concept of borrow checking, illustrate it with practical examples, and explain why it’s essential for you to master it. By the end, you’ll see why Rust’s borrow checker isn’t just a gatekeeper—it’s a trusted partner in writing safe, efficient code.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-is-borrow-checking-&quot;&gt;What is Borrow Checking?&lt;/h3&gt;
&lt;p&gt;At its core, &lt;a rel=&quot;nofollow&quot; href=&quot;https://rustc-dev-guide.rust-lang.org/borrow_check.html&quot;&gt;borrow checking&lt;/a&gt; is Rust’s mechanism for ensuring that references to data are valid and follow strict rules about ownership and mutability. This is part of Rust’s ownership system, which guarantees memory safety by enforcing three key rules at compile time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Each piece of data in &lt;a rel=&quot;nofollow&quot; href=&quot;http://rust-lang.org&quot;&gt;Rust&lt;/a&gt; is owned by a single variable at any given time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data can be borrowed as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One mutable reference&lt;/strong&gt; (&lt;code&gt;&amp;amp;mut&lt;/code&gt;), or&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Any number of immutable references&lt;/strong&gt; (&lt;code&gt;&amp;amp;&lt;/code&gt;), but never both at the same time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;References must always be valid, meaning no dangling pointers.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Borrow checking ensures these rules are upheld. It tracks how data is borrowed and accessed, and it stops us from making unsafe memory access patterns. Let’s delve into why this is important.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-does-borrow-checking-matter-&quot;&gt;Why Does Borrow Checking Matter?&lt;/h3&gt;
&lt;p&gt;Borrow checking solves problems that plague languages with manual memory management, like C or C++. In those languages, developers must manage memory manually, leading to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use-after-free errors&lt;/strong&gt;: Accessing memory that has already been deallocated.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dangling pointers&lt;/strong&gt;: References pointing to invalid memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data races&lt;/strong&gt;: Simultaneous access to mutable data from multiple threads, causing unpredictable behaviour.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These issues often surface at runtime, making them hard to debug and costly to fix. Rust’s borrow checker prevents these bugs at compile time. It offers the performance benefits of manual memory management while ensuring safety and correctness.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;borrow-checking-in-practice&quot;&gt;Borrow Checking in Practice&lt;/h3&gt;
&lt;p&gt;Let’s walk through a series of examples to understand how borrow checking works in Rust and how it enforces ownership and borrowing rules.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;example-1-immutable-borrowing&quot;&gt;Example 1: Immutable Borrowing&lt;/h4&gt;
&lt;p&gt;Immutable borrowing allows multiple references to the same data, as long as none of them modifies it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn main() {
    let data = String::from(&quot;Hello, Coderlegion!&quot;); // `data` owns the String
    let borrowed_data = &amp;amp;data; // Immutable borrow
    
    println!(&quot;{}&quot;, borrowed_data); // Safe access to the borrowed reference
    println!(&quot;{}&quot;, data); // Safe access to the original owner
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;borrowed_data&lt;/code&gt; holds an immutable reference (&lt;code&gt;&amp;amp;data&lt;/code&gt;) to &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both &lt;code&gt;borrowed_data&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; can be accessed concurrently because they don’t modify the underlying data.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id=&quot;example-2-mutable-borrowing&quot;&gt;Example 2: Mutable Borrowing&lt;/h4&gt;
&lt;p&gt;When data is borrowed mutably, only one reference is allowed, ensuring exclusive access.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn main() {
    let mut data = String::from(&quot;Coderlegion is amazing!&quot;); // Mutable data
    let borrowed_data = &amp;amp;mut data; // Mutable borrow

    borrowed_data.push_str(&quot; Let's learn borrow checking.&quot;); // Modify the data
    println!(&quot;{}&quot;, borrowed_data); // Safe because access is exclusive
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;amp;mut data&lt;/code&gt; creates a mutable borrow, allowing &lt;code&gt;borrowed_data&lt;/code&gt; to modify the data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While &lt;code&gt;borrowed_data&lt;/code&gt; exists, no other references to &lt;code&gt;data&lt;/code&gt;—immutable or mutable—are allowed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id=&quot;example-3-mixing-mutable-and-immutable-borrows&quot;&gt;Example 3: Mixing Mutable and Immutable Borrows&lt;/h4&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://rust-lang.org&quot;&gt;Rust&lt;/a&gt; enforces strict separation between mutable and immutable borrows to prevent conflicts.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn main() {
    let mut data = String::from(&quot;Concurrency made safe!&quot;);
    let immut_borrow = &amp;amp;data; // Immutable borrow
    
    let mut_borrow = &amp;amp;mut data; // Mutable borrow - ERROR
    println!(&quot;{}&quot;, immut_borrow);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Compile-Time Error:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error[E0502]: cannot borrow `data` as mutable because it is also borrowed as immutable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Allowing a mutable borrow (&lt;code&gt;mut_borrow&lt;/code&gt;) alongside an immutable borrow (&lt;code&gt;immut_borrow&lt;/code&gt;) could lead to data races.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rust’s borrow checker prevents this, ensuring data integrity.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id=&quot;example-4-lifetimes-and-borrow-checking&quot;&gt;Example 4: Lifetimes and Borrow Checking&lt;/h4&gt;
&lt;p&gt;Rust extends borrow checking to lifetimes, ensuring references remain valid throughout their usage.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn longest&amp;lt;'a&amp;gt;(x: &amp;amp;'a str, y: &amp;amp;'a str) -&amp;gt; &amp;amp;'a str {
    if x.len() &amp;gt; y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let string1 = String::from(&quot;Coderlegion&quot;);
    let string2 = String::from(&quot;Borrow checker&quot;);

    let result = longest(&amp;amp;string1, &amp;amp;string2);
    println!(&quot;The longest string is: {}&quot;, result);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;'a'&lt;/code&gt; is a lifetime annotation ensuring both &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; live as long as the return value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This guarantees no dangling references, even when dealing with complex ownership patterns.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;how-does-borrow-checking-work-internally-&quot;&gt;How Does Borrow Checking Work Internally?&lt;/h3&gt;
&lt;p&gt;Rust’s compiler enforces borrow checking through its &lt;strong&gt;abstract syntax tree (AST)&lt;/strong&gt; and &lt;strong&gt;control flow analysis&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ownership Tracking:&lt;/strong&gt; The compiler tracks which variable owns a piece of data at any point.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Borrow Graphs:&lt;/strong&gt; References are analyzed for conflicts. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Immutable references are grouped into a single “read” set.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mutable references form an exclusive “write” set.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lifetime Validation:&lt;/strong&gt; Rust ensures that references are valid for their declared lifetimes, preventing dangling references.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By performing these checks at compile time, Rust guarantees memory safety without runtime penalties.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;common-borrow-checking-errors-and-how-to-fix-them&quot;&gt;Common Borrow Checking Errors and How to Fix Them&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simultaneous Mutable and Immutable Borrows&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt; &quot;Cannot borrow as mutable because it is also borrowed as immutable.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Use only one type of borrow at a time, and drop immutable references before mutable ones.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dangling References&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt; &quot;Borrowed value does not live long enough.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Ensure the borrowed reference doesn’t outlive its source.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Invalid Lifetimes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt; &quot;Cannot return reference to a local variable.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Avoid returning references to local variables that will be dropped.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;rust-has-a-steep-learning-curve&quot;&gt;Rust has a steep Learning Curve&lt;/h3&gt;
&lt;p&gt;Borrow checking might feel restrictive at first. Developers transitioning from other languages may find it challenging to adjust to Rust’s ownership rules. However, these restrictions force us to write safer, more predictable code. Over time, borrow checking becomes second nature and even a guide for designing better systems.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-borrow-checking-matters-for-you-and-your-team-&quot;&gt;Why Borrow Checking Matters for you and your team.&lt;/h3&gt;
&lt;p&gt;As we adopt Rust in our projects, borrow checking will become an integral part of our development workflow. Here’s why it matters:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Safety First:&lt;/strong&gt; Borrow checking eliminates entire classes of bugs at compile time, saving debugging time and ensuring reliability.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Without Garbage Collection:&lt;/strong&gt; We get the efficiency of manual memory management with the safety of high-level languages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concurrency Made Easy:&lt;/strong&gt; Borrow checking prevents data races, enabling us to write safe concurrent code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h3&gt;
&lt;p&gt;Rust’s borrow checker is more than just a set of rules—it’s a tool for writing safe, performant, and maintainable code. By embracing borrow checking, we’re not just avoiding bugs; we’re adopting a mindset of precision and care that will make us better developers.&lt;/p&gt;
&lt;p&gt;Let’s continue exploring Rust together. The more you practice, the more intuitive borrow checking will become. If you have questions or need further clarification or drop a comment. Let’s make memory safety a cornerstone of our development culture!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;If you found this post helpful, feel free to share it with others. Together, we can master Rust and build robust software that we’re proud of.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://michaeldabydeen.com&quot;&gt;Mike Dabydeen&lt;/a&gt; a Software Development Manager and college professor with over 20 years of experience and a passion for building scalable solutions and fostering growth in the tech community. With expertise in various technologies, he enjoys creating innovative tools and mentoring teams to achieve their goals. Outside of managing projects and teaching, he also writes, in both English &amp;amp; Spanish, about software development, team dynamics, and tech education, while also pursuing personal challenges.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/504/mastering-borrow-checking-in-rust-the-key-to-safe-and-efficient-memory-management</guid>
<pubDate>Fri, 06 Dec 2024 23:26:30 +0000</pubDate>
</item>
</channel>
</rss>