Rust 中的泛型参数及其在内部项目中的使用规则
在探讨 Rust 中泛型参数在内部项目中的使用规则之前,我们首先来看看官方是如何解释这个问题的:
Inner items do not inherit type or const parameters from the functions they are embedded in.
换句话说,内部项目不会从它们嵌套的函数中继承类型或常量参数。
以下是一些错误的代码示例:
fn foo(x: T) {
fn bar(y: T) { // 这里的 T 是在"外部"函数中定义的
// ..
}
bar(x);
}
这种写法也不行:
fn foo(x: T) {
type MaybeT = Option;
// ...
}
还有这种:
fn foo(x: T) {
struct Foo {
x: T,
}
// ...
}
简而言之,函数内部的项目基本上就像顶层项目一样,只是它们只能在所在的函数中使用。 针对这个问题,有几种解决方案。
如果项目是一个函数,你可以使用闭包:
fn foo(x: T) {
let bar = |y: T| { // 显式类型注解可能不是必需的
// ..
};
bar(x);
}
还可以直接复制泛型参数参数:
fn foo(x: T) {
fn bar(y: T) {
// ..
}
bar(x);
}
fn foo(x: T) {
type MaybeT = Option;
}
同时确保复制所有的Bound:
fn foo(x: T) {
fn bar(y: T) {
// ..
}
bar(x);
}
fn foo(x: T) {
struct Foo {
x: T,
}
}
如果项目是 impl 中的一个函数,定义一个私有辅助函数可能更为简单:
impl Foo {
pub fn foo(&self, x: T) {
self.bar(x);
}
fn bar(&self, y: T) {
// ..
}
}
总结
在 Rust 中,函数、结构体定义和 type 定义被视为顶层项目(top items),除了它们只能在定义的范围内使用外,没有其他区别。简而言之,在定义泛型函数、结构体和 type 定义时,只需再定义一次泛型参数即可。 例如:
fn foo(x: T) {
fn bar(y: T) { // T 是在"外部"函数中定义的
// ..
}
bar(x);
}
修改为:
fn foo(x: T) {
fn bar(y: T) { // 注意这里的区别
// ..
}
bar(x);
}