From 262987a1e0cc478e30c84f8ea36fc106762c9dea Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:08 +0900 Subject: [PATCH] =?UTF-8?q?ch19=20=E9=AB=98=E5=BA=A6=E3=81=AA=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=81=AE=E5=92=8C=E8=A8=B3=E3=82=92=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E7=89=88=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- .../listing-19-01/Cargo.toml | 3 +- .../listing-19-02/Cargo.toml | 3 +- .../listing-19-03/Cargo.toml | 3 +- .../listing-19-04/Cargo.toml | 3 +- .../listing-19-05/Cargo.toml | 3 +- .../listing-19-05/output.txt | 29 +- .../listing-19-05/src/main.rs | 6 +- .../listing-19-06/Cargo.toml | 3 +- .../listing-19-06/src/main.rs | 6 +- .../listing-19-07/Cargo.toml | 3 +- .../listing-19-07/src/main.rs | 2 +- .../listing-19-08/Cargo.toml | 3 +- .../listing-19-08/src/main.rs | 1 + .../listing-19-09/Cargo.toml | 3 +- .../listing-19-10/Cargo.toml | 3 +- .../listing-19-11/Cargo.toml | 3 +- .../listing-19-11/src/main.rs | 2 + .../listing-19-12/Cargo.toml | 3 +- .../listing-19-13/Cargo.toml | 3 +- .../listing-19-14/Cargo.toml | 3 +- .../listing-19-14/src/main.rs | 2 +- .../listing-19-15/Cargo.toml | 3 +- .../listing-19-16/Cargo.toml | 3 +- .../listing-19-16/src/main.rs | 3 + .../listing-19-17/Cargo.toml | 3 +- .../listing-19-18/Cargo.toml | 3 +- .../listing-19-19/Cargo.toml | 3 +- .../listing-19-19/src/main.rs | 3 + .../listing-19-20/Cargo.toml | 3 +- .../listing-19-20/output.txt | 23 +- .../listing-19-21/Cargo.toml | 3 +- .../listing-19-22/Cargo.toml | 3 +- .../listing-19-23/Cargo.toml | 3 +- .../listing-19-24/Cargo.toml | 3 +- .../listing-19-25/Cargo.toml | 3 +- .../listing-19-27/Cargo.toml | 3 +- .../listing-19-27/src/main.rs | 1 + .../listing-19-28/Cargo.toml | 3 +- .../listing-19-30/Cargo.toml | 3 +- .../listing-19-31/hello_macro/Cargo.toml | 3 +- .../hello_macro/hello_macro_derive/Cargo.toml | 3 +- .../hello_macro/hello_macro_derive/src/lib.rs | 2 - .../hello_macro_derive/src/lib.rs.bak | 17 + .../listing-19-33/hello_macro/Cargo.toml | 3 +- .../hello_macro/hello_macro_derive/Cargo.toml | 3 +- .../hello_macro/hello_macro_derive/src/lib.rs | 2 - .../no-listing-01-unsafe-fn/Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../output.txt | 18 +- .../Cargo.toml | 3 +- .../no-listing-04-kilometers-alias/Cargo.toml | 3 +- .../no-listing-05-write-trait/Cargo.toml | 3 +- .../no-listing-06-result-alias/Cargo.toml | 3 +- .../no-listing-06-result-alias/src/lib.rs | 2 - .../no-listing-07-never-type/Cargo.toml | 3 +- .../no-listing-07-never-type/src/lib.rs | 2 - .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../no-listing-11-cant-create-str/Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../no-listing-15-map-closure/Cargo.toml | 3 +- .../no-listing-16-map-function/Cargo.toml | 3 +- .../no-listing-17-map-initializer/Cargo.toml | 3 +- .../no-listing-18-returns-closure/Cargo.toml | 3 +- .../no-listing-18-returns-closure/output.txt | 30 +- .../Cargo.toml | 3 +- .../hello_macro/Cargo.toml | 3 +- .../pancakes/Cargo.toml | 3 +- .../hello_macro/Cargo.toml | 3 +- .../hello_macro/hello_macro_derive/Cargo.toml | 3 +- .../hello_macro/hello_macro_derive/src/lib.rs | 2 - .../pancakes/Cargo.toml | 3 +- .../Cargo.lock | 0 .../Cargo.toml | 3 +- .../src/lib.rs | 2 - .../output-only-01-missing-unsafe/Cargo.toml | 3 +- .../output-only-01-missing-unsafe/output.txt | 7 +- src/ch19-00-advanced-features.md | 14 +- src/ch19-01-unsafe-rust.md | 465 +++++------- src/ch19-03-advanced-traits.md | 714 +++++++----------- src/ch19-04-advanced-types.md | 352 ++++----- ...ch19-05-advanced-functions-and-closures.md | 181 +++-- src/ch19-06-macros.md | 160 ++-- 86 files changed, 957 insertions(+), 1265 deletions(-) create mode 100644 listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs.bak rename listings/ch19-advanced-features/{listing-13-21-reproduced => no-listing-22-iterator-on-counter}/Cargo.lock (100%) rename listings/ch19-advanced-features/{listing-13-21-reproduced => no-listing-22-iterator-on-counter}/Cargo.toml (50%) rename listings/ch19-advanced-features/{listing-13-21-reproduced => no-listing-22-iterator-on-counter}/src/lib.rs (96%) diff --git a/listings/ch19-advanced-features/listing-19-01/Cargo.toml b/listings/ch19-advanced-features/listing-19-01/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-01/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-02/Cargo.toml b/listings/ch19-advanced-features/listing-19-02/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-02/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-03/Cargo.toml b/listings/ch19-advanced-features/listing-19-03/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-03/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-04/Cargo.toml b/listings/ch19-advanced-features/listing-19-04/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-04/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-05/Cargo.toml b/listings/ch19-advanced-features/listing-19-05/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-05/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-05/output.txt b/listings/ch19-advanced-features/listing-19-05/output.txt index 3df0e2b64..405f779aa 100644 --- a/listings/ch19-advanced-features/listing-19-05/output.txt +++ b/listings/ch19-advanced-features/listing-19-05/output.txt @@ -1,21 +1,22 @@ $ cargo run Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example) -error[E0499]: cannot borrow `*slice` as mutable more than once at a time - --> src/main.rs:6:30 +error[E0499]: cannot borrow `*values` as mutable more than once at a time +(エラー: 一度に2回以上、`*values`を可変で借用できません) + --> src/main.rs:6:31 | -1 | fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { - | - let's call the lifetime of this reference `'1` +1 | fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { + | - let's call the lifetime of this reference `'1` + | (この参照のライフタイムを`'1`とします) ... -6 | (&mut slice[..mid], &mut slice[mid..]) - | -------------------------^^^^^-------- - | | | | - | | | second mutable borrow occurs here +6 | (&mut values[..mid], &mut values[mid..]) + | --------------------------^^^^^^-------- + | | | | + | | | second mutable borrow occurs here + | | | (2回目の可変参照はここで発生します) | | first mutable borrow occurs here - | returning this value requires that `*slice` is borrowed for `'1` - -error: aborting due to previous error + | | (1回目の可変参照はここで発生します) + | returning this value requires that `*values` is borrowed for `'1` + | (この値を返すためには`*values`が`'1`の間借用されていることが必要です) For more information about this error, try `rustc --explain E0499`. -error: could not compile `unsafe-example`. - -To learn more, run the command again with --verbose. +error: could not compile `unsafe-example` (bin "unsafe-example") due to 1 previous error diff --git a/listings/ch19-advanced-features/listing-19-05/src/main.rs b/listings/ch19-advanced-features/listing-19-05/src/main.rs index c4b83effa..dabf63de1 100644 --- a/listings/ch19-advanced-features/listing-19-05/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-05/src/main.rs @@ -1,10 +1,10 @@ // ANCHOR: here -fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { - let len = slice.len(); +fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { + let len = values.len(); assert!(mid <= len); - (&mut slice[..mid], &mut slice[mid..]) + (&mut values[..mid], &mut values[mid..]) } // ANCHOR_END: here diff --git a/listings/ch19-advanced-features/listing-19-06/Cargo.toml b/listings/ch19-advanced-features/listing-19-06/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-06/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-06/src/main.rs b/listings/ch19-advanced-features/listing-19-06/src/main.rs index f25cbf49d..3af21f761 100644 --- a/listings/ch19-advanced-features/listing-19-06/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-06/src/main.rs @@ -1,9 +1,9 @@ // ANCHOR: here use std::slice; -fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { - let len = slice.len(); - let ptr = slice.as_mut_ptr(); +fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { + let len = values.len(); + let ptr = values.as_mut_ptr(); assert!(mid <= len); diff --git a/listings/ch19-advanced-features/listing-19-07/Cargo.toml b/listings/ch19-advanced-features/listing-19-07/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-07/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-07/src/main.rs b/listings/ch19-advanced-features/listing-19-07/src/main.rs index 0ab39ae1d..b4d6cdb7c 100644 --- a/listings/ch19-advanced-features/listing-19-07/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-07/src/main.rs @@ -5,6 +5,6 @@ fn main() { let address = 0x01234usize; let r = address as *mut i32; - let slice: &[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) }; + let values: &[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) }; // ANCHOR_END: here } diff --git a/listings/ch19-advanced-features/listing-19-08/Cargo.toml b/listings/ch19-advanced-features/listing-19-08/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-08/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-08/src/main.rs b/listings/ch19-advanced-features/listing-19-08/src/main.rs index 8b56630c9..d3755040f 100644 --- a/listings/ch19-advanced-features/listing-19-08/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-08/src/main.rs @@ -4,6 +4,7 @@ extern "C" { fn main() { unsafe { + // -3の絶対値は、Cによると{} println!("Absolute value of -3 according to C: {}", abs(-3)); } } diff --git a/listings/ch19-advanced-features/listing-19-09/Cargo.toml b/listings/ch19-advanced-features/listing-19-09/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-09/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-10/Cargo.toml b/listings/ch19-advanced-features/listing-19-10/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-10/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-10/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-11/Cargo.toml b/listings/ch19-advanced-features/listing-19-11/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/listing-19-11/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-11/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-11/src/main.rs b/listings/ch19-advanced-features/listing-19-11/src/main.rs index 885c1aa1d..ca3bcf171 100644 --- a/listings/ch19-advanced-features/listing-19-11/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-11/src/main.rs @@ -1,9 +1,11 @@ unsafe trait Foo { // methods go here + // メソッドがここに来る } unsafe impl Foo for i32 { // method implementations go here + // メソッドの実装がここに来る } fn main() {} diff --git a/listings/ch19-advanced-features/listing-19-12/Cargo.toml b/listings/ch19-advanced-features/listing-19-12/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-12/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-12/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-13/Cargo.toml b/listings/ch19-advanced-features/listing-19-13/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-13/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-13/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-14/Cargo.toml b/listings/ch19-advanced-features/listing-19-14/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-14/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-14/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-14/src/main.rs b/listings/ch19-advanced-features/listing-19-14/src/main.rs index 7dea568d9..9111fbc55 100644 --- a/listings/ch19-advanced-features/listing-19-14/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-14/src/main.rs @@ -1,6 +1,6 @@ use std::ops::Add; -#[derive(Debug, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq)] struct Point { x: i32, y: i32, diff --git a/listings/ch19-advanced-features/listing-19-15/Cargo.toml b/listings/ch19-advanced-features/listing-19-15/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-15/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-15/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-16/Cargo.toml b/listings/ch19-advanced-features/listing-19-16/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-16/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-16/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-16/src/main.rs b/listings/ch19-advanced-features/listing-19-16/src/main.rs index d854e287d..64d9b9ba3 100644 --- a/listings/ch19-advanced-features/listing-19-16/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-16/src/main.rs @@ -11,18 +11,21 @@ struct Human; impl Pilot for Human { fn fly(&self) { + // こちら機長です。 println!("This is your captain speaking."); } } impl Wizard for Human { fn fly(&self) { + // 上がれ! println!("Up!"); } } impl Human { fn fly(&self) { + // *激しく腕を振る* println!("*waving arms furiously*"); } } diff --git a/listings/ch19-advanced-features/listing-19-17/Cargo.toml b/listings/ch19-advanced-features/listing-19-17/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-17/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-17/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-18/Cargo.toml b/listings/ch19-advanced-features/listing-19-18/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-18/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-18/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-19/Cargo.toml b/listings/ch19-advanced-features/listing-19-19/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-19/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-19/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-19/src/main.rs b/listings/ch19-advanced-features/listing-19-19/src/main.rs index 44affe0ee..10a011fde 100644 --- a/listings/ch19-advanced-features/listing-19-19/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-19/src/main.rs @@ -6,16 +6,19 @@ struct Dog; impl Dog { fn baby_name() -> String { + // スポット String::from("Spot") } } impl Animal for Dog { fn baby_name() -> String { + // 子犬 String::from("puppy") } } fn main() { + // 赤ちゃん犬は{}と呼ばれる println!("A baby dog is called a {}", Dog::baby_name()); } diff --git a/listings/ch19-advanced-features/listing-19-20/Cargo.toml b/listings/ch19-advanced-features/listing-19-20/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-20/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-20/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-20/output.txt b/listings/ch19-advanced-features/listing-19-20/output.txt index 46c7dafa0..123884626 100644 --- a/listings/ch19-advanced-features/listing-19-20/output.txt +++ b/listings/ch19-advanced-features/listing-19-20/output.txt @@ -1,19 +1,22 @@ $ cargo run Compiling traits-example v0.1.0 (file:///projects/traits-example) -error[E0283]: type annotations needed +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type +(エラー: 対応する`impl`型を指定せずにトレイト上の関連関数を呼び出すことはできません) --> src/main.rs:20:43 | 2 | fn baby_name() -> String; - | ------------------------- required by `Animal::baby_name` + | ------------------------- `Animal::baby_name` defined here + | (`Animal::baby_name`はここで定義されています) ... 20 | println!("A baby dog is called a {}", Animal::baby_name()); - | ^^^^^^^^^^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | (トレイトの関連関数を呼び出すことができません) | - = note: cannot resolve `_: Animal` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0283`. -error: could not compile `traits-example`. +help: use the fully-qualified path to the only available implementation +(ヘルプ: 利用可能な実装のうち1つを指すフルパスを使用してください) + | +20 | println!("A baby dog is called a {}", ::baby_name()); + | +++++++ + -To learn more, run the command again with --verbose. +For more information about this error, try `rustc --explain E0790`. +error: could not compile `traits-example` (bin "traits-example") due to 1 previous error diff --git a/listings/ch19-advanced-features/listing-19-21/Cargo.toml b/listings/ch19-advanced-features/listing-19-21/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-21/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-21/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-22/Cargo.toml b/listings/ch19-advanced-features/listing-19-22/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-22/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-22/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-23/Cargo.toml b/listings/ch19-advanced-features/listing-19-23/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/listing-19-23/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-23/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-24/Cargo.toml b/listings/ch19-advanced-features/listing-19-24/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/listing-19-24/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-24/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-25/Cargo.toml b/listings/ch19-advanced-features/listing-19-25/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/listing-19-25/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-25/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-27/Cargo.toml b/listings/ch19-advanced-features/listing-19-27/Cargo.toml index 2bed56c36..b196f35b5 100644 --- a/listings/ch19-advanced-features/listing-19-27/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-27/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-27/src/main.rs b/listings/ch19-advanced-features/listing-19-27/src/main.rs index 91b2cf04b..20ab62b18 100644 --- a/listings/ch19-advanced-features/listing-19-27/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-27/src/main.rs @@ -9,5 +9,6 @@ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { fn main() { let answer = do_twice(add_one, 5); + // 答えは: {} println!("The answer is: {}", answer); } diff --git a/listings/ch19-advanced-features/listing-19-28/Cargo.toml b/listings/ch19-advanced-features/listing-19-28/Cargo.toml index 1829b0fa6..9218091c8 100644 --- a/listings/ch19-advanced-features/listing-19-28/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-28/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "macros-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-30/Cargo.toml b/listings/ch19-advanced-features/listing-19-30/Cargo.toml index 5a93a685c..c6fb92087 100644 --- a/listings/ch19-advanced-features/listing-19-30/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-30/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml b/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml index 5a93a685c..c6fb92087 100644 --- a/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml index 168cbae53..aa076ac48 100644 --- a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "hello_macro_derive" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs index 8757a2f77..dddbf62c8 100644 --- a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs +++ b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs @@ -1,5 +1,3 @@ -extern crate proc_macro; - use proc_macro::TokenStream; use quote::quote; use syn; diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs.bak b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs.bak new file mode 100644 index 000000000..8757a2f77 --- /dev/null +++ b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs.bak @@ -0,0 +1,17 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use quote::quote; +use syn; + +#[proc_macro_derive(HelloMacro)] +pub fn hello_macro_derive(input: TokenStream) -> TokenStream { + // 操作可能な構文木としてのRustコードの表現を構築する + // Construct a representation of Rust code as a syntax tree + // that we can manipulate + let ast = syn::parse(input).unwrap(); + + // トレイトの実装内容を構築 + // Build the trait implementation + impl_hello_macro(&ast) +} diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml b/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml index 5a93a685c..c6fb92087 100644 --- a/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml b/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml index 168cbae53..aa076ac48 100644 --- a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml +++ b/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "hello_macro_derive" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs index 591f0c359..dac6c98f6 100644 --- a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs +++ b/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs @@ -1,5 +1,3 @@ -extern crate proc_macro; - use proc_macro::TokenStream; use quote::quote; use syn; diff --git a/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml b/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml b/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt b/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt index e7a028e35..f1333e875 100644 --- a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt +++ b/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt @@ -1,17 +1,21 @@ $ cargo run Compiling traits-example v0.1.0 (file:///projects/traits-example) error[E0277]: `Point` doesn't implement `std::fmt::Display` - --> src/main.rs:20:6 +(エラー: `Point`は`std::fmt::Display`を実装していません) + --> src/main.rs:20:23 | 20 | impl OutlinePrint for Point {} - | ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter + | ^^^^^ `Point` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Point` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - -error: aborting due to previous error +note: required by a bound in `OutlinePrint` +(注釈: `OutlinePrint`境界によって要求されています) + --> src/main.rs:3:21 + | +3 | trait OutlinePrint: fmt::Display { + | ^^^^^^^^^^^^ required by this bound in `OutlinePrint` + | (`OutlinePrint`のこの境界によって要求されています) For more information about this error, try `rustc --explain E0277`. -error: could not compile `traits-example`. - -To learn more, run the command again with --verbose. +error: could not compile `traits-example` (bin "traits-example") due to 1 previous error diff --git a/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml b/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml b/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml b/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml b/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs b/listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs index c53a927e3..573559934 100644 --- a/listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs +++ b/listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs @@ -13,5 +13,3 @@ pub trait Write { fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()>; } // ANCHOR_END: there - -fn main() {} diff --git a/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml b/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml index 1e3df0242..52395a587 100644 --- a/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs b/listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs index 236224186..f0f7acac2 100644 --- a/listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs +++ b/listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs @@ -6,5 +6,3 @@ fn bar() -> ! { // ANCHOR: here } // ANCHOR_END: here - -fn main() {} diff --git a/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml b/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml b/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml b/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml b/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml b/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml b/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml b/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml index 9b4ee689b..a2ae20c77 100644 --- a/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "types-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml b/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml index 2bed56c36..b196f35b5 100644 --- a/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml b/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml index 2bed56c36..b196f35b5 100644 --- a/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml b/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml index 2bed56c36..b196f35b5 100644 --- a/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml b/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml index 2bed56c36..b196f35b5 100644 --- a/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt b/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt index 2d4be9b0a..bc736bd68 100644 --- a/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt +++ b/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt @@ -1,30 +1,20 @@ $ cargo build Compiling functions-example v0.1.0 (file:///projects/functions-example) -error[E0277]: the size for values of type `(dyn std::ops::Fn(i32) -> i32 + 'static)` cannot be known at compilation time +error[E0746]: return type cannot have an unboxed trait object --> src/lib.rs:1:25 | 1 | fn returns_closure() -> dyn Fn(i32) -> i32 { | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn(i32) -> i32 + 'static)` - = note: to learn more, visit - = note: the return type of a function must have a statically known size - -error[E0308]: mismatched types - --> src/lib.rs:2:5 +help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type | -1 | fn returns_closure() -> dyn Fn(i32) -> i32 { - | ------------------ expected `(dyn std::ops::Fn(i32) -> i32 + 'static)` because of return type -2 | |x| x + 1 - | ^^^^^^^^^ expected trait `std::ops::Fn`, found closure +1 | fn returns_closure() -> impl Fn(i32) -> i32 { + | ~~~~ +help: box the return type, and wrap all of the returned values in `Box::new` + | +1 ~ fn returns_closure() -> Box i32> { +2 ~ Box::new(|x| x + 1) | - = note: expected trait object `(dyn std::ops::Fn(i32) -> i32 + 'static)` - found closure `[closure@src/lib.rs:2:5: 2:14]` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. -error: could not compile `functions-example`. -To learn more, run the command again with --verbose. +For more information about this error, try `rustc --explain E0746`. +error: could not compile `functions-example` (lib) due to 1 previous error diff --git a/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml b/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml index 2bed56c36..b196f35b5 100644 --- a/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml b/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml index 5a93a685c..c6fb92087 100644 --- a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml b/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml index 4b6c267b4..3ad910862 100644 --- a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "pancakes" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] hello_macro = { path = "../hello_macro" } \ No newline at end of file diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml index 5a93a685c..c6fb92087 100644 --- a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml index 168cbae53..aa076ac48 100644 --- a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "hello_macro_derive" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs index 7a3279d86..5e0b96c27 100644 --- a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs +++ b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs @@ -1,5 +1,3 @@ -extern crate proc_macro; - use proc_macro::TokenStream; use quote::quote; use syn; diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml b/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml index cc0addaa4..cb3a98c3a 100644 --- a/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "pancakes" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] hello_macro = { path = "../hello_macro" } diff --git a/listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.lock b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.lock rename to listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.toml b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml similarity index 50% rename from listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.toml rename to listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml index 4eb29e80c..9e103f3eb 100644 --- a/listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.toml +++ b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "counter" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/listing-13-21-reproduced/src/lib.rs b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs similarity index 96% rename from listings/ch19-advanced-features/listing-13-21-reproduced/src/lib.rs rename to listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs index b71b54fbc..04c7f38f5 100644 --- a/listings/ch19-advanced-features/listing-13-21-reproduced/src/lib.rs +++ b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs @@ -23,5 +23,3 @@ impl Iterator for Counter { } } } - -fn main() {} diff --git a/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml b/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml index aabe3bdf5..3e8a29201 100644 --- a/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml +++ b/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt b/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt index bfe082a8b..36e1175bb 100644 --- a/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt +++ b/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt @@ -1,6 +1,7 @@ $ cargo run Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example) error[E0133]: call to unsafe function is unsafe and requires unsafe function or block +(エラー: unsafe関数の呼び出しはunsafeであり、unsafeな関数かブロックが必要です) --> src/main.rs:4:5 | 4 | dangerous(); @@ -8,9 +9,5 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error - For more information about this error, try `rustc --explain E0133`. -error: could not compile `unsafe-example`. - -To learn more, run the command again with --verbose. +error: could not compile `unsafe-example` (bin "unsafe-example") due to 1 previous error diff --git a/src/ch19-00-advanced-features.md b/src/ch19-00-advanced-features.md index 48190a7a7..ce33baa36 100644 --- a/src/ch19-00-advanced-features.md +++ b/src/ch19-00-advanced-features.md @@ -7,16 +7,16 @@ 今までに、Rustプログラミング言語の最もよく使われる部分を学んできました。第20章でもう1つ別のプロジェクトを行う前に、 -時折遭遇する言語の側面をいくつか見ましょう。この章は、Rustを使用する際に知らないことに遭遇した時に参考にすることができます。 -この章で使用することを学ぶ機能は、かなり限定的な場面でしか役に立ちません。あまり頻繁には手を伸ばすことがない可能性はありますが、 +時折遭遇するが、毎日は使わないような言語の側面をいくつか見ましょう。この章は、知らないことに遭遇した時に参考にすることができます。 +ここで扱う機能は、かなり限定的な場面でしか役に立ちません。あまり頻繁には手を伸ばすことがない可能性はありますが、 Rustが提供しなければならない機能全ての概要を確かに把握してもらいたいのです。 静的解析は原理的に保守的なので、unsafe Rustが存在します。コードが保証を保持しているかコンパイラが決定しようとする際、 -なんらかの不正なプログラムを受け入れるよりも合法なプログラムを拒否したほうがいいのです。コードは大丈夫かもしれないけれど、 -コンパイラにわかる範囲ではダメなのです!このような場合、unsafeコードを使用してコンパイラに「信じて!何をしているかわかってるよ」と教えられます。 -欠点は、自らのリスクで使用することです: unsafeコードを誤って使用したら、 +なんらかの不正なプログラムを受け入れるよりも合法なプログラムを拒否したほうがいいのです。コードは大丈夫*かもしれない*けれど、 +Rustコンパイラが大丈夫と確信するために十分な情報を持っていなければ、コンパイラはそのコードを拒否するでしょう。 +このような場合、unsafeコードを使用してコンパイラに「信じて!何をしているかわかってるよ」と教えられます。 +しかし注意してください、unsafe Rustは自己責任で使用するものです: unsafeコードを誤って使用したら、 nullポインタ参照外しなどのメモリ非安全に起因する問題が起こることもあるのです。 unsafe Rustに切り替えるには、`unsafe`キーワードを使用し、それからunsafeコードを保持する新しいブロックを開始してください。 -safe Rustでは行えない4つの行動をunsafe Rustでは行え、これは*unsafe superpowers*と呼ばれます。 +safe Rustでは行えない5つの行動をunsafe Rustでは行うことができ、これは*unsafe superpowers*と呼ばれます。 そのsuperpowerには、以下の能力が含まれています: * 生ポインタを参照外しすること * unsafeな関数やメソッドを呼ぶこと * 可変で静的な変数にアクセスしたり変更すること * unsafeなトレイトを実装すること +* `union`のフィールドにアクセスすること `unsafe`は、借用チェッカーや他のRustの安全性チェックを無効にしないことを理解するのは重要なことです: -unsafeコードで参照を使用しても、チェックはされます。`unsafe`キーワードにより、これら4つの機能にアクセスできるようになり、 +unsafeコードで参照を使用しても、チェックはされます。`unsafe`キーワードにより、これら5つの機能にアクセスできるようになり、 その場合、コンパイラによってこれらのメモリ安全性は確認されないのです。unsafeブロック内でも、ある程度の安全性は得られます。 -人間は失敗をするもので、間違いも起きますが、これら4つのunsafeな処理を`unsafe`で注釈されたブロックに入れる必要があることで、 +人間は失敗をするもので、間違いも起きますが、これら5つのunsafeな処理を`unsafe`で注釈されたブロックに入れる必要があることで、 メモリ安全性に関するどんなエラーも`unsafe`ブロック内にあるに違いないと知ります。`unsafe`ブロックは小さくしてください; メモリのバグを調査するときに感謝することになるでしょう。 @@ -128,11 +132,11 @@ unsafeなコードをできるだけ分離するために、unsafeなコード 安全な抽象を使用することは、安全だからです。 -4つのunsafeなsuperpowerを順に見ていきましょう。unsafeなコードへの安全なインターフェイスを提供する一部の抽象化にも目を向けます。 +5つのunsafeなsuperpowerを順に見ていきましょう。unsafeなコードへの安全なインターフェイスを提供する一部の抽象化にも目を向けます。 -第4章の「ダングリング参照」節で、コンパイラは、参照が常に有効であることを保証することに触れました。 +第4章の[「宙に浮いた参照」][dangling-references]節で、コンパイラは、参照が常に有効であることを保証することに触れました。 unsafe Rustには参照に類似した*生ポインタ*と呼ばれる2つの新しい型があります。参照同様、 生ポインタも不変や可変になり得て、それぞれ`*const T`と`*mut T`と表記されます。このアスタリスクは、参照外し演算子ではありません; 型名の一部です。生ポインタの文脈では、*不変*は、参照外し後に直接ポインタに代入できないことを意味します。 @@ -163,7 +168,7 @@ Different from references and smart pointers, raw pointers: @@ -191,10 +196,7 @@ references. リスト19-1は、参照から不変と可変な生ポインタを生成する方法を示しています。 ```rust -let mut num = 5; - -let r1 = &num as *const i32; -let r2 = &mut num as *mut i32; +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-01/src/main.rs:here}} ``` -次に、有効であることが確信できない生ポインタを生成します。リスト19-2は、メモリの任意の箇所を指す生ポインタの生成法を示しています。 +これを示すために、次は、有効であることが確信できない生ポインタを生成します。リスト19-2は、メモリの任意の箇所を指す生ポインタの生成法を示しています。 任意のメモリを使用しようとすることは未定義です: そのアドレスにデータがある可能性もあるし、ない可能性もあり、 コンパイラがコードを最適化してメモリアクセスがなくなる可能性もあるし、プログラムがセグメンテーションフォールトでエラーになる可能性もあります。 通常、このようなコードを書くいい理由はありませんが、可能ではあります。 ```rust -let address = 0x012345usize; -let r = address as *const i32; +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-02/src/main.rs:here}} ``` -これらの危険がありながら、一体何故生ポインタを使うのでしょうか?主なユースケースの1つは、次の節「unsafeな関数やメソッドを呼ぶ」で見るように、 +これらの危険がありながら、一体何故生ポインタを使うのでしょうか?主なユースケースの1つは、 +次の節[「unsafeな関数やメソッドを呼ぶ」](#unsafeな関数やメソッドを呼ぶ)で見るように、 Cコードとのインターフェイスです。別のユースケースは、借用チェッカーには理解できない安全な抽象を構成する時です。 unsafeな関数を導入し、それからunsafeコードを使用する安全な抽象の例に目を向けます。 @@ -323,17 +319,17 @@ unsafeな関数を導入し、それからunsafeコードを使用する安全 ### unsafeな関数やメソッドを呼ぶ -unsafeブロックが必要になる2番目の処理は、unsafe関数の呼び出しです。unsafeな関数やメソッドも見た目は、 +unsafeブロック内で行うことができる2番目の処理は、unsafe関数の呼び出しです。unsafeな関数やメソッドも見た目は、 普通の関数やメソッドと全く同じですが、残りの定義の前に追加の`unsafe`があります。この文脈での`unsafe`キーワードは、 この関数を呼ぶ際に保持しておく必要のある要求が関数にあることを示唆します。コンパイラには、 この要求を満たしているか保証できないからです。`unsafe`ブロックでunsafeな関数を呼び出すことで、 @@ -347,11 +343,7 @@ body: こちらは、本体で何もしない`dangerous`というunsafeな関数です: ```rust -unsafe fn dangerous() {} - -unsafe { - dangerous(); -} +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-01-unsafe-fn/src/main.rs:here}} ``` - | -4 | dangerous(); - | ^^^^^^^^^^^ call to unsafe function +```console +{{#include ../listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt}} ``` -`dangerous`への呼び出しの周りに`unsafe`ブロックを挿入することで、コンパイラに関数のドキュメンテーションを読み、 +`unsafe`ブロックを使うことで、コンパイラに関数のドキュメンテーションを読み、 適切に使用する方法を理解したことをアサートし、関数の契約を満たしていると実証しました。 関数がunsafeなコードを含んでいるだけで関数全体をunsafeでマークする必要があることにはなりません。 事実、安全な関数でunsafeなコードをラップすることは一般的な抽象化です。例として、 -なんらかのunsafeコードが必要になる標準ライブラリの関数`split_at_mut`を学び、その実装方法を探究しましょう。 +なんらかのunsafeコードが必要になる標準ライブラリの`split_at_mut`関数を学びましょう。 +どのように実装することができるのかを探究します。 この安全なメソッドは、可変なスライスに定義されています: スライスを1つ取り、引数で与えられた添え字でスライスを分割して2つにします。 リスト19-4は、`split_at_mut`の使用法を示しています。 ```rust -let mut v = vec![1, 2, 3, 4, 5, 6]; - -let r = &mut v[..]; - -let (a, b) = r.split_at_mut(3); - -assert_eq!(a, &mut [1, 2, 3]); -assert_eq!(b, &mut [4, 5, 6]); +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-04/src/main.rs:here}} ``` この関数はまず、スライスの全体の長さを得ます。それから引数で与えられた添え字が長さ以下であるかを確認してスライス内にあることをアサートします。 -このアサートは、スライスを分割する添え字よりも大きい添え字を渡したら、その添え字を使用しようとする前に関数がパニックすることを意味します。 +このアサートは、スライスを分割するために長さよりも大きい添え字を渡したら、その添え字を使用しようとする前に関数がパニックすることを意味します。 - | -6 | (&mut slice[..mid], - | ----- first mutable borrow occurs here -7 | &mut slice[mid..]) - | ^^^^^ second mutable borrow occurs here -8 | } - | - first borrow ends here +```console +{{#include ../listings/ch19-advanced-features/listing-19-05/output.txt}} ``` -第4章の「スライス型」節から、スライスはなんらかのデータへのポインタとスライスの長さであることを思い出してください。 +第4章の[「スライス型」][the-slice-type]節から、スライスはなんらかのデータへのポインタとスライスの長さであることを思い出してください。 `len`メソッドを使用してスライスの長さを得て、`as_mut_ptr`メソッドを使用してスライスの生ポインタにアクセスしています。 この場合、`i32`値の可変スライスがあるので、`as_mut_ptr`は型`*mut i32`の生ポインタを返し、これを変数`ptr`に格納しました。 @@ -557,7 +509,7 @@ in the variable `ptr`. We keep the assertion that the `mid` index is within the slice. Then we get to the unsafe code: the `slice::from_raw_parts_mut` function takes a raw pointer and a length, and it creates a slice. We use this function to create a slice -that starts from `ptr` and is `mid` items long. Then we call the `offset` +that starts from `ptr` and is `mid` items long. Then we call the `add` method on `ptr` with `mid` as an argument to get a raw pointer that starts at `mid`, and we create a slice using that pointer and the remaining number of items after `mid` as the length. @@ -565,15 +517,15 @@ items after `mid` as the length. `mid`添え字がスライス内にあるかというアサートを残しています。そして、unsafeコードに到達します: `slice::from_raw_parts_mut`関数は、生ポインタと長さを取り、スライスを生成します。この関数を使って、 -`ptr`から始まり、`mid`の長さのスライスを生成しています。それから`ptr`に`mid`を引数として`offset`メソッドを呼び出し、 +`ptr`から始まり、`mid`の長さのスライスを生成しています。それから`ptr`に`mid`を引数として`add`メソッドを呼び出し、 `mid`で始まる生ポインタを得て、そのポインタと`mid`の後の残りの要素数を長さとして使用してスライスを生成しています。 関数`slice::from_raw_parts_mut`は、unsafeです。何故なら、生ポインタを取り、このポインタが有効であることを信用しなければならないからです。 -生ポインタの`offset`メソッドもunsafeです。オフセット位置もまた有効なポインタであることを信用しなければならないからです。 -故に、`slice::from_raw_parts_mut`と`offset`を呼べるように、その呼び出しの周りに`unsafe`ブロックを置かなければならなかったのです。 +生ポインタの`add`メソッドもunsafeです。オフセット位置もまた有効なポインタであることを信用しなければならないからです。 +故に、`slice::from_raw_parts_mut`と`add`を呼べるように、その呼び出しの周りに`unsafe`ブロックを置かなければならなかったのです。 コードを眺めて`mid`が`len`以下でなければならないとするアサートを追加することで、 `unsafe`ブロック内で使用されている生ポインタが全てスライス内のデータへの有効なポインタであることがわかります。 これは、受け入れられ、適切な`unsafe`の使用法です。 @@ -602,21 +554,14 @@ data this function has access to. 対照的に、リスト19-7の`slice::from_raw_parts_mut`の使用は、スライスが使用されるとクラッシュする可能性が高いでしょう。 -このコードは任意のメモリアドレスを取り、10,000要素の長さのスライスを生成します: +このコードは任意のメモリアドレスを取り、10,000要素の長さのスライスを生成します。 ```rust -use std::slice; - -let address = 0x012345usize; -let r = address as *mut i32; - -let slice = unsafe { - slice::from_raw_parts_mut(r, 10000) -}; +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-07/src/main.rs:here}} ``` この任意の場所のメモリは所有していなく、このコードが生成するスライスに有効な`i32`値が含まれる保証もありません。 -`slice`を有効なスライスであるかのように使用しようとすると、未定義動作に陥ります。 +`values`を有効なスライスであるかのように使用しようとすると、未定義動作に陥ります。 -今までずっと、*グローバル変数*について語りませんでした。グローバル変数をRustは確かにサポートしていますが、 +この本では、まだ*グローバル変数*について語っていませんでした。グローバル変数をRustは確かにサポートしていますが、 Rustの所有権規則で問題になることもあります。2つのスレッドが同じ可変なグローバル変数にアクセスしていたら、 データ競合を起こすこともあります。 @@ -785,12 +721,7 @@ Rustでは、グローバル変数は、*static*(静的)変数と呼ばれます ファイル名: src/main.rs ```rust -static HELLO_WORLD: &str = "Hello, world!"; - -fn main() { - // 名前は: {} - println!("name is: {}", HELLO_WORLD); -} +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-09/src/main.rs}} ``` - -静的変数は、定数に似ています。定数については、第3章の「変数と定数の違い」節で議論しました。 -静的変数の名前は慣習で`SCREAMING_SNAKE_CASE`(`直訳`: 叫ぶスネークケース)になり、変数の型を注釈し*なければなりません*。 -この例では`&'static str`です。静的変数は、`'static`ライフタイムの参照のみ格納でき、 -これは、Rustコンパイラがライフタイムを推量できることを意味します; 明示的に注釈する必要はありません。 +[“Differences Between Variables and +Constants”][differences-between-variables-and-constants] section +in Chapter 3. The names of static variables are in `SCREAMING_SNAKE_CASE` by +convention. Static variables can only store references with the `'static` +lifetime, which means the Rust compiler can figure out the lifetime and we +aren’t required to annotate it explicitly. Accessing an immutable static +variable is safe. +--> + +静的変数は、定数に似ています。定数については、第3章の[「変数と定数の違い」][differences-between-variables-and-constants]節で議論しました。 +静的変数の名前は慣習で`SCREAMING_SNAKE_CASE`(`直訳`: 叫ぶスネークケース)になります。 +静的変数は`'static`ライフタイムの参照のみ格納でき、 +これは、Rustコンパイラがライフタイムを推量でき、明示的に注釈する必要はないことを意味します。 不変で静的な変数にアクセスすることは安全です。 - -定数と不変で静的な変数は、類似して見える可能性がありますが、微妙な差異は、 -静的変数の値は固定されたメモリアドレスになることです。値を使用すると、常に同じデータにアクセスします。 -一方、定数は使用される度にデータを複製させることができます。 - - -定数と静的変数の別の違いは、静的変数は可変にもなることです。可変で静的な変数にアクセスし変更することは、unsafeです。 +定数と不変で静的な変数との微妙な差異は、 +静的変数の値は固定されたメモリアドレスになることです。値を使用すると、常に同じデータにアクセスします。 +一方、定数は使用される度にデータを複製させることができます。 +別の違いは、静的変数は可変にもなることです。可変で静的な変数にアクセスし変更することは、unsafeです。 リスト19-10は、`COUNTER`という可変で静的な変数を宣言し、アクセスし、変更する方法を表示しています。 -`unsafe`でのみ動く最後の行動は、unsafeなトレイトを実装することです。少なくとも、1つのメソッドにコンパイラが確かめられないなんらかの不変条件があると、 -トレイトはunsafeになります。`trait`の前に`unsafe`キーワードを追加し、トレイトの実装も`unsafe`でマークすることで、 -トレイトが`unsafe`であると宣言できます。リスト19-11のようにですね。 +`unsafe`を使用することで、unsafeなトレイトを実装することができます。トレイトは、 +そのメソッドのうち少なくとも1つにコンパイラが確かめられないなんらかの不変条件があると、 +unsafeになります。`trait`の前に`unsafe`キーワードを追加し、トレイトの実装も`unsafe`でマークすることで、 +トレイトが`unsafe`であると宣言します。リスト19-11のようにですね。 ```rust -unsafe trait Foo { - // methods go here - // メソッドがここに来る -} - -unsafe impl Foo for i32 { - // method implementations go here - // メソッドの実装がここに来る -} +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-11/src/main.rs}} ``` - -例として、第16章の「`Sync`と`Send`トレイトで拡張可能な並行性」節で議論した`Sync`と`Send`マーカートレイトを思い出してください: +[“Extensible Concurrency with the `Sync` and `Send` +Traits”][extensible-concurrency-with-the-sync-and-send-traits] +section in Chapter 16: the compiler implements these traits automatically if +our types are composed entirely of `Send` and `Sync` types. If we implement a +type that contains a type that is not `Send` or `Sync`, such as raw pointers, +and we want to mark that type as `Send` or `Sync`, we must use `unsafe`. Rust +can’t verify that our type upholds the guarantees that it can be safely sent +across threads or accessed from multiple threads; therefore, we need to do +those checks manually and indicate as such with `unsafe`. +--> + +例として、第16章の[「`Sync`と`Send`トレイトで拡張可能な並行性」][extensible-concurrency-with-the-sync-and-send-traits]節で議論した`Sync`と`Send`マーカートレイトを思い出してください: 型が完全に`Send`と`Sync`型だけで構成されていたら、コンパイラはこれらのトレイトを自動的に実装します。 生ポインタなどの`Send`や`Sync`でない型を含む型を実装し、その型を`Send`や`Sync`でマークしたいなら、 `unsafe`を使用しなければなりません。コンパイラは、型がスレッド間を安全に送信できたり、 複数のスレッドから安全にアクセスできるという保証を保持しているか確かめられません; 故に、そのチェックを手動で行い、 `unsafe`でそのように示唆する必要があります。 + + +### 共用体のフィールドにアクセスする + + + +`unsafe`でのみ動く最後の行動は、*共用体*のフィールドへのアクセスです。 +`union`は`struct`と似ていますが、宣言されたフィールドのうち、特定のインスタンスに対しては1つだけが同時に使用されます。 +共用体は主に、Cコードの共用体とのインターフェースとして使用されます。 +Rustは共用体インスタンスに現在保管されているデータの型を保証することができないので、 +共用体フィールドへのアクセスはunsafeになっています。 +共用体については[Rust Reference][reference]でさらに深く学ぶことができます。 + @@ -962,14 +891,34 @@ manually and indicate as such with `unsafe`. ### いつunsafeコードを使用するべきか -`unsafe`を使って議論したばかりの4つの行動(強大な力)のうちの1つを行うのは間違っていたり、認められさえもしないものではありません。 +`unsafe`を使って議論したばかりの5つの行動(強大な力)のうちの1つを行うのは間違っていたり、認められさえもしないものではありません。 ですが、`unsafe`コードを正しくするのは、より巧妙なことでしょう。コンパイラがメモリ安全性を保持する手助けをできないからです。 -`unsafe`コードを使用する理由があるなら、そうすることができ、明示的に`unsafe`注釈をすることで問題が起きたら、 +`unsafe`コードを使用する理由があるなら、そうすることができ、明示的に`unsafe`注釈をすることで問題が起きたときに、 その原因を追求するのが容易になります。 + + + +[dangling-references]: +ch04-02-references-and-borrowing.html#宙に浮いた参照 +[differences-between-variables-and-constants]: +ch03-01-variables-and-mutability.html#定数 +[extensible-concurrency-with-the-sync-and-send-traits]: +ch16-04-extensible-concurrency-sync-and-send.html#syncとsendトレイトで拡張可能な並行性 +[the-slice-type]: ch04-03-slices.html#スライス型 +[reference]: https://doc.rust-lang.org/reference/items/unions.html diff --git a/src/ch19-03-advanced-traits.md b/src/ch19-03-advanced-traits.md index 5c82711af..437afa856 100644 --- a/src/ch19-03-advanced-traits.md +++ b/src/ch19-03-advanced-traits.md @@ -5,13 +5,14 @@ ## 高度なトレイト -最初にトレイトについて講義したのは、第10章の「トレイト: 共通の振る舞いを定義する」節でしたが、 -ライフタイム同様、より高度な詳細は議論しませんでした。今や、Rustに詳しくなったので、核心に迫れるでしょう。 +最初にトレイトについて講義したのは、第10章の[「トレイト: 共通の振る舞いを定義する」][traits-defining-shared-behavior]節でしたが、 +より高度な詳細は議論しませんでした。今や、Rustに詳しくなったので、核心に迫れるでしょう。 *関連型*は、トレイトのメソッド定義がシグニチャでプレースホルダーの型を使用できるように、トレイトと型のプレースホルダーを結び付けます。 -トレイトを実装するものがこの特定の実装で型の位置に使用される具体的な型を指定します。そうすることで、 +トレイトを実装するものがこの特定の実装でプレースホルダー型の代わりに使用される具体的な型を指定します。そうすることで、 なんらかの型を使用するトレイトをトレイトを実装するまでその型が一体なんであるかを知る必要なく定義できます。 関連型があるトレイトの一例は、標準ライブラリが提供する`Iterator`トレイトです。その関連型は`Item`と名付けられ、 -`Iterator`トレイトを実装している型が走査している値の型の代役を務めます。第13章の「`Iterator`トレイトと`next`メソッド」節で、 -`Iterator`トレイトの定義は、リスト19-20に示したようなものであることに触れました。 +`Iterator`トレイトを実装している型が走査している値の型の代役を務めます。 +`Iterator`トレイトの定義は、リスト19-12に示したようなものです。 -```rust -pub trait Iterator { - type Item; - - fn next(&mut self) -> Option; -} +```rust,noplayground +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-12/src/lib.rs}} ``` -リスト19-20: 関連型`Item`がある`Iterator`トレイトの定義 +リスト19-12: 関連型`Item`がある`Iterator`トレイトの定義 -型`Item`はプレースホルダー型で`next`メソッドの定義は、型`Option`の値を返すことを示しています。 +型`Item`はプレースホルダーで、`next`メソッドの定義は、型`Option`の値を返すことを示しています。 `Iterator`トレイトを実装するものは、`Item`の具体的な型を指定し、`next`メソッドは、 その具体的な型の値を含む`Option`を返します。 @@ -93,20 +89,13 @@ method will return an `Option` containing a value of that concrete type. 関連型は、ジェネリクスにより扱う型を指定せずに関数を定義できるという点でジェネリクスに似た概念のように思える可能性があります。 -では、何故関連型を使用するのでしょうか? - - - -2つの概念の違いを第13章から`Counter`構造体に`Iterator`トレイトを実装する例で調査しましょう。 -リスト13-21で、`Item`型は`u32`だと指定しました: +2つの概念の違いを調査するために、`Counter`という型に対する、`Item`型を`u32`と指定する、`Iterator`トレイトの実装を見てみましょう: -この記法は、ジェネリクスと比較可能に思えます。では、何故単純にリスト19-21のように、 +この記法は、ジェネリクスと比較可能に思えます。では、何故単純にリスト19-13のように、 `Iterator`トレイトをジェネリクスで定義しないのでしょうか? -```rust -pub trait Iterator { - fn next(&mut self) -> Option; -} +```rust,noplayground +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-13/src/lib.rs}} ``` -リスト19-21: ジェネリクスを使用した架空の`Iterator`トレイトの定義 +リスト19-13: ジェネリクスを使用した架空の`Iterator`トレイトの定義 -差異は、リスト19-21のようにジェネリクスを使用すると、各実装で型を注釈しなければならないことです; +差異は、リスト19-13のようにジェネリクスを使用すると、各実装で型を注釈しなければならないことです; `Iterator for Counter`や他のどんな型にも実装することができるので、 `Counter`の`Iterator`の実装が複数できるでしょう。換言すれば、トレイトにジェネリックな引数があると、 毎回ジェネリックな型引数の具体的な型を変更してある型に対して複数回実装できるということです。 @@ -162,7 +145,7 @@ indicate which implementation of `Iterator` we want to use. 関連型なら、同じ型に対してトレイトを複数回実装できないので、型を注釈する必要はありません。 -関連型を使用する定義があるリスト19-20では、`Item`の型は1回しか選択できませんでした。 +関連型を使用する定義があるリスト19-12では、`Item`の型は1回しか選択できませんでした。 1つしか`impl Iterator for Counter`がないからです。`Counter`に`next`を呼び出す度に、 `u32`値のイテレータが欲しいと指定しなくてもよいわけです。 + + +関連型もトレイトの契約の一部になります: トレイトの実装者は、関連型プレースホルダーの代わりとなる型を提供しなくてはなりません。 +関連型は、その型がどのように使われることになるかの説明となる名前を持つことが多く、 +APIドキュメンテーションで関連型をドキュメント化するのは良い取り組みです。 + @@ -183,36 +177,35 @@ that we call `next` on `Counter`. ジェネリックな型引数を使用する際、ジェネリックな型に対して既定の具体的な型を指定できます。これにより、 -既定の型が動くのなら、トレイトを実装する側が具体的な型を指定する必要を排除します。ジェネリックな型に既定の型を指定する記法は、 -ジェネリックな型を宣言する際に``です。 +既定の型が動くのなら、トレイトを実装する側が具体的な型を指定する必要を排除します。 +ジェネリックな型を宣言する際に、``記法で既定の型を指定します。 -このテクニックが有用になる場面の好例が、演算子オーバーロードです。*演算子オーバーロード*とは、 -特定の状況で演算子(`+`など)の振る舞いをカスタマイズすることです。 +このテクニックが有用になる場面の好例が*演算子オーバーロード*で、 +これにより特定の状況で演算子(`+`など)の振る舞いをカスタマイズします。 Rustでは、独自の演算子を作ったり、任意の演算子をオーバーロードすることはできません。しかし、 演算子に紐づいたトレイトを実装することで`std::ops`に列挙された処理と対応するトレイトをオーバーロードできます。 -例えば、リスト19-22で`+`演算子をオーバーロードして2つの`Point`インスタンスを足し合わせています。 +例えば、リスト19-14で`+`演算子をオーバーロードして2つの`Point`インスタンスを足し合わせています。 `Point`構造体に`Add`トレイトを実装することでこれを行なっています。 -リスト19-22: `Add`トレイトを実装して`Point`インスタンス用に`+`演算子をオーバーロードする +リスト19-14: `Add`トレイトを実装して`Point`インスタンス用に`+`演算子をオーバーロードする このコードは一般的に馴染みがあるはずです: 1つのメソッドと関連型が1つあるトレイトです。 -新しい部分は、`RHS=Self`です: この記法は、*デフォルト型引数*と呼ばれます。 -RHSというジェネリックな型引数("right hand side": 右辺の省略形)が、`add`メソッドの`rhs`引数の型を定義しています。 -`Add`トレイトを実装する際に`RHS`の具体的な型を指定しなければ、`RHS`の型は標準で`Self`になり、 +新しい部分は、`Rhs=Self`です: この記法は、*デフォルト型引数*と呼ばれます。 +`Rhs`というジェネリックな型引数("right hand side": 右辺の省略形)が、`add`メソッドの`rhs`引数の型を定義しています。 +`Add`トレイトを実装する際に`Rhs`の具体的な型を指定しなければ、`Rhs`の型は標準で`Self`になり、 これは`Add`を実装している型になります。 -`Point`に`Add`を実装する際、2つの`Point`インスタンスを足したかったので、`RHS`の規定を使用しました。 -既定を使用するのではなく、`RHS`の型をカスタマイズしたくなる`Add`トレイトの実装例に目を向けましょう。 +`Point`に`Add`を実装する際、2つの`Point`インスタンスを足したかったので、`Rhs`の規定を使用しました。 +既定を使用するのではなく、`Rhs`の型をカスタマイズしたくなる`Add`トレイトの実装例に目を向けましょう。 異なる単位で値を保持する構造体、`Millimeters`と`Meters`(それぞれ`ミリメートル`と`メートル`)が2つあります。 +このように既存の型を別の構造体で薄くラップすることは*ニュータイプパターン*として知られ、 +これについては[「ニュータイプパターンを使用して外部の型に外部のトレイトを実装する」][newtype]節でより詳しく説明します。 ミリメートルの値をメートルの値に足し、`Add`の実装に変換を正しくしてほしいです。 -`Add`を`RHS`に`Meters`のある`Millimeters`に実装することができます。リスト19-23のように: +`Add`を`Rhs`に`Meters`のある`Millimeters`に実装することができます。リスト19-23のように: -リスト19-23: `Millimeters`に`Add`トレイトを実装して、`Meters`に`Millimeters`を足す +リスト19-15: `Millimeters`に`Add`トレイトを実装して、`Meters`に`Millimeters`を足す `Millimeters`を`Meters`に足すため、`Self`という既定を使う代わりに`impl Add`を指定して、 -`RHS`型引数の値をセットしています。 +`Rhs`型引数の値をセットしています。 主に2通りの方法でデフォルト型引数を使用します: @@ -407,15 +372,15 @@ Rustにおいて、別のトレイトのメソッドと同じ名前のメソッ トレイトのメソッドと同じ名前のメソッドを直接型に実装することも可能です。 同じ名前のメソッドを呼ぶ際、コンパイラにどれを使用したいのか教える必要があるでしょう。両方とも`fly`というメソッドがある2つのトレイト、 -`Pilot`と`Wizard`(`訳注`: パイロットと魔法使い)を定義したリスト19-24のコードを考えてください。 +`Pilot`と`Wizard`(`訳注`: パイロットと魔法使い)を定義したリスト19-16のコードを考えてください。 それから両方のトレイトを既に`fly`というメソッドが実装されている型`Human`(`訳注`: 人間)に実装します。 各`fly`メソッドは異なることをします。 @@ -426,54 +391,25 @@ on it. Each `fly` method does something different. ファイル名: src/main.rs ```rust -trait Pilot { - fn fly(&self); -} - -trait Wizard { - fn fly(&self); -} - -struct Human; - -impl Pilot for Human { - fn fly(&self) { - // キャプテンのお言葉 - println!("This is your captain speaking."); - } -} - -impl Wizard for Human { - fn fly(&self) { - // 上がれ! - println!("Up!"); - } -} - -impl Human { - fn fly(&self) { - // *激しく腕を振る* - println!("*waving arms furiously*"); - } -} +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-16/src/main.rs:here}} ``` -リスト19-24: 2つのトレイトに`fly`があるように定義され、`Human`に実装されつつ、 +リスト19-16: 2つのトレイトに`fly`があるように定義され、`Human`に実装されつつ、 `fly`メソッドは`Human`に直接にも実装されている `Human`のインスタンスに対して`fly`を呼び出すと、コンパイラは型に直接実装されたメソッドを標準で呼び出します。 -リスト19-25のようにですね: +リスト19-17のようにですね: -リスト19-25: `Human`のインスタンスに対して`fly`を呼び出す +リスト19-17: `Human`のインスタンスに対して`fly`を呼び出す `Pilot`トレイトか、`Wizard`トレイトの`fly`メソッドを呼ぶためには、 より明示的な記法を使用して、どの`fly`メソッドを意図しているか指定する必要があります。 -リスト19-26は、この記法をデモしています。 +リスト19-18は、この記法をデモしています。 -リスト19-26: どのトレイトの`fly`メソッドを呼び出したいか指定する +リスト19-18: どのトレイトの`fly`メソッドを呼び出したいか指定する メソッド名の前にトレイト名を指定すると、コンパイラにどの`fly`の実装を呼び出したいか明確化できます。 -また、`Human::fly(&person)`と書くこともでき、リスト19-26で使用した`person.fly()`と等価ですが、 +また、`Human::fly(&person)`と書くこともでき、リスト19-18で使用した`person.fly()`と等価ですが、 こちらの方は明確化する必要がないなら、ちょっと記述量が増えます。 -しかしながら、トレイトの一部になる関連関数には`self`引数がありません。同じスコープの2つの型がそのトレイトを実装する場合、 -*フルパス記法*(fully qualified syntax)を使用しない限り、どの型を意図しているかコンパイラは推論できません。例えば、 -リスト19-27の`Animal`トレイトには、関連関数`baby_name`、構造体`Dog`の`Animal`の実装、 -`Dog`に直接定義された関連関数`baby_name`があります。 +しかしながら、メソッドではない関連関数には`self`引数がありません。同じ関数名で非メソッド関数を定義する型またはトレイトが複数ある場合、 +*フルパス記法*(fully qualified syntax)を使用しない限り、どの型を意図しているかコンパイラが常に理解するとは限りません。例えば、 +リスト19-19では、全ての赤ちゃん犬を*スポット*(`訳注`: Wikipediaによると、飼い主の事故死後もその人の帰りを待つ忠犬の名前の模様) +と名付けたいアニマル・シェルター(`訳注`: 身寄りのないペットを保護する保健所みたいなところ)のためのトレイトを作成します。 +関連非メソッド関数`baby_name`を持つ、`Animal`トレイトを作成します。 +`Animal`トレイトは構造体`Dog`に対して実装され、さらに`Dog`はその上に直接定義された関連非メソッド関数`baby_name`を提供します。 -リスト19-27: 関連関数のあるトレイトとそのトレイトも実装し、同じ名前の関連関数がある型 +リスト19-19: 関連関数のあるトレイトとそのトレイトも実装し、同じ名前の関連関数がある型 -このコードは、全ての子犬をスポットと名付けたいアニマル・シェルター(`訳注`: 身寄りのないペットを保護する保健所みたいなところ)用で、 -`Dog`に定義された`baby_name`関連関数で実装されています。`Dog`型は、トレイト`Animal`も実装し、 -このトレイトは全ての動物が持つ特徴を記述します。赤ちゃん犬は子犬と呼ばれ、 +`Dog`に定義された`baby_name`関連関数で、すべての子犬にスポットと名付けるためのコードを実装しています。 +`Dog`型は、トレイト`Animal`も実装し、このトレイトは全ての動物が持つ特徴を記述します。赤ちゃん犬は子犬と呼ばれ、 それが`Dog`の`Animal`トレイトの実装の`Animal`トレイトと紐づいた`base_name`関数で表現されています。 この出力は、欲しかったものではありません。`Dog`に実装した`Animal`トレイトの一部の`baby_name`関数を呼び出したいので、 -コードは`A baby dog is called a puppy`と出力します。リスト19-26で使用したトレイト名を指定するテクニックは、 -ここでは役に立ちません; `main`をリスト19-28のようなコードに変更したら、コンパイルエラーになるでしょう。 +コードは`A baby dog is called a puppy`と出力します。リスト19-18で使用したトレイト名を指定するテクニックは、 +ここでは役に立ちません; `main`をリスト19-20のようなコードに変更したら、コンパイルエラーになるでしょう。 -リスト19-28: `Animal`トレイトの`baby_name`関数を呼び出そうとするも、コンパイラにはどの実装を使うべきかわからない +リスト19-20: `Animal`トレイトの`baby_name`関数を呼び出そうとするも、コンパイラにはどの実装を使うべきかわからない -`Animal::baby_name`はメソッドではなく関連関数であり、故に`self`引数がないので、どの`Animal::baby_name`が欲しいのか、 -コンパイラには推論できません。こんなコンパイルエラーが出るでしょう: +`Animal::baby_name`は`self`引数を持たず、`Animal`トレイトを実装する他の型があるかもしれないので、 +どの`Animal::baby_name`が欲しいのか、コンパイラには推論できません。こんなコンパイルエラーが出るでしょう: -```text -error[E0283]: type annotations required: cannot resolve `_: Animal` -(エラー: 型注釈が必要です: `_: Animal`を解決できません) - --> src/main.rs:20:43 - | -20 | println!("A baby dog is called a {}", Animal::baby_name()); - | ^^^^^^^^^^^^^^^^^ - | - = note: required by `Animal::baby_name` - (注釈: `Animal::baby_name`に必要です) +```console +{{#include ../listings/ch19-advanced-features/listing-19-20/output.txt}} ``` -`Dog`に対して`Animal`実装を使用したいと明確化し、コンパイラに指示するには、フルパス記法を使う必要があります。 -リスト19-29は、フルパス記法を使用する方法をデモしています。 +何らかの他の型に対する`Animalの実装ではなく`Dog`に対する`Animal`実装を使用したいことを、 +コンパイラに明確化して指示するには、フルパス記法を使う必要があります。 +リスト19-21は、フルパス記法を使用する方法をデモしています。 -リスト19-29: フルパス記法を使って`Dog`に実装されているように、 - `Animal`トレイトからの`baby_name`関数を呼び出したいと指定する +リスト19-21: フルパス記法を使って`Dog`に実装されているように、 +`Animal`トレイトからの`baby_name`関数を呼び出したいと指定する -関連関数では、`receiver`がないでしょう: 他の引数のリストがあるだけでしょう。関数やメソッドを呼び出す箇所全部で、 +メソッドでない関連関数には、`receiver`がないでしょう: 他の引数のリストがあるだけでしょう。関数やメソッドを呼び出す箇所全部で、 フルパス記法を使用することもできるでしょうが、プログラムの他の情報からコンパイラが推論できるこの記法のどの部分も省略することが許容されています。 同じ名前を使用する実装が複数あり、どの実装を呼び出したいかコンパイラが特定するのに助けが必要な場合だけにこのより冗長な記法を使用する必要があるのです。 @@ -851,24 +672,29 @@ implementation you want to call. ### スーパートレイトを使用して別のトレイト内で、あるトレイトの機能を必要とする -時として、あるトレイトに別のトレイトの機能を使用させる必要がある可能性があります。この場合、 -依存するトレイトも実装されることを信用する必要があります。信用するトレイトは、実装しているトレイトの*スーパートレイト*です。 +時として、別のトレイトに依存するトレイト定義を書くことがあるかもしれません: +型がそのトレイトを実装するためには、別のトレイトも実装していることを要求したいということです。 +前者のトレイト定義が後者のトレイトの要素を利用できるように、これを行うことになるでしょう。 +トレイト定義が依存するトレイトは、そのトレイトの*スーパートレイト*と呼ばれます。 -例えば、アスタリスクをフレームにする値を出力する`outline_print`メソッドがある`OutlinePrint`トレイトを作りたくなったとしましょう。 -つまり、`Display`を実装し、`(x, y)`という結果になる`Point`構造体が与えられて、 +例えば、与えられた値をアスタリスクの枠で囲うように整形して出力する、`outline_print`メソッドを持つ`OutlinePrint`トレイトを作りたくなったとしましょう。 +つまり、標準ライブラリトレイトの`Display`を実装し、`(x, y)`という結果になる`Point`構造体が与えられて、 `x`が`1`、`y`が`3`の`Point`インスタンスに対して`outline_print`を呼び出すと、以下のような出力をするはずです: ```text @@ -880,18 +706,19 @@ call `outline_print` on a `Point` instance that has `1` for `x` and `3` for ``` -`outline_print`の実装では、`Display`トレイトの機能を使用したいです。故に、`Display`も実装する型に対してだけ`OutlinePrint`が動くと指定し、 +`outline_print`メソッドの実装では、`Display`トレイトの機能を使用したいです。故に、`Display`も実装する型に対してだけ`OutlinePrint`が動くと指定し、 `OutlinePrint`が必要とする機能を提供する必要があるわけです。トレイト定義で`OutlinePrint: Display`と指定することで、 そうすることができます。このテクニックは、トレイトにトレイト境界を追加することに似ています。 -リスト19-30は、`OutlinePrint`トレイトの実装を示しています。 +リスト19-22は、`OutlinePrint`トレイトの実装を示しています。 -リスト19-30: `Display`からの機能を必要とする`OutlinePrint`トレイトを実装する +リスト19-22: `Display`からの機能を必要とする`OutlinePrint`トレイトを実装する @@ -948,14 +763,8 @@ doesn’t implement `Display`, such as the `Point` struct: ファイル名: src/main.rs -```rust -# trait OutlinePrint {} -struct Point { - x: i32, - y: i32, -} - -impl OutlinePrint for Point {} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs:here}} ``` src/main.rs:20:6 - | -20 | impl OutlinePrint for Point {} - | ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter; -try using `:?` instead if you are using a format string - | - = help: the trait `std::fmt::Display` is not implemented for `Point` +```console +{{#include ../listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt}} ``` - -第10章の「型にトレイトを実装する」節で、トレイトか型がクレートにローカルな限り、型にトレイトを実装できると述べるオーファンルールについて触れました。 +new type in a tuple struct. (We covered tuple structs in the [“Using Tuple +Structs without Named Fields to Create Different Types”][tuple-structs] +section of Chapter 5.) The tuple struct will have one field and be a +thin wrapper around the type we want to implement a trait for. Then the wrapper +type is local to our crate, and we can implement the trait on the wrapper. +*Newtype* is a term that originates from the Haskell programming language. +There is no runtime performance penalty for using this pattern, and the wrapper +type is elided at compile time. +--> + +第10章の[「トレイトを型に実装する」][implementing-a-trait-on-a-type]節で、 +トレイトか型がクレートにローカルな場合に限り型にトレイトを実装できるとする、オーファンルールについて触れました。 *ニュータイプパターン*を使用してこの制限を回避することができ、タプル構造体に新しい型を作成することになります。 -(タプル構造体については、第5章の「異なる型を生成する名前付きフィールドのないタプル構造体を使用する」節で講義しました。) +(タプル構造体については、第5章の[「異なる型を生成する名前付きフィールドのないタプル構造体を使用する」][tuple-structs]節で講義しました。) タプル構造体は1つのフィールドを持ち、トレイトを実装したい型の薄いラッパになるでしょう。そして、 ラッパの型はクレートにローカルなので、トレイトをラッパに実装できます。*ニュータイプ*という用語は、 Haskellプログラミング言語に端を発しています。このパターンを使用するのに実行時のパフォーマンスを犠牲にすることはなく、 @@ -1046,12 +840,12 @@ As an example, let’s say we want to implement `Display` on `Vec`, which the orphan rule prevents us from doing directly because the `Display` trait and the `Vec` type are defined outside our crate. We can make a `Wrapper` struct that holds an instance of `Vec`; then we can implement `Display` on -`Wrapper` and use the `Vec` value, as shown in Listing 19-31. +`Wrapper` and use the `Vec` value, as shown in Listing 19-23. --> 例として、`Vec`に`Display`を実装したいとしましょう。`Display`トレイトも`Vec`型もクレートの外で定義されているので、 直接それを行うことはオーファンルールにより妨げられます。`Vec`のインスタンスを保持する`Wrapper`構造体を作成できます; -そして、`Wrapper`に`Display`を実装し、`Vec`値を使用できます。リスト19-31のように。 +そして、`Wrapper`に`Display`を実装し、`Vec`値を使用できます。リスト19-23のように。 -リスト19-31: `Vec`の周りに`Wrapper`を作成して`Display`を実装する +リスト19-23: `Vec`の周りに`Wrapper`を作成して`Display`を実装する このテクニックを使用する欠点は、`Wrapper`が新しい型なので、保持している値のメソッドがないことです。 `self.0`に委譲して、`Wrapper`を`Vec`と全く同様に扱えるように、`Wrapper`に直接`Vec`の全てのメソッドを実装しなければならないでしょう。 内部の型が持つ全てのメソッドを新しい型に持たせたいなら、 -`Deref`トレイト(第15章の「`Deref`トレイトでスマートポインタを普通の参照のように扱う」節で議論しました)を`Wrapper`に実装して、 +`Deref`トレイト(第15章の[「`Deref`トレイトでスマートポインタを普通の参照のように扱う」][smart-pointer-deref]節で議論しました)を`Wrapper`に実装して、 内部の型を返すことは解決策の1つでしょう。内部の型のメソッド全部を`Wrapper`型に持たせたくない(例えば、`Wrapper`型の機能を制限するなど)なら、 本当に欲しいメソッドだけを手動で実装しなければならないでしょう。 + +このニュータイプパターンは、トレイトが絡まなくても有用です。 +焦点を変更して、Rustの型システムと相互作用する一部の高度な方法を見ましょう。 + + -もう、トレイトに関してニュータイプパターンが使用される方法を知りました; トレイトが関連しなくても、 -有用なパターンでもあります。焦点を変更して、Rustの型システムと相互作用する一部の高度な方法を見ましょう。 +[newtype]: ch19-03-advanced-traits.html#ニュータイプパターンを使用して外部の型に外部のトレイトを実装する +[implementing-a-trait-on-a-type]: +ch10-02-traits.html#トレイトを型に実装する +[traits-defining-shared-behavior]: +ch10-02-traits.html#トレイト-共通の振る舞いを定義する +[smart-pointer-deref]: ch15-02-deref.html#derefトレイトでスマートポインタを普通の参照のように扱う +[tuple-structs]: ch05-01-defining-structs.html#異なる型を生成する名前付きフィールドのないタプル構造体を使用する diff --git a/src/ch19-04-advanced-types.md b/src/ch19-04-advanced-types.md index 8f57369ff..b05091457 100644 --- a/src/ch19-04-advanced-types.md +++ b/src/ch19-04-advanced-types.md @@ -5,54 +5,55 @@ ## 高度な型 -Rustの型システムには、この本で触れたけれども、まだ議論していない機能があります。ニュータイプが何故型として有用なのかを調査するため、 +Rustの型システムには、ここまで触れたけれども、まだ議論していない機能があります。ニュータイプが何故型として有用なのかを調査するため、 一般化してニュータイプを議論することから始めます。そして、型エイリアスに移ります。ニュータイプに類似しているけれども、 多少異なる意味を持つ機能です。また、`!`型と動的サイズ決定型も議論します。 -> 注釈: 次の節は、前節「外部の型に外部のトレイトを実装するニュータイプパターン」を読了済みであることを前提にしています。 +### 型安全性と抽象化を求めてニュータイプパターンを使用する -### 型安全性と抽象化を求めてニュータイプパターンを使用する +> 注釈: この節は、以前の節[「ニュータイプパターンを使用して外部の型に外部のトレイトを実装する」][using-the-newtype-pattern]を読了済みであることを前提にしています。 ここまでに議論した以上の作業についてもニュータイプパターンは有用で、静的に絶対に値を混同しないことを強制したり、 -値の単位を示すことを含みます。ニュータイプを使用して単位を示す例をリスト19-23で見かけました: +値の単位を示すことを含みます。ニュータイプを使用して単位を示す例をリスト19-15で見かけました: `Millimeters`と`Meters`構造体は、`u32`値をニュータイプにラップしていたことを思い出してください。 型`Millimeters`を引数にする関数を書いたら、誤ってその関数を型`Meters`や普通の`u32`で呼び出そうとするプログラムはコンパイルできないでしょう。 -型の実装の詳細を抽象化する際にニュータイプパターンを使用するでしょう: 例えば、新しい型を直接使用して、 -利用可能な機能を制限したら、非公開の内部の型のAPIとは異なる公開APIを新しい型は露出できます。 +ニュータイプパターンは、型の実装の詳細を抽象化するためにも使用することができます: +非公開の内部の型のAPIとは異なる公開APIを新しい型は露出できます。 ニュータイプはまた、内部の実装を隠匿(いんとく)することもできます。例を挙げれば、`People`型を提供して、 @@ -70,7 +73,7 @@ Hides Implementation Details” section of Chapter 17. `People`を使用するコードは、名前の文字列を`People`コレクションに追加するメソッドなど、 提供している公開APIとだけ相互作用するでしょう; そのコードは、内部で`i32`IDを名前に代入していることを知る必要はないでしょう。 ニュータイプパターンは、カプセル化を実現して実装の詳細を隠匿する軽い方法であり、 -実装の詳細を隠匿することは、第17章の「カプセル化は実装詳細を隠蔽する」節で議論しましたね。 +実装の詳細を隠匿することは、第17章の[「カプセル化は、実装詳細を隠蔽する」][encapsulation-that-hides-implementation-details]節で議論しましたね。 -ニュータイプパターンに付随して、Rustでは、既存の型に別の名前を与える*型エイリアス*(type alias: 型別名)を宣言する能力が提供されています。 +Rustでは、既存の型に別の名前を与える*型エイリアス*(type alias: 型別名)を宣言する能力が提供されています。 このために、`type`キーワードを使用します。例えば、以下のように`i32`に対して`Kilometers`というエイリアスを作れます。 ```rust -type Kilometers = i32; +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:here}} ``` -これで、別名の`Kilometers`は`i32`と*同義語*になりました; リスト19-23で生成した`Millimeters`と`Meters`とは異なり、 +これで、別名の`Kilometers`は`i32`と*同義語*になりました; リスト19-15で生成した`Millimeters`と`Meters`とは異なり、 `Kilometers`は個別の新しい型ではありません。型`Kilometers`の値は、型`i32`の値と同等に扱われます。 ```rust -type Kilometers = i32; - -let x: i32 = 5; -let y: Kilometers = 5; - -println!("x + y = {}", x + y); +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:there}} ``` `Kilometers`と`i32`が同じ型なので、両方の型の値を足し合わせたり、`Kilometers`の値を`i32`引数を取る関数に渡せたりします。 ですが、この方策を使用すると、先ほど議論したニュータイプパターンで得られる型チェックの利便性は得られません。 +つまり、`Kilometers`と`i32`の値をどこかでごちゃ混ぜにしてしまっても、コンパイラはエラーを出してくれないでしょう。 この長ったらしい型を関数シグニチャや型注釈としてコードのあちこちで記述するのは、面倒で間違いも起きやすいです。 -リスト19-32のそのようなコードで溢れかえったプロジェクトがあることを想像してください。 +リスト19-24のそのようなコードで溢れかえったプロジェクトがあることを想像してください。 ```rust -let f: Box = Box::new(|| println!("hi")); - -fn takes_long_type(f: Box) { - // --snip-- -} - -fn returns_long_type() -> Box { - // --snip-- -# Box::new(|| ()) -} +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-24/src/main.rs:here}} ``` -リスト19-32: 長い型を多くの場所で使用する +リスト19-24: 長い型を多くの場所で使用する -型エイリアスは、繰り返しを減らすことでこのコードをより管理しやすくしてくれます。リスト19-33で、 +型エイリアスは、繰り返しを減らすことでこのコードをより管理しやすくしてくれます。リスト19-25で、 冗長な型に`Thunk`(`注釈`: 塊)を導入し、その型の使用全部をより短い別名の`Thunk`で置き換えることができます。 ```rust -type Thunk = Box; - -let f: Thunk = Box::new(|| println!("hi")); - -fn takes_long_type(f: Thunk) { - // --snip-- -} - -fn returns_long_type() -> Thunk { - // --snip-- -# Box::new(|| ()) -} +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-25/src/main.rs:here}} ``` -リスト19-33: 型エイリアスの`Thunk`を導入して繰り返しを減らす +リスト19-25: 型エイリアスの`Thunk`を導入して繰り返しを減らす -`Result<..., Error>`が何度も繰り返されてます。そんな状態なので、`std::io`にはこんな類のエイリアス宣言があります: +`Result<..., Error>`が何度も繰り返されてます。そんな状態なので、`std::io`にはこんな型エイリアス宣言があります: -```rust,ignore -type Result = Result; +```rust,noplayground +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:here}} ``` @@ -251,14 +223,8 @@ looking like this: つまり、`E`が`std::io::Error`で埋められた`Result`です。その結果、`Write`トレイトの関数シグニチャは、 以下のような見た目になります: -```rust,ignore -pub trait Write { - fn write(&mut self, buf: &[u8]) -> Result; - fn flush(&mut self) -> Result<()>; - - fn write_all(&mut self, buf: &[u8]) -> Result<()>; - fn write_fmt(&mut self, fmt: Arguments) -> Result<()>; -} +```rust,noplayground +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:there}} ``` -ですが、値を絶対に生成できない型をどう使用するのでしょうか?リスト2-5のコードを思い出してください; -リスト19-34に一部を再掲します。 +ですが、値を絶対に生成できない型をどう使用するのでしょうか?数当てゲームの一部である、 +リスト2-5のコードを思い出してください; リスト19-26にその一部を再掲します。 -```rust -# let guess = "3"; -# loop { -let guess: u32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, -}; -# break; -# } + +```rust,ignore +{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs:ch19}} ``` -リスト19-34: `continue`になるアームがある`match` +リスト19-26: `continue`になるアームがある`match` -この時点では、このコードの詳細の一部を飛ばしました。第6章の「`match`制御フロー演算子」節で、 +この時点では、このコードの詳細の一部を飛ばしました。第6章の[「`match`制御フロー演算子」][the-match-control-flow-operator]節で、 `match`アームは全て同じ型を返さなければならないと議論しました。従って、例えば以下のコードは動きません: -```rust,ignore -let guess = match guess.trim().parse() { - Ok(_) => 5, - Err(_) => "hello", -} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-08-match-arms-different-types/src/main.rs:here}} ``` このコードの`guess`は整数*かつ*文字列にならなければならないでしょうが、Rustでは、`guess`は1つの型にしかならないことを要求されます。 -では、`continue`は何を返すのでしょうか?どうやってリスト19-34で1つのアームからは`u32`を返し、別のアームでは、 +では、`continue`は何を返すのでしょうか?どうやってリスト19-26で1つのアームからは`u32`を返し、別のアームでは、 `continue`で終わっていたのでしょうか? -never型は、`panic!`マクロとも有用です。`Option`値に対して呼び出して、値かパニックを生成した`unwrap`関数を覚えていますか? -こちらがその定義です: +never型は、`panic!`マクロとも有用です。`Option`値に対して呼び出して、 +値かパニックを生成する`unwrap`関数を思い出してください。こちらがその定義です: ```rust,ignore -impl Option { - pub fn unwrap(self) -> T { - match self { - Some(val) => val, - None => panic!("called `Option::unwrap()` on a `None` value"), - } - } -} +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-09-unwrap-definition/src/lib.rs:here}} ``` -このコードにおいて、リスト19-34の`match`と同じことが起きています: コンパイラは、`val`の型は`T`で、 +このコードにおいて、リスト19-26の`match`と同じことが起きています: コンパイラは、`val`の型は`T`で、 `panic!`の型は`!`なので、`match`式全体の結果は`T`と確認します。`panic!`は値を生成しないので、 このコードは動きます。つまり、プログラムを終了するのです。`None`の場合、`unwrap`から値は返さないので、 このコードは合法なのです。 @@ -424,13 +374,7 @@ One final expression that has the type `!` is a `loop`: 型が`!`の最後の式は、`loop`です: ```rust,ignore -// 永遠に -print!("forever "); - -loop { - // さらに永遠に - print!("and ever "); -} +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-10-loop-returns-never/src/main.rs:here}} ``` -コンパイラが特定の型の値1つにどれくらいのスペースのメモリを確保するのかなどの特定の詳細を知る必要があるために、 -Rustの型システムには混乱を招きやすい細かな仕様があります: *動的サイズ決定型*の概念です。時として*DST*や*サイズなし型*とも称され、 +コンパイラは、特定の型の値1つにどれくらいのスペースのメモリを確保するのかなど、 +その型についての特定の詳細を知る必要があります。ただしこれには、 +最初は少し混乱しやすい型システムのコーナーケースがあります: +*動的サイズ決定型*の概念です。時として*DST*や*サイズなし型*とも称され、 これらの型により、実行時にしかサイズを知ることのできない値を使用するコードを書かせてくれます。 - -では、どうすればいいのでしょうか?この場合、もう答えはご存知です: `s1`と`s2`の型を`str`ではなく、 -`&str`にすればいいのです。第4章の「文字列スライス」節でスライスデータ構造は、 -開始地点とスライスの長さを格納していると述べたことを思い出してください。 - - +では、どうすればいいのでしょうか?この場合、もう答えはご存知です: `s1`と`s2`の型を`str`ではなく、 +`&str`にすればいいのです。第4章の[「文字列スライス」][string-slices]節で学んだように、 +スライスデータ構造は単に開始地点とスライスの長さを格納したものだということを思い出してください。 従って、`&T`は、`T`がどこにあるかのメモリアドレスを格納する単独の値だけれども、`&str`は*2つ*の値なのです: `str`のアドレスとその長さです。そのため、コンパイル時に`&str`のサイズを知ることができます: `usize`の長さの2倍です。要するに、参照している文字列の長さによらず、常に`&str`のサイズがわかります。 @@ -527,34 +466,34 @@ types behind a pointer of some kind. We can combine `str` with all kinds of pointers: for example, `Box` or `Rc`. In fact, you’ve seen this before but with a different dynamically sized type: traits. Every trait is a dynamically sized type we can refer to by -using the name of the trait. In Chapter 17 in the “Using Trait Objects that -Allow for Values of Different Types” section, we mentioned that to use traits -as trait objects, we must put them behind a pointer, such as `&Trait` or -`Box` (`Rc` would work too). +using the name of the trait. In Chapter 17 in the [“Using Trait Objects That +Allow for Values of Different +Types”][using-trait-objects-that-allow-for-values-of-different-types] +section, we mentioned that to use traits as trait objects, we must +put them behind a pointer, such as `&dyn Trait` or `Box` (`Rc` would work too). --> `str`を全ての種類のポインタと組み合わせられます: 例を挙げれば、`Box`や`Rc`などです。 実際、これまでに見かけましたが、異なる動的サイズ決定型でした: トレイトです。全てのトレイトは、 -トレイト名を使用して参照できる動的サイズ決定型です。第17章の「トレイトオブジェクトで異なる型の値を許容する」節で、 -トレイトをトレイトオブジェクトとして使用するには、`&Trait`や`Box`(`Rc`も動くでしょう)など、 +トレイト名を使用して参照できる動的サイズ決定型です。第17章の[「トレイトオブジェクトで異なる型の値を許容する」][using-trait-objects-that-allow-for-values-of-different-types]節で、 +トレイトをトレイトオブジェクトとして使用するには、`&dyn Trait`や`Box`(`Rc`も動くでしょう)など、 ポインタの背後に配置しなければならないことに触れました。 -DSTを扱うために、Rustには`Sized`トレイトと呼ばれる特定のトレイトがあり、型のサイズがコンパイル時にわかるかどうかを決定します。 +DSTを扱うために、Rustは`Sized`トレイトを提供しており、型のサイズがコンパイル時にわかるかどうかを決定します。 このトレイトは、コンパイル時にサイズの判明する全てのものに自動的に実装されます。加えて、 コンパイラは暗黙的に全てのジェネリックな関数に`Sized`の境界を追加します。つまり、こんな感じのジェネリック関数定義は: ```rust,ignore -fn generic(t: T) { - // --snip-- -} +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs}} ``` -`?Sized`のトレイト境界は、`Sized`のトレイト境界の逆になります: これを「`T`は`Sized`かもしれないし、違うかもしれない」と解読するでしょう。 -この記法は、`Sized`にのみ利用可能で、他のトレイトにはありません。 +`?Sized`のトレイト境界は「`T`は`Sized`かもしれないし、違うかもしれない」という意味であり、 +この記法は、ジェネリック型はコンパイル時に既知のサイズを持たなくてはならないという、 +デフォルトの制約を無効化します。この意味を持つ`?Trait`記法は、`Sized`にのみ利用可能で、 +他のトレイトに対しては利用できません。 次は、関数とクロージャについて語ります! + + + +[encapsulation-that-hides-implementation-details]: +ch17-01-what-is-oo.html#カプセル化は実装詳細を隠蔽する +[string-slices]: ch04-03-slices.html#文字列スライス +[the-match-control-flow-operator]: +ch06-02-match.html#match制御フロー構造 +[using-trait-objects-that-allow-for-values-of-different-types]: +ch17-02-trait-objects.html#トレイトオブジェクトで異なる型の値を許容する +[using-the-newtype-pattern]: ch19-03-advanced-traits.html#ニュータイプパターンを使用して外部の型に外部のトレイトを実装する diff --git a/src/ch19-05-advanced-functions-and-closures.md b/src/ch19-05-advanced-functions-and-closures.md index 8b7eab5cc..da9314b8d 100644 --- a/src/ch19-05-advanced-functions-and-closures.md +++ b/src/ch19-05-advanced-functions-and-closures.md @@ -5,11 +5,12 @@ ## 高度な関数とクロージャ -最後に関数とクロージャに関連する高度な機能の一部を探究し、これには関数ポインタとクロージャの返却が含まれます。 +この節では関数とクロージャに関連する高度な機能の一部を探究し、 +これには関数ポインタとクロージャの返却が含まれます。 クロージャを関数に渡す方法について語りました; 普通の関数を関数に渡すこともできるのです! 新しいクロージャを定義するのではなく、既に定義した関数を渡したい時にこのテクニックは有用です。 -これを関数ポインタで行うと、関数を引数として他の関数に渡して使用できます。関数は、型`fn`(小文字のfです)に型強制されます。 +関数は、型`fn`(小文字のfです)に型強制されます。 `Fn`クロージャトレイトと混同すべきではありません。`fn`型は、*関数ポインタ*と呼ばれます。 -引数が関数ポインタであると指定する記法は、クロージャのものと似ています。リスト19-35のように。 +関数ポインタで関数を渡すことで、関数を引数として他の関数に渡して使用できます。 -ファイル名: src/main.rs -```rust -fn add_one(x: i32) -> i32 { - x + 1 -} +引数が関数ポインタであると指定する記法は、リスト19-27に示すように、クロージャのものと似ています。 +ここでは引数に1を足す関数`add_one`を定義しています。関数`do_twice`は2個の引数を取ります: +`i32`引数を取り`i32`を返す任意の関数への関数ポインタと、1個の`i32`値です。 +`do_twice`関数は、関数`f`に`arg`値を渡して2度呼び出し、その後2回の関数呼び出しの結果を足し合わせます。 +`main`関数は`do_twice`を引数`add_one`と`5`で呼び出します。 -fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { - f(arg) + f(arg) -} + -fn main() { - let answer = do_twice(add_one, 5); +ファイル名: src/main.rs - // 答えは{} - println!("The answer is: {}", answer); -} +```rust +{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-27/src/main.rs}} ``` -リスト19-35: `fn`型を使用して引数として関数ポインタを受け入れる +リスト19-27: `fn`型を使用して引数として関数ポインタを受け入れる -関数ポインタは、クロージャトレイト3つ全て(`Fn`、`FnMut`、`FnOnce`)を実装するので、常に関数ポインタを引数として、 -クロージャを期待する関数に渡すことができます。関数が関数とクロージャどちらも受け入れられるように、 +関数ポインタはクロージャトレイト3つ全て(`Fn`、`FnMut`、`FnOnce`)を実装するので、 +つまり、クロージャを期待する関数には常に関数ポインタを引数として渡すことができます。 +関数が関数とクロージャどちらも受け入れられるように、 ジェネリックな型とクロージャトレイトの1つを使用して関数を書くのが最善です。 -クロージャではなく`fn`だけを受け入れたくなる箇所の一例は、クロージャのない外部コードとのインターフェイスです: +とはいえ、クロージャではなく`fn`だけを受け入れたくなる箇所の一例は、 +クロージャのない外部コードとのインターフェイスです: C関数は引数として関数を受け入れられますが、Cにはクロージャがありません。 -インラインでクロージャが定義されるか、名前付きの関数を使用できるであろう箇所の例として、`map`の使用に目を向けましょう。 +インラインでクロージャが定義されるか、名前付きの関数を使用できるであろう箇所の例として、 +標準ライブラリの`Iterator`トレイトによって提供される`map`メソッドの使用に目を向けましょう。 `map`関数を使用して数字のベクタを文字列のベクタに変換するには、このようにクロージャを使用できるでしょう: ```rust -let list_of_numbers = vec![1, 2, 3]; -let list_of_strings: Vec = list_of_numbers - .iter() - .map(|i| i.to_string()) - .collect(); +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-15-map-closure/src/main.rs:here}} ``` -先ほど「高度なトレイト」節で語ったフルパス記法を使わなければならないことに注意してください。 +先ほど[「高度なトレイト」][advanced-traits]節で語ったフルパス記法を使わなければならないことに注意してください。 というのも、`to_string`という利用可能な関数は複数あるからです。ここでは、 `ToString`トレイトで定義された`to_string`関数を使用していて、このトレイトは標準ライブラリが、 `Display`を実装するあらゆる型に実装しています。 + +第6章の[「Enumの値」][enum-values]節で学んだように、 +各enum列挙子の名前は初期化子関数にもなることを思い出してください。 +これらの初期化子関数は、クロージャトレイトを実装する関数ポインタとして使用することができます。 +つまり、次のように、クロージャを取るメソッドの引数として初期化子関数を指定することができるのです: + +```rust +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-17-map-initializer/src/main.rs:here}} +``` + + -このスタイルを好む方もいますし、クロージャを使うのを好む方もいます。どちらも結果的に同じコードにコンパイルされるので、 -どちらでも、自分にとって明確な方を使用してください。 +ここでは、`map`が呼ばれる範囲内の各`u32`値を使用して、 +`Status::Value`の初期化子関数を使用することで、`Status::Value`インスタンスを作成しています。 +このスタイルを好む方もいますし、クロージャを使うのを好む方もいます。 +どちらも結果的に同じコードにコンパイルされるので、どちらでも、自分にとって明確な方を使用してください。 @@ -188,10 +210,8 @@ The following code tries to return a closure directly, but it won’t compile: 以下のコードは、クロージャを直接返そうとしていますが、コンパイルできません: -```rust,ignore -fn returns_closure() -> Fn(i32) -> i32 { - |x| x + 1 -} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-18-returns-closure/src/lib.rs}} ``` - | -1 | fn returns_closure() -> Fn(i32) -> i32 { - | ^^^^^^^^^^^^^^ `std::ops::Fn(i32) -> i32 + 'static` - does not have a constant size known at compile-time - | - = help: the trait `std::marker::Sized` is not implemented for - `std::ops::Fn(i32) -> i32 + 'static` - = note: the return type of a function must have a statically known size +```console +{{#include ../listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt}} ``` このコードは、問題なくコンパイルできます。トレイトオブジェクトについて詳しくは、 -第17章の「トレイトオブジェクトで異なる型の値を許容する」節を参照してください。 +第17章の[「トレイトオブジェクトで異なる型の値を許容する」][using-trait-objects-that-allow-for-values-of-different-types]節を参照してください。 次は、マクロを見てみましょう! + + + +[advanced-traits]: +ch19-03-advanced-traits.html#高度なトレイト +[enum-values]: ch06-01-defining-an-enum.html#enumの値 +[using-trait-objects-that-allow-for-values-of-different-types]: +ch17-02-trait-objects.html#トレイトオブジェクトで異なる型の値を許容する diff --git a/src/ch19-06-macros.md b/src/ch19-06-macros.md index 6e6279568..e010bd0f8 100644 --- a/src/ch19-06-macros.md +++ b/src/ch19-06-macros.md @@ -104,9 +104,9 @@ opposed to functions you can define anywhere and call anywhere. ### 一般的なメタプログラミングのために`macro_rules!`で宣言的なマクロ ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-28/src/lib.rs}} ``` @@ -217,28 +217,28 @@ one arm. Valid pattern syntax in macro definitions is different than the pattern syntax covered in Chapter 18 because macro patterns are matched against Rust code structure rather than values. Let’s walk through what the pattern pieces in -Listing 19-28 mean; for the full macro pattern syntax, see [the reference]. +Listing 19-28 mean; for the full macro pattern syntax, see the [Rust +Reference][ref]. --> マクロ定義で合法なパターン記法は、第18章で講義したパターン記法とは異なります。というのも、 マクロのパターンは値ではなく、Rustコードの構造に対してマッチされるからです。リスト19-28のパターンの部品がどんな意味か見ていきましょう; -マクロパターン記法全ては[参考文献]をご覧ください。 - - - -[参考文献]: https://doc.rust-lang.org/reference/macros.html +マクロパターン記法全ては[Rust Reference][ref]をご覧ください。 -まず、1組のカッコがパターン全体を囲んでいます。次にドル記号(`$`)、そして1組のカッコが続き、 +まず、パターン全体を囲む1組の丸かっこを使用しています。次に、 +パターンにマッチするRustコードを含むマクロシステム内の変数を宣言するために、 +ドル記号(`$`)を使用しています。このドル記号は、 +これが通常のRust変数ではなくマクロ変数であることを明確にしています。次に1組のカッコが続き、 このかっこは、置き換えるコードで使用するためにかっこ内でパターンにマッチする値をキャプチャします。 `$()`の内部には、`$x:expr`があり、これは任意のRust式にマッチし、その式に`$x`という名前を与えます。 @@ -295,17 +295,21 @@ have a second kind of declarative macro that will work in a similar fashion but fix some of these edge cases. After that update, `macro_rules!` will be effectively deprecated. With this in mind, as well as the fact that most Rust programmers will *use* macros more than *write* macros, we won’t discuss -`macro_rules!` any further. To learn more about how to write macros, consult -the online documentation or other resources, such as [“The Little Book of Rust -Macros”][tlborm]. +`macro_rules!` any further. --> `macro_rules!`には、いくつかの奇妙なコーナーケースがあります。 将来、Rustには別種の宣言的マクロが登場する予定です。これは、同じように働くけれども、それらのコーナーケースのうちいくらかを修正します。 そのアップデート以降、`macro_rules!`は事実上非推奨 (deprecated) となる予定です。 この事実と、ほとんどのRustプログラマーはマクロを*書く*よりも*使う*ことが多いということを考えて、`macro_rules!`についてはこれ以上語らないことにします。 -もしマクロの書き方についてもっと知りたければ、オンラインのドキュメントや、[“The Little Book of Rust Macros”][tlborm]のようなその他のリソースを参照してください。 -[tlborm]: https://danielkeep.github.io/tlborm/book/index.html + +もしマクロの書き方についてもっと知りたければ、オンラインのドキュメントや、 +Daniel Keepによって開始されLukas Wirthによって継続されている[“The Little Book of Rust Macros”][tlborm]のような、 +その他のリソースを参照してください。 2つ目のマクロの形は、*手続き的マクロ*と呼ばれ、より関数のように働きます(そして一種の手続きです)。 宣言的マクロがパターンマッチングを行い、マッチしたコードを他のコードで置き換えていたのとは違い、 手続き的マクロは、コードを入力として受け取り、そのコードに対して作用し、出力としてコードを生成します。 - - -3種の手続き的マクロ (カスタムのderiveマクロ, 属性風マクロ、関数風マクロ)はみな同じような挙動をします。 +カスタムのderiveマクロ、属性風マクロ、関数風マクロの、3種の手続き的マクロがあり、 +これらはみな同じように機能します。 手続き的マクロを作る際は、その定義はそれ専用の特殊なクレート内に置かれる必要があります。 これは複雑な技術的理由によるものであり、将来的には解消したいです。 -手続き的マクロを使うとListing 19-29のコードのようになります。`some_attribute`がそのマクロを使うためのプレースホールダーです。 +リスト19-29では、手続き的マクロを定義する方法を示しています。 +`some_attribute`がそのマクロを使うためのプレースホールダーです。 -Listing 19-29: 手続き的マクロの使用例 +リスト19-29: 手続き的マクロの定義例 `hello_macro_derive`関数は、ライブラリの使用者が型に`#[derive(HelloMacro)]`を指定した時に呼び出されます。 @@ -636,7 +635,7 @@ struct we get from parsing the `struct Pancakes;` string: この関数はまず、`TokenStream`からの`input`をデータ構造に変換し、解釈したり操作したりできるようにします。 ここで`syn`が登場します。 `syn`の`parse`関数は`TokenStream`を受け取り、パースされたRustのコードを表現する`DeriveInput`構造体を返します。 -Listing 19-32は`struct Pancakes;`という文字列をパースすることで得られる`DeriveInput`構造体の関係ある部分を表しています。 +リスト19-32は`struct Pancakes;`という文字列をパースすることで得られる`DeriveInput`構造体の関係ある部分を表しています。 ```rust,ignore DeriveInput { @@ -662,7 +661,7 @@ DeriveInput { Listing 19-32: The `DeriveInput` instance we get when parsing the code that has the macro’s attribute in Listing 19-30 --> -Listing 19-32: このマクロを使った属性を持つListing 19-30のコードをパースしたときに得られる`DeriveInput`インスタンス +リスト19-32: このマクロを使った属性を持つリスト19-30のコードをパースしたときに得られる`DeriveInput`インスタンス -[syn-docs]: https://docs.rs/syn/1.0/syn/struct.DeriveInput.html - この構造体のフィールドは、構文解析したRustコードが`Pancakes`という`ident`(識別子、つまり名前)のユニット構造体であることを示しています。 この構造体にはRustコードのあらゆる部分を記述するフィールドがもっと多くあります; [`DeriveInput`の`syn`ドキュメンテーション][syn-docs]で詳細を確認してください。 @@ -715,7 +712,7 @@ into a `DeriveInput` instance, let’s generate the code that implements the --> 今や、`TokenStream`からの注釈されたRustコードを`DeriveInput`インスタンスに変換するコードができたので、 -Listing 19-33のように、注釈された型に`HelloMacro`トレイトを実装するコードを生成しましょう: +リスト19-33のように、注釈された型に`HelloMacro`トレイトを実装するコードを生成しましょう: -Listing 19-33: パースされたRustコードを用いて`HelloMacro`トレイトを実装する +リスト19-33: パースされたRustコードを用いて`HelloMacro`トレイトを実装する `ast.ident`を使って、注釈された型の名前(識別子)を含む`Ident`構造体インスタンスを得ています。 -Listing 19-32の構造体を見ると、`impl_hello_macro`関数をListing 19-30のコードに実行したときに私達の得る`ident`は、フィールド`ident`の値として`"Pancakes"`を持つだろうとわかります。 -従って、Listing 19-33における変数`name`は構造体`Ident`のインスタンスをもちます。このインスタンスは、printされた時は文字列`"Pancakes"`、即ちListing 19-30の構造体の名前となります。 +リスト19-32の構造体を見ると、`impl_hello_macro`関数をリスト19-30のコードに実行したときに私達の得る`ident`は、フィールド`ident`の値として`"Pancakes"`を持つだろうとわかります。 +従って、リスト19-33における変数`name`は構造体`Ident`のインスタンスをもちます。このインスタンスは、printされた時は文字列`"Pancakes"`、即ちリスト19-30の構造体の名前となります。 @@ -901,11 +896,11 @@ Function-like macros define macros that look like function calls. Similarly to `macro_rules!` macros, they’re more flexible than functions; for example, they can take an unknown number of arguments. However, `macro_rules!` macros can be defined only using the match-like syntax we discussed in the section -[“Declarative Macros with `macro_rules!` for General Metaprogramming”][decl] -earlier. Function-like macros take a `TokenStream` parameter and their -definition manipulates that `TokenStream` using Rust code as the other two -types of procedural macros do. An example of a function-like macro is an `sql!` -macro that might be called like so: +[“Declarative Macros with `macro_rules!` for General +Metaprogramming”][decl] earlier. Function-like macros take a +`TokenStream` parameter and their definition manipulates that `TokenStream` +using Rust code as the other two types of procedural macros do. An example of a +function-like macro is an `sql!` macro that might be called like so: [decl]: #declarative-macros-with-macro_rules-for-general-metaprogramming --> @@ -916,8 +911,6 @@ macro that might be called like so: 関数風マクロは引数として`TokenStream`をとり、その`TokenStream`を定義に従って操作します。操作には、他の2つの手続き的マクロと同じように、Rustコードが使われます。 例えば、`sql!`マクロという関数風マクロで、以下のように呼び出されるものを考えてみましょう: -[decl]: #%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%AA%E3%83%A1%E3%82%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E3%81%9F%E3%82%81%E3%81%ABmacro_rules%E3%81%A7%E5%AE%A3%E8%A8%80%E7%9A%84%E3%81%AA%E3%83%9E%E3%82%AF%E3%83%AD - ```rust,ignore let sql = sql!(SELECT * FROM posts WHERE id=1); ``` @@ -948,15 +941,16 @@ generate. ## まとめ ふう! -あなたがいま手にしたRustの機能はあまり頻繁に使うものではありませんが、非常に特殊な状況ではその存在を思い出すことになるでしょう。 +あなたがいま手にしたRustの機能はおそらくあまり頻繁に使うものではありませんが、 +非常に特殊な状況ではその存在を思い出すことになるでしょう。 たくさんの難しいトピックを紹介しましたが、これは、もしあなたがエラー時の推奨メッセージや他の人のコードでそれらに遭遇した時、その概念と文法を理解できるようになっていてほしいからです。 この章を、解決策にたどり着くためのリファレンスとして活用してください。 @@ -965,3 +959,21 @@ Next, we’ll put everything we’ve discussed throughout the book into practice and do one more project! --> 次は、この本で話してきたすべてのことを実際に使って、もう一つプロジェクトをやってみましょう! + + + +[ref]: https://docs.rust-lang.org/reference/macros-by-example.html +[tlborm]: https://veykril.github.io/tlborm/ +[`syn`]: https://crates.io/crates/syn +[`quote`]: https://crates.io/crates/quote +[syn-docs]: https://docs.rs/syn/1.0/syn/struct.DeriveInput.html +[quote-docs]: https://docs.rs/quote +[decl]: #一般的なメタプログラミングのためにmacro_rulesで宣言的なマクロ