# Package for Rust-like borrow checker in Julia?

**URL:** https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442
**Category:** General Usage
**Tags:** question
**Created:** [January 5, 2025, 11:17am UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442 "2025-01-05T11:17:12Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 11:17am UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/1 "2025-01-05T11:17:12Z")

</div>

My least favorite bugs are usually caused by:

1. Thread races
2. Aliased memory

While Rust doesn’t fill the same niche as Julia with respect to scientific computing, I really like the safety guarantees around ownership and borrow checker. At the expense of flexibility of code, the model provides some formal guarantees about thread races and mutability.

I’m therefore wondering if there is any Julia package that can help provide guarantees for these sorts of issues? The dream is to have some kind of compiler flag to do scope analysis similar to Rust:

```rust
fn main() {
    let mut x = 42;

    let ref1 = &x; // Immutable borrow
    let ref2 = &mut x;
    // ERROR: cannot borrow `x` as mutable because
    // it is also borrowed as immutable

    println!("ref1: {}", ref1);
}

```

Rust literally refuses to compile this, and the static analysis tool points it out:

 ![Screenshot 2025-01-05 at 10.38.22](https://global.discourse-cdn.com/julialang/original/3X/9/5/95152860b7305732b88e4b2d784e5f43d4e702b0.png)

I think it would be awesome if Julia itself eventually had an _opt-in_ system that could do borrow checking and ownership like this. But I of course understand such a thing would take a lot of work.

In the meantime I’m wondering if there are any packages available for this sort of thing? I’m looking for something like this –

```julia
@borrow_checker function main()
    @safe :mut x = 42
    
    # Borrow x as an immutable reference:
    ref1 = @ref x # defaults to :immutable
    
    # Attempt to borrow x as a mutable reference:
    ref2 = @ref :mut x
    # ^This should error because ref1 is still active
    
    println(ref1[])
end

```

- `@borrow_checker`  
A macro that does a “function-wide” analysis and unwrapping (either purely syntactic or some combination of syntactic + runtime checks). I think this would basically unwrap `x` at function call sites so that external functions don’t need to accommodate a `Safe{T}` type. But it would _only unwrap a variable once_ - so it can’t be owned by multiple scopes.

- `@safe`  
Tells the `@borrow_checker` to track it. Wraps an object (like Ref(1) or an Array) in a “tracked” container that knows how many mutable/immutable borrows currently exist.

- `@ref`  
Extracts either an immutable reference or a mutable reference. If a mutable reference is requested (with `:mut`) but an immutable one is still active, we fail. Similarly, if a mutable reference is active, we can’t even create an immutable reference.

### Edit: see updated syntax later in thread

I guess it should really go into the compiler though. It would also permit additional optimizations if the compiler knows a given variable will not be mutated in a given scope – especially things like arrays.

Maybe a JET-style approach could work as well.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [January 5, 2025, 1:12pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/2 "2025-01-05T13:12:19Z")

</div>

> [@MilesCranmer](#):
>
> ```julia
> # Borrow x as an immutable reference:
> ref1 = @ref x # defaults to :immutable
>     
> # Attempt to borrow x as a mutable reference:
> ref2 = @ref :mut x
> 
> ```

What would this even do or expand to in Julia? Julia doesn’t distinguish variables as immutable or mutable, rather the types of the instances they happen to be assigned to at the moment, and variables don’t reference each other. If that gets reconciled with Julia’s variable model somehow, I can see such static analysis being implemented for an unidiomatic subset, but that stops at the vast majority of code that isn’t written with `@ref`, `@mut`, or whatever other macros mimicking Rust’s keywords. It won’t know what to do at `push!(an_array, value)`.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 1:18pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/3 "2025-01-05T13:18:23Z")

</div>

> [@Benny](#):
>
> Julia doesn’t distinguish variables as immutable or mutable

While of course you can’t do this at a low level, you can get most of the practical benefit by overloading `setproperty!` and `getproperty` to control mutability. So if you make a type

```julia
mutable struct Owned{T}
    value::T
    moved::Bool

    function Owned{T}(value::T) where {T}
        new{T}(value, false)
    end
end

```

For ownership, you can have the accessor check if a variable is still owned or not before returning:

```julia
function Base.getindex(x::Owned)
    x.moved && throw(MovedError())
    x.value
end

```

and the `@ref` and `@ref :mut` can wrap values in these other structs:

```julia
struct _Ref{T}
    owner::Owned{T}
end

struct _MutRef{T}
    owner::Owned{T}
end

# Forward all property access to the underlying value
function Base.getproperty(r::Union{_Ref, _MutRef}, name::Symbol)
    name === :owner && return getfield(r, :owner)
    getproperty(r.owner[], name)
end
function Base.setproperty!(r::_Ref, name::Symbol, value)
    error("Cannot modify immutable reference")
end
function Base.setproperty!(r::_MutRef, name::Symbol, value)
    name === :owner && error("Cannot modify reference ownership")
    setproperty!(r.owner[], name, value)
end

```

To be clear I am only talking about “simulating” ownership and borrow checking in user space. Of course you can’t do that with Julia itself yet.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [January 5, 2025, 1:20pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/4 "2025-01-05T13:20:03Z")

</div>

Also, Julia’s immutable don’t have references. So I’m not entirely sure what’s meant here. In Julia, if you want a reference to an immutable you’d wrap it in a `Ref`, and so all references are mutable, so this error shouldn’t be possible. Reusing the same immutable is an optimization that is possible in some instances by the compiler, but there isn’t a system for immutable references at the user level.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 1:25pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/5 "2025-01-05T13:25:06Z")

</div>

It’s the same way I can define a `ReadOnlyArray` that simply wraps an `Array` and denies every call to `setindex!`. While it is not preventing the user from going under the hood and modifying `data._contents[:] = ...`, practically speaking, it’s incredibly useful to have loud errors for unintended mutations.

In rust you can turn off these strict rules with `unsafe { ... }`. But it just forces you to code in a safer way by having these explicit automatic checks.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [January 5, 2025, 1:40pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/6 "2025-01-05T13:40:16Z")

</div>

> [@MilesCranmer](#):
>
> `@ref` and `@ref :mut` can wrap values in these other structs:

Interesting approach to make Julia types more like Rust variables, but 2 immediate problems:

- none of the methods outside this unidiomatic subset will work on these types. I can’t add 2 `_Ref{Int}` together with `+(::Int, ::Int)`. You could unwrap these before normal Julia function calls, but then the static analysis only covers the scope of the caller function.
- you’re still dragged down by the mutability/immutability property of Julia types (the `T`). `setproperty!` there handles scalars, but what if you have a vector? If you store an immutable vector, then the only thing you can do semantically is replace it with another immutable vector, even if you only need to change 1 element. Sure there’s Accessors.jl, but even if you hack `new` to skip constructors, there’s no guarantee the compiler can optimize things to essentially mutation (we’ll have to wait for escape analysis to mature). If you instead store a mutable vector (all of Rust’s types are potentially mutable), then you get all the performance drawbacks because Julia variables don’t have the semantics of Rust’s.

At best you may implement a slow Rust on top of Julia that is incapable of using other Julia code, which I don’t think is what you’re hoping to work with. Rust can go at full speed because it doesn’t go through another high level language’s rules and limitations, so if you want Rust’s semantics and zero-cost benefits, use Rust.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 1:54pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/7 "2025-01-05T13:54:18Z")

</div>

I think we might be overindexing on performance concerns here. The primary goal is catching bugs and enforcing safer coding patterns - performance is really a secondary consideration. Ideally, this would be something you could enable during development and testing to catch issues early, then disable in production if needed. Think of the `@ref` and `@move` annotations as development-time guardrails that could evaporate when you’re not in test mode.

Regarding compatibility with existing methods, that’s actually aligned with what I’m aiming for here. When unwrapping a mutable value before function calls, it would be marked as _moved_ - preventing any further access to that mutable variable within the function scope - unless you obtain ownership again.

I’m envisioning this initially as an internally-used module. While it’s true that external functions could still have bugs and perform unexpected mutations, having these safety guarantees within your own codebase is still incredibly valuable. It’s similar to how ErrorTypes.jl approaches error handling - while it can’t handle error propagation in external packages, it’s extremely useful for handling errors in your own code.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [January 5, 2025, 2:48pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/8 "2025-01-05T14:48:02Z")

</div>

> [@MilesCranmer](#):
>
> Ideally, this would be something you could enable during development and testing to catch issues early, then disable in production if needed.

A desirable approach, but this typically doesn’t change the semantics of the code like macros do; after all, you want to check what your production code does as well.

> [@MilesCranmer](#):
>
> While it’s true that external functions could still have bugs and perform unexpected mutations, having these safety guarantees within your own codebase is still incredibly valuable.

That works if you only use your own code, at which point you might as well reinvent Rust. Once you pass an “immutable reference” to a method that can mutate it in some callee (which can be totally unknown as an argument and can’t be identified with input and output types like Rust’s function pointer types), you lose all those safety guarantees. Unsafe Rust at least still has Rust’s variable semantics and respects the borrow checker, and it’s idiomatically isolated to rare blocks. What you’re proposing is a small island of “safe” Julia that isn’t isolated at all from the vast ecosystem of no-concept-of-safe Julia. That has zero guarantee of stopping the mentioned bugs; it’s why Rust isn’t just a C library.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 2:49pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/9 "2025-01-05T14:49:21Z")

</div>

> [@Benny](#):
>
> What you’re proposing is a small island of “safe” Julia that isn’t isolated at all from the vast ecosystem of no-concept-of-safe Julia.

Yes

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 2:53pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/10 "2025-01-05T14:53:45Z")

</div>

I don’t need guarantees for all code executed, I just want to prevent internal race conditions in any library I write. Shouldn’t really be controversial 😅 Don’t we all want this?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [January 5, 2025, 3:01pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/11 "2025-01-05T15:01:11Z")

</div>

Those guarantees for “all code executed” _are_ what reduces those internal race conditions. There’s no mechanism isolating your code from the unsafe dependencies, so it’s just as unsafe no matter what safety rules you make for yourself. Like sure, you made sure you’re not doing multiple mutable borrows in some sense; `Base` can still give you race conditions.

> [@MilesCranmer](#):
>
> Don’t we all want this?

Yes, and that desire produced languages like Rust. If it were possible to tack such safety semantics onto a language without it, then all those languages would just be C libraries.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 3:03pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/12 "2025-01-05T15:03:03Z")

</div>

> [@Benny](#):
>
> reduces

To clarify – this is all I want. I know “eliminates” is impossible without the entire language imposing such a thing. My race conditions have more often been by my own hand than by `Base` (thankfully).

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [January 5, 2025, 3:14pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/13 "2025-01-05T15:14:04Z")

</div>

If someone is interested in taking a crack at a compiler pass that does this, I would recommend starting with the escape analysis compiler machinery (e.g. `code_escapes` and so on) partially documented here: [EscapeAnalysis · The Julia Language](https://docs.julialang.org/en/v1.12-dev/devdocs/EscapeAnalysis/)

Using `code_escapes` on a function should theoretically have all the requisite information you’d need to determine if something is borrowable, it’s really just a question of traversing that datastructure and detecting cases where you want to throw a compile-time error.

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [January 5, 2025, 3:22pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/14 "2025-01-05T15:22:48Z")

</div>

> [@Benny](#):
>
> Yes, and that desire produced languages like Rust. If it were possible to tack such safety semantics onto a language without it, then all those languages would just be C libraries.

Julia _is_ a flexible enough language with strong enough analysis tools that compiler passes really can do this sort of thing if you have the time and will to implement them.

And from a certain point of view, Julia _is_ just a C library, it just happens to be a very big, isolated, and heavily abstracted C library.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 3:46pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/15 "2025-01-05T15:46:33Z")

</div>

That’s awesome! Thanks.

Here’s a current attempt at an API from messing around in case people were curious.

First, we look to create an `Owned{T}` (immutable) and `OwnedMut{T}` type with the `@own` and `@own_mut` macros, respectively:

```julia
@own x = 1
@own_mut y = 2

```

Instead of assigning this variable, you want to always use `@move` (I’m not sure how to force this though)

```julia
@move z = x

```

This will result in the original `x` being marked as `.moved` and thus is unusable:

```julia
@take x # MovedError

```

You can mutate mutable owned values with `@set`:

```julia
@set x = 5

```

which will again check for `.moved` and also whether it is `OwnedMut`.

The API is written in such a way that if all the macros disappeared, it would just be normal Julia code (so you can turn it on just for testing). This means that you can define functions with signatures like

```julia
const ValueOrBorrowed{T} = Union{T,Borrowed{T}}

function foo(bar::ValueOrBorrowed{T}) where {T}
   #= ... =#
end

```

to permit borrowing a reference to type `T` or just the actual type `T`. The `Borrowed{T}` would be analogous to the rust syntax `bar: &T`.

You could also declare it

```julia
function foo(bar::Union{T,BorrowedMut{T}}) where {T}
   #= ... =#
end

```

if you want to allow _mutable_ references, analogous to rust syntax `bar: &mut T`. This forces difference behavior in the caller, because you would need to pass a mutable reference instead.

Now, for references, you can use `@ref` to borrow `x` (immutable reference), or `@ref_mut` to get a mutable reference (only for `OwnedMut{T}` types). But you can only use these inside a `@scoped_refs` block to ensure the correct lifetime.

```julia
@scoped_refs let
    rx = @ref x
    ry = @ref_mut y

    # modifying y here would be an error, since
    # there is a mutable reference to it! We also
    # can't `@take x` or `@take y` since there are
    # active borrows

    println(rx, ry)
end

# now we can modify y and take from them

```

The regular `Borrowed{T}` denies every attempt at a `setproperty!`, but you can have multiple of them. Meanwhile the `BorrowedMut{T}` is only allowed to exist one at a time.

At the end of this scope block, the reference counters are reset for `x` and `y` and those references are finalized.

I think this `@scoped_refs` is where you would want to try something like EscapeAnalysis to just handle it automatically!

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 4:41pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/16 "2025-01-05T16:41:15Z")

</div>

Actually I like this syntax better because there’s less spooky action at a distance. Explicit lifetime scope blocks!

```julia
@own_mut a = [1, 2, 3]
@own b = [4, 5, 6]

# This block lasts for lifetime `lt`, after which
# the borrows are cleared
@lifetime lt let

    # Mutable borrow
    mut_ref = @ref_mut lt a
    # @ref lt a
    ## ^Would throw an error here, since it's already mutably borrowed!
    push!(mut_ref, 4)

    # Immutable borrow
    imm_ref = @ref lt b
    imm_ref2 = @ref lt b # We can do multiple immutable references!
    @test imm_ref == [4, 5, 6]
    @test_throws "Cannot modify immutable reference" push!(imm_ref, 7)

    # c = @move a
    ## ^Error when trying to move a or b while borrowed
end

```

But yeah it would be really nice to do this escape analysis automatically rather than needing explicit scopes.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [January 5, 2025, 4:44pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/17 "2025-01-05T16:44:06Z")

</div>

> [@Mason](#):
>
> Julia _is_ a flexible enough language with strong enough analysis tools that compiler passes really can do this sort of thing if you have the time and will to implement them.

> [@Mason](#):
>
> …detecting cases where you want to throw a compile-time error.

This I believe, excepting the unpredictable runtime dispatches. AllocCheck.jl analyzes compiled code for possible heap allocations and identifies the problematic source code in a stacktrace, not fooled by runtime branching and doesn’t need to be followed by execution. That doesn’t give Julia allocation-free semantics (or fully user-controlled allocations like Zig), and escape analysis seems intended for optimizing idiomatic Julia, not enforcing special semantics. MilesCranmer is also accepting that the proposed semantics are only enforced for source code inside the `@borrow_checker` call, as we can’t control how preexisting Julia code is designed or what bugs they enable. I’m not at all confident that would help reduce said bugs; causes of race conditions aren’t evenly distributed across source code, and fixing a personal module may not make an obvious improvement, ie race conditions involving fewer threads rather than reducing race conditions. To definitely oversimplify with an extreme analogy, `foo() = [1, 2] + [3, 4]` does not directly allocate anything; `AllocCheck.check_allocs` identifies `new`s and `ccall`s down several layers of callees from the `vect` and `+` I wrote and would be essentially useless if it only errored for my direct calls.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 4:59pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/18 "2025-01-05T16:59:31Z")

</div>

> [@Benny](#):
>
> would help reduce said bugs

I guess I’ll just add my motivation – I’ve had to debug multiple race conditions in SymbolicRegression.jl which nowadays is quite a complex library with deep call stacks, a lot of memory optimizations, asynchronous stuff, buffers, etc. Every race condition\[1\] is an absolute pain to debug. In retrospect it feels like each one could have been prevented with a borrow checker.

At the very least it would be nice if there was some sort of pure-Julia MemCheck/Sanitizer that could find such things automatically. (But maybe I’m just not fluent enough in parsing Valgrind analysis into the Julia side)

* * *

1. I mean race conditions produced within SymbolicRegression.jl; I haven’t had one in Base yet, luckily, other than some GC issues I found in 1.11.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [January 5, 2025, 5:08pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/19 "2025-01-05T17:08:45Z")

</div>

> [@MilesCranmer](#):
>
> it would be nice if there was some sort of pure-Julia MemCheck/Sanitizer that could find such things automatically

That seems more reasonable and I think that’s what Mason meant with the escape analysis stuff, that is you wouldn’t need special annotations to catch things like 2 variables being assigned to the same mutable object (a bit stringent) that is consequently mutated in 2 separate threads (danger!), whether it’s in your source code or the code you’re using. Again a silly extreme analogy, AllocCheck doesn’t need us to annotate lines with `@malloc` to find allocations.

---

<div class="post-metadata">

### Author: ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)
#### Post date: [January 5, 2025, 5:20pm UTC](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442/20 "2025-01-05T17:20:24Z")

</div>

I’m not sure how it could work without some extra metadata to declare stuff as mutable/immutable. There currently isn’t a concept of an immutable “reference” to an object in Julia, which is part of the issue. But the EscapeAnalysis certainly seems like it would make it _easier_ to check rules on top of those references/ownerships.

[Next page](https://discourse.julialang.org/t/package-for-rust-like-borrow-checker-in-julia/124442.md?page=2)
