Rustの{integer}および{float}
O'ReillyのProgramming Rustを読んでいて、不思議に思った部分があったのでメモ。
前提となる知識
Rustでは最低限の型の情報さえ与えれば、残りの部分は推論される。たとえば、
fn sample1() -> i32 { let x:i32 = 100; x }
という関数において、戻り値の型から、戻り値
x
がi32
となるのは自明なので、fn sample2() -> i32 { let x = 100; x }
と書ける。
Rustでは、Cで
int
とlong
に相当する型はそれぞれi32
とi64
、float
とdouble
に相当する型はそれぞれf32
とf64
になっている。i32
とi64
のどちらにも推論できる場合はi32
となる。それ以外の場合は、曖昧さをエラーとして報告する。f32
とf64
のどちらにも推論できる場合はf64
となる。それ以外の場合は、曖昧さをエラーとして報告する。
本題
Chapter 3. Basic TypesのFloating-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());
としてみたが、これも先ほどと同様のエラーが出てしまう。
let y = 1.0; // yはf64型を持つ
と書かれているので、上記のような書き方でも問題はないはずである。
結論
ここやここをみる感じでは、どうやらこの現象はrustcのバグっぽい…?
また、{float}
だけでなく{integer}
でも起こる場合がある模様。