You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2026-03-15 00:04:48 +02:00
docs: fix typos and grammar in unsafe deep dive pages (#3022)
Fix grammar, spelling, and capitalization across the Unsafe Rust deep dive chapters. Ran `dprint fmt`. --------- Co-authored-by: Martin Geisler <martin@geisler.net>
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
Uses of `unsafe` in production that may be useful for further study:
|
||||
|
||||
| Case study | Topics |
|
||||
| ------------------------------- | -------------------------------------- |
|
||||
| tokio's [Intrusive Linked List] | UnsafeCell, PhantomData, PhantomPinned |
|
||||
| Case study | Topics |
|
||||
| --------------------------------- | -------------------------------------- |
|
||||
| `tokio`'s [Intrusive Linked List] | UnsafeCell, PhantomData, PhantomPinned |
|
||||
|
||||
[Intrusive Linked List]: case-studies/intrusive-linked-list.md
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
This segment of the class is about the foreign function interface with Rust.
|
||||
|
||||
outline:
|
||||
Outline:
|
||||
|
||||
Start by wrapping a simple C function
|
||||
|
||||
progress into more complex cases which involve pointers and uninitialized memory
|
||||
- Start by wrapping a simple C function.
|
||||
- Progress into more complex cases which involve pointers and uninitialized
|
||||
memory.
|
||||
|
||||
@@ -32,9 +32,9 @@ unsafe extern "C" {
|
||||
}
|
||||
```
|
||||
|
||||
Explain that many POSIX functions are available Rust because cargo links against
|
||||
the C standard library (libc) by default, which makes its symbols into the
|
||||
program’s scope.
|
||||
Explain that many POSIX functions are available in Rust because Cargo links
|
||||
against the C standard library (libc) by default, which brings its symbols into
|
||||
the program’s scope.
|
||||
|
||||
Show `man 3 abs` in the terminal or [a webpage][abs].
|
||||
|
||||
@@ -53,7 +53,7 @@ unsafe extern "C" {
|
||||
|
||||
Discuss rationale: using `ffi::c_int` increases the portability of our code.
|
||||
When the standard library is compiled for the target platform, the platform can
|
||||
determine the widths. According to the C standard, an `c_int` may be defined as
|
||||
determine the widths. According to the C standard, a `c_int` may be defined as
|
||||
an `i16` rather than the much more common `i32`.
|
||||
|
||||
(Optional) Show the [documentation for c_int][c_int] to reveal that it is a type
|
||||
@@ -87,7 +87,8 @@ unsafe extern "C" {
|
||||
}
|
||||
```
|
||||
|
||||
Explain the `safe fn` marks `abs` as safe to call without an `unsafe` block.
|
||||
Explain that the `safe fn` marks `abs` as safe to call without an `unsafe`
|
||||
block.
|
||||
|
||||
Completed program for reference:
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class StringInterner {
|
||||
std::unordered_set<std::string> strings;
|
||||
|
||||
public:
|
||||
// Returns pointer to interned string (valid for lifetime of interner)
|
||||
// Returns a pointer to the interned string (valid for lifetime of interner)
|
||||
const char* intern(const char* s) {
|
||||
auto [it, _] = strings.emplace(s);
|
||||
return it->c_str();
|
||||
|
||||
@@ -14,12 +14,13 @@ minutes: 3
|
||||
|
||||
<details>
|
||||
|
||||
C++ includes a number of features that don’t exist in C with an FFI impact:
|
||||
C++ includes a number of features that don't exist in C with an FFI impact:
|
||||
|
||||
Overloading: overloads become impossible to express because of name mangling
|
||||
Overloading: Overloads become impossible to express because of name mangling
|
||||
|
||||
Exceptions: must catch exceptions at the FFI boundary and convert as escaping
|
||||
exceptions in `extern "C"` functions is undefined behavior
|
||||
Exceptions: Must catch exceptions at the FFI boundary and convert them to error
|
||||
codes, as escaping exceptions in `extern "C"` functions constitute undefined
|
||||
behavior
|
||||
|
||||
Destructors: C callers won't run destructors; must expose explicit `*_destroy()`
|
||||
functions
|
||||
|
||||
@@ -19,17 +19,17 @@ Errors: Must convert `Result` to abide by C conventions; easy to forget to check
|
||||
errors on C side.
|
||||
|
||||
Strings: Conversion cost; null bytes in Rust strings cause truncation; UTF-8
|
||||
validation on ingress
|
||||
validation on ingress.
|
||||
|
||||
Nullability: Every pointer from C must be checked to create an
|
||||
`Option<NonNull<T>>`, implying unsafe blocks or runtime cost
|
||||
`Option<NonNull<T>>`, implying unsafe blocks or runtime cost.
|
||||
|
||||
Ownership: Must document and enforce object lifetimes manually
|
||||
Ownership: Must document and enforce object lifetimes manually.
|
||||
|
||||
Callbacks: Must decompose closures into fn pointer + context; lifetime of
|
||||
context is manual
|
||||
context is manual.
|
||||
|
||||
Panics: Panic across FFI boundary is undefined behavior; must catch at boundary
|
||||
with `catch_unwind`
|
||||
with `catch_unwind`.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -18,7 +18,7 @@ the languages that impact FFI:
|
||||
|
||||
_Trivial relocatability_
|
||||
|
||||
Cannot safely move C++ objects on Rust side; must pin or keep in C++ heap.
|
||||
Cannot safely move C++ objects on the Rust side; must pin or keep in C++ heap.
|
||||
|
||||
In Rust, object movement, which occurs during assignment or by being passed by
|
||||
value, always copies values bit by bit.
|
||||
@@ -35,10 +35,10 @@ Objects with the same semantics are impossible to define in Rust.
|
||||
_Destruction safety_
|
||||
|
||||
Moved-from C++ object semantics don't map; must prevent Rust from "moving" C++
|
||||
types
|
||||
types.
|
||||
|
||||
_Exception safety_
|
||||
|
||||
Neither can cross into the other safely; both must catch at boundary
|
||||
Neither can cross into the other safely; both must catch at the boundary.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -14,13 +14,13 @@ Steps:
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
fn main() {
|
||||
// Step 1: create MaybeUninit
|
||||
// Step 1: Create MaybeUninit
|
||||
let mut uninit = MaybeUninit::uninit();
|
||||
|
||||
// Step 2: write a valid value to the memory
|
||||
// Step 2: Write a valid value to the memory
|
||||
uninit.write(1);
|
||||
|
||||
// Step 3: inform the type system that the memory location is valid
|
||||
// Step 3: Inform the type system that the memory location is valid
|
||||
let init = unsafe { uninit.assume_init() };
|
||||
|
||||
println!("{init}");
|
||||
@@ -29,16 +29,17 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
“To work with uninitialized memory, follow this general workflow: create, write,
|
||||
confirm.”
|
||||
To work with uninitialized memory, follow this general workflow: create, write,
|
||||
confirm.
|
||||
|
||||
“1. Create `MaybeUninit<T>`. The `::uninit()` constructor is the most general
|
||||
purpose one, but there are others which perform a write as well.”
|
||||
1. Create `MaybeUninit<T>`. The `::uninit()` constructor is the most
|
||||
general-purpose one, but there are others which perform a write as well.
|
||||
|
||||
“2. Write a value of T. Notice that this is available from safe Rust. Staying in
|
||||
safe Rust is useful because you must ensure that the value you write is valid.”
|
||||
2. Write a value of T. Notice that this is available from safe Rust. Staying in
|
||||
safe Rust is useful because you must ensure that the value you write is
|
||||
valid.
|
||||
|
||||
“3. Confirm to the type system that the memory is now initialized with the
|
||||
`.assume_init()` method.”
|
||||
3. Confirm to the type system that the memory is now initialized with the
|
||||
`.assume_init()` method.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -53,9 +53,9 @@ When creating a sub-slice of a partially-initialized array, be careful with
|
||||
ownership and correctly implementing drop. Reminder: `MaybeUninit<T>` will not
|
||||
call drop on its `T`.
|
||||
|
||||
`MaybeUninit<[u8;2048]>` is distinct from `[MaybeUninit::<u8>; 2048]` the
|
||||
difference between an array of uninitialized memory and an array that contains
|
||||
uninitialized elements.
|
||||
`MaybeUninit<[u8;2048]>` is distinct from `[MaybeUninit::<u8>; 2048]`. This is
|
||||
the difference between an array of uninitialized memory and an array that
|
||||
contains uninitialized elements.
|
||||
|
||||
- `MaybeUninit<[u8;2048]>` is "all or nothing". You either fully initialize the
|
||||
whole array and then call `assume_init`, or you must keep it as
|
||||
|
||||
@@ -24,7 +24,7 @@ Q: “Although the memory has been written to, the type remains `MaybeUninit<T>`
|
||||
Can anyone think of why?”
|
||||
|
||||
A: Some types require their values to be non-zero or non-null. The classic case
|
||||
is references, but this applies to many other types as well. Consider
|
||||
is references, but this applies to many other types as well. Consider the
|
||||
`NonZeroUsize` integer type and others in its family.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -34,8 +34,8 @@ know how many bytes you'll receive. Using `MaybeUninit<T>` lets you allocate the
|
||||
buffer once without paying for a redundant initialization pass.
|
||||
|
||||
If we were to create the array with the standard syntax (`buf = [0u8; 2048]`),
|
||||
the whole buffer will be flushed with zeroes. `MaybeUninit<T>` tells the
|
||||
compiler to reserve space, but don't touch the memory yet.
|
||||
the whole buffer would be flushed with zeroes. `MaybeUninit<T>` tells the
|
||||
compiler to reserve space, but not to touch the memory yet.
|
||||
|
||||
Q: Which part of the code snippet is performing a similar role to
|
||||
`.assume_init()`? A: The pointer cast and the implicit read.
|
||||
|
||||
@@ -37,9 +37,9 @@ fn main() {
|
||||
|
||||
Code using `unsafe` _might_ be faster.
|
||||
|
||||
`fast_sum()` skips skips bounds checks. However, benchmarking is necessary to
|
||||
validate performance claims. For cases like this, Rust's iterators can usually
|
||||
elide bounds checks anyway.
|
||||
`fast_sum()` skips bounds checks. However, benchmarking is necessary to validate
|
||||
performance claims. For cases like this, Rust's iterators can usually elide
|
||||
bounds checks anyway.
|
||||
|
||||
Optional: [show identical generated assembly][godbolt] for the two functions.
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ The unsafe operations from the [Rust Reference] (Avoid spending too much time):
|
||||
> - Accessing a field of a union, other than to assign to it.
|
||||
> - Calling an `unsafe` function.
|
||||
> - Calling a safe function marked with a `<target_feature>` from a function
|
||||
> that does not have a `<target_feature>` attribute enabling the same features
|
||||
> that does not have a `<target_feature>` attribute enabling the same
|
||||
> features.
|
||||
> - Implementing an unsafe trait.
|
||||
> - Declaring an extern block.
|
||||
> - Applying an unsafe attribute to an item.
|
||||
|
||||
@@ -17,7 +17,7 @@ Enhanced code review
|
||||
|
||||
<details>
|
||||
|
||||
“The unsafe keyword places more responsibility on the programmer, therefore it
|
||||
“The unsafe keyword places more responsibility on the programmer; therefore it
|
||||
requires a stronger development workflow.
|
||||
|
||||
“This class assumes a specific software development workflow where code review
|
||||
|
||||
@@ -24,7 +24,7 @@ the compiler to programmers. It signals that there are preconditions that must
|
||||
be satisfied.
|
||||
|
||||
“To uphold that responsibility, programmers must ensure that they've understood
|
||||
what the preconditions are and that they code will always satisfy them.
|
||||
what the preconditions are and that their code will always satisfy them.
|
||||
|
||||
“Throughout this course, we'll use the term _safety preconditions_ to describe
|
||||
this situation.”
|
||||
|
||||
@@ -34,7 +34,7 @@ defining unsafe functions and unsafe traits.
|
||||
careful.”
|
||||
|
||||
“The creator of the API should communicate what care needs to be taken. Unsafe
|
||||
APIs are not complete without documentation about safety requirements.. Callers
|
||||
APIs are not complete without documentation about safety requirements. Callers
|
||||
need to know that they have satisfied any requirements, and that’s impossible if
|
||||
they’re not written down.”
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Warm up examples
|
||||
# Warm-up examples
|
||||
|
||||
Examples to demonstrate:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Memory Lifecycle
|
||||
|
||||
Memory moves through different phases as objects (values) are created and
|
||||
destroyed
|
||||
destroyed.
|
||||
|
||||
| Memory State | Readable from Safe Rust? |
|
||||
| ------------ | ------------------------ |
|
||||
@@ -11,8 +11,8 @@ destroyed
|
||||
|
||||
<details>
|
||||
|
||||
“This section discusses what it happens as memory from the operating system
|
||||
becomes a valid variable in the program.
|
||||
This section discusses what happens as memory from the operating system becomes
|
||||
a valid variable in the program.
|
||||
|
||||
When memory is available, the operating system has provided our program with it.
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
minutes: 1
|
||||
---
|
||||
|
||||
# Why for learning unsafe Rust
|
||||
# Why learn unsafe Rust?
|
||||
|
||||
We know that writing code without the guarantees that Rust provides ...
|
||||
|
||||
> “Use-after-free (UAF), integer overflows, and out of bounds (OOB) reads/writes
|
||||
> comprise 90% of vulnerabilities with OOB being the most common.”
|
||||
>
|
||||
> --— **Jeff Vander Stoep and Chong Zang**, Google.
|
||||
> — **Jeff Vander Stoep and Chong Zhang**, Google.
|
||||
> "[Queue the Hardening Enhancements](https://security.googleblog.com/2019/05/queue-hardening-enhancements.html)"
|
||||
|
||||
... so why is `unsafe` part of the language?
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# pinning
|
||||
# Pinning
|
||||
|
||||
> **Important Note**
|
||||
>
|
||||
> To not add this section to the project's SUMMARY.md yet. Once CLs/PRs to
|
||||
> Do not add this section to the project's SUMMARY.md yet. Once CLs/PRs to
|
||||
> accept all the new segments for the Unsafe Deep Dive have been included in the
|
||||
> repository, an update to SUMMARY.md will be made.
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ that implements `Deref`.
|
||||
|
||||
However, `Pin::new()` only accepts types that dereference into a target that
|
||||
implements `Unpin` (`Deref<Target: Unpin>`). This allows `Pin` to rely on the
|
||||
the type system to enforce its guarantees.
|
||||
type system to enforce its guarantees.
|
||||
|
||||
Types that do not implement `Unpin`, i.e. types that require pinning, must
|
||||
Types that do not implement `Unpin`, i.e., types that require pinning, must
|
||||
create a `Pin` via the unsafe `Pin::new_unchecked()`.
|
||||
|
||||
Aside: Unlike other `new()`/`new_unchecked()` method pairs, `new` does not do
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
minutes: 5
|
||||
---
|
||||
|
||||
# Worked example Implementing `Drop` for `!Unpin` types
|
||||
# Worked Example: Implementing `Drop` for `!Unpin` types
|
||||
|
||||
```rust,editable,ignore
|
||||
use std::cell::RefCell;
|
||||
@@ -67,7 +67,7 @@ telemetry or logging.
|
||||
`self.data` in an invalid state. `self.data` will be dropped again at the end of
|
||||
the method, which is a double free.
|
||||
|
||||
Ask the class for fix the code.
|
||||
Ask the class to fix the code.
|
||||
|
||||
**Suggestion 0: Redesign**
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
minutes: 10
|
||||
---
|
||||
|
||||
# With Pin<Ptr>
|
||||
# With `Pin<Ptr>`
|
||||
|
||||
Pinning allows Rust programmers to create a type which is much more similar to
|
||||
the C++ class.
|
||||
C++ classes.
|
||||
|
||||
```rust,editable
|
||||
use std::marker::PhantomPinned;
|
||||
|
||||
@@ -63,7 +63,7 @@ Talking points:
|
||||
|
||||
- Emphasize that `unsafe` appears frequently. This is a hint that another design
|
||||
may be more appropriate.
|
||||
- `unsafe` blocks lack of safety comments. Therefore, this code is unsound.
|
||||
- `unsafe` blocks lack safety comments. Therefore, this code is unsound.
|
||||
- `unsafe` blocks are too broad. Good practice uses smaller `unsafe` blocks with
|
||||
specific behavior, specific preconditions and specific safety comments.
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ pub struct SelfReferentialBuffer {
|
||||
class SelfReferentialBuffer {
|
||||
char data[1024];
|
||||
char* cursor;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<details>
|
||||
|
||||
“We've seen many examples of code that has problems in the class, but we lack
|
||||
consistent terminology
|
||||
consistent terminology.
|
||||
|
||||
“The goal of the next section is to introduce some terms that describe many of
|
||||
the concepts that we have been thinking about.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
minutes: 5
|
||||
---
|
||||
|
||||
# 3 shapes of sound Rust
|
||||
# 3 Shapes of Sound Rust
|
||||
|
||||
- Functions written only in Safe Rust
|
||||
- Functions that contain `unsafe` blocks which are impossible to misuse
|
||||
|
||||
@@ -23,7 +23,7 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
“The implementation only uses safe Rust
|
||||
“The implementation only uses safe Rust.
|
||||
|
||||
What can we learn from this?
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ problems.
|
||||
|
||||
“Sound code is made up of _sound functions_ and _sound operations_.
|
||||
|
||||
“A sound function as a function where none of its possible inputs could provoke
|
||||
“A sound function is a function where none of its possible inputs could provoke
|
||||
soundness problems.
|
||||
|
||||
Sound functions have common shapes.
|
||||
|
||||
@@ -12,7 +12,8 @@ satisfied.
|
||||
- Read the definition of sound functions.
|
||||
|
||||
- Remind the students that the programmer who implements the caller is
|
||||
responsible to satisfy the safety precondition, the compiler is not helping.
|
||||
responsible for satisfying the safety precondition; the compiler is not
|
||||
helping.
|
||||
|
||||
- Translate into informal terms. Soundness means that the function is nice and
|
||||
plays by the rules. It documents its safety preconditions, and when the caller
|
||||
|
||||
@@ -16,12 +16,12 @@ Unsound code is _bad_.
|
||||
|
||||
- Read the definition of unsound functions.
|
||||
|
||||
- Translate into infomal terms: unsound code is not nice. No, that's an
|
||||
- Translate into informal terms: unsound code is not nice. No, that's an
|
||||
understatement. Unsound code is BAD. Even if you play by the documented rules,
|
||||
unsound code can still trigger UB!
|
||||
|
||||
- We don't want any unsound code in our repositories.
|
||||
|
||||
- Finding unsound code is the **primary** goal of the code review
|
||||
- Finding unsound code is the **primary** goal of the code review.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -29,7 +29,7 @@ impl<'a> Ascii<'a> {
|
||||
|
||||
"The `Ascii` type is a minimal wrapper around a byte slice. Internally, they
|
||||
share the same representation. However, `Ascii` requires that the high bit must
|
||||
is not be used."
|
||||
not be used."
|
||||
|
||||
Optional: Extend the example to mention that it's possible to use
|
||||
`debug_assert!` to test the preconditions during tests without impacting release
|
||||
|
||||
@@ -38,7 +38,7 @@ Some conditions are even more subtle than they first seem.
|
||||
|
||||
Consider "in-bounds array access". Reading from the memory location, i.e.
|
||||
dereferencing, is not required to break the program. Creating an out-of-bounds
|
||||
reference already break's the compiler's assumptions, leading to erratic
|
||||
reference already breaks the compiler's assumptions, leading to erratic
|
||||
behavior.
|
||||
|
||||
Rust tells LLVM to use its `getelementptr inbounds` assumption. That assumption
|
||||
|
||||
@@ -37,8 +37,8 @@ Highlight Safety section.
|
||||
Click the "convertible to a reference" hyperlink to the "Pointer to reference
|
||||
conversion"
|
||||
|
||||
Track down the rules for converting a pointer to a reference, aka is
|
||||
"_deferencerable_".
|
||||
Track down the rules for converting a pointer to a reference, i.e., whether it
|
||||
is "dereferenceable".
|
||||
|
||||
Consider the implications of this excerpt (Rust 1.90.0) "You must enforce Rust’s
|
||||
aliasing rules. The exact aliasing rules are not decided yet, ..."
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
minutes: 10
|
||||
---
|
||||
|
||||
# Example: references
|
||||
# Example: References
|
||||
|
||||
```rust,editable,ignore
|
||||
fn main() {
|
||||
@@ -24,7 +24,7 @@ Confirm understanding of the syntax
|
||||
enforced without assistance from the compiler.
|
||||
- Note: raw pointers do not provide ownership info to Rust. A pointer can be
|
||||
semantically owning the data, or semantically borrowing, but that
|
||||
information only exists in the programmer's mind
|
||||
information only exists in the programmer's mind.
|
||||
|
||||
- `&mut *boxed as *mut _` expression:
|
||||
- `*boxed` is ...
|
||||
@@ -36,30 +36,30 @@ Confirm understanding of the syntax
|
||||
|
||||
Confirm understanding of ownership
|
||||
|
||||
- Step through code
|
||||
- (Line 3) Creates raw pointer to the `123` by de-referencing the box,
|
||||
creating a new reference and casting the new reference as a pointer
|
||||
- Step through code:
|
||||
- (Line 3) Creates raw pointer to the `123` by dereferencing the box, creating
|
||||
a new reference and casting the new reference as a pointer.
|
||||
- (Line 4) Creates raw pointer with a NULL value
|
||||
- (Line 7) Converts the raw pointer to an Option with `.as_mut()`
|
||||
|
||||
- Highlight that pointers are nullable in Rust (unlike references).
|
||||
|
||||
- Compile to reveal the error messages
|
||||
- Compile to reveal the error messages.
|
||||
|
||||
- Discuss
|
||||
- (Line 6) `println!("{:?}", *a);`
|
||||
- Prefix star dereferences a raw pointer
|
||||
- Prefix star dereferences a raw pointer.
|
||||
- It is an explicit operation. Whereas regular references have implicit
|
||||
dereferencing most of the time thanks to the Deref trait. This is referred
|
||||
to as "auto-deref".
|
||||
- Dereferencing a raw pointer is an unsafe operation
|
||||
- Requires an unsafe block
|
||||
- Dereferencing a raw pointer is an unsafe operation.
|
||||
- Requires an unsafe block.
|
||||
- (Line 7) `println!("{:?}", b.as_mut());`
|
||||
- `as_mut()` is an unsafe function.
|
||||
- Calling unsafe function requires an unsafe block
|
||||
- Calling an unsafe function requires an unsafe block.
|
||||
|
||||
- Demonstrate: Fix the code (add unsafe blocks) and compile again to show the
|
||||
working program
|
||||
working program.
|
||||
|
||||
- Demonstrate: Replace `as *mut i32` with `as *mut _`, show that it compiles.
|
||||
|
||||
@@ -67,7 +67,7 @@ Confirm understanding of ownership
|
||||
that the source of the cast is a `&mut i32`. This reference type can only be
|
||||
converted to one pointer type, `*mut i32`.
|
||||
|
||||
- Add safety comments
|
||||
- Add safety comments:
|
||||
- We said that the unsafe code marks the responsibility shift from the
|
||||
compiler to the programmer.
|
||||
- How do we convey that we thought about our unusual responsibilities while
|
||||
@@ -75,9 +75,9 @@ Confirm understanding of ownership
|
||||
- Safety comments explain why unsafe code is correct.
|
||||
- Without a safety comment, unsafe code is not safe.
|
||||
|
||||
- Discuss: Whether to use one large unsafe block or two smaller ones
|
||||
- Possibility of using a single unsafe block rather than multiple
|
||||
- Using more allows safety comments as specific as possible
|
||||
- Discuss: Whether to use one large unsafe block or two smaller ones:
|
||||
- Possibility of using a single unsafe block rather than multiple.
|
||||
- Using more allows safety comments as specific as possible.
|
||||
|
||||
[ptr-as_mut]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ rustc 1.87
|
||||
TODO (tim): We should be able to avoid this by just relying on the `cc` crate
|
||||
|
||||
We recommend that you install the [Bazel build system](https://bazel.build/install).
|
||||
This will allow you to easily compile project that combine multiple languages.
|
||||
This will allow you to easily compile projects that combine multiple languages.
|
||||
|
||||
-->
|
||||
|
||||
@@ -39,7 +39,7 @@ $ cargo serve # then open http://127.0.0.1:3000/ in a browser
|
||||
<details>
|
||||
|
||||
Ask everyone to confirm that everyone is able to execute `rustc` with a version
|
||||
older that 1.87.
|
||||
newer than 1.87.
|
||||
|
||||
For those people who do not, tell them that we'll resolve that in the break.
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ We’ll work on three areas:
|
||||
|
||||
The goal of this class is to teach you enough Unsafe Rust for you to be able to
|
||||
review easy cases yourself, and distinguish difficult cases that need to be
|
||||
reviewed my more experienced Unsafe Rust engineers.
|
||||
reviewed by more experienced Unsafe Rust engineers.
|
||||
|
||||
- Establishing a mental model of Unsafe Rust
|
||||
- what the `unsafe` keyword means
|
||||
@@ -38,12 +38,12 @@ reviewed my more experienced Unsafe Rust engineers.
|
||||
- common patterns
|
||||
- expectations for code that uses `unsafe`
|
||||
|
||||
- Practice working with unsafe
|
||||
- Practicing working with unsafe
|
||||
- reading and writing both code and documentation
|
||||
- use unsafe APIs
|
||||
- design and implement them
|
||||
- using unsafe APIs
|
||||
- designing and implementing them
|
||||
|
||||
- Review code
|
||||
- Reviewing code
|
||||
- the confidence to self-review easy cases
|
||||
- the knowledge to detect difficult cases
|
||||
|
||||
|
||||
Reference in New Issue
Block a user