Skip to content

Commit ee09e8a

Browse files
committed
Infer @unsafe on imported C structs/enums/classes/unions with pointers in them
1 parent 694d95a commit ee09e8a

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

proposals/0458-strict-memory-safety.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,66 @@ This repeated `unsafe` also occurs with the other effects: if an `async throws`
447447
for try await x in try await getAsyncSequence() { ... }
448448
```
449449

450+
### C(++) interoperability
451+
452+
The C family of languages does not provide an equivalent to the strict safety mode described in this proposal, and unlike Swift, the defaults tend to be unsafe along all of the dimensions of memory safety. C(++) libriaries used within Swift can, therefore, introduce memory safety issues into the Swift code.
453+
454+
The primary issue with memory safety in C(++) concerns the presence of pointers. C(++) pointers will generally be imported into Swift as an `Unsafe*Pointer` type of some form. For C functions (and C++ member functions), that means that a potentially unsafe API such as
455+
456+
```swift
457+
char *strstr(const char * haystack, const char *needle);
458+
```
459+
460+
will be treated as implicitly `@unsafe` in Swift because its signature contains unsafe types:
461+
462+
```swift
463+
func strstr(
464+
_ haystack: UnsafePointer<CChar>?,
465+
_ needle: UnsafePointer<CChar>?
466+
) -> UnsafeMutablePointer<CChar>?
467+
```
468+
469+
A C function that doesn't use pointer types, on the other hand, will implicitly be considered to be safe, because there are no unsafe types in its Swift signature. For example, the following would be considered safe:
470+
471+
```swift
472+
// int getchar(void);
473+
func getchar() -> CInt
474+
```
475+
476+
C and C++ also have user-defined types in the form of `struct`s, `enum`s, `union`s, and (in C++) `class`es. For such types, this proposal infers them to be `@unsafe` when their non-static data contains any C pointers or C types that are explicitly marked as unsafe. For example, a `Point` struct could be considered safe:
477+
478+
```cpp
479+
struct Point {
480+
double x, y;
481+
};
482+
```
483+
484+
but a `struct` with a pointer or C++ reference in it would be implicitly `@unsafe` in Swift:
485+
486+
```swift
487+
struct ListNode {
488+
void *element;
489+
struct ListNode *next;
490+
};
491+
```
492+
493+
The C attribute `swift_attr` can be used to make specific declarations safe or unsafe, e.g., we could mark a C++ class that manages its internal pointer correctly as being safe, e.g.,
494+
495+
```cpp
496+
class __attribute__((swift_attr("@safe"))) MyString {
497+
char *data;
498+
size_t length;
499+
500+
MyString(const MyString &);
501+
MyString(MyString &&);
502+
MyString &operator=(const MyString&);
503+
MyString &operator=(MyString&&);
504+
~MyString();
505+
};
506+
```
507+
508+
Note that C `enum`s will never be inferred to be `@unsafe` because they don't carry any values other than their underlying integral type, which is always a safe type.
509+
450510
### Strict safety mode and escalatable warnings
451511

452512
The strict memory safety mode can be enabled with the new compiler flag `-strict-memory-safety`.
@@ -770,6 +830,7 @@ We could introduce an optional `message` argument to the `@unsafe` attribute, wh
770830
* **Revision 3 (following second review eextension)**
771831
* Do not require declarations with unsafe types in their signature to be marked `@unsafe`; it is implied. They may be marked `@safe` to indicate that they are actually safe.
772832
* Add `unsafe` for iteration via the `for..in` syntax.
833+
* Add C(++) interoperability section that infers `@unsafe` for C types that involve pointers.
773834

774835
* **Revision 2 (following first review extension)**
775836
* Specified that variables of unsafe type passed in to uses of `@safe` declarations (e.g., calls, property accesses) are not diagnosed as themselves being unsafe. This makes means that expressions like `unsafeBufferePointer.count` will be considered safe.

0 commit comments

Comments
 (0)