Skip to content

Commit

Permalink
Rust 2024: update Ch. 20 for new unsafe rules
Browse files Browse the repository at this point in the history
- `extern` now requires `unsafe extern`, but in turn allows functions
  within it to be marked as `safe`. Add examples to both effects within
  the text, and update listing numbers accordingly.
- `#[no_mangle]` now requires `#[unsafe(no_mangle)]`

These are all backwards-compatible, so we can opt the chapter into using
the new rules without issue.
  • Loading branch information
chriskrycho committed Nov 22, 2024
1 parent e16dd73 commit 93d741a
Show file tree
Hide file tree
Showing 60 changed files with 303 additions and 262 deletions.
2 changes: 1 addition & 1 deletion listings/ch20-advanced-features/listing-20-08/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
extern "C" {
unsafe extern "C" {
fn abs(input: i32) -> i32;
}

Expand Down
6 changes: 4 additions & 2 deletions listings/ch20-advanced-features/listing-20-09/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
static HELLO_WORLD: &str = "Hello, world!";
unsafe extern "C" {
safe fn abs(input: i32) -> i32;
}

fn main() {
println!("name is: {HELLO_WORLD}");
println!("Absolute value of -3 according to C: {}", abs(-3));
}
15 changes: 2 additions & 13 deletions listings/ch20-advanced-features/listing-20-10/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
static mut COUNTER: u32 = 0;

/// SAFETY: Calling this from more than a single thread at a time is undefined
/// behavior, so you *must* guarantee you only call it from a single thread at
/// a time.
unsafe fn add_to_count(inc: u32) {
COUNTER += inc;
}
static HELLO_WORLD: &str = "Hello, world!";

fn main() {
unsafe {
// SAFETY: This is only called from a single thread in `main`.
add_to_count(3);
println!("COUNTER: {}", COUNTER);
}
println!("name is: {HELLO_WORLD}");
}
19 changes: 13 additions & 6 deletions listings/ch20-advanced-features/listing-20-11/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
unsafe trait Foo {
// methods go here
}
static mut COUNTER: u32 = 0;

unsafe impl Foo for i32 {
// method implementations go here
/// SAFETY: Calling this from more than a single thread at a time is undefined
/// behavior, so you *must* guarantee you only call it from a single thread at
/// a time.
unsafe fn add_to_count(inc: u32) {
COUNTER += inc;
}

fn main() {}
fn main() {
unsafe {
// SAFETY: This is only called from a single thread in `main`.
add_to_count(3);
println!("COUNTER: {}", COUNTER);
}
}
2 changes: 1 addition & 1 deletion listings/ch20-advanced-features/listing-20-12/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion listings/ch20-advanced-features/listing-20-12/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "traits-example"
name = "unsafe-example"
version = "0.1.0"
edition = "2021"

Expand Down
5 changes: 0 additions & 5 deletions listings/ch20-advanced-features/listing-20-12/src/lib.rs

This file was deleted.

9 changes: 9 additions & 0 deletions listings/ch20-advanced-features/listing-20-12/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
unsafe trait Foo {
// methods go here
}

unsafe impl Foo for i32 {
// method implementations go here
}

fn main() {}
6 changes: 4 additions & 2 deletions listings/ch20-advanced-features/listing-20-13/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub trait Iterator<T> {
fn next(&mut self) -> Option<T>;
pub trait Iterator {
type Item;

fn next(&mut self) -> Option<Self::Item>;
}
3 changes: 3 additions & 0 deletions listings/ch20-advanced-features/listing-20-14/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub trait Iterator<T> {
fn next(&mut self) -> Option<T>;
}
31 changes: 0 additions & 31 deletions listings/ch20-advanced-features/listing-20-16/src/main.rs

This file was deleted.

9 changes: 3 additions & 6 deletions listings/ch20-advanced-features/listing-20-17/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ANCHOR: here
trait Pilot {
fn fly(&self);
}
Expand Down Expand Up @@ -25,10 +26,6 @@ impl Human {
println!("*waving arms furiously*");
}
}

// ANCHOR: here
fn main() {
let person = Human;
person.fly();
}
// ANCHOR_END: here

fn main() {}
2 changes: 0 additions & 2 deletions listings/ch20-advanced-features/listing-20-18/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ impl Human {
// ANCHOR: here
fn main() {
let person = Human;
Pilot::fly(&person);
Wizard::fly(&person);
person.fly();
}
// ANCHOR_END: here
6 changes: 4 additions & 2 deletions listings/ch20-advanced-features/listing-20-19/output.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.54s
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.46s
Running `target/debug/traits-example`
A baby dog is called a Spot
This is your captain speaking.
Up!
*waving arms furiously*
35 changes: 25 additions & 10 deletions listings/ch20-advanced-features/listing-20-19/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
trait Animal {
fn baby_name() -> String;
trait Pilot {
fn fly(&self);
}

struct Dog;
trait Wizard {
fn fly(&self);
}

struct Human;

impl Pilot for Human {
fn fly(&self) {
println!("This is your captain speaking.");
}
}

impl Dog {
fn baby_name() -> String {
String::from("Spot")
impl Wizard for Human {
fn fly(&self) {
println!("Up!");
}
}

impl Animal for Dog {
fn baby_name() -> String {
String::from("puppy")
impl Human {
fn fly(&self) {
println!("*waving arms furiously*");
}
}

// ANCHOR: here
fn main() {
println!("A baby dog is called a {}", Dog::baby_name());
let person = Human;
Pilot::fly(&person);
Wizard::fly(&person);
person.fly();
}
// ANCHOR_END: here
19 changes: 3 additions & 16 deletions listings/ch20-advanced-features/listing-20-20/output.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--> src/main.rs:20:43
|
2 | fn baby_name() -> String;
| ------------------------- `Animal::baby_name` defined here
...
20 | println!("A baby dog is called a {}", Animal::baby_name());
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
help: use the fully-qualified path to the only available implementation
|
20 | println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
| +++++++ +

For more information about this error, try `rustc --explain E0790`.
error: could not compile `traits-example` (bin "traits-example") due to 1 previous error
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.54s
Running `target/debug/traits-example`
A baby dog is called a Spot
4 changes: 1 addition & 3 deletions listings/ch20-advanced-features/listing-20-20/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ impl Animal for Dog {
}
}

// ANCHOR: here
fn main() {
println!("A baby dog is called a {}", Animal::baby_name());
println!("A baby dog is called a {}", Dog::baby_name());
}
// ANCHOR_END: here
19 changes: 16 additions & 3 deletions listings/ch20-advanced-features/listing-20-21/output.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.48s
Running `target/debug/traits-example`
A baby dog is called a puppy
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--> src/main.rs:20:43
|
2 | fn baby_name() -> String;
| ------------------------- `Animal::baby_name` defined here
...
20 | println!("A baby dog is called a {}", Animal::baby_name());
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
help: use the fully-qualified path to the only available implementation
|
20 | println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
| +++++++ +

For more information about this error, try `rustc --explain E0790`.
error: could not compile `traits-example` (bin "traits-example") due to 1 previous error
2 changes: 1 addition & 1 deletion listings/ch20-advanced-features/listing-20-21/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ impl Animal for Dog {

// ANCHOR: here
fn main() {
println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
println!("A baby dog is called a {}", Animal::baby_name());
}
// ANCHOR_END: here
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.46s
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.48s
Running `target/debug/traits-example`
This is your captain speaking.
Up!
*waving arms furiously*
A baby dog is called a puppy
32 changes: 19 additions & 13 deletions listings/ch20-advanced-features/listing-20-22/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
// ANCHOR: here
use std::fmt;
trait Animal {
fn baby_name() -> String;
}

struct Dog;

trait OutlinePrint: fmt::Display {
fn outline_print(&self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {output} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
impl Dog {
fn baby_name() -> String {
String::from("Spot")
}
}

impl Animal for Dog {
fn baby_name() -> String {
String::from("puppy")
}
}
// ANCHOR_END: here

fn main() {}
// ANCHOR: here
fn main() {
println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
}
// ANCHOR_END: here
21 changes: 12 additions & 9 deletions listings/ch20-advanced-features/listing-20-23/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// ANCHOR: here
use std::fmt;

struct Wrapper(Vec<String>);

impl fmt::Display for Wrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
trait OutlinePrint: fmt::Display {
fn outline_print(&self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {output} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}
// ANCHOR_END: here

fn main() {
let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {w}");
}
fn main() {}
2 changes: 1 addition & 1 deletion listings/ch20-advanced-features/listing-20-24/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion listings/ch20-advanced-features/listing-20-24/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "types-example"
name = "traits-example"
version = "0.1.0"
edition = "2021"

Expand Down
22 changes: 10 additions & 12 deletions listings/ch20-advanced-features/listing-20-24/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
fn main() {
// ANCHOR: here
let f: Box<dyn Fn() + Send + 'static> = Box::new(|| println!("hi"));
use std::fmt;

fn takes_long_type(f: Box<dyn Fn() + Send + 'static>) {
// --snip--
}
struct Wrapper(Vec<String>);

fn returns_long_type() -> Box<dyn Fn() + Send + 'static> {
// --snip--
// ANCHOR_END: here
Box::new(|| ())
// ANCHOR: here
impl fmt::Display for Wrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
// ANCHOR_END: here
}

fn main() {
let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {w}");
}
Loading

0 comments on commit 93d741a

Please sign in to comment.