Rust 为什么类型推断在加法期间不起作用,而在赋值期间起作用
我正在用rust_decimal板条箱制作一个应用程序。我的应用程序的一部分涉及值“1”是操作数的操作,因此我尝试使用num_traits::identies::one()并遇到一些意外错误:Rust 为什么类型推断在加法期间不起作用,而在赋值期间起作用,rust,type-inference,Rust,Type Inference,我正在用rust_decimal板条箱制作一个应用程序。我的应用程序的一部分涉及值“1”是操作数的操作,因此我尝试使用num_traits::identies::one()并遇到一些意外错误: use rust_decimal::Decimal; use num_traits::identities::*; fn foo(val : Decimal) { let _1 = one(); // E0282, expected let _one : Decimal = one();
use rust_decimal::Decimal;
use num_traits::identities::*;
fn foo(val : Decimal) {
let _1 = one(); // E0282, expected
let _one : Decimal = one(); // Ok, expected
let add : Decimal = one() + val; // E0283, unexpected
let inc : Decimal = val + one(); // E0284, unexpected
}
令我惊讶的是,编译器无法确定在最后两行中要返回什么类型的one()。这是为什么?只有一种类型可以分配给
十进制
-十进制
本身-但是可以添加到十进制
中的类型可能有很多
let add: Decimal = one() + val;
one()
必须是实现Add
的某种类型。但是可能有许多类型满足该约束,并且编译器不会选择其中一种,因此会出现错误
let inc: Decimal = val + one();
在这种情况下,如果one()
的类型为T
,Decimal
必须实现Add
。但同样,可能有许多T
s满足此约束,编译器不会选择一个
要修复这两个错误,您可以明确表示希望使用one
的Decimal
版本:
let add = one::<Decimal>() + val;
let add=one::()+val;
(不再需要添加
上的:十进制
注释,因为添加
实现明确地确定了输出
类型。)
Decimal只允许与其他小数相加(否则我将使用文字“1”),因此我不确定在这种特殊情况下的歧义是什么
实际上,满足需求的类型有多少并不重要。编译器不会“寻找”满足所有约束的类型;必须仅通过本地信息明确地确定类型。假设只有一种类型有效,但它是在第三方板条箱中定义的;编译器应该知道吗?或者,如果今天只有一种类型可以工作,但是明天您将包含一个新的板条箱,并且有两种这样的类型,那么您的代码是否应该中断?为了避免这种非局部断裂,Rust拒绝为您选择一种类型。一般来说,编译器只会推断类型;这不是推测
这个问题很像
好吧,这绝对不是真的。可以强制为
Decimal
的类型也可以指定给Decimal
变量。但是强制只有在编译器已经知道赋值的两边时才可能,因此无法通过=
推断强制何时发生
²编译器可以在有限的上下文中选择类型。参见示例。描述如何使用类似的技术。我找不到一种方法将此应用于您的问题。这就是Rust如何解决运算符重载的问题。 对于像
a+b
这样的表达式,Rust将首先确定a
的类型,假设它具有类型T
,b
具有类型U
。
当T
实现Add
时,可以编译加法,得到的类型将是V
在某些情况下,编译器可以根据上下文推断a
的类型,但在您的示例中并非如此
因为one()
有多个实现Add
特性的类型,所以它无法确定one()
应该具有哪种类型。可能是f64
实现了Add
,这会使表达式变得模棱两可
在表达式
val+one()
中,确定了第一个操作数的类型,但仍然可以应用Add
的多个实现:Add
,Add这是否回答了您的问题?摘要:可能有许多类型实现了Add
,编译器不会选择一种。要修复它,最简单的方法可能是使用turbofish:let add=one::()+val
(不需要add
上的:Decimal
注释,因为add
实现明确地确定了输出类型。)有没有办法让编译器显示它无法选择的内容?Decimal只允许与其他小数相加(否则我将使用文字“1”),因此我不确定在这种特殊情况下的歧义是什么。