Borrow Accessors
--preview borrow_accessors to use. See ADR-0062 for the design.A borrow accessor is a method that hands out a second-class borrow of a projection of its receiver: v.get_ref(i) produces a borrowed place naming element i in place — no copy, no move-out — checked by the ordinary law-of-exclusivity loan machinery and scoped to the enclosing full expression (core calculus docs/formal/01-core-calculus.md §5.8, rule (Accessor-Call)). This is the ADR-0062 read-accessor form; mutable accessors (inout self → exclusive result) are a later phase.
Declaration
accessor = "fn" IDENT "(" "borrow" "self" [ "," params ] ")"
"->" "borrow" type "{" { statement } yield_expr [ ";" ] "}" ;
yield_expr = "yield" expression ;
A -> borrow result position and the yield form require the borrow_accessors preview feature. Without --preview borrow_accessors, a program using either is rejected at compile time (E1100), per 8.4.
An accessor MUST declare a borrow self receiver. A -> borrow result on a free function, an associated function, a by-value or mut self method, an inout self method, or a method of an anonymous struct type is rejected (E0257).
Accessor value parameters MUST be plain by-value parameters: borrow, inout, and comptime parameter modes are rejected on an accessor (E0260).
The accessor body
Every non-diverging path through an accessor body MUST fall through to the body's single trailing yield: the final statement of the body is a yield, no other yield may appear, no code may follow it, and the body MUST NOT contain return or ? (E0254). Guard code before the yield may only diverge — trap or @panic — or fall through. A yield outside an accessor body is rejected (E0256).
The operand of the yield MUST be a place rooted at the receiver parameter: self, or a projection chain from self through fields, indices, or nested accessor calls (E0255). Yielding a local, a parameter other than the receiver, or a computed value would hand out a place that dies with the accessor's guards.
Calls
A call to an accessor requires its receiver to be a place, exactly as passing it as a borrow argument does (6.4:27), and evaluates its arguments by value. The result is a borrowed place, not a first-class value: a shared loan on the receiver's root variable whose extent is the enclosing full expression (core calculus docs/formal/01-core-calculus.md §5.8, rule (Accessor-Call)). Within that extent the result may be read, projected further (v.get_ref(i).name), passed as a borrow argument, or compared.
An accessor result MUST NOT escape its full expression: returning it (E0250), storing it by assignment (E0251), binding it with a plain let (E0252), or capturing it in a struct or array literal (E0253) is rejected.
The law of exclusivity extends over the accessor loan's whole extent: an exclusive use of the borrowed root — passing it inout, an inout self receiver access, assigning to it, or moving it — anywhere within the same full expression is rejected (E0259). use(v.get_ref(i), g(inout v)) is ill-formed even though the read syntactically precedes the exclusive access.
Reading a value that owns resources (one with drop glue) out of an accessor result by value is rejected (E0258): the result is a borrow, not an owner, and a by-value read would mint an aliasing second owner — the same soundness argument as the by-copy container-read gate (E0711). Only trivially droppable values may be read out; owning values are used in place through projection, borrow arguments, comparison, or borrow self methods.
Dynamics and lowering
An accessor call evaluates by the accessor's inlined body: the guards run in the calling context — and may trap — and the call's result is then the yielded place itself, projected from the caller's receiver place (core calculus §5.8 dynamics note). No function call occurs at runtime.
Accessors are required-inlineable by design: no calling convention for "returning a place" exists, which is the forward-compatibility contract that keeps the future coroutine-accessor generalization (RUE-1012) free to choose its own call shape.