Nested Resources

Fields in composite types behave differently when they have a resource type.

If a resource type has fields that have a resource type, it must declare a destructor, which must invalidate all resource fields, i.e. move or destroy them.

pub resource Child {
    let name: String

    init(name: String)
        self.name = name
    }
}

// Declare a resource with a resource field named `child`.
// The resource *must* declare a destructor
// and the destructor *must* invalidate the resource field.
//
pub resource Parent {
    let name: String
    var child: @Child

    init(name: String, child: @Child) {
        self.name = name
        self.child <- child
    }

    // Declare a destructor which invalidates the resource field
    // `child` by destroying it.
    //
    destroy() {
        destroy self.child
    }
}

Accessing a field or calling function on a resource field is valid, however moving a resource out of a variable resource field is not allowed. Instead, use a swap statement to replace the resource with another resource.

let child <- create Child(name: "Child 1")
let parent <- create Parent(name: "Parent", child: <-child)

child.name  // is "Child"
parent.child.name  // is "Child"

// Invalid: Cannot move resource out of variable resource field.
let childAgain <- parent.child

// Instead, use a swap statement.
//
var otherChild <- create Child(name: "Child 2")
parent.child <-> otherChild
// `parent.child` is the second child, Child 2.
// `otherChild` is the first child, Child 1.

Last updated