Rust Playground

trait B<T> {}
impl<T> B<T> for T {}

fn f<K>()
where
    // u32: B<u32>, // 4
    u32: B<K>, // 3
{
    // get::<u32>(&1u32); // 2
    get(&1u32); // 1 error
}

fn get<Q>(k: &Q)
where
    u32: B<Q>,
{
}

fn main() {}

错误发生在1:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:10:9
   |
4  | fn f<K>()
   |      - expected this type parameter
...
10 |     get(&1u32); // 1 error
   |     --- ^^^^^ expected `&K`, found `&u32`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected reference `&K`
              found reference `&u32`
note: function defined here
  --> src/main.rs:13:4
   |
13 | fn get<Q>(k: &Q)
   |    ^^^    -----

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to 1 previous error

然而,&u32也满足get的性状界限.

如果我把1改成2,就可以了.

如果我删除3,就可以了.

如果我加4,就可以了.

为什么?

我认为f上的特征可能暂时改变了u32上已经存在的约束,从而影响了get函数对类型参数Q的 Select .如果是这样的话,u32的界限是如何变化的?get如何 Select 类型参数?

还是有更简单的方法来理解它?

推荐答案

这是Rust推论中一个鲜为人知的细节:if there are two possible method candidates, and one of them comes from a trait bound of the function (and the other does not), Rust prefers the trait bound's method, unless explicitly told otherwise.

在您的示例中,泛型参数Q中有两个可能的get::<_>(&u32)(写成get(&1u32))候选者.第一个 Select 是Q = u32,第二个 Select 是Q = K.由于该方法要求u32: B<Q>,即使两者都满足该界限,Q = K被 Select ,因为它来自调用者方法中的特性界限,而Q = u32来自环境(impl impl<T> B<T> for T).

这个特殊情况是为了帮助在以下情况下进行推理:

fn foo<T: Into<String>>(v: T) {
    let s = v.into();
}

在这里,程序员显然希望s具有类型String.然而,这里实际上有两个候选:一个是<T as Into<String>>::into(),另一个是std提供的自反impl <T as Into<T>>::into().为了使这一点不含糊,Rust更倾向于使用trait绑定,除非明确告知.

Rust相关问答推荐

使用pyo3::Types::PyIterator的无限内存使用量

在Rust中,如果Result是Err,运行副作用(如日志(log)记录)的惯用方法是什么

如何模拟/创建ReqData以测试Actix Web请求处理程序?

在本例中,为什么我不能一次多次borrow 可变变量?

创建Rust中元对象协议的动态对象 Select /重新分配机制

我如何制作一个变异迭代器来锁定内部数据直到删除?

JSON5中的变量类型(serde)

为什么 vec![Vec::with_capacity(n)] 为子向量创建 0 容量?

类型生命周期绑定的目的是什么?

try 实现线程安全的缓存

`UnsafeCell` 在没有锁定的情况下跨线程共享 - 这可能会导致 UB,对吗?

在没有任何同步的情况下以非原子方式更新由宽松原子操作 Select 的值是否安全?

如何将 C++ 程序链接到 Rust 程序,然后将该 Rust 程序链接回 C++ 程序? (cpp -> rust -> cpp)

在多核嵌入式 Rust 中,我可以使用静态 mut 进行单向数据共享吗?

如何判断服务器是否正确接收数据

当 T 不是副本时,为什么取消引用 Box 不会抱怨移出共享引用?

为什么1..=100返回一个范围而不是一个整数?

改变不实现克隆的 dioxus UseState struct

如何从 many0 传播 Nom 失败上下文?

在特征中返回一个 Self 类型的值