Skip to content

Commit ce8b4bd

Browse files
committed
SE-0458: Allow @safe declarations to subsume some responsibility for their arguments
1 parent 4c7c8a3 commit ce8b4bd

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

proposals/0458-strict-memory-safety.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ extension UnsafeMutableBufferPointer {
125125
@unsafe public func swapAt(_ i: Index, _ j: Index) {
126126
guard i != j else { return }
127127
precondition(i >= 0 && j >= 0)
128-
precondition(unsafe i < endIndex && j < endIndex)
128+
precondition(i < endIndex && j < endIndex)
129129
let pi = unsafe (baseAddress! + i)
130130
let pj = unsafe (baseAddress! + j)
131131
let tmp = unsafe pi.move()
@@ -217,7 +217,7 @@ There are a few exemptions to the rule that any unsafe constructs within the sig
217217

218218
### `@safe` attribute
219219

220-
Like the `@unsafe` attribute, the `@safe` attribute ise used on declarations whose signatures involve unsafe types. However, the `@safe` attribute means that the declaration is consider safe to use even though its signature includes unsafe types. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those particular operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`:
220+
Like the `@unsafe` attribute, the `@safe` attribute is used on declarations whose signatures involve unsafe types. However, the `@safe` attribute means that the declaration is consider safe to use even though its signature includes unsafe types. For example, marking `UnsafeBufferPointer` as `@unsafe` means that all operations involving an unsafe buffer pointer are implicitly considered `@unsafe`. The `@safe` attribute can be used to say that those particular operations are actually safe. For example, any operation involving buffer indices or count are safe, because they don't touch the memory itself. This can be indicated by marking these APIs `@safe`:
221221

222222
```swift
223223
extension UnsafeBufferPointer {
@@ -249,6 +249,20 @@ extension Array<Int> {
249249
}
250250
```
251251

252+
The `@safe` annotation on a declaration takes responsibility for its direct arguments, so (for example) a variable of unsafe type used as an argument to a `@safe` function (or as the `self` for a property or subscript reference) will not be diagnosed as unsafe:
253+
254+
```swift
255+
extension Array<Int> {
256+
func sum() -> Int {
257+
withUnsafeBufferPointer { buffer in
258+
let count = buffer.count // count is `@safe`, no diagnostic even though 'buffer' has unsafe type
259+
let address = buffer.baseAddress // warning: 'buffer' and 'baseAddress' are both unsafe
260+
c_library_sum_function(address, count, 0) // warning: 'c_library_sum_function' and 'address' are both unsafe
261+
}
262+
}
263+
}
264+
```
265+
252266
### `unsafe` expression
253267

254268
When a declaration is marked `@unsafe`, it is free to use any other unsafe types as part of its interface. Any time there is executable code that makes use of unsafe constructs, that code must be within an `unsafe` expression or it will receive a diagnostic about uses of unsafe code. In the example from the previous section, `wrapper` can be marked as `@unsafe` to suppress diagnostics by explicitly propagating unsafety to their clients:

0 commit comments

Comments
 (0)