SHAPE

SHIFT

Back to homepage

The Borrow Checker Is A Merge Surface

The borrow checker is usually described as a compiler feature.

For semantic merge, it is also a review surface.

That matters because ownership is not only about memory safety. It is a language-level way of saying who may read, who may mutate, when a value may move, and when a reference stops being valid.

Those are merge questions.

If two changes both touch the same value, the hard part is not always the text conflict. The hard part is whether the combined output still respects the permission model of the program.

Ownership SurfaceBorrow Facts Are Merge Facts
SurfaceClaimRequired proofCurrent evidenceRoute
RequiredMoveValue is not used after transferMove and use-site evidenceMoved value, last use, output use sitesReject use-after-move
RequiredShared borrowRead aliases do not overlap mutationLoan scope evidenceBorrow start, borrow end, mutation spanAdmit or request scope proof
MissingMutable borrowOnly one writer existsExclusive access evidenceMutable loan, escape boundary, reborrowBlock overlapping writers
MissingLifetimeReference outlives its useLifetime/region constraintProducer, consumer, escape pathRequire lifetime proof
MissingInterior mutabilityRuntime borrow rule is preservedRuntime or API proofCell/refcell/lock boundaryRoute to runtime evidence
Borrow checking gives the merge system a vocabulary for permissions, not just a compiler error after the fact.

Ownership Is Permission

Text diff sees this:

line 12 changed
line 18 changed

Ownership sees something else:

value moved here
shared reference created here
mutable reference requested here
borrow escapes this scope
drop order changed here

Those facts decide whether two edits commute.

One branch may add a read. Another branch may add a mutation. Textually, they can live far apart. Semantically, they can overlap the same loan.

That is why ownership belongs in the merge model.

Text Distance Is Not Permission Distance
1fn render(user: &User) -> String {2  let name = user.name();3  format!("Hello {name}")4}
Base permissionThe function only takes a shared borrow and reads user.name().
Two edits can be textually simple and still change the permission structure of the function.

The output is not automatically wrong.

But it is not automatically safe either.

The merge system needs the same kind of evidence the compiler needs: loan scopes, move sites, mutation rights, and use sites bound to the output.

The Constraint Is Portable

Borrow checking is associated with Rust, but the underlying idea appears everywhere.

Rust: ownership, borrow, lifetime
C++: move, reference, RAII, aliasing
Swift: exclusivity, inout, copy-on-write
Kotlin: mutability and nullability boundaries
JavaScript: shared mutable object references
React: state ownership and effect lifetime
Databases: transaction ownership and locks

Not every language enforces the same rules.

That is exactly why the universal layer needs to model the rules as constraints. A source language may have a strong ownership fact that the target cannot express directly.

When that happens, the target needs another route: a wrapper, runtime check, cloning policy, lock boundary, immutability convention, or explicit loss.

Borrow Route TableWhen Ownership Proof Is Missing
RouteSignalRequiresProduces
PreserveTarget has equivalent ownership constructSource and target loan scopes matchOwnership constraint attached
AdaptTarget needs wrapper or clone policyAdapter declares alias/mutation behaviorReviewable lowering
ProbeSafety depends on runtime stateTrace or fixture around mutation boundaryRuntime-bounded proof
SplitOne patch changes reads and writesIndependent read and mutation regionsSmaller review objects
BlockUse-after-move or overlapping writerRecorded failed constraintNo admission
The useful outcome is not always apply or reject. Ownership evidence tells the coordinator what kind of work comes next.

Review Before Compiler Error

A compiler error is late evidence.

It tells you the combined output failed a rule.

A semantic merge system should use ownership records earlier:

this edit introduces a mutable loan
this edit lengthens a shared borrow
these branches both mutate through aliases
this lowering erases move-only semantics
this target needs a clone or wrapper decision

That lets the coordinator shape the work before the final output exists.

It can ask one worker for a focused rebase. It can ask another for a runtime proof. It can block the unsafe combination while preserving the safe hunks.

The Mental Model

The borrow checker is not just a Rust feature.

It is a visible permission system.

Semantic merge should treat permission systems as merge surfaces.

If a change affects who can read, who can write, who owns, who borrows, or who outlives whom, the merge needs evidence at that level.

Text tells us where the edit happened.

Ownership tells us whether the edit is allowed to coexist.