G.ERR.02 不要滥用 expect,请考虑用 unwrap_or_ 系列方法代替

【级别】 建议

【描述】

使用 expect 的时候请遵循 expect 的语义,不要滥用。

expect 的语义:

我不打算处理 NoneErr 这种可能性,因为我知道这种可能性永远不会发生,或者,它不应该发生。但是 类型系统并不知道它永远不会发生。所以,我需要像类型系统保证,如果它确实发生了,它可以认为是一种错误,并且程序应该崩溃,并带着可以用于跟踪和修复该错误的栈跟踪信息。

但是对于一些存在“副作用”的函数,在 遇到 NoneErr 时,可能需要返回一些指定的值。这个时候用 expect 就不太符合语义。

如果你的用法完全符合 expect 语义,那么可以设置 #![allow(clippy::expect_fun_call]

【反例】

#![warn(clippy::expect_used)]
fn main(){
    let foo = Some(String::new());
    let err_code = "418";
    let err_msg = "I'm a teapot";
    // 不符合:因为要返回指定的错误码等信息,不适合 expect 语义
    foo.expect(&format!("Err {}: {}", err_code, err_msg)); 
}

【正例】

#![warn(clippy::expect_used)]
fn main(){
    let foo = Some(String::new());
    let err_code = "418";
    let err_msg = "I'm a teapot";
    // 符合
    foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg));  // 你可以根据场景选择性使用 panic! 或者 不 panic!
}

【例外】

完全符合 expect 语义的使用。


#![allow(unused)]
#![allow(clippy::expect_fun_call]

fn main() {
// 这个配置文件默认会跟随源码出现,所以,必定可以读取到
// 这个配置文件不应该没有被提供,如果万一出现了没有提供的情况,需要 Panic 并提供错误信息方便调试,或者让使用者知道原因
let config = Config::read("some_config.toml").expect("Provide the correct configuration file"); 


// 或者

use std::net::IpAddr;
let _home: IpAddr = "127.0.0.1".parse().expect("Provide the correct Ip addr");

}

【Lint 检测】

lint nameClippy 可检测Rustc 可检测Lint Grouplevel
expect_fun_callyesnoperfwarn
expect_usedyesnorestrictionallow