Skip to content

Commit c19ab8c

Browse files
authored
Merge pull request #44 from stlab/sean-parent/algorithms
Sean parent/algorithms
2 parents ac444d6 + e99e321 commit c19ab8c

File tree

9 files changed

+646
-10
lines changed

9 files changed

+646
-10
lines changed

.vscode/settings.json

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
{
2-
"grammarly.selectors": [
3-
{
4-
"language": "markdown",
5-
"scheme": "file"
6-
}
7-
],
82
"rewrap.autoWrap.enabled": true,
93
"rewrap.wrappingColumn": 80,
104
"cSpell.words": [
5+
"deinit",
6+
"deinitialization",
7+
"discardability",
118
"footgun",
129
"Gitter",
10+
"inout",
1311
"irreflexivity",
14-
"preorder"
15-
]
16-
}
12+
"postconditions",
13+
"preorder",
14+
"Subrange",
15+
"subranges",
16+
"unencapsulated"
17+
],
18+
"cmake.ignoreCMakeListsMissing": true
19+
}

.vscode/tasks.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "Open in Notepad",
6+
"type": "shell",
7+
"command": "notepad",
8+
"args": [
9+
"${file}"
10+
],
11+
"presentation": {
12+
"reveal": "never",
13+
"panel": "shared"
14+
},
15+
"problemMatcher": []
16+
}
17+
]
18+
}

better-code/book.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ build-dir = "book"
1010

1111
[output.html]
1212
git-repository-url = "https://github.com/stlab/better-code"
13-
edit-url-template = "https://github.com/stlab/better-code/edit/main/better-code/src/{path}"
13+
edit-url-template = "https://github.com/stlab/better-code/edit/main/better-code/{path}"
1414
site-url = "/better-code/"
1515
cname = "stlab.github.io"
1616

better-code/js/mathjax-config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* Must load before MathJax runs */
2+
if (window.MathJax && window.MathJax.Hub) {
3+
MathJax.Hub.Config({
4+
"HTML-CSS": {
5+
availableFonts: [], // do not try local STIX
6+
webFont: "TeX", // download TeX webfonts
7+
imageFont: null
8+
}
9+
});
10+
}
9.81 KB
Loading
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
## Terminology
2+
3+
- **Safety** in engineering is the prevention of harm through system design.
4+
5+
- An **operation** is any executable program or program fragment, from an integer addition to a whole application.
6+
7+
8+
- A **[safety property](https://en.wikipedia.org/wiki/Safety_and_liveness_properties)** is the *impossibility* of some occurrence when an operation is used correctly. For example, this function upholds the safety property that nothing is printed to the console:
9+
10+
```swift
11+
/// Returns `x`.
12+
///
13+
/// - Precondition: `x >= 0`
14+
func identity(_ x: Int) -> Int {
15+
if x < 0 { print("Precondition violated!") }
16+
return x
17+
}
18+
```
19+
To be a safety property, it must *compose*. That is, when any two operations *P* and *Q* uphold the property, so does *P* followed by *Q*. For example, freedom from data races is a safety property, but freedom from logical races is not, because when two consecutive non-racy mutations are composed into a larger mutation, another thread can observe the partially mutated state between the two steps.
20+
21+
- A **[liveness property](https://en.wikipedia.org/wiki/Safety_and_liveness_properties)** is the *guarantee* of some occurrence when an operation is used correctly. For example, this function upholds the liveness property that it eventually returns:
22+
23+
```swift
24+
/// Returns `x`.
25+
///
26+
/// - Precondition: `x >= 0`
27+
func identity2(_ x: Int) -> Int {
28+
while x < 0 { /* loop forever */ }
29+
return x
30+
}
31+
```
32+
33+
- An ***X* safe operation** upholds some safety property *X* **even if preconditions are violated**. [^qualification] For example, when `a` is an array, `a[0] = 3` never modifies a variable not mentioned in the expression, even if `a` is empty (which violates the precondition of `a[0]`). We might say that the operation is “expression-mutation safe.”
34+
35+
[^qualification]: note this important distinction—an operation can uphold the memory safety property but not be memory-safe by this definition, because the former depends on preconditions being satisfied but the latter does not.
36+
37+
- An ***X* safe language** is one where all primitive operations are *X safe*. It follows that all non-primitive operations—and all possible programs in the language—are *X safe*. A language subset, such as “Swift programs in which no identifier contains the substring `Unsafe` or `unsafe`,” can be considered a language.
38+
39+
- **Memory safety**: the property that invalid memory operations such as out-of-bounds accesses and use-after-free do not occur.
40+
41+
- **Type safety**: the property that an instance of one type is never accessed as an instance of another type.
42+
43+
- **Thread safety**: the property that a data race does not occur. Sometimes “thread safe” is used to mean that, additionally, deadlock does not occur. Freedom from deadlock can also be viewed as part of a liveness property guaranteeing forward progress.
44+
45+
- **Data race safety**: the property that a data race does not occur (explicitly excluding freedom from deadlock as a constraint).
46+
47+
- **Undefined behavior** is not bounded by any constraints and thus nullifies every safety property. An operation that can have undefined behavior, or a language that includes such an operation, is never *X* safe for any *X*.
48+
49+
Violations of memory safety, type safety, and data race safety have effects that can't be usefully described in terms of any portable programming language. For example, the effects of an out-of-bounds write can be understood when memory is viewed as a linear collection of bytes, but can't be described in terms of distinct variables and constants of many types. Therefore, in unsafe programming languages, these violations typically cause undefined behavior.[^java-data-race]
50+
51+
- A **safe operation** will never exhibit undefined behavior, even if preconditions are violated. Safety is often a consequence of type checking (you can't access `x.5` when `x` is a 2-element tuple), but sometimes runtime checks are needed, as when indexing a variable-length array. “Trapping” or otherwise stopping the program when preconditions are violated is one way to achieve safety.
52+
53+
- A **safe language** (such as Java or Haskell) has only safe operations, so all possible programs in the language are safe. The distinction is important because proving a safety property of arbitrary code is tedious and sometimes very difficult, unless—as with a safe language—all code is safe by construction.
54+
55+
- In practice, “**memory-safe language**” is synonymous with “safe language.” Since undefined behavior invalidates all guarantees (including memory safety), a memory-safe language can have no undefined behavior and is therefore a safe language. Because the behavior of a memory safety violation can't be defined at the language level, any language without undefined behavior must be memory safe.
56+
57+
- A **safe-by-default language** (such as Swift or Rust) contains a minority of unsafe operations that can be easily recognized by tooling and banned or flagged for extra scrutiny in code review. This arrangement provides unconditional safety in most code while allowing the direct use of primitive operations such as pointer dereferencing, without expensive validity checks. When unsafe operations are used correctly in the implementation details of safe abstractions, the vocabulary of safe operations grow, with little compromise to overall security. Safe-by-default languages are often referred to as “memory safe” despite the availability of operations that can compromise memory safety.
58+
59+
- The **safe subset of a safe-by-default language** is a safe language.
60+
61+
[^java-data-race]: Some languages, such as Java and JavaScript, define the behavior of data races, but in such a way as to be useless for most programming.
62+
63+
64+
----
65+
66+
In Lamport’s framework, safety is defined semantically—as a prefix‑closed set of behaviors—but this definition alone does not guarantee compositionality under functional composition. As Abadi and Lamport show in Composing Specifications, and as later clarified by Abadi and Plotkin’s work on refinement‑preserving transformations, safety properties become compositional only when the functions involved are themselves safety‑preserving. In other words, from the fact that a safety property p holds for f(x) and for g(x), nothing follows about p(f(g(x))) unless f and g each preserve p. This distinction—emphasized in surveys such as Freiling and Santen’s work on compositional reasoning—makes clear that prefix‑closure characterizes the semantic nature of safety, while congruence under composition requires an additional structural assumption about the operators acting on behaviors.
67+
68+
preserving.dvi
69+
https://lamport.org/pubs/abadi-preserving.pdf
70+
lamport.org
71+
72+
73+
99583.99626
74+
https://dlnext.acm.org/doi/pdf/10.1145/99583.99626
75+
dlnext.acm.org
76+
77+
78+
On the Composition of Compositional Reasoning | Springer Nature Link
79+
https://link.springer.com/chapter/10.1007/11786160_8
80+
link.springer.com
81+
82+
https://lamport.azurewebsites.net/pubs/abadi-composing.pdf

better-code/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
- [Introduction](./chapter-1-introduction.md)
44
- [Contracts](./chapter-2-contracts.md)
55
- [Errors](./chapter-3-errors.md)
6+
- [Algorithms](./chapter-4-algorithms.md)
67
- [Types](./chapter-4-types.md)

0 commit comments

Comments
 (0)