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
TaKO8Ki
August 30, 2023
Programming
14
6.4k
Rustソースコードのざっくりとした歩き方 🦀
https://techfeed.io/events/techfeed-experts-night-24
TaKO8Ki
August 30, 2023
Tweet
Share
More Decks by TaKO8Ki
See All by TaKO8Ki
RustのReturn-position impl trait in trait (RPITIT) の実装を雑に見てみる
tako8ki
1
360
Rustで始めるコードファーストなOpenAPI定義の生成 🦀
tako8ki
1
2.3k
簡単なシェルを作ってRustを学ぼう
tako8ki
1
540
How to contribute to Rust and what I have recently been working on
tako8ki
0
280
RustでTUIのSQLクライアントを作った
tako8ki
0
1.3k
A Ruby version manager written in Rust, which is 7 seconds faster than rbenv
tako8ki
1
1.7k
Other Decks in Programming
See All in Programming
[JAWS-UG横浜 #79] re:Invent 2024 の DB アップデートは Multi-Region!
maroon1st
1
140
最近のVS Codeで気になるニュース 2025/01
74th
1
250
“あなた” の開発を支援する AI エージェント Bedrock Engineer / introducing-bedrock-engineer
gawa
11
1.8k
2024年のkintone API振り返りと2025年 / kintone API look back in 2024
tasshi
0
210
パスキーのすべて ── 導入・UX設計・実装の紹介 / 20250213 パスキー開発者の集い
kuralab
3
640
お前もAI鬼にならないか?👹Bolt & Cursor & Supabase & Vercelで人間をやめるぞ、ジョジョー!👺
taishiyade
5
3.6k
AWSマネコンに複数のアカウントで入れるようになりました
yuhta28
2
160
WebDriver BiDiとは何なのか
yotahada3
1
130
社内フレームワークとその依存性解決 / in-house framework and its dependency management
vvakame
1
550
ISUCON14公式反省会LT: 社内ISUCONの話
astj
PRO
0
180
チームリードになって変わったこと
isaka1022
0
190
いりゃあせ、PHPカンファレンス名古屋2025 / Welcome to PHP Conference Nagoya 2025
ttskch
1
270
Featured
See All Featured
Automating Front-end Workflow
addyosmani
1367
200k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
How STYLIGHT went responsive
nonsquared
98
5.3k
Six Lessons from altMBA
skipperchong
27
3.6k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
240
Docker and Python
trallard
44
3.3k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Testing 201, or: Great Expectations
jmmastey
41
7.2k
Raft: Consensus for Rubyists
vanstee
137
6.8k
Documentation Writing (for coders)
carmenintech
67
4.6k
Adopting Sorbet at Scale
ufuk
74
9.2k
Transcript
Rustソースコードのざっくり とした歩き方 🦀 Takayuki Maeda / TaKO8Ki
• Rust committer (member of compiler contributors team and diagnostic
working group) • Rust Foundation 2023 Fellow Takayuki Maeda / TaKO8Ki @TaKO8Ki @TaKOBKi
テーマ
rustcのコードをほとんど読んだことないRustacean がコントリビュートするための ざっくり入門編
セットアップ
セットアップ 「Rust Compiler Development Guide」という素晴らしいドキュメントがある。 ref:
https://rustc-dev-guide.rust-lang.org
とりあえずgit cloneしてみる。 $ git clone https://github.com/rust-lang/rust.git $ cd rust
セットアップ rustリポジトリのbuildにはx.pyというツールを使います。これで標準ライブラリ含めて 丸っとbuildできます。 ref: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html
次にsetupしてみる。色々出てくるので最後compilerを選択する。 $ ./x.py setup
VSCodeユーザー向けに setting.jsonが自動的に追加される。 ref: Configuring rust-analyzer for rustc
その他サブコマンド (cargoと同じ感じ): $ ./x.py check $ ./x.py build $ ./x.py
test $ ./x.py fmt $ ./x.py clean
いよいよ、buildしてみる。 $ ./x.py build
buildしたcompilerをcargoやrustcで使う。 $ rustup toolchain link stage1 build/[your host]/stage1 $ cargo
+stage1 -vV $ rustc +stage1 -vV
準備が整ったのでとりあえずテストを実行してみる。 $ ./x.py test
セットアップ デバッグはどうやるのか? ref: https://rustc-dev-guide.rust-lang.org/compiler-debugging.html
backtraceが欲しい時は、 $ RUST_BACKTRACE=1 cargo +stage1 build
エラーの発生箇所が知りたい場合は、 $ RUSTFLAGS='-Z track-diagnostics' cargo +stage1 build
また、Rustではloggingにtracingというtokio organizationで開発されて いるcrateを使っている。 ref: Using tracing to debug the compiler
$ RUSTC_LOG=rustc_parse=debug cargo +stage1 build
セットアップ 基本は、修正 → UIテスト追加 → ./x.pyでテスト実行して壊れてないか確認 → プルリク の流れが多い。
コードを読んでみる
コードを読んでみる 全ては紹介しきれないので、まず、比較的優しい気がするparserを読んでみる。parse はparseがprefixとしてつくmethodやfunctionを目印に読んでいけばいい。 Rustのparserはトップダウンな再帰下降パーサー。 ref: https://rustc-dev-guide.rust-lang.org/overview.html#lexing-and-parsing
entry pointは、 - Parser::parse_crate_mod - Parser::parse_mod
parse_modを読み進めてみる。
parse_modを読み進めてみる。 上から順に見ていくと、 ここでloopでitemをparseしてそう
次にparse_itemに飛んでみる。
parse_item_を実行しているのでそっちに行ってみる。
parse_item_はこんな感じなのでそれっぽいparse_item_commonを見て みる。
parse_item_はこんな感じなのでそれっぽいparse_item_commonを見て みる。
まだコアの実装ぽいところにきて無さそうなので、parse_item_common_に ジャンプする。
まだコアの実装ぽいところにきて無さそうなので、parse_item_common_に ジャンプする。
なんかそれっぽくなってきた。 Parser::parse_item_commont_
なんかそれっぽくなってきた。 Parser::parse_item_commont_
拡大すると、なんか色々やってそうなmethodが見える。
ついにparse_item_kindに辿り着いた。
例えばここでenumをparseしてる。
せっかくなので、parse_item_enumも覗いてみる。
確かにmethodの下の方でコンマ区切りでEnum variantをparseしてそう。
では、ここで変更加えてbuildしてみる。 例えばこのエラーメッセージでリポジトリ 内を検索してみると
するとUIテスト用のファイルが見つかる。 tests/ui/structs-enums/issue-103869.rs
コードを読んでみる UIテストとは何か? > tests that check the stdout/stderr from the
compilation and/or running the resulting executable コンパイルによるstdout/stderrと 実行可能ファイルを実行した結果をチェックするためのテスト ref: https://rustc-dev-guide.rust-lang.org/tests/compiletest.html#test-suites
では適当なdebug用のcrateを作ってmain.rsに下記をコピペしてみる。
試しにstage1コンパイラでbuildしてみると、 $ cargo +stage1 build
こういうエラーが得られる。
こういうエラーが得られる。 さっきparse_item_enumで見つけたエ ラーがある
試しにエラーメッセージを変更してみる。 perhaps you meant to use `struct` here foobar
再度buildする。 $ ./x.py build
もう一度デバッグ用のcrateをbuildしてみると、確かにエラーが変わってる。
これであなたもRustコントリビューター 🦀
コードを読んでみる rustc_parseの他にもRustリポジトリにはさまざまなcrateがある。 - rustc_ast_lowering - rustc_ast_passes - rustc_hir - rustc_hir_typeck
- rustc_borrowck などなど。
コードを読んでみる 例えば rustc_ast_lowering はrustc_parseで作ったASTをHIRにloweringするため のcrate。lowerがprefixなmethod、functionが目印。
rustc_ast_loweringのentry pointは、 rustc_ast_lowring::lower_to_hir
同じように覗いてみると、
同じように覗いてみると、 ast_indexごとにlower_nodeを呼んでそう
lower_nodeの実装は、
ここまでくるとなんかいけそう
同じように下に読み進めていけば良さそう
コードを読んでみる 基本はこんな感じで下記のようなcrateなら読める。 - rustc_resolve - rustc_hir - rustc_hir_typeck rustc_borrwckとかは割と複雑で難しい。
実際にissueに取り組 んでみる
実際にissueに取り組んでみる 今回は自分が過去に取り組んだ比較的シンプルなissueを参考に見てみます。 “consider dereferencing here” help doesn’t account for
operator precedence of the deref operator · Issue #105429 · rust-lang/rust
issueを見ると、下記のソースコードが与えられた時に、
このようなエラーが得られるとあります。(現時点では修正済み)
正しくないのはこの箇所です。
実際はこのようにdereferenceする必要があります。
検索したり-Zフラグを使ってエラーの発生箇所を特定してみると、 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs#L778
検索したり-Zフラグを使ってエラーの発生箇所を特定してみると、 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs#L778
やる必要があるのは、dereferenceする対象がmethodのreceiverの際に 特別なハンドリングをすること。 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs#L778
何から始めたらいいか分からないと仮定してまず、spanに定義ジャンプしてみ る。 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs#L778
ありました。これがspan。ObligationCauseのspanというfieldから取れるっ ぽい。 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs
obligationはここでも使われてる。codeという概念があるらしい。 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs
obligation.causeのなかにエラー発生箇所のspanなどの情報が詰められて そう?なことが分かる。 今回のissueではintoなのでargはありませ んが、これは引数のことっぽい。 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs
obligation.causeのなかにエラー発生箇所のspanなどの情報が詰められて そう?なことが分かる。 また、hir_idというのが取れると、それがどう いうNodeかチェックできるっぽい ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs
このNode enumの定義を見てみる。 ref: rustc_trait_selection/src/traits/error_reporting/suggestions.rs
このNode enumの定義を見てみる。
このNode enumの定義を見てみる。
このNode enumの定義を見てみる。
さらにExpr structに飛んでみる。
Exprはkindを持ってるので、これでmethodのreceiverかどうか判別できる のでは?
でもarg_hir_idはあるが、対象のexprがmethod callで対象がその receiverかどうか判別できないとダメそう。 試しにFunctionArgumentObligationを見に行ってみる。
それっぽいのがあるので、いけそう!
ということでこの実装をcall_hir_idを使って修正してみる。
None
call_hir_idを元にexprがmethod callかど うか判別できた
あとはmethod callでかつ対象がそのreceiverの時だけ()で 囲ってdereferenceすればいい
実際にissueに取り組んでみる あとはUIテストを書いて全てのテストにパスすることを確認して、プルリクの完成 Suggest dereferencing receiver arguments properly by TaKO8Ki
· Pull Request #105595 · rust-lang/rust
まとめ
© Money Forward, Inc. まとめ • 基本は「Rust Compiler Development Guide」を読めば大体のことが分
かる。 • 下に下に掘り下げていけば割と読める。 • 分からないことはある程度推測しながら身につけていけば、全体像が見え なくても修正を加えたりできる。
We are hiring!
None