Rustの{integer}および{float}

O'ReillyのProgramming Rustを読んでいて、不思議に思った部分があったのでメモ。

前提となる知識

  • Rustでは最低限の型の情報さえ与えれば、残りの部分は推論される。たとえば、

    fn sample1() -> i32 { let x:i32 = 100; x }

    という関数において、戻り値の型から、戻り値xi32となるのは自明なので、

    fn sample2() -> i32 { let x = 100; x }

    と書ける。

  • Rustでは、Cでintlongに相当する型はそれぞれi32i64floatdoubleに相当する型はそれぞれf32f64になっている。

  • i32i64のどちらにも推論できる場合はi32となる。それ以外の場合は、曖昧さをエラーとして報告する。

  • f32f64のどちらにも推論できる場合はf64となる。それ以外の場合は、曖昧さをエラーとして報告する。

本題

Chapter 3. Basic TypesFloating-Point Typesには

println!("{}", (2.0).sqrt());

を実行すると、

error: no method named `sqrt` found for type `{float}` in the current scope

といったエラーが出るが、

println!("{}", (2.0_f64).sqrt());
println!("{}", f64::sqrt(2.0));

などとすれば、きちんと実行されると書かれている。

(2.0)浮動小数点数であることは自明であり、Rustはf64に優先して推論されるはずだが、なぜだかうまく推論してくれない。変数に代入するときなどに推論され、(2.0).sqrt()を実行した時点ではうまく推論してくれないのかと思い、

let x = 2.0;
println!("{}", x.sqrt());

としてみたが、これも先ほどと同様のエラーが出てしまう。

日本語のRustのドキュメントには

let y = 1.0; // yはf64型を持つ

と書かれているので、上記のような書き方でも問題はないはずである。

結論

ここここをみる感じでは、どうやらこの現象はrustcのバグっぽい…?

また、{float}だけでなく{integer}でも起こる場合がある模様。

参考文献

http://ykomatsu.github.io/rust/book-ja/README.html