为什么rustc允许我泄漏一个私有类型



我做了一个最小的例子。在lib.rs:中

mod sealed {
pub enum Choice {
A,
B,
}
}
pub fn print_choice(choice: sealed::Choice) {
match choice {
sealed::Choice::A => println!("Choice A"),
sealed::Choice::B => println!("Choice B"),
}
}

我认为:枚举Choice是公共的。然而,它是在一个私人的mod中,不能从板条箱外面到达。因此,函数print_choice根本不可调用。

我的想法出了什么问题?

我的想法出了什么问题?

你可以有类似的东西

pub use sealed::Choice;

在顶层。这是在为外部用户提供简单的单模块接口的同时拆分实现的常见方法。

或者甚至只是一个返回Choice实例的其他函数。由于它是pub,所以不认为它是私有类型。

如果将pub enum更改为pub(crate) enum(意味着您声明枚举不能在机箱外可见(,则编译将失败。

需要理解的一件重要事情是Choice不是私有的。它在一个私有模块内,因此不可损坏,但它是公共的。

模块的隐私唯一会影响的是,您不能通过此路径访问枚举。你可以用它做任何其他事情,例如通过它重新导出到的其他路径访问它:

mod sealed {
pub enum Choice {
A,
B,
}
}
pub use sealed::Choice;
// In other module
crate::Choice::A;

或者用泛型和特征来操纵它,例如:

mod sealed {
pub enum Choice {
A,
B,
}
impl Default for Choice {
fn default() -> Self { Self::A }
}
}
pub fn print_choice(choice: sealed::Choice) { ... }
// In other module
crate::print_choice(Default::default());
mod sealed {
#[derive(Debug)]
pub enum Choice {
A,
B,
}
}
pub fn print_choice(choice: sealed::Choice) { crate::print(choice) }
// In other module
pub fn print<T: Debug>(v: T) { ... }

这个私有类型似乎会泄漏,但您无法完全控制它。

你不能构建这样一个私有的Choice,但另一个公共函数可以为你提供它

mod outer {
mod sealed {
pub enum Choice {
A,
B,
}
}
pub fn print_choice(choice: sealed::Choice) {
match choice {
sealed::Choice::A => println!("Choice A"),
sealed::Choice::B => println!("Choice B"),
}
}
pub fn make_choice(n: u32) -> sealed::Choice {
if n % 2 == 0 {
sealed::Choice::A
} else {
sealed::Choice::B
}
}
}
fn main() {
// let ch = outer::sealed::Choice::A; // error: module `sealed` is private
let ch = outer::make_choice(2);
outer::print_choice(ch);
}

最新更新