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:
Optiontype. We already have a lint in clippy that suggest to replace it with
ok_or_elseif any computations are done there. It’s a good signal that it shall be done. On the other hand,
or_or_elsewith constant value lambda would be always inlined and thus have same performance as before.
or_or_elsesignature and implementation, remove the latter (or make it just the proxy to the
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.