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.