# Ownership

Ownership is the part of C+ that differs most from C. There is **no `&T` and no `&mut T`**. Borrowing is expressed by *parameter markers*, not by reference types. The call site carries no markers at all; the function signature is the single place that describes the data flow.

## The parameter forms

Non-Copy values **move by default**. `borrow` is the opt-out that says "the caller keeps ownership".

| Form | On non-Copy types | On Copy types |
|---|---|---|
| `x: T` | **Move** (caller can't use the value after the call) | Pass-by-value copy |
| `mut x: T` | Exclusive borrow (function may mutate; mutations propagate back) | Pass-by-value, locally mutable |
| `move x: T` | Move (explicit; same as `x: T`) | Pass-by-value |
| `borrow x: T` | Shared borrow (caller keeps ownership, function reads only) | Redundant on Copy |

Method receivers mirror these, with one deliberate difference in the default:

| Receiver | Meaning |
|---|---|
| `self` | Shared borrow: read-only access, caller keeps ownership |
| `mut self` | Exclusive borrow: may mutate, mutations propagate back |
| `move self` | Move: consumes the receiver, caller can't use it after |

There is no `borrow self`; bare `self` already *is* the shared borrow. The asymmetry (a bare `self` reads, but a bare `x: T` parameter moves) is intentional: each defaults to its common case. Most method calls only want to look at the receiver, and most function calls hand a value over to the callee. When you want the other behaviour you say so, and the marker is always visible in the signature.

## Copy is structural

A type is `Copy` if every component is. Primitives and plain enums are `Copy`. A struct of `Copy` fields is `Copy` automatically. A struct that defines `fn drop(mut self)` is forced to be **non-Copy**, because silently bit-copying something that owns a resource would lead to a double free.

```cplus
struct Point { x: i32, y: i32 }            // Copy (all fields Copy)

struct Buf { ptr: *u8, len: usize }
impl Buf {
    fn drop(mut self) { unsafe { free(self.ptr); } }   // forces non-Copy
}
```

Return values always move:

```cplus
fn make_buf() -> Buf { ... }    // no marker; returning is always a move
```

## When to use `borrow`

Since non-Copy params move by default, the question flips: when does the callee *not* need to consume the value? Use `borrow`:

```cplus
// Default: x moves in. Caller can't use `s` after the call.
fn echo(x: string) -> string { return x; }

// Caller keeps `s`; callee only reads. To return a string it makes its own,
// typically via .clone().
fn label(borrow x: string) -> string { return x.clone(); }

let s: string = "hello".to_string();
let r: string = label(s);     // s still usable after this call
```

When the compiler sees a `borrow`-shaped use (read-only, no consume) inside a default-move body, it suggests `borrow` with a precise fix-it (**E0902**).

## `restrict`: opt-in noalias for raw pointers

The borrow checker does not reason about `*T` raw pointers, so by default LLVM must assume any two pointer arguments may alias. For numeric hot paths that is a real tax: the autovectorizer inserts a runtime alias check and a scalar fallback. The `restrict` parameter marker asserts that the pointer does not alias any other pointer reachable in the body, and lowers to LLVM `noalias`.

```cplus
fn axpy(n: usize, a: f32, restrict x: *f32, restrict y: *f32) {
    let mut i: usize = 0 as usize;
    while i < n {
        unsafe { y[i] = a * x[i] + y[i]; }
        i = i +% (1 as usize);
    }
    return;
}
```

`restrict` is only valid on `*T` params (other shapes fire **E0411**), needs no `unsafe` at the declaration, composes with `mut`, and is C ABI compatible (a `pub extern fn` exports the same C signature with or without it).

## What the compiler checks, and what it trusts

C+ ownership is **boundary-checked, not whole-program inferred**. It is worth knowing exactly where a rule is enforced and where you are trusted.

**Enforced by the compiler:**

- **Use after move**: reading a value after it moves is **E0335**.
- **Aliasing XOR mutation**: a place has shared borrows *or* one exclusive borrow, never both (see [the borrow checker](/docs/borrow-checker)).
- **Partial move out of a `Drop` type**: rejected (**E0509**), since the destructor frees fields by hand and stealing one would double free.
- **Returned borrows**: a `str` / `T[]` / `borrow REGION` result must come from a parameter or `'static` data, never from a local that drops at return (**E0513**).

**Trusted to you (the escape hatches):**

- **A `str` / `T[]` view stored into a longer-lived place.** These are `Copy` views, not tracked references. The compiler checks the function boundary, but once you copy a view into a field or another binding it no longer tracks that the backing storage outlives it.
- **Raw pointers (`*T`).** Completely outside the borrow checker. The `unsafe` you write at each dereference is where you take on the validity obligation.

One rule covers all of it: **a borrow, a view, or a raw pointer must not outlive the value it points into.** The compiler proves this at the enforced cases; everywhere else it is a contract you keep, and `unsafe` marks where you signed up for it.

## Next

Continue with [the borrow checker](/docs/borrow-checker).
