Rust新手疑问:match分支未加return报类型不兼容,为何需添加return?
Rust async函数中match分支为何需要添加return?
我是Rust新手,编写了如下async函数:
async fn create(body: String) -> impl IntoResponse { let j = match serde_json::from_str::<CreationJSON>(&body) { Ok(j) => j, Err (_) => ( StatusCode::UNPROCESSABLE_ENTITY, "body is invalid".to_string(), ), }; println!("{:?}", j.record_stringified); ( StatusCode::CREATED, "created".to_string(), ) }
这段代码报错:
error[E0308]: `match` arms have incompatible types --> src/main.rs:128:20 | 126 | let j = match serde_json::from_str::<CreationJSON>(&body) { | ------------------------------------------------- `match` arms have incompatible types 127 | Ok(j) => j, | - this is found to be of type `CreationJSON` 128 | Err (_) => ( | ____________________^ 129 | | StatusCode::UNPROCESSABLE_ENTITY, 130 | | "body is invalid".to_string(), 131 | | ), | |_________^ expected `CreationJSON`, found `(StatusCode, String)` | = note: expected struct `CreationJSON` found tuple `(axum::http::StatusCode, std::string::String)`
但在Err分支添加return后代码可正常运行:
async fn create(body: String) -> impl IntoResponse { let j = match serde_json::from_str::<CreationJSON>(&body) { Ok(j) => j, Err (_) => return ( StatusCode::UNPROCESSABLE_ENTITY, "body is invalid".to_string(), ), }; println!("{:?}", j.record_stringified); ( StatusCode::CREATED, "created".to_string(), ) }
我疑惑为何需要在Err分支添加return?我以为Rust中函数末尾无分号会自动返回结果。
原因解析
match表达式的类型一致性要求
Rust的match是一个表达式,它的所有分支必须返回完全相同的类型——因为你把match的结果赋值给了变量j,Ok分支返回的是CreationJSON类型,而Err分支返回的是(StatusCode, String)元组,这两个类型完全不匹配,编译器自然会抛出类型不兼容的错误。return的作用是提前终止函数
当你在Err分支添加return后,这个分支就不再是给j赋值了,而是直接提前返回整个函数的结果。你的函数返回类型是impl IntoResponse,不管是Err分支的(StatusCode, String),还是函数末尾的成功响应元组,都实现了IntoResponsetrait,符合返回类型要求。同时,添加return后,Err分支会直接跳出函数,不会执行后面的println!和成功响应代码,也就不需要给j赋值了,类型不匹配的问题自然消失。关于自动返回的误解
你说的“函数末尾无分号自动返回”是对的,但那是指函数的最终返回值。而你最初的写法里,Err分支是在给j赋值,属于函数中间的变量赋值逻辑,不是在返回函数结果,所以自动返回的规则在这里不适用。
内容的提问来源于stack exchange,提问作者sudoExclamationExclamation
相关产品推荐
相关产品推荐

