Deinitializers
A deinitializer runs when an instance is about to be freed. Use it to release resources the type holds — file handles, locks, network connections, foreign memory.
struct FileHandle: not Copyable {
let fd: Int
deinit {
println("closing fd \(self.fd)"); // realistically: a close() syscall
}
}
@main func main() {
let f = FileHandle(fd: 3);
println("working with fd \(f.fd)");
} // f goes out of scope here — deinit runs
Kestrel manages memory through ownership and scope-based drop. When a value goes out of scope, the compiler inserts a call to deinit (if you defined one) and then frees the memory. You can also write deinit variable; explicitly to release a resource early, but most of the time the compiler handles it automatically.
Mark a type with a deinit as : not Copyable. Any struct may declare one, but on a copyable struct every copy runs the deinitializer — for a resource type that means double-release. not Copyable makes the compiler reject accidental duplication, so cleanup runs exactly once.
For most struct types you'll never need a deinitializer. Reach for one only when the type owns something that must be cleaned up explicitly. See Concepts → Memory Model for the full story.
A deinitializer takes no parameters and has no return value. It can read fields freely but should not, for example, store self somewhere — by the time deinit runs, the object is on its way out.