Repository: rust-lang/rfcs

Issue #1922: Lazy version of Option's ".expect()"
Created: 2017-02-23T01:13:23Z
One use of Options's .expect() might be to print a run-time determined string using format!. But this can leads to unexpected performance problems since the string interpolation code is unconditionally executed. It would be nice to have a lazy version of .expect() that takes a closure that returns a String instead.
A possible workaround is to use .unwrap_or_else(|| panic!(...)). Is this considered idiomatic?

Duplicate issue #1952: Lazy formatting equivalent of [Result, Option]::expect()
Created: 2017-03-15T10:48:40Z
I've oft-encountered a want for a version of Result::expect() which performs lazy formatting so I can provide dynamic information in panic messages, without paying the cost of formatting up-front if the unwrap operation succeeds. Currently, it's either necessary to format the error message first, regardless of whether the operation failed or not, or match manually and call panic!().
A naive search shows a number of occurrences of the former pattern in-tree (ignoring the false positives from asm.rs which use an entirely different API):
rust $ grep -r --exclude-dir=parse --include \*.rs "expect(&"
src/libsyntax_ext/format_foreign.rs:                Num::Arg(arg.parse().expect(&format!("invalid format arg `{:?}`", arg)))
src/libsyntax_ext/format_foreign.rs:                Num::Num(s.parse().expect(&format!("invalid format num `{:?}`", s)))
src/libsyntax_ext/format.rs:            panictry!(p.expect(&token::Eq));
src/librustc_trans/back/rpath.rs:        .expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
src/vendor/toml/src/parser.rs:    fn expect(&mut self, ch: char) -> bool {
src/grammar/verify.rs:    let proto_tok = tokens.get(toknum).expect(&not_found[..]);
src/tools/compiletest/src/header.rs:    let major: isize = version_string.parse().ok().expect(&error_string);
src/tools/compiletest/src/runtest.rs:                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:                    .expect(&format!("failed to exec `{:?}`", gdb_path));
src/tools/compiletest/src/runtest.rs:                         input).expect(&format!("failed to exec `{}`", prog));
src/tools/compiletest/src/runtest.rs:            .expect(&format!("failed to exec `{}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:            .expect(&format!("failed to exec `{}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:            .expect(&format!("failed to exec `{}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:            .expect(&format!("failed to exec `{}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:            .expect(&format!("failed to exec `{}`", self.config.adb_path));
src/tools/compiletest/src/runtest.rs:                    .expect(&format!("failed to exec `{}`", self.config.adb_path));

I'd like to propose one of three APIs:


[Result, Option]::expect_fmt(args: std::fmt::Arguments) which is roughly equivalent to .expect(&args.to_string())

Pros: No code bloat due to monomorphization
Cons: further proliferation of fmt::Arguments (which I've always considered to be more of an implementation detail of formatting which is still sometimes useful externally);
expect_fmt(format_args!(...)) is more verbose than expect(&format!(...)), though negligibly.



Changing [Result, Option]::expect() to take some T: Display.

Pros: Works with more things (including fmt::Arguments), doesn't introduce a new API
Cons: more code bloat due to monomorphization (or it could take a trait object), potentially a breaking change (though I doubt it)



Adding a new method which takes some T: Display and prints like expect()

Pros: no potential for breakage
Cons: more API surface, same monomorphization bloat

Closing comment (2017-03-16T16:28:27Z): Also, this is a dupe of #1922.