rust-lang / rfcs

RFCs for changes to Rust
https://rust-lang.github.io/rfcs/
Apache License 2.0
5.96k stars 1.57k forks source link

[RFC] Add `Option::todo` and `Result::todo` #3706

Open zkrising opened 1 month ago

zkrising commented 1 month ago

This RFC proposes Result::todo and Option::todo functions which work like .unwrap() but imply that error handling should be implemented later.

As an example:

// unwrap is still used for cases where you *actually* want to panic-on-err
TcpListener::bind(&addr).unwrap();

// we're panicking because error handling is not implemented yet.
// this use case is common in prototype applications.
let int: i32 = input.parse().todo();
let arg2 = std::env::args().nth(2).todo();
let file_content = fs::read("file.txt").todo();

This is available as a crate, in case you want to use it right now. I've been using this for quite a while now.


n.b. The initial version of this RFC also proposed .unreachable(). Upon more thought and some feedback I've decided that .unreachable() isn't ideal -- It is easily emulated with .expect("reason for why error cannot happen"). Attaching .unreachable() onto this RFC drags it down quite a bit. I think .todo() is a strong improvement to Rust, but I can't think a strong case for .unreachable().


Rendered

Srlion commented 4 weeks ago

It would be great to have something like this. I often find myself thinking, "Why isn't there a tool, like todo!() for Result and Option, that can remind me to handle it later?" Sure, you can set deny rules, but am I really going to deny unwrap everywhere when I have mutex locks scattered around using unwrap? This feature would be perfect for building quick applications where I can focus on error handling later. It's frustrating to have to worry about it right from the start, especially when I might forget an unwrap I used or end up searching through files for an unwrap I left in while testing.

leb-kuchen commented 3 weeks ago

What's wrong with Option::unwrap_or_else? todo! is a macro, so the signature wouldn't even be clear. Should it be &str or format_args!, latter wouldn't even be more ergonomic. There is even a clippy lint for expect(format!), but I guess former can be inefficient, since it should be only used or todos. What about Option::unimplemented, which I guess would have to be efficient, since it would be used in application code? With todo!, unreachable! and unimplemented! there are already 3 similar ways to panic, so why add more?

castarco commented 3 weeks ago

As a not sophisticated Rust user (I follow many of the weird theoretical discussions about the language, but I rarely engage, as my real use cases are pretty simple) I'm sympathetic to the goal of being able to write very clear and concise code (where the intent is always "self-evident", or almost).

I understand that .unwrap() and its siblings might not feel as enough given that many people have slightly different understanding of the intent behind their usage and how and when to use them...

But .todo() seems to me like a strange choice of words to convey the specific intent expressed in this RFC. I see how it relates to the todo! macro, but that's the only reason I can understand what .todo() does without having to go into its documentation (seeing it called as a trait method doesn't feel the same as seeing a standalone "function" call), I think it shouldn't be like that.

In short, I support the idea of continuing the exploration for better names, even if this leads to a small amount of redundancy on the std lib side, but I also think that RFCs like this one (which one should expect to be at least slightly controversial) should have some extra work behind before being pushed:

danakj commented 3 weeks ago

It may be nice if you could shove a bug number or arbitrary string in the arguments.

SOF3 commented 3 weeks ago

Rephrasing @leb-kuchen's comment, .unwrap_or_else(|| todo!()) totally satisfies the "IDE could mark .todo differently from .expect" requirement as @lebensterben mentioned above as well. So .todo() only serves the purpose of conciseness, but if we cannot come up with a good, short, clear name, it would be no better than .unwrap_or_else(|| todo!()).