如何将特征绑定到非泛型类型?
我有这个简单的通用函数:
fn add_five<T: Into<i32>>(t: T) -> i32 {
5_i32 + t.into()
}
我想使用From特征而不是特征来表达Into,但是我尝试重构:
fn add_five<T, i32: From<T>>(t: T) -> i32 {
5_i32 + <i32 as From<T>>::from(t)
}
抛出这个编译错误:
error[E0277]: cannot add `i32` to `i32`
--> src/main.rs:24:11
|
| 5_i32 + <i32 as From<T>>::from(t)
| ^ no implementation for `i32 + i32`
|
= help: the trait `Add<i32>` is not implemented for `i32`
这很令人困惑,因为impl Add<i32> for i32标准库中确实有一个,那么真正的问题是什么?
回答
添加绑定到非泛型类型的特征只能通过 where 子句完成:
fn add_five<T>(t: T) -> i32
where
i32: From<T> // now compiles!
{
5_i32 + <i32 as From<T>>::from(t)
}
<T, i32: From<T>>失败的原因是因为编译器将其中使用的所有名称解析<>为泛型类型参数的标识符。
错误消息令人困惑,因为编译器没有说明何时i32引用具体的 32 位有符号整数类型与具有相同名称的泛型类型参数的函数本地标识符(现在也隐藏了具体整数类型)。
这是错误消息,但添加了说明:
error[E0277]: cannot add `i32` (generic type) to `i32` (concrete integer type)
--> src/main.rs:24:11
|
| 5_i32 + <i32 (generic type) as From<T>>::from(t)
| ^ no implementation for `i32 (concrete integer type) + i32 (generic type)`
|
= help: the trait `Add<i32 (generic type)>` is not implemented for `i32` (concrete integer type)
或者将令人困惑的歧义替换i32为更常规U的泛型类型:
error[E0277]: cannot add `U` to `i32`
--> src/main.rs:24:11
|
| 5_i32 + <U as From<T>>::from(t)
| ^ no implementation for `i32 + U`
|
= help: the trait `Add<U>` is not implemented for `i32`
解决方法是简单地将边界移动到 where 子句中,如上所述,以避免意外声明i32为泛型类型。