Motivation
There is plenty of issues when people unintendely use the eager version of mapping result method just because it saves some typing. It results in confusion among the community. It happens even with the compiler team itself.
The most popular using of this method is something like following:
let path = try_get_path(my_str).ok_or(MyError::InvalidPath(my_str))?;
The problem here is that MyError struct is created not only if error actually happened, but on happy path too.
In most cases, people really want to write
let path = try_get_path(my_str).ok_or_else(|| MyError::InvalidPath(my_str))?;
But they donât use it, mostly because it requires a bit more typing as well as they might not notice the difference. Of course, if they find a significant slowdown, they could benchmark code, spot these places and fix them, but in most cases it would remain unnoticed (although it affects performance drastically).
Rust is going into the new epoch, so I believe itâs a good time to consider the change.
The proposal is:
- Deprecate
ok_or method on Option type. We already have a lint in clippy that suggest to replace it with ok_or_else if any computations are done there. Itâs a good signal that it shall be done. On the other hand, or_or_else with constant value lambda would be always inlined and thus have same performance as before.
-
(Optional) Replace
or_or method via or_or_else signature and implementation, remove the latter (or make it just the proxy to the ok_or).
I believe that we mostly want a lazy evaluation rather than eager one. Error value is never a constant, except when itâs just âsomething bad happenedâ static string. So its recalculation on happy paths seems to be a undesirable behavior. In the rare cases when itâs required compiler could always figure out that constant function may be inlined and replaced by value.
This change serves two goals: remove a possible pitfall and make standard library more consistend so user donât have to choose between two similar methods, just pick one, and if it may be optimized compiler will do so.