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/inoutfunction 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/inoutfunction 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:
- Access to a mutable variable
- Access to an
out/inout/__refparameter - Access to an
inparameter that has been declared using the traditional variable declaration (C-style)- Note: the argument is still passed by value copy
- Pointer dereference when the pointer access type is
Access.ReadWrite - Access to a reference
- Access to a property when it has a setter accessor and the base is an L-value
- 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
- Access to
thisin a mutating context - Return value for a non-copyable return type
- Access to a member when the base is an L-value
- Swizzle expression when both:
- The base is an L-value
- The swizzle expression has no duplicate components
- Cast of an L-value object to a conforming type
- Access to an interface-typed mutable object (dynamic dispatch)
- Implicit casts that preserve the L-value category (e.g. for
inout/outparameters)
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/__refparameter - 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].