# Value Categories

Slang has two primary value categories:

- An _L-value_ has underlying mutable storage. Hence, an L-value can be on the left side of an assignment,
  and it can be used as an argument to an `out`/`inout` function parameter.
- An _R-value_ is a temporary or otherwise immutable value. It can only be used in contexts where a pure value
  is adequate. It cannot be used as an argument to an `out`/`inout` function parameter. An R-value is
  typically a result of a computation, a value passed as a copy, or a result of a function invocation.

The following expressions are L-values:

1. Access to a mutable variable
2. Access to an `out`/`inout`/`__ref` parameter
3. Access to an `in` parameter that has been declared using the traditional variable declaration (C-style)
   - Note: the argument is still passed by value copy
4. Pointer dereference when the pointer access type is `Access.ReadWrite`
5. Access to a reference
6. Access to a property when it has a setter accessor and the base is an L-value
7. Applying a subscript operator when both:
   - The base is an L-value
   - The subscript operator is built-in, OR it is user-defined with a setter accessor
8. Access to `this` in a mutating context
9. Return value for a non-copyable return type
10. Access to a member when the base is an L-value
11. Swizzle expression when both:
    - The base is an L-value
    - The swizzle expression has no duplicate components
12. Cast of an L-value object to a conforming type
13. Access to an interface-typed mutable object (dynamic dispatch)
14. Implicit casts that preserve the L-value category (e.g. for `inout`/`out` parameters)

Other expressions are R-value expressions.

Slang expressions are also categorized as addressable and non-addressable:

- An _addressable_ value has underlying storage that may be mutable, read-only, or immutable. Its address
  may be requested with `__getAddress()` on targets that support pointers.
- A _non-addressable_ value does not have underlying storage, and in that sense, it is a true temporary
  value.

> 📝 **Remark:** Pointer support in Slang is currently experimental. The details are subject to change.

## Where L-values Are Required

L-values are required in the following places:

- Argument to an `out`/`inout`/`__ref` parameter
- Left-hand-side operand of an assignment operator, including compound assignment operators
- Operand to pre-increment, pre-decrement, post-increment, and post-decrement operators
- Object receiving a `[mutating]` or `[ref]` member function call
- Object receiving a property setter call or a user-defined subscript operator setter call, unless the setter
  has been explicitly marked as `[nonmutating]`.
