为何此Rust代码中调用get需手动指定类型?多场景验证解析
Rust类型推断与Trait约束问题解析
问题代码
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() {}
报错信息
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`
问题说明与修复原因
尽管&u32满足get的Trait约束,但以下三种修改方式都能让代码正常编译,具体原因如下:
1. 显式指定类型参数(标记1改标记2)
直接写get::<u32>(&1u32)时,相当于强制告诉编译器get的类型参数Q是u32,跳过自动推断步骤。此时u32: B<u32>因为impl<T> B<T> for T的全局实现自动成立,完全满足get的约束,和f函数里K的约束互不干扰,自然能编译通过。
2. 移除标记3的约束(删掉u32: B<K>)
删掉f<K>的u32: B<K>约束后,编译器在处理get(&1u32)时,没有了K这个类型参数的干扰,会直接从传入的&u32参数推断出Q=u32,而u32: B<u32>的约束天然成立,所以代码正常编译。
3. 添加标记4的约束(加上u32: B<u32>)
添加u32: B<u32>看起来是冗余的(毕竟impl<T> B<T> for T已经覆盖了这种情况),但它能帮编译器明确:u32可以作为B的参数绑定到自身。结合原有的u32: B<K>约束,编译器会推断出K必须等于u32(因为当前没有其他B的实现)。此时get的Q会被推断为K=u32,和传入的&u32参数完全匹配,因此编译通过。
内容的提问来源于stack exchange,提问作者yymmyb
相关产品推荐
相关产品推荐

