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.