Back to Blog

Deepfrying My Brain: What Rust's Borrow Checker Taught Me

Deepfrying My Brain: What Rust's Borrow Checker Taught Me

Deepfrying My Brain: What Rust's Borrow Checker Taught Me About Systems Thinking

Brainwashing phase? Is it really worth it?

Learning Rust as a Python or JavaScript developer isn't just about learning new syntax - it's about adopting a different operating system for your brain, a strict tutor who refuses to introduce bad practises to the code.

When you start, you think you are just replacing null with Option and var with let. Then you hit your first compile error. The compiler doesn't just tell you it's broken. It tells you why it's broken, where the memory lives, and who is responsible for cleaning it up. I started calling it the "The Strict Mentor." It doesn't let you pass go until you prove, beyond a shadow of a doubt, that you understand the data flow.

However, me getting slowly brainwashed to learn Rust dates way back than this incident of getting time back in July and exploring the language, let's leave that for another blog post :3 .


What I have to say?

This piece is not a tutorial. It is a reflection on how learning a systems language reshaped my entire engineering identity.

  • I will explore memory management (ownership, borrowing, and lifetimes) not as a hurdle, but as a design tool.
  • I will discuss Programming Language Theory (PLT) - how the constraints of a language shape the architecture of your programs.
  • And most importantly, I will walk you through my personal journey from the forgiving, garbage-collected world of JavaScript to the explicit, compile-time safety of Rust.

The Deep Dive: Trust me bro

To understand the shift, look at a simple data transformation pipeline. In JavaScript, we write this almost instinctively:

function transform(data) {
    return data
        .filter(item => item.active)
        .map(item => item.value * 2);
}

It is fluid. The garbage collector silently manages the memory of the temporary arrays. We don't think about it. I never even thought about it.

The Rust version is a mirror held to your intentions. It's a one-to-one correspondence of what you actually want the code to do.

fn transform(data: Vec<Data>) -> Vec<i32> {
    data.into_iter()
        .filter(|item| item.active)
        .map(|item| item.value * 2)
        .collect()
}

At first glance, it looks similar. But look at the type signature. In Rust, I had to decide: Do I want to borrow the data (&[Data]) or take ownership (Vec<Data>)? Same as renting or buying a car. If you rent a car, you can't just damage it give it back to the owner and expect an "Ok" as a Result<T, E> in return, but you can go whateverunsafe path you want to go if that's your car.

Please try to study Rust if you have time, and are a masochist instead of a larper.

That single decision forces me to define the contract upfront, to think about what I "really" want to do with the data I want to bring into the scope. If I take ownership, the caller cannot use the data again. I am effectively destroying it to save memory, changing it's scope, relocating it without have an URI associated to it. If I borrow, I promise not to mutate it, but I must ensure the reference outlives the function call. In JavaScript, these are invisible architectural decisions. In Rust, they are laws written into the function signature.


The Specific Moment: Redesigning My Architecture

I vividly remember the moment the borrow checker broke my brain and then rebuilt it. I was building a simple CLI tool (a search program, a smaller, scoped-down re-implementation of grep calling it minigrep). I wanted to hold a reference to a string and pass it around to different functions for searching and output formatting.

The compiler yelled at me: "cannot move out of borrowed content."

My Python instinct told me this is wrong, declare it in the global scope, My JavaScript instinct told me to just clone the string everywhere - duplicate the data to make the compiler happy. But that felt wrong, that felt slow, that felt slow. I was writing a CLI tool to be fast, not to choke on memory.

So, I had to redesign, good old pen and paper. Instead of treating the string as a "thing" that I passed around, I treated it as a resource with a single owner. I restructured my entire program so that the main function owned the string and simply borrowed it (&str) to the functions that needed to read it. It may have a lot of references that don't destroy this resource, but it can only have one reference that destroys it (arch nemesis), but not all at once, have to be procedural, but that to with guardrails.

The architecture went from a tangled web of "this uses that" to a clean, linear tree of ownership. The borrow checker didn't just catch a bug. It forced me to map out the entire data flow of my program on a whiteboard. It taught me that good systems design isn't about making the code run fast; it's about organizing the data so that it naturally falls out of scope cleanly.


How Rust Rewired My Garbage Collector brain (Even When I'm Not Writing It)?

Here is the strangest outcome. Even when I go back to writing Python or JavaScript, I write better code. Why?

I now see the invisible GC, got one right inside my head.

I instinctively try to write functions that take data and return new data, rather than modifying the original. I think in terms of "Who owns this variable right now?" even in languages that don't care. Rust effectively installed a borrow checker in my brain-and it runs silently in the background no matter what language I'm using.


Now, brainwashing you!

This journey is not just about learning to code in Rust; it's about upgrading your mental model of how software actually works, or maybe recuriting new people to join and learn Rust, demand for a Rust workshop from the core community members and type #rewriteinrust trend :3 . Here is the breakdown of what I took away:

| Layer | Takeaway | | :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Skill | How to reason about ownership and borrowing-not just to pass the compiler, but to write efficient code that avoids costly heap allocations. | | New Way of Thinking | View programs as data flow + ownership, not just sequential instructions. The architecture is defined by who holds the data, not by the order of the lines. | | Curiosity | A nudge to explore systems languages. Even if you stick with JS/Python, understanding how memory works makes you a better user of your tools. | | Technique | How to read Rust compiler errors effectively. They are not gibberish-they are a diagnostic blueprint. The compiler tells you exactly where the lifecycle mismatch is. |


Finally...

The borrow checker is not the enemy, clippy is not a suggestion engine, both are lot more than just that. Sure, it's the most rigorous code reviewer you will ever have, sure you may sob, you may wanna leave Rust for good; However, It forces you to state your assumptions explicitly, while you are yet to write the code. It humbles you when you think you can get away with "just making it work." And it eventually gives you the power to know that if your code compiles, it is memory safe. And it gives you the ability to say "safe, fearlessly concurrent, and proper memory management at compile time without needing a garbage collector" in every conversions you would need to have from that day on.

That level of certainty is addictive, bewitching, painful??? It changes how you think about code forever, for better or worse.

If you've ever felt curious about systems programming but were intimidated by the complexity, my advice is simple: pick up THE beginner book, install Rust, and let the compiler be your mentor not something you fight with. It will take your cognitive load off your working memory and put it into proven, machine-checked logic, which is developed by a large community far better engineers over the last decade, a tool that addresses a lot of painpoints while introducting some.