{"componentChunkName":"component---src-templates-post-template-js","path":"/rust-thiserror","result":{"data":{"markdownRemark":{"id":"cbd4aed4-fe1e-5585-891f-362f97716d68","html":"<p>今回は、Rust の thiserror crate の概要や利用方法などについて簡単にまとめます。</p>\n<p>参考：<a href=\"https://docs.rs/thiserror/latest/thiserror/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">thiserror - Rust</a></p>\n<!-- omit in toc -->\n<h2 id=\"もくじ\" style=\"position:relative;\"><a href=\"#%E3%82%82%E3%81%8F%E3%81%98\" aria-label=\"もくじ permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>もくじ</h2>\n<ul>\n<li><a href=\"#thiserror-crate-%E3%81%A8%E3%81%AF\">thiserror crate とは</a></li>\n<li><a href=\"#rust-%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AA%E3%83%B3%E3%82%B0\">Rust におけるエラーハンドリング</a></li>\n<li><a href=\"#%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB-thiserror-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B\">エラーハンドリングに thiserror を使用する</a></li>\n<li><a href=\"#thiserror-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E6%9C%80%E5%B0%8F%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB\">thiserror を使用する最小サンプル</a></li>\n<li><a href=\"#%E3%81%BE%E3%81%A8%E3%82%81\">まとめ</a></li>\n</ul>\n<h2 id=\"thiserror-crate-とは\" style=\"position:relative;\"><a href=\"#thiserror-crate-%E3%81%A8%E3%81%AF\" aria-label=\"thiserror crate とは permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>thiserror crate とは</h2>\n<p>thiserror は、Rust の <code class=\"language-text\">std::error::Error</code> トレイト(異なる型に対して共通のメソッドを定義したもの)を derive マクロ(struct や enum を使用してトレイトのコードを自動的に生成するもの)で簡潔に実装するためのクレート(Rust におけるライブラリ)です。</p>\n<p>Rust のエラーハンドリングに有効なクレートとしては anyhow がありますが、thiserror は anyhow と比較してカスタムエラー型の実装などに利点があり、主にエラーの型を明示的に公開し呼び出し元側で判別できるようにする必要があるライブラリの実装などで使用されることが一般的なようです。</p>\n<p>参考：<a href=\"https://qiita.com/Aqua-218/items/6dbb5b9fd4f431598e37\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">thiserror vs anyhow、エラーハンドリング宗教戦争 #Rust - Qiita</a></p>\n<h2 id=\"rust-におけるエラーハンドリング\" style=\"position:relative;\"><a href=\"#rust-%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AA%E3%83%B3%E3%82%B0\" aria-label=\"rust におけるエラーハンドリング permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Rust におけるエラーハンドリング</h2>\n<p>前提として、Rust では try-catch によるエラーハンドリングは存在せず、エラーは <code class=\"language-text\">Result&lt;T, E></code> 型で表現されます。</p>\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre class=\"language-rust\"><code class=\"language-rust\"><span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">T</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">E</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">T</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>   <span class=\"token comment\">// 成功時の値</span>\n    <span class=\"token class-name\">Err</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">E</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>  <span class=\"token comment\">// エラー時の値</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>参考：<a href=\"https://zenn.dev/0x/articles/5591cb490cebe5\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Rustはいいぞ: エラーハンドリング編</a></p>\n<p>そして、Rust ではこの Result 型は「エラーが発生するかもしれない処理」の結果として使用されます。</p>\n<p>以下の関数は、<code class=\"language-text\">read_to_string</code> 関数を使用する場合のエラーハンドリングを愚直に実装したものです。</p>\n<p>Rust では、このような match によるパターンマッチングを使用して、Result 型の戻り値に基づくエラーハンドリングを行うことができます。</p>\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre class=\"language-rust\"><code class=\"language-rust\"><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>fs<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>io<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Error</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> content <span class=\"token operator\">=</span> <span class=\"token keyword\">match</span> <span class=\"token namespace\">fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">read_to_string</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"test.txt\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> text<span class=\"token punctuation\">,</span>\n        <span class=\"token class-name\">Err</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">return</span> <span class=\"token class-name\">Err</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"{}\"</span><span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>参考：<a href=\"https://doc.rust-lang.org/rust-by-example/flow_control/match.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">match - Rust By Example</a></p>\n<p>さらに Rust では <code class=\"language-text\">?</code> 演算子を使用することでこの match 式を使用する場合とほぼ同等の Result 型に対する処理を以下のように実装することができます。</p>\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre class=\"language-rust\"><code class=\"language-rust\"><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>fs<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>io<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Error</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> content <span class=\"token operator\">=</span> <span class=\"token namespace\">fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">read_to_string</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"test.txt\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"{}\"</span><span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>参考：<a href=\"https://doc.rust-jp.rs/book-ja/ch09-02-recoverable-errors-with-result.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Resultで回復可能なエラー - The Rust Programming Language 日本語版</a></p>\n<p>参考：<a href=\"https://qiita.com/kanna/items/a0c10a0563573d5b2ed0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Rustの?演算子 #Rust - Qiita</a></p>\n<p>また、このコードと同じような処理は以下のように実装することもできます。</p>\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre class=\"language-rust\"><code class=\"language-rust\"><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>fs<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Box</span><span class=\"token operator\">&lt;</span><span class=\"token keyword\">dyn</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>error<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Error</span><span class=\"token operator\">>></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> message<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span> <span class=\"token operator\">=</span> <span class=\"token namespace\">fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">read_to_string</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"message.txt\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"{}\"</span><span class=\"token punctuation\">,</span> message<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>上記のコードでは、<code class=\"language-text\">Box&lt;dyn std::error::Error></code> を使用してエラーを受け取ります。</p>\n<p>Rust のコンパイル時には関数の戻り値の型が明確であることが要求されますが、ここでは <code class=\"language-text\">dyn std::error::Error</code> のように <code class=\"language-text\">std::error::Error</code> トレイトを実装する何らかの型を動的にディスパッチします。</p>\n<p>このような場合は、ヒープに格納するデータを指す Box を使用します。</p>\n<p>これにより、コンパイル時には型のサイズを特定できない場合でもその型を使用することができるようになり、以下のように関数内で異なる型のエラーが返される可能性がある場合でもそのエラーを受け取ることができるようになります。</p>\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre class=\"language-rust\"><code class=\"language-rust\"><span class=\"token keyword\">use</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span>fs<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Box</span><span class=\"token operator\">&lt;</span><span class=\"token keyword\">dyn</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>error<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Error</span><span class=\"token operator\">>></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// io::Error が ? で Box&lt;dyn Error> に自動変換される</span>\n    <span class=\"token comment\">// let content = fs::read_to_string(\"Cargo.toml\")?;</span>\n    <span class=\"token keyword\">let</span> content <span class=\"token operator\">=</span> <span class=\"token namespace\">fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">read_to_string</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"xxx.toml\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// ParseIntError も同じ Box&lt;dyn Error> に変換できる</span>\n    <span class=\"token keyword\">let</span> port<span class=\"token punctuation\">:</span> <span class=\"token keyword\">u16</span> <span class=\"token operator\">=</span> content<span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"port = {}\"</span><span class=\"token punctuation\">,</span> port<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>参考：<a href=\"https://doc.rust-jp.rs/rust-by-example-ja/trait/dyn.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">dynを利用してトレイトを返す - Rust By Example 日本語版</a></p>\n<p>参考：<a href=\"https://doc.rust-jp.rs/book-ja/ch15-01-box.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ヒープのデータを指すBox<T>を使用する - The Rust Programming Language 日本語版</a></p>\n<h2 id=\"エラーハンドリングに-thiserror-を使用する\" style=\"position:relative;\"><a href=\"#%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB-thiserror-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B\" aria-label=\"エラーハンドリングに thiserror を使用する permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>エラーハンドリングに thiserror を使用する</h2>\n<p>呼び出し側でエラーハンドリングを行う場合、前述した <code class=\"language-text\">Box&lt;dyn std::error::Error></code> を使用すると手軽に複数の型を扱えるようになりますが、一方で呼び出し側ではエラーの種類を判断しにくいなどのデメリットがあります。</p>\n<p>thiserror を使用すると、明示的なカスタムエラー型を簡単に実装することができるので、エラー型を構造的に公開し、呼び出し側でパターンマッチを可能とする必要があるようなライブラリの実装で主に使用されます。</p>\n<h2 id=\"thiserror-を使用する最小サンプル\" style=\"position:relative;\"><a href=\"#thiserror-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E6%9C%80%E5%B0%8F%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB\" aria-label=\"thiserror を使用する最小サンプル permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>thiserror を使用する最小サンプル</h2>\n<p>以下は、thiserror を使用したシンプルなエラーハンドリングの実装です。ここでは enum により AppError というエラーを定義しています。</p>\n<p>先頭の <code class=\"language-text\">#[derive(Debug, Error)]</code> は  <code class=\"language-text\">std::error::Error</code> トレイトの自動実装のための要件として記述しています。</p>\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre class=\"language-rust\"><code class=\"language-rust\"><span class=\"token keyword\">use</span> <span class=\"token namespace\">thiserror<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Error</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token attribute attr-name\">#[derive(Debug, Error)]</span>\n<span class=\"token keyword\">pub</span> <span class=\"token keyword\">enum</span> <span class=\"token type-definition class-name\">AppError</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token attribute attr-name\">#[error(<span class=\"token string\">\"I/O エラー: {0}\"</span>)]</span>\n    <span class=\"token class-name\">Io</span><span class=\"token punctuation\">(</span><span class=\"token attribute attr-name\">#[from]</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>io<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Error</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">handle_error</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">AppError</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">match</span> err <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">AppError</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Io</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n            <span class=\"token macro property\">eprintln!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"[IO] ファイル操作失敗: {}\"</span><span class=\"token punctuation\">,</span> e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">read_config</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">AppError</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> content <span class=\"token operator\">=</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">read_to_string</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\n    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"--- 1. 存在しないファイルの読み込み (#[from] による自動変換) ---\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">match</span> <span class=\"token function\">read_config</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"nonexistent.toml\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"{}\"</span><span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token class-name\">Err</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">handle_error</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\n--- 2. 存在するファイルの読み込み (#[from] による自動変換) ---\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">match</span> <span class=\"token function\">read_config</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Cargo.toml\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token macro property\">println!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"{}\"</span><span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token class-name\">Err</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">handle_error</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>e<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span>\n\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>上記のコードでは、<code class=\"language-text\">#[from]</code> により <code class=\"language-text\">std::io::Error</code> を AppError に変換する実装を自動生成しており、<code class=\"language-text\">?</code> 演算子でエラー委譲が行われた際に自動的に io::Error → AppError への変換が行われます。</p>\n<h2 id=\"まとめ\" style=\"position:relative;\"><a href=\"#%E3%81%BE%E3%81%A8%E3%82%81\" aria-label=\"まとめ permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>まとめ</h2>\n<p>thiserror を使用する実装パターンについてはそのうち追記します。</p>","fields":{"slug":"/rust-thiserror","tagSlugs":["/tag/rust/"]},"frontmatter":{"date":"2026-05-23","description":"Rust のエラーハンドリングと thiserror に関するメモ書きです。","tags":["Rust"],"title":"Rust のエラーハンドリングと thiserror に関するメモ書き","socialImage":{"publicURL":"/static/25f109c28784e3626b8123a90088ff95/rust-thiserror.png"}}}},"pageContext":{"slug":"/rust-thiserror"}},"staticQueryHashes":["251939775","401334301","825871152"]}