惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
IT之家
IT之家
C
Check Point Blog
T
The Blog of Author Tim Ferriss
S
SegmentFault 最新的问题
人人都是产品经理
人人都是产品经理
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
M
MIT News - Artificial intelligence
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Security Blog
Microsoft Security Blog
G
Google Developers Blog
F
Fortinet All Blogs
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
Hugging Face - Blog
Hugging Face - Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)

The Rust Programming Language Forum - Latest topics

Beginner building a Rust backend framework (AI-assisted) — feedback appreciated C++ to Rust -- Exceptions Re-exporting a trait with a custom derive_macro Gold linker is deprecated Why is using PhantomData valid in this case? Code review for Static Pool Allocator Looking for a pool based allocator Why is this legal? What does it mean for Rustc to run "out of TLS keys"? Using async/await internally with no internal runtime, but exposing a nonblocking poll API — is this a reasonable design? Testing functions that use randomness `cargo-path`: improve coding agents&#39; ability to find Rust documentation Rust task runners Lifetime weird case Windows - USB device not detected A random rustc-ice-[...].txt file appeared Develop rust where the environment is setup in a docker Undefined Behavior: in-bounds pointer arithmetic failed: attempting to offset pointer by 20 bytes, but got alloc238 which is only 1 byte from the end of the allocation Unbug 0.5 - Runtime debug assertions Is there a tiny error in section 6.2 Reference types? Lifetime woes implementing ratatui::Widget for a reference Rusqlite + Chrono: How do I simplify code to obtain chrono datetime value From OOP to Rust – struggling with code organization and data structure design Way to avoid a self-referential struct Rust RF and audio resources/communities Whyhttp - HTTP mocks that fail where the bug actually is Using tokio channel permits in a tower service Arc::increment_strong_count design question (cross-post) `&T`, `&mut T`, `Pin<&mut T>` and `&Cell<T>`: Ways of Borrowing a `T` Ratatui detect arrow key press and release
How to make Rust as vertical as possible?
ujjwal · 2026-04-17 · via The Rust Programming Language Forum - Latest topics

April 16, 2026, 6:38pm 1

Hi. I am a beginner. Please don't harass me for the sake of my mental health. It's already going down very quickly since the day I learned about Rust.

I have two questions. I think that these two may be related.

I once heard that vertical code is easier to follow along. In other words, one should ignore nesting as much as possible. I believe everyone would agree on this.
Consider the following example from a C++ like language:

void do_something() {
    if (condition) {
        // do something
    } else {
        return;
    }
}

A cleaner version of the above can be:

void do_something() {
    if (!condition) return;
    // do something
}

I personally prefer this style and am used to it.
But it looks impossible to do in Rust.
I mean, every here and there we have let Some(x) = Option<_> and it just needs to have those curly braces.
Then we have the question mark (?) operator. As we all know, it is used to propagate errors.
Suppose we have 10 functions. Second function calling the first one, third one calling the second one, and so on...
Suppose only the first function gives a meaningful error and all other functions just propagate it to higher-number functions.
So the last function would just know that there is some error occurred, but it's just too deep. So, it will require keeping too much context in mind.
As an API user, I don't want errors corresponding to very deep functions.
In my opinion, it would be better if we have error message for each of those functions.
So, here, again comes issue, how to make Rust vertical?

It would help a lot if you gave concrete snippets of code you don't like. It's hard to know where to begin without knowing where you're at.

As for error handling, you can... handle errors? If function 2 has a better way to report the error from function 1, then it's on you to make function 2 do that (perhaps with map_err).

2 Likes

Rather than aiming to make your code vertical, you should aim to make it as much readable as possible.

Your code is meant to be read by at least one human: yourself. Never forget that.

5 Likes

The equivalent would simply be:

fn do_something() {
    if !condition {
        return;
    }
    // do something
}

Likewise, it's common to see:

let Some(whatever) = option else { return /*or `break` or `continue`*/ };

As already mentioned, for handling errors, when possible, I use result.map_err(|err| err.add_context())? instead of just result?. Sometimes, the added context would need ownership over some !Copy variable that I still need to use in the success case, in which case I do:

let success = match result {
    Ok(success) => success,
    // This avoids needing to call `Clone::clone` or similar on `owned_value`.
    Err(err) => return Err(ErrorWithContext(owned_value, err)),
};

8 Likes

kornel April 18, 2026, 1:22am 5

? propagating errors without context can be a problem, but is fixable.

There's .ok_or(Error::Foo) that converts Option to a Result with an error type that can carry more context. For results there's .map_err(…) that gives you an opportunity to add more context to an existing error.

There's a bunch of similar helper methods and you can have a very tight control over this if you want, by using different error types.

If you don't want to write your own boilerplate for custom errors, there are libraries like anyhow that do it for you and let you write .context("whatever") on any Option or Result, so you can provide all the context to build breadcrumbs of what went wrong.