@@ -968,74 +968,109 @@ func foo() {
968
968
969
969
A noncopyable struct or enum may declare a `deinit `, which will run
970
970
implicitly when the lifetime of the value ends (unless explicitly suppressed
971
- as noted below):
971
+ with `discard` as explained below):
972
972
973
973
```swift
974
- struct FileDescriptor: ~ Copyable {
975
- private var fd: Int32
974
+ struct File: ~ Copyable {
975
+ var descriptor: Int32
976
+
977
+ func write <S : Sequence >(_ values : S) { /* ..*/ }
978
+
979
+ consuming func close () {
980
+ print (" closing file" )
981
+ }
976
982
977
983
deinit {
978
- close (fd)
984
+ print (" deinitializing file" )
985
+ closeFile (rawDescriptor : descriptor)
979
986
}
980
987
}
981
988
```
982
989
983
- Like a class `deinit `, a struct or enum `deinit ` may not propagate any uncaught
984
- errors. `self ` behaves as in a `borrowing ` method; it may not be
985
- modified or consumed by the body of `deinit `. (Allowing for mutation and
986
- partial invalidation inside a `deinit ` is explored as a future direction.)
990
+ Like a class `deinit `, a struct or enum `deinit ` may not propagate any
991
+ uncaught errors. Within the body of the `deinit `, `self ` behaves as in
992
+ a `borrowing ` method; it may not be modified or consumed inside the
993
+ `deinit `. (Allowing for mutation and partial invalidation inside a
994
+ `deinit ` is explored as a future direction.)
987
995
988
996
A value's lifetime ends, and its `deinit ` runs if present, in the following
989
997
circumstances:
990
998
991
- - For a local `var ` or `let ` binding, or `consuming ` function parameter, that
992
- is not itself consumed, `deinit ` runs after the last non- consuming use.
993
- If, on the other hand, the binding is consumed, then responsibility for
994
- deinitialization gets forwarded to the consumer (which may in turn forward
995
- it somewhere else ).
999
+ - For a local `var ` or `let ` binding, or `consuming ` function parameter, that is
1000
+ not itself consumed, `deinit ` runs at the end of the binding's lexical
1001
+ scope. If, on the other hand, the binding is consumed, then responsibility
1002
+ for deinitialization gets forwarded to the consumer (which may in turn forward
1003
+ it somewhere else ). As explained later, a `_ = consume` operator with no
1004
+ destination immediately runs the `deinit `.
996
1005
997
1006
```swift
998
1007
do {
999
- var x = FileDescriptor ( 42 )
1000
-
1001
- x. close () // consuming use
1002
- // x's deinit doesn't run here (but might run inside `close` )
1008
+ let file = File ( descriptor : 42 )
1009
+ file. close () // consuming use
1010
+ // file's deinit runs inside `close`
1011
+ print ( " done writing " )
1003
1012
}
1004
-
1013
+ // Output:
1014
+ // closing file
1015
+ // deinitializing file
1016
+ // done writing
1017
+
1005
1018
do {
1006
- var x = FileDescriptor (42 )
1007
- x.write ([1 ,2 ,3 ]) // borrowing use
1008
- // x's deinit runs here
1009
-
1019
+ let file = File (descriptor : 42 )
1020
+ file.write ([1 ,2 ,3 ]) // borrowing use
1010
1021
print (" done writing" )
1022
+ // file's deinit runs here
1011
1023
}
1024
+ // Output:
1025
+ // done writing
1026
+ // deinitializing file
1012
1027
```
1013
1028
1014
- - When a `struct`, `enum`, or `class` contains a member of noncopyable type,
1015
- the member is destroyed, and its `deinit ` is run, after the container's
1016
- `deinit ` if any runs.
1029
+ If a noncopyable value is conditionally consumed, then the deinitializer
1030
+ runs as late as possible on any nonconsumed paths:
1017
1031
1018
1032
```swift
1019
- struct Inner: ~ Copyable {
1020
- deinit { print (" destroying inner" ) }
1021
- }
1022
-
1023
- struct Outer: ~ Copyable {
1024
- var inner = Inner ()
1025
- deinit { print (" destroying outer" ) }
1026
- }
1027
-
1033
+ let condition = false
1028
1034
do {
1029
- _ = Outer ()
1035
+ let file = File (descriptor : 42 )
1036
+ file.write ([1 ,2 ,3 ]) // borrowing use
1037
+ if condition {
1038
+ file.close ()
1039
+ } else {
1040
+ print (" not closed" )
1041
+ // file's deinit runs here
1042
+ }
1043
+ print (" done writing" )
1030
1044
}
1045
+ // Output:
1046
+ // not closed
1047
+ // deinitializing file
1048
+ // done writing
1031
1049
```
1032
1050
1033
- will print:
1051
+ - When a struct, enum, or class contains a member of noncopyable type, the member is destroyed, and its deinit is
1052
+ run, after the container's deinit runs. For example:
1034
1053
1035
- ```swift
1036
- destroying outer
1037
- destroying inner
1038
- ```
1054
+ ```swift
1055
+ struct Inner: ~ Copyable {
1056
+ deinit { print (" destroying inner" ) }
1057
+ }
1058
+
1059
+ struct Outer: ~ Copyable {
1060
+ var inner = Inner ()
1061
+ deinit { print (" destroying outer" ) }
1062
+ }
1063
+
1064
+ do {
1065
+ _ = Outer ()
1066
+ }
1067
+ ```
1068
+
1069
+ will print:
1070
+ ```
1071
+ destroying outer
1072
+ destroying inner
1073
+ ```
1039
1074
1040
1075
### Suppressing `deinit ` in a `consuming ` method
1041
1076
0 commit comments