E0072: recursive type has infinite size の原因と直し方
構造体が自分自身の型を直接フィールドに持つと、サイズが無限になってしまいコンパイルエラーになります。Boxなどのポインタ経由の間接参照を挟むことで、サイズを確定させる必要があります。
エラーメッセージの読み方
error[E0072]: recursive type `Node` has infinite size
E0072- エラーコード — `rustc --explain E0072` で詳しい説明が見られます
recursive type `Node` has infinite size- 詳細メッセージ — 何が問題だったか
このエラーが出る典型パターン
パターン1
1 struct Node { 2 value: i32, 3 next: Option<Node> , ^ 4 } 5 fn main() { 6 let n = Node { value: 1, next: None }; 7 println!("{}", n.value); 8 }
Nodeが自分自身を直接含むとサイズが確定しません。Boxを挟んでポインタ経由にする必要があります。
直し方: Option<Node> を Option<Box<Node>> にします。
パターン2
1 struct ListItem { 2 data: i32, 3 child: Option<ListItem> , ^ 4 } 5 fn main() { 6 let n = ListItem { data: 1, child: None }; 7 println!("{}", n.data); 8 }
再帰的な構造体の典型的な解決策は、フィールドをBoxで包んでポインタとして持つことです。
直し方: Option<ListItem> を Option<Box<ListItem>> にします。
パターン3
1 struct TreeNode { 2 value: i32, 3 left: Option<TreeNode> , ^ 4 } 5 fn main() { 6 let n = TreeNode { value: 1, left: None }; 7 println!("{}", n.value); 8 }
木構造のようなデータ構造では、子ノードへの参照は必ずBoxやRcなどの間接参照にする必要があります。
直し方: Option<TreeNode> を Option<Box<TreeNode>> にします。
パターン4
1 struct Chain { 2 id: i32, 3 next: Option<Chain> , ^ 4 } 5 fn main() { 6 let n = Chain { id: 1, next: None }; 7 println!("{}", n.id); 8 }
コンパイラは構造体のサイズをコンパイル時に確定させる必要があるため、無限に自己参照する定義は許されません。
直し方: Option<Chain> を Option<Box<Chain>> にします。
パターン5
1 struct Frame { 2 depth: i32, 3 parent: Option<Frame> , ^ 4 } 5 fn main() { 6 let n = Frame { depth: 1, parent: None }; 7 println!("{}", n.depth); 8 }
Box<Frame>はヒープ上のFrameへのポインタなので、Frame自体のサイズによらず一定サイズになります。
直し方: Option<Frame> を Option<Box<Frame>> にします。
よくある誤解
「Option<Node>のように包んでおけば、再帰的な構造体でもサイズは決まるはず」という思い込みは誤りです。Optionは中身をそのまま埋め込む型なので、Node自身のサイズがまだ確定していない問題は解決しません。ポインタであるBoxを挟んで初めて、サイズが確定します。
まとめ
E0072: recursive type has infinite sizeは中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。