Looking at this convert function, I was surprised that it doesn’t have a hint::cold_path. IMHO both consuming and producing an error, doubly make the second branch a candidate. OTOH, if it didn’t have the const-hack, a ? would offer no place to put the hint. That makes me wonder, whether just like for panic!() that happens automatically.
pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
// FIXME(const-hack): This should use `?` again, once it's `const`
match run_utf8_validation(v) {
Ok(_) => {
// SAFETY: validation succeeded.
Ok(unsafe { from_utf8_unchecked(v) })
}
Err(err) => Err(err),
}
}
That raises the question: what about None. That might be more common than Err. But is it common enough to make an automatically inserted hint::cold_path counterproductive?
It's not obvious to me that this is the right thing for the standard library to do.
Notably, things like u32::from_str it's not obvious that the Err being cold is necessarily the right choice. And adding anything in ? is at risk of a pretty bad compilation-time hit. (IIRC serde isn't using ? because its generality and From made it materially slower to compile, even if it optimized away.)
So overall, I generally think that leaving this kind of thing to PGO is the better choice.
I definitely don't think doing it for Option would be good, because things like try { x?.foo() } being used on stuff that happens to be None is pretty common when it's used as "this property/hook/etc really is optional". Maybe it'd work in the Err arm for Result::branch? But that'd also make try { x? } no longer a no-op, which has its own consequences. You could always try making a PR for it and see what happens, though since the compiler uses PGO I doubt it'll show any improvement in the compiler perf suite.
The other thing that people are already doing here is doing this specifically for error types.
If you look in anyhow, for example:
That's marked #[cold] so if you're using anyhow then any time ? wraps an error into an anyhow::Error it's already treated as cold automatically.
Which is nice in that it's specific to that error type, since for anyhow it definitely makes sense -- anything non-cold probably shouldn't be taking backtraces and such anyhow.
For what it's worth, in time the macro that I use to avoid calling From (due to const limitations) has an explicit cold path annotation. I have measured real improvements by doing that.