Skip to content

Commit f33f399

Browse files
committed
Address some of Gabor's comments about the merits of unsafe blocks
1 parent a857121 commit f33f399

File tree

1 file changed

+8
-20
lines changed

1 file changed

+8
-20
lines changed

proposals/nnnn-strict-memory-safety.md

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ There are downsides to this approach. It partially undermines the source compati
414414

415415
The attribute `@safe(unchecked)` indicates that a definition is safe despite the use of unsafe constructs in its body. The attribute has no effect on the client, and could effectively be eliminated from the public interface (e.g., documentation, Swift textual interfaces, etc.) without changing how clients behave.
416416

417-
There is an alternative formulation for acknowledging unsafe code that is used in some peer languages like C# and Rust: an `unsafe` block, which is a statement (or expression) that suppresses diagnostics about uses of unsafe code within it. For example, the `sum` example could be written as follows:
417+
There is an alternative formulation for acknowledging unsafe code that is used in some peer languages like C# and Rust: an `unsafe` block, which is a statement that suppresses diagnostics about uses of unsafe code within it. For example, the `sum` example could be written as follows:
418418

419419
```swift
420420
extension Array<Int> {
@@ -428,7 +428,12 @@ extension Array<Int> {
428428
}
429429
```
430430

431-
For Swift, `unsafe` would be a statement that can also be used as an expression when its body is an expression, much like `if` or `switch` expressions following [SE-0380](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md).
431+
For Swift, an `unsafe` block would be a statement that can also be used as an expression when its body is an expression, much like `if` or `switch` expressions following [SE-0380](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md).
432+
433+
`unsafe` blocks have some advantages over the proposed `@safe(unchecked)` attribute, including:
434+
435+
* They can be limited to smaller amounts of code than a whole function, which can make auditing for the unsafe parts of a function easier.
436+
* The `unsafe` blocks are more clearly part of the implementation of a function, not the interface.
432437

433438
This proposal suggests the `@safe(unchecked)` attribute instead of `unsafe` blocks for a few reasons, but the choice is effectively arbitrary: either syntax will work with the rest of this proposal. Some of the reasons for preferring `@safe(unchecked)` include:
434439

@@ -443,24 +448,7 @@ This proposal suggests the `@safe(unchecked)` attribute instead of `unsafe` bloc
443448

444449
* The `unsafe` blocks end up adding another level of nesting, which also means that introducing them to silence warnings causes unnecessarily large amount of code change when adopting the feature.
445450

446-
* The `unsafe` blocks aren't a natural boundary between unsafe and safe code in the same way as a function boundary, because there is no place to state the expected invariants. Combined with pressure to make `unsafe` blocks have as little code as possible (as a proxy for that code being safer), it becomes easy for "minimizing the amount of code in unsafe blocks" to introduce more safety problems. For example, `sum` might be incorrectly factored as follows:
447-
448-
```swift
449-
extension Array<Int> {
450-
func sum() -> Int {
451-
let (ptr, count) = unsafe {
452-
withUnsafeBufferPointerSimplified { buffer in
453-
(buffer.baseAddress, buffer.count)
454-
}
455-
}
456-
return unsafe { c_library_sum_function(ptr, count, 0) }
457-
}
458-
}
459-
```
460-
461-
Here, the base address pointer has escaped the `withUnsafeBufferPointerSimplified` block, causing a member safety problem that wouldn't have been there before. If we tried to do this kind of factoring with the `@safe(unchecked)` approach, the intermediate function producing the pointer would have to be marked `@unsafe`.
462-
463-
451+
* `@safe(unchecked)` can be used in places that aren't executable code, such as protocol conformances.
464452

465453
### Strictly-safe-by-default
466454

0 commit comments

Comments
 (0)