From b9960614850f121d7f009b28c681fee9c78e6084 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 11 Jan 2024 21:20:15 -0800 Subject: [PATCH] Tune the inlinability of `unwrap` --- library/core/src/option.rs | 12 +++++++-- library/core/src/result.rs | 2 +- .../debuginfo-inline-callsite-location.rs | 4 +-- tests/codegen/infallible-unwrap-in-opt-z.rs | 26 +++++++++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 tests/codegen/infallible-unwrap-in-opt-z.rs diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ff4353492498c..975aff90d35f0 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -921,14 +921,14 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.unwrap(), "air"); // fails /// ``` - #[inline] + #[inline(always)] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn unwrap(self) -> T { match self { Some(val) => val, - None => panic("called `Option::unwrap()` on a `None` value"), + None => unwrap_failed(), } } @@ -1970,6 +1970,14 @@ impl Option> { } } +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cold] +#[track_caller] +const fn unwrap_failed() -> ! { + panic("called `Option::unwrap()` on a `None` value") +} + // This is a separate function to reduce the code size of .expect() itself. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index eff1b9b59b14e..1f448984e531c 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1061,7 +1061,7 @@ impl Result { /// let x: Result = Err("emergency failure"); /// x.unwrap(); // panics with `emergency failure` /// ``` - #[inline] + #[inline(always)] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap(self) -> T diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs index b1475ee793160..d529f9ccead56 100644 --- a/tests/codegen/debuginfo-inline-callsite-location.rs +++ b/tests/codegen/debuginfo-inline-callsite-location.rs @@ -4,9 +4,9 @@ // can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail // calls to panic. -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E // CHECK-SAME: !dbg ![[#first_dbg:]] -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E // CHECK-SAME: !dbg ![[#second_dbg:]] // CHECK-DAG: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap" diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs new file mode 100644 index 0000000000000..5c57b41532fbb --- /dev/null +++ b/tests/codegen/infallible-unwrap-in-opt-z.rs @@ -0,0 +1,26 @@ +// compile-flags: -C opt-level=z --edition=2021 +// ignore-debug + +#![crate_type = "lib"] + +// From + +// CHECK-LABEL: @read_up_to_8( +#[no_mangle] +pub fn read_up_to_8(buf: &[u8]) -> u64 { + // CHECK-NOT: unwrap_failed + if buf.len() < 4 { + // actual instance has more code. + return 0; + } + let lo = u32::from_le_bytes(buf[..4].try_into().unwrap()) as u64; + let hi = u32::from_le_bytes(buf[buf.len() - 4..][..4].try_into().unwrap()) as u64; + lo | (hi << 8 * (buf.len() as u64 - 4)) +} + +// CHECK-LABEL: @checking_unwrap_expectation( +#[no_mangle] +pub fn checking_unwrap_expectation(buf: &[u8]) -> &[u8; 4] { + // CHECK: call void @_ZN4core6result13unwrap_failed17h + buf.try_into().unwrap() +}