如何为非泛型类型添加特质约束?

15

我有这个简单的通用函数:

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,那么问题到底出在哪里呢?
1个回答

19

在非泛型类型上添加特质限定只能从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)

或者用更常规的U替换令人困惑的模糊不清的i32作为通用类型:

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 为通用类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接