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

fn add_five<T: Into<i32>>(t: T) -> i32 {
    5_i32 + t.into()
}

我想用Fromtrait 而不是Intotrait 来表达这一点,但是我try 了重构:

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声明为泛型类型.

Rust相关问答推荐

重新导出proc宏导致未解决的extern crate错误""

有没有更好的方法从HashMap的条目初始化 struct ?

为什么允许我们将可变引用转换为不可变引用?

为昂贵的for循环制作筛子

为什么铁 rust S的默认排序功能比我对小数组的 Select 排序稍微慢一些?

变量需要parse()中的显式类型

循环访问枚举中的不同集合

写入引用会更新基础值,但引用会打印意外的值

如何从宏调用闭包?

Rust,如何从 Rc> 复制内部值并返回它?

Rust FFI 和 CUDA C 性能差异

Rust中的一生语法有什么作用?

如何从trait方法返回std :: iter :: Map?

枚举的利基优化如何在 Rust 中工作?

Rust 中的生命周期:borrow 的 mut 数据

push 方法是否取得所有权?

如何使返回 XMLError 的方法与 anyhow::Error 兼容?

如何断言代码不会在测试中编译?

如何在宏中的多个参数上编写嵌套循环?

为什么一个整型变量赋值给另一个变量后仍然可以使用?