Borrowed references are borrowed from a variable or some other reference. They have no idea what allocator created the object and are able to point to substructures within compound objects. This flexibility makes them ideal for passing information to general-purpose functions or methods. However, the lifetime of a borrowed reference is constrained; it cannot outlive the variable or reference it borrowed from.

Use of a borrowed reference typically focuses only on the object it references. In fact, a reference is often implicitly understood to just be a stand-in for the object it references. Strict safety rules ensure that references always refer to a valid object of the right type.

Here's a simple example that shows a borrowed reference being created and used. The & operator obtains a reference to a variable's contents. The * operator accesses the contents referred to by a reference:

imm a = 3
imm ref = &a    // ref holds a reference to a's contents
imm val = *ref  // val is now 3

Borrowed Reference Type Declarations

Similar to numbers and structures, references are value types. Mirroring the & operator used to create a reference, a borrowed reference declaration begins with &, followed by the reference's permission, lifetime (optional), and the value type of the object being referred to.

imm ptr2 &mut Coord
imm ptr3 &Coord       // omitted permission is 'const'

The const permission is the default given to a borrowed reference when none is specified. const grants a reference the ability to view the contents of the object but not change it.

Borrowed references may be declared for:

Creating Borrowed References

Borrowed references may be borrowed from:

Permission

If a borrowed reference requires some other permission than const, specify it following the &.

mut a = 3
imm ref = &mut a  // ref holds a mutable reference to a's contents
imm val = *ref    // val is now 3
*ref = 10         // a is now 10. val is still 3.

Note that the permission specified for a borrowed reference may not exceed the permission granted to the variable or reference it borrowed from. Thus, you cannot get a mut reference from an imm variable.

Also notice that the variable 'ref' that holds the reference is itself immutable (it can only ever refer to 'a'). However, it holds a reference able to change (mutate) 'a'. In this statement, the first permission governs the variable 'ref' and the second governs the reference held by 'ref'. These are two different concerns.

Lifetime Constraints

Borrowed references are lifetime-constrained, which means that a borrowed reference may never outlive the object it refers to. This constraint is enforced by ensuring the lexical scope of the borrowed reference is wholly encompassed by the lexical scope of the reference or object it borrowed from.

For example, a reference may not be borrowed from an object whose lifetime is shorter than the reference:

imm a = 3
mut ref = &a
do
  imm b = 4
  ref = &b  // ERROR! b's lexical lifetime is shorter than ref's

When borrowing from a uni variable or reference, the owner becomes inaccessible for the lifetime of borrowed reference. In the case of a substructure borrow, it is the collection (not the field or element) that is being borrowed from.

uni a = 3
do
  imm ref = &a
  a = 4   // ERROR! a is unavailable due to the borrow
a = 5     // This one is okay, since lifetime of 'ref' has expired

Note that any reference known to have borrowed from a global variable has no lifetime constraint.

The compiler loses important lifetime information when borrowed references are passed to and from another function. In such situations, lifetime annotations may be required to ensure correct enforcement of lifetime constraints.

Dereferencing

The * operator is used to access the contents of a reference. Normally, in an expression, it obtains the contents referred to by the reference. However, when used to the left of an assignment expression, it modifies the referred-to contents:

mut a = 3
imm ref = &mut a  // ref holds a mutable reference to a's contents
*ref = 10         // a is now 10.

Such derefencing happens implicitly whenever applying a method to (or calling) an object referred to by a reference:

mut a = -4
imm ptr = &mut a
imm y = ptr.abs()    // y is 4. Equivalent to: (*ptr).abs

Borrowed References to Functions

A reference may borrow from any function. Later, that reference may be used to call the function it refers to.

fn incr(x i32) i32
  x + 1

fn caller()
  imm fnref = &incr
  fnref(4)            // returns 5 (automatic de-referencing)

Using a similar technique, it is also possible to make use of anonymous functions:

fn caller()
  imm fnref = &fn (nbr i32) i32 {nbr+1}
  fnref(4)            // returns 5

Although these are borrowed references, the default lifetime for function references is 'static, which means they can be moved around freely without any lifetime constraints.

Lifetime Annotations

TBD.

_