You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Swift provides memory safety with a combination of language affordances and runtime checking.
41
41
However, Swift also deliberately includes some unsafe constructs, such as the `UnsafePointer` and `UnsafeMutablePointer`
42
42
types in the standard library.
43
-
Swift occasionally needs additional information that is not present in the C++ type and API declarations
43
+
In some cases, Swift needs additional information that is not present in the C++ type and API declarations
44
44
to safely interface with them. This document describes how such code needs to be annotated.
45
45
46
46
### Annotating foreign types
47
47
48
-
Types imported from C++ are considered foreign to Swift. Many of these types are considered safe,
49
-
including the built-in integral types like `int`, some standard library types like `std::string`,
50
-
and aggregate types built from other safe types.
51
-
52
-
On the other hand, some C++ types are imported as unsafe by default. Consider the following C++ type
53
-
and APIs:
48
+
Types imported from C++ are considered foreign to Swift.
49
+
Types imported from C++ are considered foreign to Swift. Normally, most C++ types are imported into Swift
50
+
without any restriction. However, a small set of C++ APIs e.g. pointers/references and methods returning
51
+
pointers will be imported as unsafe (section [Working with C++ references and view types in Swift](https://www.swift.org/documentation/cxx-interop/#working-with-c-references-and-view-types-in-swift)
52
+
explains this in more detail.) Under the strict memory safe mode, the compiler will flip the polarity and
53
+
treat all types that are not known to be safe as unsafe, and will diagnose uses of them. In this section,
54
+
we will show how to annotate unsafe C++ types so that they can be accessed safely and correctly from Swift.
55
+
Note that the features here are agnostic to whether strictly-safe mode is on or off. When the strictly safe
56
+
mode is on, the compiler warnings can serve as a guide to properly annotate C++ types and also help ensure
57
+
that the code doesn't use unsafe APIs anywhere. When the strictly-memory-safe mode is off, it is still
58
+
recommended to adopt these annotation whereever appropriate, especially on C++ types that are potentially
59
+
lifetime dependent on other objects.
60
+
61
+
Under strictly-memory-safe mode the built-in integral types like `int`, some standard library types like `std::string`,
62
+
and aggregate types built from other safe types are considered safe. Whereas all other unannotated types
63
+
are considered unsafe. Let's see what happens when we are trying to use an unannotated type in
64
+
strictly-safe mode. Consider the following C++ type and APIs:
54
65
55
66
```c++
56
67
classStringRef {
@@ -143,28 +154,25 @@ contracts helping us to write code that is free of memory safety errors.
143
154
144
155
## Escapability annotations in detail
145
156
146
-
Currently, unannotated types are imported as `Escapable` to maintain backward
157
+
Under the strictly-safe mode, even though compiler warns on unannotated types,
158
+
they are imported as if they are `Escapable` to maintain backward
147
159
compatibility. This might change in the future under a new interoperability version.
148
160
We have already seen that we can import a type as `~Escapable` to Swift by adding
149
161
the `SWIFT_NONESCAPABLE` annotation:
150
162
151
163
```c++
152
164
structSWIFT_NONESCAPABLE View {
153
-
View() : member(nullptr) {}
154
165
View(const int *p) : member(p) {}
155
-
View(const View&) = default;
156
166
private:
157
167
const int *member;
158
168
};
159
169
```
160
170
161
171
Moreover, we can explicitly mark types as `Escapable` using the `SWIFT_ESCAPABLE`
162
-
annotation:
172
+
annotation to express that they are not lifetime dependent on any other values:
163
173
164
174
```c++
165
-
struct SWIFT_ESCAPABLE Owner {
166
-
...
167
-
};
175
+
struct SWIFT_ESCAPABLE Owner { ... };
168
176
```
169
177
170
178
The main reason for explicitly annotating a type as `SWIFT_ESCAPABLE` is to make sure
@@ -193,28 +201,63 @@ In this example, `MyList<View>` should be imported as `~Escapable` while `MyList
193
201
should be imported as `Escapable`. This can be achieved via conditional escapability
194
202
annotations:
195
203
196
-
```
204
+
```c++
197
205
template<typename T>
198
206
structSWIFT_ESCAPABLE_IF(T) MyList {
199
207
...
200
208
};
201
209
```
202
210
211
+
Here, instantiations of `MyList` are imported as `Escapable` when `T` is substituted
212
+
with an `Escapable` type.
213
+
214
+
The `SWIFT_ESCAPABLE_IF` macro can take multiple template parameters:
215
+
216
+
```c++
217
+
template<typename F, typename S>
218
+
structSWIFT_ESCAPABLE_IF(F, S) MyPair {
219
+
F first;
220
+
S second;
221
+
};
222
+
```
223
+
224
+
`MyPair` instantiations are only imported as `Escapable` if both template arguments
225
+
are `Escapable`.
226
+
227
+
`Escapable` types cannot have `~Escapable` fields. The following code snippet will
228
+
trigger a compiler error:
229
+
230
+
```c++
231
+
structSWIFT_NONESCAPABLE View { ... };
232
+
struct SWIFT_ESCAPABLE Owner {
233
+
View v;
234
+
};
235
+
```
236
+
237
+
Escapability annotations will not only help the Swift compiler to import C++ types
238
+
safely, it will also help discover missing lifetime annotations as all `~Escapable`
239
+
parameters and return values need to be annotated in an API to make its use safe in
240
+
Swift.
241
+
203
242
## Lifetime annotations in detail
204
243
205
-
The `lifetimebound` attribute can be used to annotate code in various scenarios.
206
-
On a constructor, it describes the lifetime of the created object:
244
+
The `lifetimebound` attribute on a function parameter or implicit object parameter
245
+
indicates that the returned object's lifetime could end when any of the `lifetimebound`
246
+
annotated parameters' lifetime ended.
247
+
This annotation a constructor describes the lifetime of the created object:
207
248
208
249
```c++
209
250
struct SWIFT_NONESCAPABLE View {
210
251
View(const int *p [[clang::lifetimebound]]) : member(p) {}
211
-
private:
212
-
const int *member;
252
+
...
213
253
};
214
254
```
215
255
256
+
In this example, the object initialized by the `View` constructor has the same
257
+
lifetime as the input argument of the constructor.
258
+
216
259
In case the attribute is after the method signature, the returned object has
217
-
the same lifetime as the `this` object.
260
+
the same lifetime as the implicit `this`parameter.
218
261
219
262
```c++
220
263
structOwner {
@@ -226,27 +269,28 @@ struct Owner {
226
269
};
227
270
```
228
271
229
-
In case the attribute is applied to a subset of the formal parameters, the return
272
+
Consider a call site like `View v = o.handOutView()`. The `v` object has the same lifetime
273
+
as `o`.
274
+
275
+
In case the attribute is applied to a subset of the parameters, the return
230
276
value might depend on the corresponding arguments:
0 commit comments