Progrust Library.

// dictionary

型推論.

型推論(Type Inference)は、型注釈を書かなくてもコンパイラが文脈から型を決める仕組みです。Rustは静的型付け言語なのですべての値の型がコンパイル時に確定しますが、変数の宣言では型注釈を省略でき、初期値やその後の使われ方から型が決まります。

推論の材料はletの右辺だけではありません。同じ関数の本体であれば、後の行での使われ方まで見て型を決めます。次の例のstocksは、宣言した時点ではベクタ(Vec)の要素型が決まっていません。

fn main() {
    let price = 500; // 整数リテラルから i32
    let tax_rate = 0.1; // 小数リテラルから f64

    let mut stocks = Vec::new(); // この時点では要素型が未確定
    stocks.push(3_u8); // 後の行の使われ方から Vec<u8> に確定

    println!("価格: {}円 / 税率: {} / 在庫: {}個", price, tax_rate, stocks[0]);
}
Playgroundで開く

型注釈が必須になる場面

推論が働くのは、関数の本体やconstの初期化式といった「式の内部」だけです。関数の引数のようなシグネチャ部分は呼び出し側と実装側の境界になるため、型を明示する必要があります。

場所 型注釈 例
letで宣言する変数 省略可 let price = 500;
fnの引数 必須 fn tax(price: i32)
fnの戻り値 推論されない(->を省略するとユニット型) fn tax(price: i32) -> i32
定数・静的変数 必須 const TAX_RATE: f64 = 0.1;
構造体のフィールド 必須 struct Item { price: i32 }

関数の引数や定数のようなシグネチャ部分には、推論を頼む_(後述)も書けません。

決め手がないときの既定型

数値リテラルの型は、注釈・接尾辞・周囲の文脈から絞り込めるならその型になり、決め手がない場合に限り整数型はi32、浮動小数点型はf64が既定として採用されます1。

リテラル 手がかり 決まる型
3 let x: u8 = 3; u8(注釈が優先)
3 3_i64 i64(接尾辞が優先)
3 なし i32(既定)
3.0 なし f64(既定)

補足

letでも注釈が必要になるとき

letであっても、周囲から型が絞り込めなければ注釈が必要です。次のparseは変換先の型が呼び出し側で決まるため、注釈なしではコンパイルできません。

fn main() {
    let stock = "12".parse().unwrap(); // エラー: E0284(型注釈が必要)
    println!("在庫: {}個", stock);
}
Playgroundで開く

let stock: u32 = ...と注釈するか、"12".parse::<u32>()のように型を直接渡せば解決します。

型の一部だけを推論に任せる_

型の中に_を書くと、その部分だけをコンパイラに決めてもらえます。全体を注釈するほどではないものの、変数の型そのものは固定したいときに便利です。

fn main() {
    let prices: Vec<_> = (1..=3).map(|n| n * 100).collect(); // Vecであることだけ伝え、要素型i32は推論に任せる
    println!("{:?}", prices);
}
Playgroundで開く
推論が関数をまたがない理由

呼び出し先の実装を覗いて引数の型を決めないおかげで、シグネチャさえ変えなければ本体の書き換えが呼び出し側の型に波及せず、型エラーも原因のある関数の中に収まります。関数の引数に型注釈が必須なのは、この境界を成り立たせるためです。

Footnotes

  1. The Rust Reference - Literal expressions「If the program context under-constrains the type, it defaults to the signed 32-bit integer i32.」(浮動小数点リテラルは同様にf64) ↩

この辞書が使われているページ

backlinks 12

  1. 辞書Defaultトレイト
  2. 辞書never型
  3. 辞書ジェネリクス
  4. 辞書関数
  5. 辞書数値演算
  6. 辞書整数型
  7. 辞書比較演算子
  8. 辞書変換トレイト
  9. 本動かして学ぶRustプログラミング問題集 › 第17章 ジェネリクス
  10. 本動かして学ぶRustプログラミング問題集 › 第19章 derive属性と標準トレイト
  11. 本動かして学ぶRustプログラミング問題集 › 第2章 基本の型と演算
  12. 本動かして学ぶRustプログラミング問題集 › 第6章 文字列とベクタ