生锈错误:无法推断出足够的类型信息来定位特征的impl

时间:2014-11-18 11:17:52

标签: rust

我不太明白为什么这没关系

use std::num;

fn main() {
    let mut p_: int = num::pow(16, 2);
    let mut p: f64 = p_ as f64;
}

但这是失败的

use std::num;

fn main() {
    let mut p: f64 = num::pow(16, 2) as f64;
}

有错误

error: unable to infer enough type information to locate the impl of the trait `core::num::Int` for the type `_`; type annotations required
let mut p: f64 = num::pow(16, 2) as f64;
                 ^~~~~~~~

为了上下文,这是我正在尝试做的事情(pi近似):

fn main() {
    let mut pi: f64 = 0.0;
    let precision: int = 10;

    for i in range(0, precision) {
        let k = i as f64;
        let mut pi16: int = num::pow(16, i as uint);
        let mut p16: f64 = pi16 as f64;
        pi += 1.0/p16 * (4.0/(8.0 * k + 1.0) - 2.0/(8.0 * k + 4.0) - 1.0/(8.0 * k + 5.0) - 1.0/(8.0 * k + 6.0));
    }
}

我正在使用rustc 0.13.0-nightly (f09279395 2014-11-17 17:22:06 +0000)

2 个答案:

答案 0 :(得分:6)

更新:从Rust 1.0.0-alpha开始,pow()函数现在是Int特征上的方法,而Float特征也提供{{ 1}}和powf()方法分别用于升入浮点和整数幂。此外,powi()已更改为uint。因此,现在是电力运营的现状:

usize

也可以使用浮点运算直接在let mut p: f64 = 16us.pow(2) as f64; 上运行:

f64

然而,答案的基本思想仍然存在:你仍然需要在文字上指定确切的类型,以便找到方法。


让我们看看num::pow()签名:

let mut p: f64 = 16.0.powi(2);

它要求第一个参数实现pub fn pow<T: Int>(base: T, exp: uint) -> T trait,它将返回与第一个参数相同类型的值。列出了IntInt个实施者:

impl Int for u8
impl Int for u16
impl Int for u32
impl Int for u64
impl Int for uint
impl Int for i8
impl Int for i16
impl Int for i32
impl Int for i64
impl Int for int

这意味着此功能适用于任何这些类型。现在,让我们来看看你的例子。

这有效:

use std::num;

fn main() {
    let mut p_: int = num::pow(16, 2);
    let mut p: f64 = p_ as f64;
}

因为没有含糊之处。 Rust编译器正确地推断num::pow()被调用为num::pow::<int>()因为您明确声明p_int,这会将num::pow()返回类型约束为int因此它的参数也应该是int

然而,在这种情况下,存在歧义:

use std::num;

fn main() {
    let mut p: f64 = num::pow(16, 2) as f64;
}

整数文字是无类型的,因此编译器不知道16的确切类型。这是您看到的错误:它无法决定使用哪种实现,因为有几种适当的类型。您需要明确地放置文字类型:

use std::num;

fn main() {
    let mut p: f64 = num::pow(16u, 2) as f64;
}

use std::num;

fn main() {
    let mut p: f64 = num::pow::<uint>(16, 2) as f64;
}

它会起作用。

答案 1 :(得分:3)

这是类型推断。

以下是signature of pow

pub fn pow<T: Int>(base: T, exp: uint) -> T

let p: int = num::pow(16, 2);

结果为int,因此16也是int,因为它们具有相同的类型(根据签名)。

num::pow(16, 2) as f64

但是,您要求将结果转换为f64,但不要将转换为

如果预先确定结果的类型是个问题(需要额外的变量),那么你可以:

// precise the type at call site
num::pow::<i64>(16, 2)

// precise the type of the argument
num::pow(16i64, 2)

我显然会注意到,更准确地说明论证的类型。