Skip to main content
Version: Current

References

It is possible to create references to objects, i.e. resources or structures. A reference can be used to access fields and call functions on the referenced object.

References are copied, i.e. they are value types.

References are created by using the & operator, followed by the object, the as keyword, and the type through which they should be accessed. The given type must be a supertype of the referenced object's type.

References have the type &T, where T is the type of the referenced object.


_12
let hello = "Hello"
_12
_12
// Create a reference to the "Hello" string, typed as a `String`
_12
//
_12
let helloRef: &String = &hello as &String
_12
_12
helloRef.length // is `5`
_12
_12
// Invalid: Cannot create a reference to `hello`
_12
// typed as `&Int`, as it has type `String`
_12
//
_12
let intRef: &Int = &hello as &Int

If you attempt to reference an optional value, you will receive an optional reference. If the referenced value is nil, the reference itself will be nil. If the referenced value exists, then forcing the optional reference will yield a reference to that value:


_10
let nilValue: String? = nil
_10
let nilRef = &nilValue as &String? // r has type &String?
_10
let n = nilRef! // error, forced nil value
_10
_10
let strValue: String? = ""
_10
let strRef = &strValue as &String? // r has type &String?
_10
let n = strRef! // n has type &String

References are covariant in their base types. For example, &T is a subtype of &U, if T is a subtype of U.


_35
_35
// Declare a resource interface named `HasCount`,
_35
// that has a field `count`
_35
//
_35
resource interface HasCount {
_35
count: Int
_35
}
_35
_35
// Declare a resource named `Counter` that conforms to `HasCount`
_35
//
_35
resource Counter: HasCount {
_35
pub var count: Int
_35
_35
pub init(count: Int) {
_35
self.count = count
_35
}
_35
_35
pub fun increment() {
_35
self.count = self.count + 1
_35
}
_35
}
_35
_35
// Create a new instance of the resource type `Counter`
_35
// and create a reference to it, typed as `&Counter`,
_35
// so the reference allows access to all fields and functions
_35
// of the counter
_35
//
_35
let counter <- create Counter(count: 42)
_35
let counterRef: &Counter = &counter as &Counter
_35
_35
counterRef.count // is `42`
_35
_35
counterRef.increment()
_35
_35
counterRef.count // is `43`

References may be authorized or unauthorized.

Authorized references have the auth modifier, i.e. the full syntax is auth &T, whereas unauthorized references do not have a modifier.

Authorized references can be freely upcasted and downcasted, whereas unauthorized references can only be upcasted. Also, authorized references are subtypes of unauthorized references.


_39
_39
// Create an unauthorized reference to the counter,
_39
// typed with the restricted type `&{HasCount}`,
_39
// i.e. some resource that conforms to the `HasCount` interface
_39
//
_39
let countRef: &{HasCount} = &counter as &{HasCount}
_39
_39
countRef.count // is `43`
_39
_39
// Invalid: The function `increment` is not available
_39
// for the type `&{HasCount}`
_39
//
_39
countRef.increment()
_39
_39
// Invalid: Cannot conditionally downcast to reference type `&Counter`,
_39
// as the reference `countRef` is unauthorized.
_39
//
_39
// The counter value has type `Counter`, which is a subtype of `{HasCount}`,
_39
// but as the reference is unauthorized, the cast is not allowed.
_39
// It is not possible to "look under the covers"
_39
//
_39
let counterRef2: &Counter = countRef as? &Counter
_39
_39
// Create an authorized reference to the counter,
_39
// again with the restricted type `{HasCount}`, i.e. some resource
_39
// that conforms to the `HasCount` interface
_39
//
_39
let authCountRef: auth &{HasCount} = &counter as auth &{HasCount}
_39
_39
// Conditionally downcast to reference type `&Counter`.
_39
// This is valid, because the reference `authCountRef` is authorized
_39
//
_39
let counterRef3: &Counter = authCountRef as? &Counter
_39
_39
counterRef3.count // is `43`
_39
_39
counterRef3.increment()
_39
_39
counterRef3.count // is `44`

References are ephemeral, i.e they cannot be stored. Instead, consider storing a capability and borrowing it when needed.