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.3k
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
310
Rustで始めるコードファーストなOpenAPI定義の生成 🦀
tako8ki
1
2.2k
簡単なシェルを作ってRustを学ぼう
tako8ki
1
500
How to contribute to Rust and what I have recently been working on
tako8ki
0
260
RustでTUIのSQLクライアントを作った
tako8ki
0
1.2k
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
nekko cloudにおけるProxmox VE利用事例
irumaru
3
420
生成AIでGitHubソースコード取得して仕様書を作成
shukob
0
200
「Chatwork」Android版アプリを 支える単体テストの現在
okuzawats
0
180
useSyncExternalStoreを使いまくる
ssssota
6
1k
Full stack testing :: basic to basic
up1
1
930
Symfony Mapper Component
soyuka
2
730
暇に任せてProxmoxコンソール 作ってみました
karugamo
1
720
【re:Growth 2024】 Aurora DSQL をちゃんと話します!
maroon1st
0
770
Discord Bot with AI -for English learners-
xin9le
1
120
103 Early Hints
sugi_0000
1
220
KMP와 kotlinx.rpc로 서버와 클라이언트 동기화
kwakeuijin
0
140
数十万行のプロジェクトを Scala 2から3に完全移行した
xuwei_k
0
260
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
45
7k
A designer walks into a library…
pauljervisheath
204
24k
Docker and Python
trallard
41
3.1k
How STYLIGHT went responsive
nonsquared
95
5.2k
Rails Girls Zürich Keynote
gr2m
94
13k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
127
18k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Practical Orchestrator
shlominoach
186
10k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Optimizing for Happiness
mojombo
376
70k
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