如何将特征绑定到非泛型类型?

How to add trait bound to a non-generic type?

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

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