Return different types from match arms
โ Rust ๐ 2025-09-29 ๐ค surdeus ๐๏ธ 12I am trying to create a handle function for axum, but the compiler doesn't let me return the types Html<String> and Result<([(HeaderName, String)], Body), (StatusCode, String)> from two different match arms, even though they both implement IntoResponse. I tried wrapping impl IntoResponse into a Box Box<dyn IntoResponse>, but it seems like axum doesn't implement IntoResponse for Box<IntoResponse>.
Thanks in advance.
Edit: The two types from the if and else blocks are not compatible either, even though i created the if false block to make sure the compiler infers the exact same type.
pub async fn any(State(send_log): ArcSendLog, Path(path): Path<String>) -> impl IntoResponse {
match read_file(format!("{}/{}", HTML_DIR, path)) {
Ok(c) => Html(c),
Err(err) => {
if err.kind() == ErrorKind::InvalidData {
file(State(send_log), path).await
} else {
super::warning("Could not open file", err.kind());
not_found(State(send_log), path.as_str()).await
}
}
}
}
pub async fn file(State(_): ArcSendLog, path: String) -> impl IntoResponse {
let filename = if path.contains('/') {
path.split('/').last().unwrap()
} else {
path.as_str()
};
let file = match tokio::fs::File::open("Cargo.toml").await {
Ok(file) => file,
Err(err) => return Err((StatusCode::NOT_FOUND, format!("File not found: {}", err))),
};
// convert the `AsyncRead` into a `Stream`
let stream = ReaderStream::new(file);
// convert the `Stream` into an `axum::body::HttpBody`
let body = Body::from_stream(stream);
let headers = [
(header::CONTENT_TYPE, "text/toml; charset=utf-8".to_string()),
(
header::CONTENT_DISPOSITION,
format!("attachment; filename=\"{}\"", filename),
),
];
Ok((headers, body))
}
pub async fn not_found(State(_): ArcSendLog, path: &str) -> impl IntoResponse {
let body = read_file_panic(HTML_INVALID).replace("ยงPATHยง", path);
let headers = [(header::CONTENT_LENGTH, body.len().to_string())];
if false {
Err((StatusCode::NOT_FOUND, "File not found".to_string()))
} else {
Ok((headers, body))
}
}
error[E0308]: `if` and `else` have incompatible types
--> src/response.rs:19:17
|
15 | / if err.kind() == ErrorKind::InvalidData {
16 | | file(State(send_log), path).await
| | --------------------------------- expected because of this
17 | | } else {
18 | | super::warning("Could not open file", err.kind());
19 | | not_found(State(send_log), path.as_str()).await
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
20 | | }
| |_____________- `if` and `else` have incompatible types
...
24 | pub async fn file(State(_): ArcSendLog, path: String) -> impl IntoResponse {
| ----------------- the expected opaque type
...
52 | pub async fn not_found(State(_): ArcSendLog, path: &str) -> impl IntoResponse {
| ----------------- the found opaque type
|
= note: expected opaque type `impl IntoResponse`
found opaque type `impl IntoResponse`
= note: distinct uses of `impl Trait` result in different opaque types
2 posts - 2 participants
๐ท๏ธ Rust_feed