为何返回私有类型会触发警告,返回私有模块的公共类型却不会?
Rust中
private_interfaces警告的差异问题 首先看这段Rust代码:
struct Error; mod private { pub struct Error; } pub fn do1() -> Result<(), Error> { Ok(()) } pub fn do2() -> Result<(), private::Error> { Ok(()) }
编译时会得到如下警告:
Compiling playground v0.0.1 (/playground) warning: type `Error` is more private than the item `do1` --> src/lib.rs:7:1 | 7 | pub fn do1() -> Result<(), Error> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `do1` is reachable at visibility `pub` | note: but type `Error` is only usable at visibility `pub(crate)` --> src/lib.rs:1:1 | 1 | struct Error; | ^^^^^^^^^^^^ = note: `#[warn(private_interfaces)]` on by default
问题
我理解该警告:该错误类型对crate的调用者不可用。但据我所知,private::Error同样如此,然而do2并未触发此类警告。这是编译器的限制,还是两种情况存在微妙差异导致仅前者需警告?
解答
这两种情况存在关键的可见性逻辑差异,并非编译器限制:
- 对于
do1返回的Error:这个类型是根模块下默认可见性(pub(crate),仅当前crate内部可访问)的非pub类型。当外部crate调用do1时,完全无法在代码中引用这个Error类型——既不能写出Err(Error)这样的代码,也无法明确匹配该错误变体,连声明这个类型的变量都做不到,导致调用者根本无法正确处理do1的返回值,因此编译器触发警告。 - 对于
do2返回的private::Error:这个类型是私有模块内的pub类型,只是它所在的private模块默认是pub(crate)可见性。虽然外部crate同样无法直接访问private模块、也不能命名private::Error类型,但Rust允许pub函数返回这种“路径不可达但本身是pub”的类型——调用者可以通过通配符(_)匹配错误分支,用?传播错误,或是通过类型转换处理返回值,属于合法的封装场景,因此编译器不会触发警告。
简单来说:前者是用非pub类型作为公共API的一部分,属于API设计的不合理;后者是用私有模块封装pub类型,对外暴露不透明的API,是Rust中常见的封装手段,因此编译器的警告逻辑会区分这两种情况。
内容的提问来源于stack exchange,提问作者ollien
相关产品推荐
相关产品推荐

