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.7k
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
530
Rustで始めるコードファーストなOpenAPI定義の生成 🦀
tako8ki
1
2.8k
簡単なシェルを作ってRustを学ぼう
tako8ki
1
640
How to contribute to Rust and what I have recently been working on
tako8ki
0
340
RustでTUIのSQLクライアントを作った
tako8ki
0
1.4k
A Ruby version manager written in Rust, which is 7 seconds faster than rbenv
tako8ki
1
1.8k
Other Decks in Programming
See All in Programming
株式会社 Sun terras カンパニーデック
sunterras
0
230
NetworkXとGNNで学ぶグラフデータ分析入門〜複雑な関係性を解き明かすPythonの力〜
mhrtech
3
1k
Goで実践するドメイン駆動開発 AIと歩み始めた新規プロダクト開発の現在地
imkaoru
4
600
CSC509 Lecture 06
javiergs
PRO
0
240
AI Coding Meetup #3 - 導入セッション / ai-coding-meetup-3
izumin5210
0
590
Your Perfect Project Setup for Angular @BASTA! 2025 in Mainz
manfredsteyer
PRO
0
130
Model Pollution
hschwentner
1
180
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
130
明日から始めるリファクタリング
ryounasso
0
110
プログラミングどうやる? ~テスト駆動開発から学ぶ達人の型~
a_okui
0
190
Catch Up: Go Style Guide Update
andpad
0
170
iOSエンジニア向けの英語学習アプリを作る!
yukawashouhei
0
170
Featured
See All Featured
Statistics for Hackers
jakevdp
799
220k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.2k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Building Applications with DynamoDB
mza
96
6.6k
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.9k
Done Done
chrislema
185
16k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
How STYLIGHT went responsive
nonsquared
100
5.8k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
20k
The Invisible Side of Design
smashingmag
301
51k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
19
1.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