Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
年末ですし、今年のRustの進捗の話をしましょう
Search
Yuki Toyoda
November 30, 2022
2
2.9k
年末ですし、今年のRustの進捗の話をしましょう
TechFeed Experts Night #9 で使用した発表資料です。2022年の Rust になされた変更やアップデートから、個人的に気になったものをピックアップした発表です。
Yuki Toyoda
November 30, 2022
Tweet
Share
More Decks by Yuki Toyoda
See All by Yuki Toyoda
RustでWeb開発コソコソ噂話
helloyuk13
12
14k
SeaQL Projectsについて
helloyuk13
1
520
SwiftでAWS Lambda
helloyuk13
0
220
Rustハンズオン@エウレカ社
helloyuk13
21
11k
Rust ハンズオン第6回 ベアメタル Rust 編
helloyuk13
0
340
Rust で Web アプリケーションはどこまで開発できるのか
helloyuk13
25
72k
Rustハンズオン第4回 Webバックエンド編
helloyuk13
2
700
Rustハンズオン第3回 基礎文法編
helloyuk13
3
950
Rustハンズオン第5回 WebAssembly編
helloyuk13
6
2.5k
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
Statistics for Hackers
jakevdp
796
220k
BBQ
matthewcrist
85
9.4k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
32
2.7k
For a Future-Friendly Web
brad_frost
175
9.4k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Speed Design
sergeychernyshev
25
670
Documentation Writing (for coders)
carmenintech
66
4.5k
Side Projects
sachag
452
42k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Transcript
年末ですし、今年の Rustの進捗の話をしましょう TechFeed Experts Night #9
アジェンダ 2 自己紹介 本発表の前提と目的 2022年編: 今年の変更をおさらいする 実務での新機能への対応 まとめ
アジェンダ 3 自己紹介 本発表の前提と目的 2022年編: 今年の変更をおさらいする 実務での新機能への対応 まとめ
4 自己紹介 yuki ソフトウェアエンジニア 公認エキスパート(Rust) @helloyuki_ 所属: マップボックスジャパン合同会社
執筆 • 実践Rustプログラミング入門(共著) • WEB+DB PRESS vol.131(レビュワー) • 日経クロステック連載 その他 • Rust Tokyo の運営をしています。 • This Week in Rust の日本語記事レビュワーをしています。 • ツイッターランドでRustお役立ち情報ボットをしています。 スプラトゥーン3の chill season が楽しみで仕方ない人
Mapbox で何をしてるの? • 地図技術等を作るアメリカの会社。 • Rust がメインというわけではありません。 ◦ というか JS
や TS 、C++ がメインの会社かも。 ◦ 一部コンポーネントに Rust を使用しています。 ◦ 最近ベラルーシの C++ エンジニアが Rust を書いていたの を観測しはしました。 • 高トラフィックなサーバーや検索などに Rust を利用 しています。 自己紹介 5
アジェンダ 6 自己紹介 本発表の前提と目的 2022年編: 今年の変更をおさらいする 実務での新機能への対応 まとめ
本発表の前提 • Rust の中上級者向けの発表です。 • Rust の基礎文法に習熟していることを前提とします。 ◦ 「習熟」といっても、Rust において「構造体」「enum」「パターンマッチ」などがどういう風に書かれるか
をご存知であれば楽しめると思います。 • 既存の文法や機能の解説はほぼしません。 7
本発表の目的 • 発表者が今年「入って嬉しかった」「入った背景がおもしろかった」と思った機能や変 更を紹介します。 • 嬉しさやおもしろさは主観的なものです。 • この発表自体しゃべりたいだけなので深い意図を持ちません。 • みなさんの「嬉しかった」や「おもしろかった」も教えてください!
8
アジェンダ 9 自己紹介 本発表の前提と目的 2022年編: 今年の変更をおさらいする 実務での新機能への対応 まとめ
今年の変更をおさらいする 10
みなさんのハイライトはなんでしたか? 今年の変更をおさらいする やはりGATs? let-else便利? cargo add 嬉 しくない? Mutex周り?
今年は豊作な1年でしたね!💛 11
今年の変更をおさらいする 標準ライブラリへの変更 1 文法機能面への変更 2 周辺ツールへの変更 3 12
今年の変更をおさらいする 標準ライブラリへの変更 1 文法機能面への変更 2 周辺ツールへの変更 3 13
標準ライブラリへの変更 • [1.62, 1.63] Mutex の内部実装への変更と const 文脈化 • [1.63]
Scoped Thread が導入された 今年の変更をおさらいする 14 調べてておもしろかった
[1.62, 1.63] Mutex の内部実装への変更と const 文脈化 • Mutex (と Condvar、RwLock)の内部実装が変更され、Linux
のシステムコール の一つである futex を使うように修正されました(他のOSでも相応に修正されました) 。 • これにより、メモリ使用量の削減とパフォーマンスの向上が見込めます。 • さらに副産物として、ヒープ領域を使用する必要がなくなるため、Mutex が const 文 脈で使用できるようになりました。 ◦ = OnceCell や lazy_static を使わなくて済むようになりました。 今年の変更をおさらいする : 標準ライブラリへの変更 15
futex を利用するように実装を調整した 従来、Mutex は `Box<pthread_mutex_t>` をラップしたものでしたが、 (Linux では) futex というシステムコー
ルを利用することにより、 Box を剥がすことに成功します。 Mutex の内部実装への変更と const 文脈化 修正前の実装 修正後の実装 📝 AtomicI32 には、0, 1, 2 が入る。futex の制御に利用され る。 16
futex を利用するように実装を調整した Rust コアチームの Mara Bos 氏が中心となってこの修正を行いましたが、そのときの話が RustConf 2021 にて
されています。経緯を知ることができます。 Mutex の内部実装への変更と const 文脈化 https://www.youtube.com/watch?v=DnYQKWs_7EA 17
Mutex を const 文脈で使用できるようになった 内部実装に Box は必要なくなったため、従来 OnceCell などのクレートと組み合わせて static
で利用していた Mutex は、その必要がなくなりました。 Mutex の内部実装への変更と const 文脈化 18
[1.63] Scoped Thread が導入された • 従来の std::thread::spawn によるスレッドの利用では、キャプチャする変数に ’static ライフタイムが求められるため不便な場面がありました。
• std::thread::scope ならびにスコープの spawn を経由したスレッドの利用が可能 になりました。これを利用すると static ライフタイムは求められなくなります。 ◦ GhostCell のように、ライフタイムをきれいに整理して設計し直したよい例だなと思います。 ◦ GhostCell: https://zenn.dev/helloyuki/scraps/a242590b32655f 今年の変更をおさらいする : 標準ライブラリへの変更 19
[1.63] Scoped Thread が導入された std::thread::spawn はクロージャーのライフタイムに static を求めています。つまりスレッドはローカル変 数を借用できなかったので、clone が(あるいは
Arc に包む)必要な場面がありました。 今年の変更をおさらいする : 標準ライブラリへの変更 20
[1.63] Scoped Thread が導入された scoped_thread を利用するとクローンは不要になります。ついでにスコープを抜ける瞬間に join が走るの で、join の呼び出しも不要になります。
今年の変更をおさらいする : 標準ライブラリへの変更 21
余談: Rust 1.0 時点での Scoped Thread • Rust には昔 Scoped
Thread が存在していました。 • が、「Leakpocalypse」と呼ばれる問題が発見され削除されました。 • 数年の時を経て、標準ライブラリに戻ってくることになりました。 Scoped Thread が導入された 22
余談: Leakpocalypse • 「参照カウンタで循環参照を作ってJoinGuardをリークさせると、Scoped Threadが 解放されたメモリにアクセスできてしまう」 • Rust は静的検査などでメモリリークを防ぐことを保証していませんが、それはこうし た事例が理由となっています。
• 詳しくは下記の記事や Issue を参照。 ◦ Pre-Pooping Your Pants With Rust: https://cglab.ca/~abeinges/blah/everyone-poops/ ◦ 超焦ってる様子がわかる当時の Issue: https://github.com/rust-lang/rust/issues/24292 余談: Rust 1.0 時点での Scoped Thread 23
今年の変更をおさらいする 標準ライブラリへの変更 1 文法機能面への変更 2 周辺ツールへの変更 3 24
文法機能面への変更 • [1.65] Generic Associated Types が利用可能に • [1.65] let-else
が利用可能に • [1.62] enum のデフォルトのヴァリアントを指定可能に • [1.64] await は IntoFuture::into_future に脱糖されるように 今年の変更をおさらいする 25 便利すぎる!!
[1.65] Generic Associated Types が利用可能に • 関連型に型パラメータないしはライフタイム注釈を付与できるようになりました。 • 略して「GATs」などと呼ばれています。 •
これにより Rust 全体の型周りの抽象化の表現力が少し向上することになりました。 今年の変更をおさらいする : 文法機能への変更 26
イテレータを新しく実装し直してみる例 下記はトレイトの関連型「 Item」にライフタイム注釈を付与し、 Item 単位でライフタイムをもたせるように実装した 例です。 Generic Associated Types が利用可能に
27 「Self の全ての参照は、’a より長生きでなくてはならない」
余談: モナドが実装できる? • この手の機能は「高階カインド型(higher-kinded types)」と呼ばれるもので、関数 型プログラミングが好きな人からすると「お?モナドいける?」とテンションが上がるか もしれません。 • が、Monad から
Applicative を導出する際に、GATs では若干制約が足りない都 合上、GATs だけでモナドを実装し切るのは難しそうです。 ◦ 実験してくださった方がいました : https://zenn.dev/yyu/articles/f60ed5ba1dd9d5 • RFC にも、GATs がすぐさまモナドを実装可能にするものではないという記述がありま す。 ◦ https://rust-lang.github.io/rfcs/1598-generic_associated_types.html Generic Associated Types が利用可能に 28
[1.65] let-else が利用可能に • if let 構文(例: 「if let Some(b)
= a {} else {}」)が「let Some(b) = a else {}」のよ うに書けるようになりました。 ◦ 「a」にはパターンマッチ可能なパターンが入ります。 ◦ Swift にすでに導入されている guard という記法が元ネタのようです。 • これによりネストが減って見た目がスッキリする、処理の流れが読みやすくなるなど のメリットが享受できるようになります。 文法機能面への変更 29
[1.65] let-else が利用可能に if let Some を let-else で書き換えてみた例。この場合 None
のケースはケアしなくてもよいが、そうしたケース においてわざわざネストを 1つ増やさなくてよくなります。 文法機能面への変更 30
else の中には発散する型を返す式を書く必要がある 私も最初ハマりましたが、 else の中には発散する式( never 型; `!`)を返す処理を書く必要があります。 else 側の
型合わせの際に、返す型の不一致でコンパイルエラーにならないようにするためです。 let-else が利用可能に 31 return をなくしてみたが、これはダメ。
余談: ! 型 • ! として表現される型で、Rust では never 型といいます。loop や
continue などが実はこ の型を返しています。値を何も返さないことを表現します。 • 雑にいうと、どの型にでもなることができます(型強制といいます)。 ◦ たとえば返り値の型として i32 型を要求する関数内で never 型を返しても問題はありません。 ▪ todo! マクロなどはこの仕組みを利用しています。 ◦ let-else の else 側も同様の理屈で型合わせが行われています。 • コンパイル時のデータフロー解析に使われます。 ◦ たとえば never 型を返す関数の後にある処理は決して到達しないので、以降の処理に関する命令は一切成果 物に含める必要はない、などの判断をできます。 • 発展 ◦ https://doc.rust-jp.rs/book-ja/ch19-04-advanced-types.html#never%E5%9E%8B%E3%81%AF%E 7%B5%B6%E5%AF%BE%E3%81%AB%E8%BF%94%E3%82%89%E3%81%AA%E3%81%84 ◦ https://blog-dry.com/entry/2020/11/02/000313 let-else が利用可能に 32
[1.62] enum のデフォルトのヴァリアントを指定可能に • #[default] というアトリビュートを追加すると、Default::default を使用した際に使 われるヴァリアントを指定できるようになりました。 • ユニット型のヴァリアントにのみ付与できるという制約があります。
◦ 付与したDefault が自動導出する実装に問題がある場合があるらしい。 (rust-lang/rust #26925) 文法機能面への変更 33
[1.64] await は IntoFuture::into_future に脱糖されるように • for 式は裏で Iterator に脱糖されますが、同様に
await でも IntoFuture トレイト を実装しておけば脱糖されるようになります。 • HTTP クライアントのクレートなどで「send」を呼び出して Future 化していた部分は await と書くだけでよくなります。 文法機能面への変更 34 📝 reqwest を使った例。send 関数は実質 Future に直しているだけだが、こういう関 数の呼び出しが将来不要になるらしい。 https://github.com/yuk1ty/connpass-rs/blob/dce6d73d5d7d387bcad028d6091877348bb0c2b3/src/client.rs#L77-L78
[1.64] await は IntoFuture::into_future に脱糖されるように .await が呼び出されると、「 into_future」メソッドが呼び出しされるよう、コンパイル時に裏で処理が書き変わるイ メージです。 文法機能面への変更
35 async 関数を定義して使用した例 脱糖のイメージ
今年の変更をおさらいする 標準ライブラリへの変更 1 文法機能面への変更 2 周辺ツールへの変更 3 36
周辺ツールへの変更 • [1.60] cargo build –timings が安定化 • [1.62] cargo
add でクレートの依存を追加できるように • [1.64] ワークスペースの共通設定が書けるように 今年の変更をおさらいする 37
[1.60] cargo build --timings が安定化 • どのクレートのビルドにどれくらい時間がかかったかや、ビルド時のリソースの使用状 況などを計測できます。 • nightly
にはすでにありましたが、安定化しました。 今年の変更をおさらいする : 周辺ツールへの変更 38
[1.60] cargo build --timings が安定化 たとえば、どのクレートのビルドにどのくらい時間がかかったかを知ることができます。ビルドのパフォーマンス チューニングに利用できるかもしれません。 今年の変更をおさらいする :
周辺ツールへの変更 39
[1.62] cargo add でクレートの依存を追加できるように • コマンド一つでクレートの依存を Cargo.toml に追記してくれます。 • もともと
cargo-edit というプラグインでしたが、Rust 本体に取り込まれたようです。 ◦ ただし、本体の挙動とはいくつか微妙に異なる。ならびに、ないコマンドもある。 今年の変更をおさらいする : 周辺ツールへの変更 40
[1.64] ワークスペースの共通設定が書けるように • ワークスペースを使用している場合、ワークスペースのルート側の Cargo.toml に ワークスペース内の共通設定や共通依存クレートを定義できるようになりました。 • たとえば anyhow
などはプロジェクトをまたいでも利用するクレートですが、プロジェ クト間で共通の設定を利用することができ便利です。 ◦ もちろんプロジェクトごとに個別で設定することも引き続きできます。 今年の変更をおさらいする : 周辺ツールへの変更 41
プロジェクト単位で共通設定を使える ワークスペースのルートに共通設定を書き、使用したいプロジェクト側で「 xxx.workspace = true」とすると、共 通する設定項目を引き出せます。下記はクレートのメタ情報と一部依存クレートに適用してみた例です。 ワークスペースの共通設定が書けるように 42
アジェンダ 43 自己紹介 本発表の前提と目的 2022年編: 今年の変更をおさらいする 実務での新機能への対応 まとめ
実務での新機能への対応 • 正直あまりまじめにやっていません😅 • 先日 let-else を使いたいがために、1.65にバージョンをあげました。 • 新機能への対応は個人的には下記のスタンス。 ◦
標準ライブラリへの変更 : doc くらいは読んでおいて使えるときに思い出して使う。 ◦ 文法や機能への変更 : リリースノートは読んでおいて使えるときに思い出して使う。 ◦ 周辺ツールへの変更 : 何が入ったかは覚えておいて使えるときに思い出して使う。 • つまり、軽くリリースノートに目は通しておいて、使いたいときに使うようにしていま す。 • バージョン自体はこまめに上げるようにしておいた方がよいかもしれません。 44
アジェンダ 45 自己紹介 本発表の前提と目的 2022年編: 今年の変更をおさらいする 実務での新機能への対応 まとめ
まとめ • 2022年に Rust に入った機能を駆け足で振り返りました。 • 本発表では時間の都合上細かい議論は省略しましたが、そうした話は下記の Zenn のスクラップにまとめています。 ◦
https://zenn.dev/helloyuki/scraps/bede736a081b0a 46