类型别名与 Never 类型
问题
Rust 的类型别名和 Never 类型(!)有什么用?
答案
类型别名(Type Alias)
类型别名用 type 关键字定义,简化复杂类型签名:
// 简化长类型
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
type Callback = Box<dyn Fn(i32) -> i32 + Send + 'static>;
type Thunk = Box<dyn FnOnce() + Send + 'static>;
// 泛型别名
type ParseResult<T> = Result<T, ParseError>;
fn parse_int(s: &str) -> ParseResult<i32> {
s.parse().map_err(|e| ParseError::new(e))
}
类型别名不创建新类型
类型别名与原类型完全等价,编译器不区分。如果需要类型安全,使用 Newtype 模式。
Never 类型(!)
! 表示永远不会返回值的类型(发散类型):
// 发散函数(diverging function)
fn exit(code: i32) -> ! {
std::process::exit(code);
}
fn infinite_loop() -> ! {
loop {
// 永远循环
}
}
fn always_panic() -> ! {
panic!("崩溃");
}
Never 类型的用途
1. match 分支类型统一
let value: i32 = match result {
Ok(v) => v, // i32
Err(_) => panic!(), // ! 可以强转为任何类型
};
// continue、break、return 也返回 !
let x: i32 = loop {
if condition {
break 42; // i32
}
continue; // ! → 强转为 i32
};
2. Result<T, !> 表示不可能失败
// 转换不可能失败
fn infallible() -> Result<i32, !> {
Ok(42)
}
// 可以直接 unwrap 而不会 panic
let Ok(value) = infallible(); // ! 不可能存在 Err 分支
3. Infallible 枚举
std::convert::Infallible 是稳定版的 never 类型替代品:
impl From<String> for MyType {
// 转换不可能失败
type Error = Infallible;
}
常见面试问题
Q1: 为什么 panic!() 可以出现在任何类型的表达式位置?
答案:
因为 panic!() 返回 !(never 类型),而 ! 可以被强制转换(coerce)为任何类型。这是类型系统的特殊规则——一个永远不会产生值的表达式可以兼容任何类型上下文。
Q2: 类型别名在标准库中有哪些典型应用?
答案:
type Result<T> = Result<T, std::io::Error>—std::io::Resulttype Result<T> = Result<T, std::fmt::Error>—std::fmt::Result
这些别名让 IO 和格式化代码不用每次写完整的 Error 类型。