How to emulate `super-let` on stable Rust
⚓ Rust 📅 2025-12-23 👤 surdeus 👁️ 6I want to read an HTTP response body from a cache file; if an error occurs while reading, the data is fetched from the internet.
The cached data and the fetched data have different types: the former is Cache, the latter is Body. To abstract over them, I defined a BodyRef struct that borrows the inner data.
I tried to construct a BodyRef with an if-let-else expression, but the code fails to compile because the lifetime of the fetched data is tied to the else branch.
How should I rewrite this code on stable Rust so the fetched data lives beyond the else branch?
/*
[dependencies]
chrono = { version = "0.4.42", features = ["serde"] }
reqwest = "0.12.28"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.146"
*/
use std::{io, str::FromStr};
use chrono::{DateTime, Utc};
use reqwest::Url;
use serde::{Deserialize, Serialize};
use serde_json::{Map as JsonMap, Value as JsonValue};
struct Body {
map: JsonMap<String, JsonValue>,
text: String,
}
struct BodyRef<'a> {
map: &'a JsonMap<String, JsonValue>,
text: &'a str,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(try_from = "CacheSerde")]
struct Cache {
url: Url,
date: DateTime<Utc>,
text: String,
#[serde(skip)] map: JsonMap<String, JsonValue>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CacheSerde {
url: Url,
date: DateTime<Utc>,
text: String,
}
impl TryFrom<CacheSerde> for Cache {
type Error = serde_json::Error;
fn try_from(value: CacheSerde) -> Result<Self, Self::Error> {
let body: JsonMap<String, JsonValue> = JsonMap::from_str(&value.text)?;
Ok(Self {
url: value.url,
date: value.date,
text: value.text,
map: body,
})
}
}
fn read_cache() -> io::Result<Cache> { todo!() }
fn write_cache(_: &Cache) -> io::Result<()> { todo!() }
fn send_request() -> io::Result<Body> { todo!() }
fn main() {
let cache: Option<Cache> = read_cache()
.inspect_err(|e| {
eprintln!("INFO: Failed to read cache. Fetching data from the network.\nCache error: {e}");
})
.ok();
let body: BodyRef<'_> = if let Some(cache) = cache.as_ref() {
BodyRef {
map: &cache.map,
text: &cache.text,
}
} else {
// `super let` is experimental
// super let body = send_request().unwrap();
let body: Body = send_request().unwrap();
BodyRef {
// `body.map` does not live long enough borrowed value does not live long enough [E0597]
map: &body.map,
text: &body.text,
}
};
dbg!(body.text);
}
5 posts - 3 participants
🏷️ Rust_feed