Skip to content

Commit 0828162

Browse files
egorzhdanj-hui
andauthored
Apply suggestions from code review
Co-authored-by: John Hui <[email protected]>
1 parent f1c2fab commit 0828162

File tree

1 file changed

+28
-23
lines changed
  • documentation/cxx-interop/safe-interop

1 file changed

+28
-23
lines changed

documentation/cxx-interop/safe-interop/index.md

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ to safely interface with them. This document describes how such code needs to be
4949
Types imported from C++ are considered foreign to Swift. Normally, most C++ types are imported into Swift
5050
without any restriction. However, a small set of C++ APIs e.g. pointers/references and methods returning
5151
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,
52+
explains this in more detail.) Under the strict memory safety mode, the compiler will flip the polarity of its safety assumptions.
53+
It will treat all types that are not known to be safe as unsafe, and emit diagnostics for usage of unsafe types without the `unsafe` keyword.
54+
In this section,
5455
we will show how to annotate unsafe C++ types so that they can be accessed safely and correctly from Swift.
5556
Note that the features here are agnostic to whether strict safety mode is on or off. When the strict safety
5657
mode is on, the compiler diagnostics can serve as a guide on how to properly annotate C++ types, and also help ensure
@@ -60,7 +61,9 @@ dependent on the lifetimes of other objects.
6061

6162
Under the strict safety mode, built-in numeric types like `int`, some standard library types like `std::string`,
6263
and aggregate types built from other safe types are considered safe. All other unannotated types
63-
are considered unsafe. Let's see what happens when we are trying to use an unannotated type in
64+
are considered unsafe.
65+
66+
Let's see what happens when we are trying to use an unannotated type in
6467
strict safety mode. Consider the following C++ type and APIs:
6568

6669
```c++
@@ -108,7 +111,7 @@ emits a warning about using an unsafe type.
108111
109112
Building the code again will emit a new diagnostic for the `fileName` function about
110113
missing lifetime annotations. C and C++ functions that return non-escapable types need annotations
111-
to describe their lifetime contracts via [lifetimebound](https://clang.llvm.org/docs/AttributeReference.html#id11)
114+
to describe their lifetime contracts via [lifetimebound](https://clang.llvm.org/docs/AttributeReference.html#id8)
112115
and [lifetime_capture_by](https://clang.llvm.org/docs/AttributeReference.html#lifetime-capture-by) annotations.
113116
114117
```c++
@@ -139,7 +142,7 @@ func getFileName(_ normalizedPath: borrowing std.string) -> StringRef {
139142
}
140143
```
141144

142-
Or we could return an `Escapable` value like `std.string` instead of a dangling `StringRef`:
145+
Or we could construct and return an `Escapable` value like `std.string` instead of a dangling `StringRef`:
143146

144147
```swift
145148
func getFileName(_ path: borrowing std.string) -> std.string {
@@ -149,8 +152,8 @@ func getFileName(_ path: borrowing std.string) -> std.string {
149152
}
150153
```
151154

152-
After annotating the C++ code, the Swift compiler can enforce the lifetime
153-
contracts helping us to write code that is free of memory safety errors.
155+
After annotating the C++ code, the Swift compiler can enforce those lifetime
156+
contracts and help us to write code that is free of memory safety errors.
154157

155158
## Escapability Annotations in Detail
156159

@@ -176,10 +179,10 @@ struct SWIFT_ESCAPABLE Owner { ... };
176179
```
177180

178181
The main reason for explicitly annotating a type as `SWIFT_ESCAPABLE` is to make sure
179-
it is considered as a safe type when used from Swift. Functions returning escapable
182+
it is considered a safe type when used from Swift. Functions returning escapable
180183
types do not need lifetime annotations.
181184

182-
Escapability annotations can also be attached to types via API Notes:
185+
Escapability annotations can also be attached to types via [API Notes](https://clang.llvm.org/docs/APINotes.html):
183186

184187
```
185188
Tags:
@@ -244,7 +247,7 @@ Swift.
244247
The `lifetimebound` attribute on a function parameter or implicit object parameter
245248
indicates that the returned object's lifetime could end when any of the `lifetimebound`
246249
annotated parameters' lifetime ended.
247-
This annotation a constructor describes the lifetime of the created object:
250+
Annotating the parameters of a constructor describes the lifetime of the created object:
248251
249252
```c++
250253
struct SWIFT_NONESCAPABLE View {
@@ -276,8 +279,10 @@ In case the attribute is applied to a subset of the parameters, the return
276279
value might depend on the corresponding arguments:
277280

278281
```c++
279-
View getOneOfTheViews(const Owner& owner1 [[clang::lifetimebound]], const Owner& owner2
280-
View view1 [[clang::lifetimebound]], View view2 [[clang::lifetimebound]]) {
282+
View getOneOfTheViews(const Owner& owner1 [[clang::lifetimebound]],
283+
const Owner& owner2,
284+
View view1 [[clang::lifetimebound]],
285+
View view2 [[clang::lifetimebound]]) {
281286
if (coinFlip)
282287
return View(&owner1.data);
283288
if (coinFlip)
@@ -287,8 +292,7 @@ View getOneOfTheViews(const Owner& owner1 [[clang::lifetimebound]], const Owner&
287292
}
288293
```
289294
290-
Here, the returned `View`'s lifetime depends on `owner`, `view1`, and `view2` but it cannot
291-
depend on `owner2`.
295+
Here, the returned `View`'s lifetime depends on `owner`, `view1`, and `view2` but not on `owner2`.
292296
293297
Occasionally, a function might return a non-escapable type that has no dependency on any other values.
294298
These types might point to static data or might represent an empty sequence or lack of data.
@@ -302,7 +306,7 @@ View returnsEmpty() SWIFT_RETURNS_INDEPENDENT_VALUE {
302306

303307
Notably, the default constructor of a type is always assumed to create an independent value.
304308

305-
We can also annotate `lifetimebound` APIs via APINotes. The `-1` index represents the `this` position.
309+
We can also attach `lifetimebound` annotations to C and C++ APIs using [API Notes](https://clang.llvm.org/docs/APINotes.html). The `-1` index represents the `this` position.
306310

307311
```
308312
Tags:
@@ -321,7 +325,7 @@ Tags:
321325
Note that APINotes have some limitations around C++, they do not support overloaded functions.
322326

323327
While `lifetimebound` always describes the lifetime dependencies of the return value (or
324-
the constructed object in case of constructors), we can use can use `lifetime_capture_by`
328+
the constructed object in case of constructors), we can use can use the [`lifetime_capture_by`](https://clang.llvm.org/docs/AttributeReference.html#lifetime-capture-by)
325329
annotation to describe the lifetime of other output values, like output/inout arguments
326330
or globals.
327331

@@ -334,8 +338,8 @@ void copyView(View view1 [[clang::lifetime_capture_by(view2)]], View &view2) {
334338
In this example, `view2` will have get all of the lifetime dependencies of `view1`
335339
after a call to `copyView`. a
336340
337-
We can annotate dependency captured by the implicit `this` object, or
338-
an inout argument capturing `this`:
341+
We can use this annotation to specify that a parameter's lifetime dependencies are captured by the implicit `this` object, or
342+
conversely, that an inout argument captures the lifetime dependencies of `this`:
339343
340344
```c++
341345
struct SWIFT_NONESCAPABLE CaptureView {
@@ -351,18 +355,19 @@ struct SWIFT_NONESCAPABLE CaptureView {
351355
};
352356
```
353357

354-
All of the non-escapable inputs need lifetime annotations for a function to be
358+
All of the non-escapable arguments need lifetime annotations for a function to be
355359
considered safe. If an input never escapes from the called function we can use
356360
the `noescape` annotation:
357361

358362
```c++
359363
void is_palindrome(std::span<int> s [[clang::noescape]]);
360364
```
361365
362-
While the annotations in this section are powerful, they cannot express all of
363-
the lifetime contracts. APIs with inexpressible contracts can be used from Swift,
364-
but they are imported as unsafe APIs and need extra care from the developers
365-
to manually guarantee safety.
366+
The lifetime annotations presented in this sections are powerful,
367+
but there are still lifetime contracts that they cannot express.
368+
APIs with such contracts can still be used from Swift,
369+
but they are imported as unsafe APIs, so that developers are aware
370+
that they need to take extra care when using these APIs to avoid memory safety violations.
366371
367372
## Convenience Overloads for Annotated Spans and Pointers
368373

0 commit comments

Comments
 (0)