You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by rd...@apache.org on 2022/10/22 18:39:51 UTC

[incubator-teaclave-sgx-sdk] branch v2.0.0-preview updated: Support rust-nightly-2022-10-22

This is an automated email from the ASF dual-hosted git repository.

rduan pushed a commit to branch v2.0.0-preview
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git


The following commit(s) were added to refs/heads/v2.0.0-preview by this push:
     new 4e1860a4 Support rust-nightly-2022-10-22
4e1860a4 is described below

commit 4e1860a4f49f74fe2b8af120400d5abe870006ca
Author: volcano <vo...@163.com>
AuthorDate: Sun Oct 23 02:36:56 2022 +0800

    Support rust-nightly-2022-10-22
---
 rust-toolchain                                     |    2 +-
 rustlib/panic_abort/src/lib.rs                     |   13 +-
 rustlib/panic_unwind/Cargo.toml                    |    1 -
 rustlib/panic_unwind/src/gcc.rs                    |   78 -
 rustlib/panic_unwind/src/lib.rs                    |   16 +-
 .../hyper-rustls-https-server/enclave/src/lib.rs   |    6 +-
 samplecode/rpc/client/enclave/src/lib.rs           |    8 +-
 samplecode/rpc/server/enclave/src/lib.rs           |   10 +-
 samplecode/seal/enclave/src/lib.rs                 |   12 +-
 samplecode/switchless/app/build.rs                 |    5 +-
 samplecode/switchless/app/src/main.rs              |   14 +-
 .../zlib-lazy-static-sample/enclave/src/lib.rs     |    8 +-
 sgx_alloc/src/alignalloc.rs                        |    2 +-
 sgx_alloc/src/alignbox.rs                          |    8 +-
 sgx_backtrace/src/symbolize/libbacktrace.rs        |    2 +-
 sgx_build_helper/build_helper/src/lib.rs           |    4 +-
 sgx_dcap/tkey_exchange/src/session/manager.rs      |   10 +-
 sgx_dcap/tvl/src/capi.rs                           |    4 +-
 sgx_demangle/src/legacy.rs                         |    6 +-
 sgx_edl/edl/sgx_fd.edl                             |    3 +
 sgx_ffi/src/c_str.rs                               | 1548 +-------------------
 sgx_ffi/src/c_str/tests.rs                         |  200 ---
 sgx_ffi/src/lib.rs                                 |   11 -
 sgx_key_exchange/message/src/message.rs            |    4 +-
 .../tkey_exchange/src/session/manager.rs           |    6 +-
 sgx_key_exchange/ukey_exchange/src/capi.rs         |    4 +-
 sgx_key_exchange/ukey_exchange/src/session.rs      |    4 +-
 sgx_libc/Cargo.toml                                |    2 +-
 sgx_libc/sgx_tlibc_sys/src/lib.rs                  |    1 +
 sgx_libc/src/linux/ocall/fd.rs                     |   20 +-
 sgx_libc/src/linux/ocall/sync.rs                   |   12 +-
 sgx_libc/src/linux/pthread/mod.rs                  |    6 +-
 sgx_oc/src/lib.rs                                  |    1 +
 sgx_oc/src/linux/edl/fd.rs                         |    6 +
 sgx_oc/src/linux/mod.rs                            |   12 +-
 sgx_oc/src/linux/ocall/env.rs                      |    2 +-
 sgx_oc/src/linux/ocall/fd.rs                       |   25 +-
 sgx_oc/src/linux/ocall/mem.rs                      |    8 +-
 sgx_oc/src/linux/ocall/mod.rs                      |   37 +-
 sgx_oc/src/linux/ocall/socket.rs                   |   14 +-
 sgx_oc/src/linux/ocall/socket_msg.rs               |   16 +-
 sgx_oc/src/linux/x86_64/mod.rs                     |    5 +-
 sgx_protected_fs/tfs/src/capi.rs                   |    8 +-
 sgx_protected_fs/tfs/src/sys/error.rs              |    4 +-
 sgx_protected_fs/ufs/src/lib.rs                    |    4 +-
 sgx_rand/src/isaac.rs                              |    2 +-
 sgx_rsrvmm/src/rsrvmm/area.rs                      |    6 +-
 sgx_rsrvmm/src/rsrvmm/manager.rs                   |    2 +-
 sgx_serialize/src/json.rs                          |   13 +-
 sgx_serialize/src/lib.rs                           |    3 +-
 sgx_serialize/src/opaque.rs                        |    2 +-
 sgx_serialize/src/types.rs                         |   67 +-
 sgx_sync/Cargo.toml                                |    1 +
 sgx_sync/src/capi.rs                               |   24 +-
 sgx_sync/src/condvar.rs                            |   19 +-
 sgx_sync/src/condvar/check.rs                      |   29 +-
 sgx_sync/src/futex.rs                              |   12 +-
 sgx_sync/src/lazy_box.rs                           |  118 ++
 sgx_sync/src/lazy_lock.rs                          |   88 ++
 sgx_sync/src/lib.rs                                |   10 +-
 sgx_sync/src/mutex.rs                              |   22 +-
 sgx_sync/src/{lazy.rs => once_lock.rs}             |  200 +--
 sgx_sync/src/remutex.rs                            |   38 +-
 sgx_sync/src/rwlock.rs                             |   24 +-
 sgx_sync/src/sys/condvar.rs                        |  116 +-
 sgx_sync/src/sys/futex.rs                          |   24 +-
 sgx_sync/src/sys/mod.rs                            |    5 +-
 sgx_sync/src/sys/mutex.rs                          |  269 ++--
 sgx_sync/src/sys/ocall/mod.rs                      |    2 +-
 sgx_sync/src/sys/rwlock.rs                         |  188 ++-
 sgx_tdh/src/capi.rs                                |   10 +-
 sgx_tests/cov/src/lib.rs                           |   10 +-
 sgx_tests/utils/src/lib.rs                         |    2 -
 sgx_tests/utils/src/stats.rs                       |    6 +-
 sgx_trts/src/arch.rs                               |    2 +
 sgx_trts/src/call/ocalloc.rs                       |    4 +-
 sgx_trts/src/capi.rs                               |   30 +-
 sgx_trts/src/elf/control_flow.rs                   |    2 +-
 sgx_trts/src/elf/header.rs                         |    2 +-
 sgx_trts/src/elf/program.rs                        |    2 +-
 sgx_trts/src/elf/slice.rs                          |    1 +
 sgx_trts/src/enclave/parse.rs                      |    9 +-
 sgx_trts/src/enclave/state.rs                      |    7 +-
 sgx_trts/src/feature/sys.rs                        |    5 +-
 sgx_trts/src/inst/hyper/inst.rs                    |    2 +
 sgx_trts/src/inst/sim/tls/gnu.rs                   |    1 +
 sgx_trts/src/lib.rs                                |   10 +-
 sgx_trts/src/sync/lazy.rs                          |  257 ++++
 sgx_trts/src/sync/mod.rs                           |    6 +-
 sgx_trts/src/sync/mutex.rs                         |    2 +-
 sgx_trts/src/sync/rwlock.rs                        |    2 +-
 sgx_trts/src/tcs/list.rs                           |    2 +-
 sgx_trts/src/tcs/tc.rs                             |    2 +-
 sgx_trts/src/thread/tls/bitset.rs                  |    3 +-
 sgx_trts/src/thread/tls/mod.rs                     |    8 +-
 sgx_trts/src/veh/exception.rs                      |   10 +-
 sgx_trts/src/veh/list.rs                           |    2 +-
 sgx_trts/src/xsave.rs                              |    6 +-
 sgx_tse/src/capi.rs                                |    6 +-
 sgx_tse/src/se.rs                                  |    2 +-
 sgx_tstd/src/alloc.rs                              |   29 +-
 sgx_tstd/src/backtrace.rs                          |   15 +-
 sgx_tstd/src/backtrace/tests.rs                    |    6 +-
 sgx_tstd/src/collections/hash/benches/map.rs       |    2 -
 sgx_tstd/src/collections/hash/map.rs               |  258 +++-
 sgx_tstd/src/collections/hash/map/tests.rs         |   33 +-
 sgx_tstd/src/collections/hash/set.rs               |  107 +-
 sgx_tstd/src/collections/hash/set/tests.rs         |   10 +-
 sgx_tstd/src/collections/mod.rs                    |    9 +-
 sgx_tstd/src/env.rs                                |   77 +-
 sgx_tstd/src/error.rs                              |  909 +-----------
 sgx_tstd/src/error/tests.rs                        |   11 +-
 sgx_tstd/src/f32.rs                                |   68 +-
 sgx_tstd/src/f64.rs                                |   69 +-
 sgx_tstd/src/ffi/c_str.rs                          |   58 -
 sgx_tstd/src/ffi/mod.rs                            |   15 +-
 sgx_tstd/src/ffi/os_str.rs                         |   84 +-
 sgx_tstd/src/ffi/os_str/tests.rs                   |   14 +
 sgx_tstd/src/fs.rs                                 |  169 ++-
 sgx_tstd/src/fs/tests.rs                           |   16 +-
 sgx_tstd/src/io/buffered/bufreader.rs              |  105 +-
 sgx_tstd/src/io/buffered/bufreader/buffer.rs       |  139 ++
 sgx_tstd/src/io/buffered/bufwriter.rs              |    4 +-
 sgx_tstd/src/io/buffered/linewriter.rs             |    4 +-
 sgx_tstd/src/io/buffered/tests.rs                  |   59 +-
 sgx_tstd/src/io/copy.rs                            |   44 +-
 sgx_tstd/src/io/cursor.rs                          |  182 ++-
 sgx_tstd/src/io/cursor/tests.rs                    |  135 +-
 sgx_tstd/src/io/error.rs                           |  108 +-
 sgx_tstd/src/io/error/repr_unpacked.rs             |    6 +-
 sgx_tstd/src/io/error/tests.rs                     |   72 +-
 sgx_tstd/src/io/impls.rs                           |   62 +-
 sgx_tstd/src/io/mod.rs                             |  194 ++-
 sgx_tstd/src/io/prelude.rs                         |    2 +-
 sgx_tstd/src/io/readbuf.rs                         |  316 ++--
 sgx_tstd/src/io/readbuf/tests.rs                   |  218 ++-
 sgx_tstd/src/io/stdio.rs                           |  476 +++---
 sgx_tstd/src/io/stdio/tests.rs                     |    6 +-
 sgx_tstd/src/io/tests.rs                           |   52 +-
 sgx_tstd/src/io/util.rs                            |   14 +-
 sgx_tstd/src/io/util/tests.rs                      |   48 +-
 sgx_tstd/src/lib.rs                                |  140 +-
 sgx_tstd/src/macros.rs                             |   66 +-
 sgx_tstd/src/net/display_buffer.rs                 |   57 +
 sgx_tstd/src/net/{ip.rs => ip_addr.rs}             |  411 +++---
 sgx_tstd/src/net/{ip => ip_addr}/tests.rs          |  123 +-
 sgx_tstd/src/net/mod.rs                            |   24 +-
 sgx_tstd/src/net/parser.rs                         |  158 +-
 sgx_tstd/src/net/{addr.rs => socket_addr.rs}       |  265 ++--
 sgx_tstd/src/net/{addr => socket_addr}/tests.rs    |  102 +-
 sgx_tstd/src/net/tcp.rs                            |   15 +-
 sgx_tstd/src/net/tcp/tests.rs                      |   11 +-
 sgx_tstd/src/net/udp.rs                            |   14 +-
 sgx_tstd/src/net/udp/tests.rs                      |    6 +-
 sgx_tstd/src/num/benches.rs                        |    2 +-
 sgx_tstd/src/os/fd/mod.rs                          |   14 +-
 sgx_tstd/src/os/fd/owned.rs                        |  130 +-
 sgx_tstd/src/os/fd/raw.rs                          |   87 +-
 sgx_tstd/src/os/fd/tests.rs                        |   60 +
 sgx_tstd/src/os/linux/fs.rs                        |   26 +-
 sgx_tstd/src/os/linux/mod.rs                       |    2 +
 sgx_tstd/src/os/{unix/io/raw.rs => linux/net.rs}   |    4 +-
 sgx_tstd/src/os/linux/raw.rs                       |    4 +-
 sgx_tstd/src/os/mod.rs                             |    4 +-
 sgx_tstd/src/os/{unix/io/fd.rs => net/mod.rs}      |    7 +-
 sgx_tstd/src/os/net/tcp.rs                         |   82 ++
 sgx_tstd/src/{ffi/c_str => os/net}/tests.rs        |   45 +-
 sgx_tstd/src/os/raw/mod.rs                         |   92 +-
 sgx_tstd/src/{sys/os_str => os/raw}/tests.rs       |   19 +-
 sgx_tstd/src/os/unix/fs.rs                         |    4 +-
 sgx_tstd/src/os/unix/io/mod.rs                     |   72 +-
 sgx_tstd/src/os/unix/io/{fd => }/tests.rs          |    0
 sgx_tstd/src/os/unix/net/addr.rs                   |   37 +-
 sgx_tstd/src/os/unix/net/ancillary.rs              |   16 +-
 sgx_tstd/src/os/unix/net/datagram.rs               |   46 +-
 sgx_tstd/src/os/unix/net/listener.rs               |   10 +-
 sgx_tstd/src/os/unix/net/stream.rs                 |   34 +-
 sgx_tstd/src/os/unix/net/tests.rs                  |   13 +-
 sgx_tstd/src/os/unix/process.rs                    |   69 +-
 sgx_tstd/src/panicking.rs                          |  183 ++-
 sgx_tstd/src/path.rs                               |   76 +-
 sgx_tstd/src/path/tests.rs                         |   44 +-
 sgx_tstd/src/{io/prelude.rs => personality.rs}     |   19 +-
 .../src => sgx_tstd/src/personality}/dwarf/eh.rs   |   32 +-
 .../src => sgx_tstd/src/personality}/dwarf/mod.rs  |   22 +-
 .../{sys_common/net => personality/dwarf}/tests.rs |   28 +-
 .../src => sgx_tstd/src/personality}/gcc.rs        |   87 +-
 sgx_tstd/src/prelude/mod.rs                        |   11 +
 sgx_tstd/src/process.rs                            |  285 ++--
 sgx_tstd/src/sync/condvar.rs                       |    3 +-
 sgx_tstd/src/sync/lazy_lock.rs                     |  129 ++
 sgx_tstd/src/sync/lazy_lock/tests.rs               |  162 ++
 sgx_tstd/src/sync/mod.rs                           |    8 +-
 sgx_tstd/src/sync/mpsc/blocking.rs                 |   13 +-
 sgx_tstd/src/sync/mpsc/mod.rs                      |   20 +-
 sgx_tstd/src/sync/mpsc/mpsc_queue/tests.rs         |    4 +-
 sgx_tstd/src/sync/mpsc/oneshot.rs                  |   24 +-
 sgx_tstd/src/sync/mpsc/shared.rs                   |   33 +-
 sgx_tstd/src/sync/mpsc/spsc_queue/tests.rs         |    9 +-
 sgx_tstd/src/sync/mpsc/stream.rs                   |   31 +-
 sgx_tstd/src/sync/mpsc/sync.rs                     |    1 +
 sgx_tstd/src/sync/mpsc/sync_tests.rs               |   29 +-
 sgx_tstd/src/sync/mpsc/tests.rs                    |   24 +-
 sgx_tstd/src/sync/mutex.rs                         |   57 +-
 sgx_tstd/src/sync/mutex/tests.rs                   |    4 +-
 sgx_tstd/src/sync/once.rs                          |  302 +---
 sgx_tstd/src/{lazy.rs => sync/once_lock.rs}        |  377 ++---
 sgx_tstd/src/{lazy => sync/once_lock}/tests.rs     |  167 +--
 sgx_tstd/src/sync/poison.rs                        |   17 +-
 sgx_tstd/src/sync/rwlock.rs                        |  139 +-
 sgx_tstd/src/sync/rwlock/tests.rs                  |    4 +-
 sgx_tstd/src/sys/args.rs                           |    4 +-
 sgx_tstd/src/sys/backtrace/mod.rs                  |    8 +-
 sgx_tstd/src/sys/cmath.rs                          |    3 +
 .../src/{os/unix/io/raw.rs => sys/common/mod.rs}   |    5 +-
 sgx_tstd/src/sys/common/small_c_string.rs          |   70 +
 sgx_tstd/src/sys/common/tests.rs                   |   86 ++
 sgx_tstd/src/sys/fd.rs                             |   23 +-
 sgx_tstd/src/sys/fs.rs                             |  223 +--
 sgx_tstd/src/sys/futex.rs                          |   41 +-
 sgx_tstd/src/sys/io.rs                             |   18 +-
 sgx_tstd/src/sys/kernel_copy.rs                    |    2 +-
 sgx_tstd/src/sys/kernel_copy/tests.rs              |   19 +-
 sgx_tstd/src/sys/mod.rs                            |    1 +
 sgx_tstd/src/sys/net.rs                            |   24 +-
 sgx_tstd/src/sys/os.rs                             |   35 +-
 sgx_tstd/src/sys/os_str.rs                         |   40 +-
 sgx_tstd/src/sys/os_str/tests.rs                   |   10 +-
 sgx_tstd/src/sys/path.rs                           |    3 +-
 .../src/{sys_common/thread.rs => sys/process.rs}   |    4 +-
 sgx_tstd/src/sys/rand.rs                           |   18 +-
 sgx_tstd/src/sys/stdio.rs                          |   46 +-
 sgx_tstd/src/sys/thread.rs                         |    9 +-
 sgx_tstd/src/sys/thread_local_key.rs               |    5 -
 sgx_tstd/src/sys/time.rs                           |  203 ++-
 sgx_tstd/src/sys/unsupported/mod.rs                |    2 -
 sgx_tstd/src/sys/unsupported/process.rs            |   68 +-
 sgx_tstd/src/sys_common/backtrace.rs               |   11 +-
 sgx_tstd/src/sys_common/gnu/libbacktrace.rs        |    2 +-
 sgx_tstd/src/sys_common/mod.rs                     |    1 +
 sgx_tstd/src/sys_common/net.rs                     |  107 +-
 sgx_tstd/src/sys_common/net/tests.rs               |    2 +-
 sgx_tstd/src/sys_common/once/futex.rs              |  151 ++
 sgx_tstd/src/sys_common/once/generic.rs            |  298 ++++
 sgx_tstd/src/sys_common/once/mod.rs                |   46 +
 sgx_tstd/src/sys_common/remutex/tests.rs           |   33 +-
 sgx_tstd/src/sys_common/thread.rs                  |    1 -
 sgx_tstd/src/sys_common/thread_local_dtor.rs       |    2 +-
 sgx_tstd/src/sys_common/thread_local_key.rs        |   28 +-
 sgx_tstd/src/sys_common/thread_local_key/tests.rs  |    9 +-
 sgx_tstd/src/sys_common/thread_parker/futex.rs     |   29 +-
 sgx_tstd/src/sys_common/thread_parker/generic.rs   |   27 +-
 sgx_tstd/src/sys_common/wtf8.rs                    |  102 +-
 sgx_tstd/src/sys_common/wtf8/tests.rs              |  296 +++-
 sgx_tstd/src/thread/local.rs                       |  495 ++++++-
 sgx_tstd/src/thread/local/tests.rs                 |    2 +-
 sgx_tstd/src/thread/mod.rs                         |  394 ++++-
 sgx_tstd/src/thread/scoped.rs                      |   94 +-
 sgx_tstd/src/thread/tests.rs                       |   78 +-
 sgx_tstd/src/time.rs                               |   39 +-
 sgx_tstd/src/time/tests.rs                         |    8 +-
 sgx_tstd/src/untrusted/time.rs                     |   10 +-
 sgx_types/src/error/mod.rs                         |    8 +
 sgx_types/src/lib.rs                               |    1 +
 sgx_types/src/types/tdx.rs                         |    2 +-
 sgx_unwind/src/lib.rs                              |    1 -
 sgx_unwind/src/libunwind.rs                        |    4 +-
 sgx_urts/src/enclave/mod.rs                        |    6 +-
 sgx_urts/src/ocall/fd.rs                           |   17 +-
 269 files changed, 8774 insertions(+), 7189 deletions(-)

diff --git a/rust-toolchain b/rust-toolchain
index 480e8aa7..cd5e8eb2 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-nightly-2022-02-23
+nightly-2022-10-22
diff --git a/rustlib/panic_abort/src/lib.rs b/rustlib/panic_abort/src/lib.rs
index 36a1fc9f..1902efcf 100644
--- a/rustlib/panic_abort/src/lib.rs
+++ b/rustlib/panic_abort/src/lib.rs
@@ -9,7 +9,6 @@
 #![panic_runtime]
 #![allow(unused_features)]
 #![feature(core_intrinsics)]
-#![feature(nll)]
 #![feature(panic_runtime)]
 #![feature(std_internals)]
 #![feature(staged_api)]
@@ -62,6 +61,14 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe
 // binaries, but it should never be called as we don't link in an unwinding
 // runtime at all.
 pub mod personalities {
-    #[rustc_std_internal_symbol]
-    pub extern "C" fn rust_eh_personality() {}
+    // In the past this module used to contain stubs for the personality
+    // functions of various platforms, but these where removed when personality
+    // functions were moved to std.
+
+    // This corresponds to the `eh_catch_typeinfo` lang item
+    // that's only used on Emscripten currently.
+    //
+    // Since panics don't generate exceptions and foreign exceptions are
+    // currently UB with -C panic=abort (although this may be subject to
+    // change), any catch_unwind calls will never use this typeinfo.
 }
diff --git a/rustlib/panic_unwind/Cargo.toml b/rustlib/panic_unwind/Cargo.toml
index a6a65642..0689089e 100644
--- a/rustlib/panic_unwind/Cargo.toml
+++ b/rustlib/panic_unwind/Cargo.toml
@@ -31,5 +31,4 @@ bench = false
 doc = false
 
 [dependencies]
-sgx_types = { path = "../../sgx_types" }
 sgx_unwind = { path = "../../sgx_unwind" }
diff --git a/rustlib/panic_unwind/src/gcc.rs b/rustlib/panic_unwind/src/gcc.rs
index c1599373..a539b590 100644
--- a/rustlib/panic_unwind/src/gcc.rs
+++ b/rustlib/panic_unwind/src/gcc.rs
@@ -39,8 +39,6 @@
 use alloc::boxed::Box;
 use core::any::Any;
 
-use crate::dwarf::eh::{self, EHAction, EHContext};
-use sgx_types::types::{c_int, uintptr_t};
 use sgx_unwind as uw;
 
 #[repr(C)]
@@ -89,79 +87,3 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
     // M O Z \0  R U S T -- vendor, language
     0x4d4f_5a00_5255_5354
 }
-
-// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
-// and TargetLowering::getExceptionSelectorRegister() for each architecture,
-// then mapped to DWARF register numbers via register definition tables
-// (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
-// See also https://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
-
-#[cfg(target_arch = "x86")]
-const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
-
-#[cfg(target_arch = "x86_64")]
-const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
-
-// The following code is based on GCC's C and C++ personality routines.  For reference, see:
-// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
-// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
-
-unsafe extern "C" fn rust_eh_personality_impl(
-    version: c_int,
-    actions: uw::_Unwind_Action,
-    _exception_class: uw::_Unwind_Exception_Class,
-    exception_object: *mut uw::_Unwind_Exception,
-    context: *mut uw::_Unwind_Context,
-) -> uw::_Unwind_Reason_Code {
-    if version != 1 {
-        return uw::_URC_FATAL_PHASE1_ERROR;
-    }
-    let eh_action = match find_eh_action(context) {
-        Ok(action) => action,
-        Err(_) => return uw::_URC_FATAL_PHASE1_ERROR,
-    };
-    if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
-        match eh_action {
-            EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND,
-            EHAction::Catch(_) => uw::_URC_HANDLER_FOUND,
-            EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR,
-        }
-    } else {
-        match eh_action {
-            EHAction::None => uw::_URC_CONTINUE_UNWIND,
-            EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
-                uw::_Unwind_SetIP(context, lpad);
-                uw::_URC_INSTALL_CONTEXT
-            }
-            EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR,
-        }
-    }
-}
-
-#[lang = "eh_personality"]
-unsafe extern "C" fn rust_eh_personality(
-    version: c_int,
-    actions: uw::_Unwind_Action,
-    exception_class: uw::_Unwind_Exception_Class,
-    exception_object: *mut uw::_Unwind_Exception,
-    context: *mut uw::_Unwind_Context,
-) -> uw::_Unwind_Reason_Code {
-    rust_eh_personality_impl(version, actions, exception_class, exception_object, context)
-}
-
-unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction, ()> {
-    let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
-    let mut ip_before_instr: c_int = 0;
-    let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
-    let eh_context = EHContext {
-        // The return address points 1 byte past the call instruction,
-        // which could be in the next IP range in LSDA range table.
-        ip: if ip_before_instr != 0 { ip } else { ip - 1 },
-        func_start: uw::_Unwind_GetRegionStart(context),
-        get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
-        get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
-    };
-    eh::find_eh_action(lsda, &eh_context)
-}
diff --git a/rustlib/panic_unwind/src/lib.rs b/rustlib/panic_unwind/src/lib.rs
index 1f58df13..ea3fdd2b 100644
--- a/rustlib/panic_unwind/src/lib.rs
+++ b/rustlib/panic_unwind/src/lib.rs
@@ -1,14 +1,21 @@
 //! Implementation of panics via stack unwinding
 //!
 //! This crate is an implementation of panics in Rust using "most native" stack
-//! unwinding mechanism of the platform this is being compiled for.
+//! unwinding mechanism of the platform this is being compiled for. This
+//! essentially gets categorized into three buckets currently:
+//!
+//! 1. MSVC targets use SEH in the `seh.rs` file.
+//! 2. Emscripten uses C++ exceptions in the `emcc.rs` file.
+//! 3. All other targets use libunwind/libgcc in the `gcc.rs` file.
+//!
+//! More documentation about each implementation can be found in the respective
+//! module.
 
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
 #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))]
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
-#![feature(nll)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
 #![feature(std_internals)]
@@ -19,7 +26,6 @@
 #![feature(c_unwind)]
 
 extern crate alloc;
-extern crate sgx_types;
 extern crate sgx_unwind;
 
 use alloc::boxed::Box;
@@ -38,8 +44,6 @@ extern "C" {
     fn __rust_foreign_exception() -> !;
 }
 
-mod dwarf;
-
 /// # Safety
 #[rustc_std_internal_symbol]
 #[allow(improper_ctypes_definitions)]
@@ -51,7 +55,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any
 // Entry point for raising an exception, just delegates to the platform-specific
 // implementation.
 #[rustc_std_internal_symbol]
-pub unsafe extern "C-unwind" fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
+pub unsafe fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
     let payload = Box::from_raw((*payload).take_box());
 
     imp::panic(payload)
diff --git a/samplecode/hyper-rustls-https-server/enclave/src/lib.rs b/samplecode/hyper-rustls-https-server/enclave/src/lib.rs
index 7815a800..66ae597c 100644
--- a/samplecode/hyper-rustls-https-server/enclave/src/lib.rs
+++ b/samplecode/hyper-rustls-https-server/enclave/src/lib.rs
@@ -46,11 +46,11 @@ pub extern "C" fn run_server() -> SgxStatus {
     match result {
         Ok(Ok(_)) => SgxStatus::Success,
         Ok(Err(e)) => {
-            println!("Failed to run server: {}", e);
+            println!("Failed to run server: {e}");
             SgxStatus::Unexpected
         }
         Err(e) => {
-            println!("Failed to create tokio runtime in enclave: {}", e);
+            println!("Failed to create tokio runtime in enclave: {e}");
             SgxStatus::Unexpected
         }
     }
@@ -88,7 +88,7 @@ async fn run_sample_server() -> Result<(), Box<dyn std::error::Error + Send + Sy
     let server = Server::builder(TlsAcceptor::new(tls_cfg, incoming)).serve(service);
 
     // Run the future, keep going until an error occurs.
-    println!("Starting to serve on https://{}.", addr);
+    println!("Starting to serve on https://{addr}.");
     server.await?;
     Ok(())
 }
diff --git a/samplecode/rpc/client/enclave/src/lib.rs b/samplecode/rpc/client/enclave/src/lib.rs
index 13a39b56..cd0d9876 100644
--- a/samplecode/rpc/client/enclave/src/lib.rs
+++ b/samplecode/rpc/client/enclave/src/lib.rs
@@ -39,7 +39,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
 
     let response = client.say_hello(request).await?;
 
-    println!("RESPONSE={:?}", response);
+    println!("RESPONSE={response:?}");
 
     Ok(())
 }
@@ -56,11 +56,11 @@ pub extern "C" fn run_client() -> SgxStatus {
     match result {
         Ok(Ok(_)) => SgxStatus::Success,
         Ok(Err(e)) => {
-            println!("Failed to run client: {}", e);
+            println!("Failed to run client: {e}");
             SgxStatus::Unexpected
         }
         Err(e) => {
-            println!("Failed to create tokio runtime in enclave: {}", e);
+            println!("Failed to create tokio runtime in enclave: {e}");
             SgxStatus::Unexpected
         }
     }
@@ -73,7 +73,7 @@ pub extern "C" fn run_client() -> SgxStatus {
     //match main() {
     //    Ok(_) => SgxStatus::Success,
     //    Err(e) => {
-    //        println!("Failed to run client: {}", e);
+    //        println!("Failed to run client: {e}");
     //        SgxStatus::Unexpected
     //    }
     //}
diff --git a/samplecode/rpc/server/enclave/src/lib.rs b/samplecode/rpc/server/enclave/src/lib.rs
index 22e5bb0d..27fd42ac 100644
--- a/samplecode/rpc/server/enclave/src/lib.rs
+++ b/samplecode/rpc/server/enclave/src/lib.rs
@@ -37,7 +37,7 @@ impl Greeter for MyGreeter {
         &self,
         request: Request<HelloRequest>,
     ) -> Result<Response<HelloReply>, Status> {
-        println!("Got a request: {:?}", request);
+        println!("Got a request: {request:?}");
 
         let reply = hello_world::HelloReply {
             message: format!("Hello {}!", request.into_inner().name).into(),
@@ -54,7 +54,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
     let addr = "[::1]:50051".parse().unwrap();
     let greeter = MyGreeter::default();
 
-    println!("GreeterServer listening on {}", addr);
+    println!("GreeterServer listening on {addr}");
 
     Server::builder()
         .add_service(GreeterServer::new(greeter))
@@ -76,11 +76,11 @@ pub extern "C" fn run_server() -> SgxStatus {
     match result {
         Ok(Ok(_)) => SgxStatus::Success,
         Ok(Err(e)) => {
-            println!("Failed to run server: {}", e);
+            println!("Failed to run server: {e}");
             SgxStatus::Unexpected
         }
         Err(e) => {
-            println!("Failed to create tokio runtime in enclave: {}", e);
+            println!("Failed to create tokio runtime in enclave: {e}");
             SgxStatus::Unexpected
         }
     }
@@ -93,7 +93,7 @@ pub extern "C" fn run_server() -> SgxStatus {
     //match main() {
     //    Ok(_) => SgxStatus::Success,
     //    Err(e) => {
-    //        println!("Failed to run server: {}", e);
+    //        println!("Failed to run server: {e}");
     //        SgxStatus::Unexpected
     //    }
     //}
diff --git a/samplecode/seal/enclave/src/lib.rs b/samplecode/seal/enclave/src/lib.rs
index d4edd006..95c3f81f 100644
--- a/samplecode/seal/enclave/src/lib.rs
+++ b/samplecode/seal/enclave/src/lib.rs
@@ -59,12 +59,12 @@ pub unsafe extern "C" fn seal_data() -> SgxStatus {
     rng.fill_bytes(data.as_mut());
 
     let data = SealData::new(msg, data);
-    println!("sealdata: {:?}", data);
+    println!("sealdata: {data:?}");
 
     let sealed_bytes = match seal(data.clone(), aad.clone()) {
         Ok(bytes) => bytes,
         Err(e) => {
-            println!("seal failed. {:?}", e);
+            println!("seal failed. {e:?}");
             return e;
         }
     };
@@ -73,7 +73,7 @@ pub unsafe extern "C" fn seal_data() -> SgxStatus {
     let sealed_bytes = match fs::read("sealed_data.txt") {
         Ok(bytes) => bytes,
         Err(e) => {
-            println!("read sealed_data.txt failed. {:?}", e);
+            println!("read sealed_data.txt failed. {e:?}");
             return SgxStatus::Unexpected;
         }
     };
@@ -82,13 +82,13 @@ pub unsafe extern "C" fn seal_data() -> SgxStatus {
     let (unsealed_data, unsealed_aad) = match unseal(sealed_bytes) {
         Ok(data) => data,
         Err(e) => {
-            println!("unseal failed. {:?}", e);
+            println!("unseal failed. {e:?}");
             return e;
         }
     };
 
-    println!("unsealed data: {:?}", unsealed_data);
-    println!("aad: {:?}", unsealed_aad);
+    println!("unsealed data: {unsealed_data:?}");
+    println!("aad: {unsealed_aad:?}");
 
     assert_eq!(data, unsealed_data);
     assert_eq!(aad, unsealed_aad);
diff --git a/samplecode/switchless/app/build.rs b/samplecode/switchless/app/build.rs
index 0565b106..002ffed9 100644
--- a/samplecode/switchless/app/build.rs
+++ b/samplecode/switchless/app/build.rs
@@ -28,7 +28,10 @@ fn main() {
     println!("cargo:rustc-link-lib=static=enclave_u");
 
     println!("cargo:rustc-link-search=native={}/lib64", sdk_dir);
-    println!("cargo:rustc-link-lib=static=sgx_uswitchless");
+    println!("cargo:rustc-link-arg=-Wl,--whole-archive");
+    println!("cargo:rustc-link-arg=-lsgx_uswitchless");
+    println!("cargo:rustc-link-arg=-Wl,--no-whole-archive");
+
     match mode.as_ref() {
         "SIM" | "SW" => println!("cargo:rustc-link-lib=dylib=sgx_urts_sim"),
         "HYPER" => println!("cargo:rustc-link-lib=dylib=sgx_urts_hyper"),
diff --git a/samplecode/switchless/app/src/main.rs b/samplecode/switchless/app/src/main.rs
index ec344998..2bcad663 100644
--- a/samplecode/switchless/app/src/main.rs
+++ b/samplecode/switchless/app/src/main.rs
@@ -70,15 +70,12 @@ fn benchmark_empty_ocall(eid: EnclaveId, is_switchless: u32) {
         _ => "switchless",
     };
 
-    println!(
-        "Repeating an **{}** OCall that does nothing for {} times...",
-        info, REPEATS
-    );
+    println!("Repeating an **{info}** OCall that does nothing for {REPEATS} times...");
 
     let start = Instant::now();
     let _ = unsafe { ecall_repeat_ocalls(eid, REPEATS, is_switchless) };
     let elapsed = start.elapsed();
-    println!("Time elapsed {:?}", elapsed);
+    println!("Time elapsed {elapsed:?}");
 }
 
 fn benchmark_empty_ecall(eid: EnclaveId, is_switchless: u32) {
@@ -92,15 +89,12 @@ fn benchmark_empty_ecall(eid: EnclaveId, is_switchless: u32) {
         _ => ecall_empty_switchless,
     };
 
-    println!(
-        "Repeating an **{}** ECall that does nothing for {} times...",
-        info, REPEATS
-    );
+    println!("Repeating an **{info}** ECall that does nothing for {REPEATS} times...");
 
     let start = Instant::now();
     for _ in 0..REPEATS {
         let _ = unsafe { ecall_fn(eid) };
     }
     let elapsed = start.elapsed();
-    println!("Time elapsed {:?}", elapsed);
+    println!("Time elapsed {elapsed:?}");
 }
diff --git a/samplecode/zlib-lazy-static-sample/enclave/src/lib.rs b/samplecode/zlib-lazy-static-sample/enclave/src/lib.rs
index ed4a9407..084ce515 100644
--- a/samplecode/zlib-lazy-static-sample/enclave/src/lib.rs
+++ b/samplecode/zlib-lazy-static-sample/enclave/src/lib.rs
@@ -21,11 +21,11 @@ use inflate::inflate_bytes_zlib;
 use libflate::zlib::Encoder;
 use sgx_types::error::SgxStatus;
 use std::io::Write;
-use std::lazy::SyncLazy;
 use std::str::from_utf8;
+use std::sync::LazyLock;
 
-static HELLOSTR: SyncLazy<String> =
-    SyncLazy::new(|| String::from("This is a global rust String init by SyncLazy!"));
+static HELLOSTR: LazyLock<String> =
+    LazyLock::new(|| String::from("This is a global rust String init by LazyLock!"));
 
 /// # Safety
 #[no_mangle]
@@ -37,7 +37,7 @@ pub unsafe extern "C" fn zlib_sample() -> SgxStatus {
     encoder.write_all(HELLOSTR.as_bytes()).unwrap();
     let encoded_data = encoder.finish().into_result().unwrap();
 
-    println!("After zlib compress : {:?}", encoded_data);
+    println!("After zlib compress : {encoded_data:?}");
 
     let decoded = inflate_bytes_zlib(&encoded_data[..]).unwrap();
 
diff --git a/sgx_alloc/src/alignalloc.rs b/sgx_alloc/src/alignalloc.rs
index 3d3720fc..cc71359e 100644
--- a/sgx_alloc/src/alignalloc.rs
+++ b/sgx_alloc/src/alignalloc.rs
@@ -321,7 +321,7 @@ mod platform {
 
     fn gen_alignmask(al: usize, a: usize, m: u64) -> i64 {
         if a > al {
-            gen_alignmask(al, (a >> 1) as usize, m | (m >> (a >> 1)))
+            gen_alignmask(al, a >> 1, m | (m >> (a >> 1)))
         } else {
             m as i64
         }
diff --git a/sgx_alloc/src/alignbox.rs b/sgx_alloc/src/alignbox.rs
index fddd42f5..ebdc2c4b 100644
--- a/sgx_alloc/src/alignbox.rs
+++ b/sgx_alloc/src/alignbox.rs
@@ -60,25 +60,25 @@ impl<T> DerefMut for AlignBox<T> {
 
 impl<T> AsRef<T> for AlignBox<T> {
     fn as_ref(&self) -> &T {
-        &**self
+        self
     }
 }
 
 impl<T> AsMut<T> for AlignBox<T> {
     fn as_mut(&mut self) -> &mut T {
-        &mut **self
+        self
     }
 }
 
 impl<T> borrow::Borrow<T> for AlignBox<T> {
     fn borrow(&self) -> &T {
-        &**self
+        self
     }
 }
 
 impl<T> borrow::BorrowMut<T> for AlignBox<T> {
     fn borrow_mut(&mut self) -> &mut T {
-        &mut **self
+        self
     }
 }
 
diff --git a/sgx_backtrace/src/symbolize/libbacktrace.rs b/sgx_backtrace/src/symbolize/libbacktrace.rs
index f5bbdd79..b45d5ee3 100644
--- a/sgx_backtrace/src/symbolize/libbacktrace.rs
+++ b/sgx_backtrace/src/symbolize/libbacktrace.rs
@@ -241,7 +241,7 @@ extern "C" fn syminfo_cb(
             let mut symname = symname;
             if symname.is_null() {
                 let sym_address =
-                    uw::_Unwind_FindEnclosingFunction((pc as usize + 1) as *mut c_void) as usize;
+                    uw::_Unwind_FindEnclosingFunction((pc + 1) as *mut c_void) as usize;
                 if sym_address == MmLayout::entry_address() {
                     symname = ENCLAVE_ENTRY_NAME as *const _ as *const c_char
                 }
diff --git a/sgx_build_helper/build_helper/src/lib.rs b/sgx_build_helper/build_helper/src/lib.rs
index 139bbec3..fc265532 100644
--- a/sgx_build_helper/build_helper/src/lib.rs
+++ b/sgx_build_helper/build_helper/src/lib.rs
@@ -176,7 +176,7 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path, filter: &[&str]) {
         .read_dir()
         .unwrap()
         .map(|e| e.unwrap())
-        .filter(|e| !is_in_filter_list(&*e.file_name(), filter))
+        .filter(|e| !is_in_filter_list(&e.file_name(), filter))
         .collect::<Vec<_>>();
     while let Some(entry) = stack.pop() {
         let path = entry.path();
@@ -185,7 +185,7 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path, filter: &[&str]) {
                 path.read_dir()
                     .unwrap()
                     .map(|e| e.unwrap())
-                    .filter(|e| !is_in_filter_list(&*e.file_name(), filter)),
+                    .filter(|e| !is_in_filter_list(&e.file_name(), filter)),
             );
         } else {
             println!("cargo:rerun-if-changed={}", path.display());
diff --git a/sgx_dcap/tkey_exchange/src/session/manager.rs b/sgx_dcap/tkey_exchange/src/session/manager.rs
index 4353fe6d..eccf8243 100644
--- a/sgx_dcap/tkey_exchange/src/session/manager.rs
+++ b/sgx_dcap/tkey_exchange/src/session/manager.rs
@@ -22,7 +22,7 @@ use core::ops::Deref;
 use core::ptr;
 use core::sync::atomic::{AtomicU32, Ordering};
 use sgx_crypto::ecc::{EcPrivateKey, EcPublicKey, EcShareKey};
-use sgx_sync::{SpinMutex, SpinRwLock, SyncLazy};
+use sgx_sync::{LazyLock, SpinMutex, SpinRwLock};
 use sgx_types::types::{AlignKey128bit, EnclaveIdentity, QlQvResult, QuoteNonce, TargetInfo};
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -168,11 +168,11 @@ impl Session {
     }
 }
 
-pub static INITIATOR_SESSION_MAGAGER: SyncLazy<SpinRwLock<SessionManager>> =
-    SyncLazy::new(|| SpinRwLock::new(SessionManager::new()));
+pub static INITIATOR_SESSION_MAGAGER: LazyLock<SpinRwLock<SessionManager>> =
+    LazyLock::new(|| SpinRwLock::new(SessionManager::new()));
 
-pub static RESPONDER_SESSION_MAGAGER: SyncLazy<SpinRwLock<SessionManager>> =
-    SyncLazy::new(|| SpinRwLock::new(SessionManager::new()));
+pub static RESPONDER_SESSION_MAGAGER: LazyLock<SpinRwLock<SessionManager>> =
+    LazyLock::new(|| SpinRwLock::new(SessionManager::new()));
 
 struct Node {
     sid: u32,
diff --git a/sgx_dcap/tvl/src/capi.rs b/sgx_dcap/tvl/src/capi.rs
index fc44f545..30b8d08e 100644
--- a/sgx_dcap/tvl/src/capi.rs
+++ b/sgx_dcap/tvl/src/capi.rs
@@ -16,12 +16,12 @@
 // under the License..
 
 use crate::QveReportInfo;
+use core::ptr;
 use core::slice;
 use sgx_types::error::Quote3Error;
 use sgx_types::types::time_t;
 use sgx_types::types::{QlQeReportInfo, QlQvResult};
 
-#[allow(unaligned_references)]
 /// # Safety
 #[no_mangle]
 pub unsafe extern "C" fn sgx_tvl_verify_qve_report_and_identity(
@@ -58,7 +58,7 @@ pub unsafe extern "C" fn sgx_tvl_verify_qve_report_and_identity(
 
     let qve_report_info = &*qve_report_info;
     let qve_report_info = QveReportInfo {
-        qve_report: &qve_report_info.qe_report,
+        qve_report: &*ptr::addr_of!(qve_report_info.qe_report),
         expiration_time: expiration_check_date,
         collateral_expiration_status,
         quote_verification_result,
diff --git a/sgx_demangle/src/legacy.rs b/sgx_demangle/src/legacy.rs
index 7a1667d2..5f05d2a9 100644
--- a/sgx_demangle/src/legacy.rs
+++ b/sgx_demangle/src/legacy.rs
@@ -92,7 +92,7 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), ()> {
     let mut c = chars.next().ok_or(())?;
     while c != 'E' {
         // Decode an identifier element's length.
-        if !c.is_digit(10) {
+        if !c.is_ascii_digit() {
             return Err(());
         }
         let mut len = 0usize;
@@ -118,7 +118,7 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), ()> {
 
 // Rust hashes are hex digits with an `h` prepended.
 fn is_rust_hash(s: &str) -> bool {
-    s.starts_with('h') && s[1..].chars().all(|c| c.is_digit(16))
+    s.starts_with('h') && s[1..].chars().all(|c| c.is_ascii_hexdigit())
 }
 
 impl<'a> fmt::Display for Demangle<'a> {
@@ -127,7 +127,7 @@ impl<'a> fmt::Display for Demangle<'a> {
         let mut inner = self.inner;
         for element in 0..self.elements {
             let mut rest = inner;
-            while rest.chars().next().unwrap().is_digit(10) {
+            while rest.chars().next().unwrap().is_ascii_digit() {
                 rest = &rest[1..];
             }
             let i: usize = inner[..(inner.len() - rest.len())].parse().unwrap();
diff --git a/sgx_edl/edl/sgx_fd.edl b/sgx_edl/edl/sgx_fd.edl
index cb1f3187..141753e7 100644
--- a/sgx_edl/edl/sgx_fd.edl
+++ b/sgx_edl/edl/sgx_fd.edl
@@ -17,6 +17,7 @@
 
 enclave {
     include "inc/stat.h"
+    include "time.h"
 
     from "sgx_mem.edl" import *;
     from "sgx_msbuf.edl" import *;
@@ -42,5 +43,7 @@ enclave {
         int u_isatty_ocall([out] int *error, int fd);
         int u_dup_ocall([out] int *error, int oldfd);
         int u_eventfd_ocall([out] int *error, unsigned int initval, int flags);
+
+        int u_futimens_ocall([out] int *error, int fd, [in, count=2] const struct timespec *times);
     };
 };
diff --git a/sgx_ffi/src/c_str.rs b/sgx_ffi/src/c_str.rs
index 55ef9083..7c9b0f77 100644
--- a/sgx_ffi/src/c_str.rs
+++ b/sgx_ffi/src/c_str.rs
@@ -15,1549 +15,5 @@
 // specific language governing permissions and limitations
 // under the License..
 
-#[cfg(feature = "unit_test")]
-mod tests;
-
-use crate::ascii;
-use crate::memchr;
-use alloc::borrow::{Borrow, Cow, ToOwned};
-use alloc::boxed::Box;
-use alloc::rc::Rc;
-use alloc::slice;
-use alloc::str::{self, Utf8Error};
-use alloc::string::String;
-use alloc::sync::Arc;
-use alloc::vec::Vec;
-use core::cmp::Ordering;
-use core::fmt::{self, Write};
-use core::mem;
-use core::num::NonZeroU8;
-use core::ops;
-use core::ptr;
-use sgx_types::types::c_char;
-
-/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
-/// middle.
-///
-/// This type serves the purpose of being able to safely generate a
-/// C-compatible string from a Rust byte slice or vector. An instance of this
-/// type is a static guarantee that the underlying bytes contain no interior 0
-/// bytes ("nul characters") and that the final byte is 0 ("nul terminator").
-///
-/// `CString` is to <code>&[CStr]</code> as [`String`] is to <code>&[str]</code>: the former
-/// in each pair are owned strings; the latter are borrowed
-/// references.
-///
-/// # Creating a `CString`
-///
-/// A `CString` is created from either a byte slice or a byte vector,
-/// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for
-/// example, you can build a `CString` straight out of a [`String`] or
-/// a <code>&[str]</code>, since both implement that trait).
-///
-/// The [`CString::new`] method will actually check that the provided <code>&[[u8]]</code>
-/// does not have 0 bytes in the middle, and return an error if it
-/// finds one.
-///
-/// # Extracting a raw pointer to the whole C string
-///
-/// `CString` implements an [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`]
-/// trait. This method will give you a `*const c_char` which you can
-/// feed directly to extern functions that expect a nul-terminated
-/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a
-/// read-only pointer; if the C code writes to it, that causes
-/// undefined behavior.
-///
-/// # Extracting a slice of the whole C string
-///
-/// Alternatively, you can obtain a <code>&[[u8]]</code> slice from a
-/// `CString` with the [`CString::as_bytes`] method. Slices produced in this
-/// way do *not* contain the trailing nul terminator. This is useful
-/// when you will be calling an extern function that takes a `*const
-/// u8` argument which is not necessarily nul-terminated, plus another
-/// argument with the length of the string — like C's `strndup()`.
-/// You can of course get the slice's length with its
-/// [`len`][slice::len] method.
-///
-/// If you need a <code>&[[u8]]</code> slice *with* the nul terminator, you
-/// can use [`CString::as_bytes_with_nul`] instead.
-///
-/// Once you have the kind of slice you need (with or without a nul
-/// terminator), you can call the slice's own
-/// [`as_ptr`][slice::as_ptr] method to get a read-only raw pointer to pass to
-/// extern functions. See the documentation for that function for a
-/// discussion on ensuring the lifetime of the raw pointer.
-///
-/// [str]: prim@str "str"
-/// [`Deref`]: ops::Deref
-///
-/// # Examples
-///
-/// ```ignore (extern-declaration)
-/// # fn main() {
-/// use std::ffi::CString;
-/// use std::os::raw::c_char;
-///
-/// extern "C" {
-///     fn my_printer(s: *const c_char);
-/// }
-///
-/// // We are certain that our string doesn't have 0 bytes in the middle,
-/// // so we can .expect()
-/// let c_to_print = CString::new("Hello, world!").expect("CString::new failed");
-/// unsafe {
-///     my_printer(c_to_print.as_ptr());
-/// }
-/// # }
-/// ```
-///
-/// # Safety
-///
-/// `CString` is intended for working with traditional C-style strings
-/// (a sequence of non-nul bytes terminated by a single nul byte); the
-/// primary use case for these kinds of strings is interoperating with C-like
-/// code. Often you will need to transfer ownership to/from that external
-/// code. It is strongly recommended that you thoroughly read through the
-/// documentation of `CString` before use, as improper ownership management
-/// of `CString` instances can lead to invalid memory accesses, memory leaks,
-/// and other memory errors.
-#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")]
-pub struct CString {
-    // Invariant 1: the slice ends with a zero byte and has a length of at least one.
-    // Invariant 2: the slice contains only one zero byte.
-    // Improper usage of unsafe function can break Invariant 2, but not Invariant 1.
-    inner: Box<[u8]>,
-}
-
-/// Representation of a borrowed C string.
-///
-/// This type represents a borrowed reference to a nul-terminated
-/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
-/// slice, or unsafely from a raw `*const c_char`. It can then be
-/// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or
-/// into an owned [`CString`].
-///
-/// `&CStr` is to [`CString`] as <code>&[str]</code> is to [`String`]: the former
-/// in each pair are borrowed references; the latter are owned
-/// strings.
-///
-/// Note that this structure is **not** `repr(C)` and is not recommended to be
-/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
-/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide
-/// a safe interface to other consumers.
-///
-/// # Examples
-///
-/// Inspecting a foreign C string:
-///
-/// ```ignore (extern-declaration)
-/// use std::ffi::CStr;
-/// use std::os::raw::c_char;
-///
-/// extern "C" { fn my_string() -> *const c_char; }
-///
-/// unsafe {
-///     let slice = CStr::from_ptr(my_string());
-///     println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
-/// }
-/// ```
-///
-/// Passing a Rust-originating C string:
-///
-/// ```ignore (extern-declaration)
-/// use std::ffi::{CString, CStr};
-/// use std::os::raw::c_char;
-///
-/// fn work(data: &CStr) {
-///     extern "C" { fn work_with(data: *const c_char); }
-///
-///     unsafe { work_with(data.as_ptr()) }
-/// }
-///
-/// let s = CString::new("data data data data").expect("CString::new failed");
-/// work(&s);
-/// ```
-///
-/// Converting a foreign C string into a Rust [`String`]:
-///
-/// ```ignore (extern-declaration)
-/// use std::ffi::CStr;
-/// use std::os::raw::c_char;
-///
-/// extern "C" { fn my_string() -> *const c_char; }
-///
-/// fn my_string_safe() -> String {
-///     unsafe {
-///         CStr::from_ptr(my_string()).to_string_lossy().into_owned()
-///     }
-/// }
-///
-/// println!("string: {}", my_string_safe());
-/// ```
-///
-/// [str]: prim@str "str"
-#[derive(Hash)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")]
-// FIXME:
-// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
-// on `CStr` being layout-compatible with `[u8]`.
-// When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`.
-// Anyway, `CStr` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
-pub struct CStr {
-    // FIXME: this should not be represented with a DST slice but rather with
-    //        just a raw `c_char` along with some form of marker to make
-    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
-    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
-    inner: [c_char],
-}
-
-/// An error indicating that an interior nul byte was found.
-///
-/// While Rust strings may contain nul bytes in the middle, C strings
-/// can't, as that byte would effectively truncate the string.
-///
-/// This error is created by the [`new`][`CString::new`] method on
-/// [`CString`]. See its documentation for more.
-///
-/// # Examples
-///
-/// ```
-/// use std::ffi::{CString, NulError};
-///
-/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err();
-/// ```
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct NulError(usize, Vec<u8>);
-
-impl fmt::Display for NulError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "nul byte found in provided data at position: {}", self.0)
-    }
-}
-
-/// An error indicating that a nul byte was not in the expected position.
-///
-/// The slice used to create a [`CStr`] must have one and only one nul byte,
-/// positioned at the end.
-///
-/// This error is created by the [`CStr::from_bytes_with_nul`] method.
-/// See its documentation for more.
-///
-/// # Examples
-///
-/// ```
-/// use std::ffi::{CStr, FromBytesWithNulError};
-///
-/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
-/// ```
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct FromBytesWithNulError {
-    kind: FromBytesWithNulErrorKind,
-}
-
-impl fmt::Display for FromBytesWithNulError {
-    #[allow(deprecated, deprecated_in_future)]
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str(self.__description())?;
-        if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
-            write!(f, " at byte pos {}", pos)?;
-        }
-        Ok(())
-    }
-}
-
-impl FromBytesWithNulError {
-    fn interior_nul(pos: usize) -> FromBytesWithNulError {
-        FromBytesWithNulError {
-            kind: FromBytesWithNulErrorKind::InteriorNul(pos),
-        }
-    }
-
-    fn not_nul_terminated() -> FromBytesWithNulError {
-        FromBytesWithNulError {
-            kind: FromBytesWithNulErrorKind::NotNulTerminated,
-        }
-    }
-
-    pub fn __description(&self) -> &str {
-        match self.kind {
-            FromBytesWithNulErrorKind::InteriorNul(..) => {
-                "data provided contains an interior nul byte"
-            }
-            FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated",
-        }
-    }
-}
-
-/// An error indicating that a nul byte was not in the expected position.
-///
-/// The vector used to create a [`CString`] must have one and only one nul byte,
-/// positioned at the end.
-///
-/// This error is created by the [`CString::from_vec_with_nul`] method.
-/// See its documentation for more.
-///
-/// # Examples
-///
-/// ```
-/// use std::ffi::{CString, FromVecWithNulError};
-///
-/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err();
-/// ```
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct FromVecWithNulError {
-    error_kind: FromBytesWithNulErrorKind,
-    bytes: Vec<u8>,
-}
-
-impl fmt::Display for FromVecWithNulError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.error_kind {
-            FromBytesWithNulErrorKind::InteriorNul(pos) => {
-                write!(
-                    f,
-                    "data provided contains an interior nul byte at pos {}",
-                    pos
-                )
-            }
-            FromBytesWithNulErrorKind::NotNulTerminated => {
-                write!(f, "data provided is not nul terminated")
-            }
-        }
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, Debug)]
-enum FromBytesWithNulErrorKind {
-    InteriorNul(usize),
-    NotNulTerminated,
-}
-
-impl FromVecWithNulError {
-    /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`].
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// // Some invalid bytes in a vector
-    /// let bytes = b"f\0oo".to_vec();
-    ///
-    /// let value = CString::from_vec_with_nul(bytes.clone());
-    ///
-    /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
-    /// ```
-    #[must_use]
-    pub fn as_bytes(&self) -> &[u8] {
-        &self.bytes[..]
-    }
-
-    /// Returns the bytes that were attempted to convert to a [`CString`].
-    ///
-    /// This method is carefully constructed to avoid allocation. It will
-    /// consume the error, moving out the bytes, so that a copy of the bytes
-    /// does not need to be made.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// // Some invalid bytes in a vector
-    /// let bytes = b"f\0oo".to_vec();
-    ///
-    /// let value = CString::from_vec_with_nul(bytes.clone());
-    ///
-    /// assert_eq!(bytes, value.unwrap_err().into_bytes());
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_bytes(self) -> Vec<u8> {
-        self.bytes
-    }
-}
-
-/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
-///
-/// `CString` is just a wrapper over a buffer of bytes with a nul terminator;
-/// [`CString::into_string`] performs UTF-8 validation on those bytes and may
-/// return this error.
-///
-/// This `struct` is created by [`CString::into_string()`]. See
-/// its documentation for more.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct IntoStringError {
-    inner: CString,
-    error: Utf8Error,
-}
-
-impl IntoStringError {
-    #[allow(deprecated)]
-    pub fn __description(&self) -> &str {
-        "C string contained non-utf8 bytes"
-    }
-
-    pub fn __source(&self) -> &Utf8Error {
-        &self.error
-    }
-}
-
-impl fmt::Display for IntoStringError {
-    #[allow(deprecated, deprecated_in_future)]
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.__description().fmt(f)
-    }
-}
-
-impl CString {
-    /// Creates a new C-compatible string from a container of bytes.
-    ///
-    /// This function will consume the provided data and use the
-    /// underlying bytes to construct a new string, ensuring that
-    /// there is a trailing 0 byte. This trailing 0 byte will be
-    /// appended by this function; the provided data should *not*
-    /// contain any 0 bytes in it.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore (extern-declaration)
-    /// use std::ffi::CString;
-    /// use std::os::raw::c_char;
-    ///
-    /// extern "C" { fn puts(s: *const c_char); }
-    ///
-    /// let to_print = CString::new("Hello!").expect("CString::new failed");
-    /// unsafe {
-    ///     puts(to_print.as_ptr());
-    /// }
-    /// ```
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if the supplied bytes contain an
-    /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
-    /// the position of the nul byte.
-    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
-        trait SpecNewImpl {
-            fn spec_new_impl(self) -> Result<CString, NulError>;
-        }
-
-        impl<T: Into<Vec<u8>>> SpecNewImpl for T {
-            default fn spec_new_impl(self) -> Result<CString, NulError> {
-                let bytes: Vec<u8> = self.into();
-                match memchr::memchr(0, &bytes) {
-                    Some(i) => Err(NulError(i, bytes)),
-                    None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }),
-                }
-            }
-        }
-
-        // Specialization for avoiding reallocation
-        #[inline(always)] // Without that it is not inlined into specializations
-        fn spec_new_impl_bytes(bytes: &[u8]) -> Result<CString, NulError> {
-            // We cannot have such large slice that we would overflow here
-            // but using `checked_add` allows LLVM to assume that capacity never overflows
-            // and generate twice shorter code.
-            // `saturating_add` doesn't help for some reason.
-            let capacity = bytes.len().checked_add(1).unwrap();
-
-            // Allocate before validation to avoid duplication of allocation code.
-            // We still need to allocate and copy memory even if we get an error.
-            let mut buffer = Vec::with_capacity(capacity);
-            buffer.extend(bytes);
-
-            // Check memory of self instead of new buffer.
-            // This allows better optimizations if lto enabled.
-            match memchr::memchr(0, bytes) {
-                Some(i) => Err(NulError(i, buffer)),
-                None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }),
-            }
-        }
-
-        impl SpecNewImpl for &'_ [u8] {
-            fn spec_new_impl(self) -> Result<CString, NulError> {
-                spec_new_impl_bytes(self)
-            }
-        }
-
-        impl SpecNewImpl for &'_ str {
-            fn spec_new_impl(self) -> Result<CString, NulError> {
-                spec_new_impl_bytes(self.as_bytes())
-            }
-        }
-
-        impl SpecNewImpl for &'_ mut [u8] {
-            fn spec_new_impl(self) -> Result<CString, NulError> {
-                spec_new_impl_bytes(self)
-            }
-        }
-
-        t.spec_new_impl()
-    }
-
-    /// Creates a C-compatible string by consuming a byte vector,
-    /// without checking for interior 0 bytes.
-    ///
-    /// Trailing 0 byte will be appended by this function.
-    ///
-    /// This method is equivalent to [`CString::new`] except that no runtime
-    /// assertion is made that `v` contains no 0 bytes, and it requires an
-    /// actual byte vector, not anything that can be converted to one with Into.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let raw = b"foo".to_vec();
-    /// unsafe {
-    ///     let c_string = CString::from_vec_unchecked(raw);
-    /// }
-    /// ```
-    #[must_use]
-    pub unsafe fn from_vec_unchecked(v: Vec<u8>) -> Self {
-        debug_assert!(memchr::memchr(0, &v).is_none());
-        Self::_from_vec_unchecked(v)
-    }
-
-    unsafe fn _from_vec_unchecked(mut v: Vec<u8>) -> Self {
-        v.reserve_exact(1);
-        v.push(0);
-        Self {
-            inner: v.into_boxed_slice(),
-        }
-    }
-
-    /// Retakes ownership of a `CString` that was transferred to C via
-    /// [`CString::into_raw`].
-    ///
-    /// Additionally, the length of the string will be recalculated from the pointer.
-    ///
-    /// # Safety
-    ///
-    /// This should only ever be called with a pointer that was earlier
-    /// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take
-    /// ownership of a string that was allocated by foreign code) is likely to lead
-    /// to undefined behavior or allocator corruption.
-    ///
-    /// It should be noted that the length isn't just "recomputed," but that
-    /// the recomputed length must match the original length from the
-    /// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw`
-    /// methods should not be used when passing the string to C functions that can
-    /// modify the string's length.
-    ///
-    /// > **Note:** If you need to borrow a string that was allocated by
-    /// > foreign code, use [`CStr`]. If you need to take ownership of
-    /// > a string that was allocated by foreign code, you will need to
-    /// > make your own provisions for freeing it appropriately, likely
-    /// > with the foreign code's API to do that.
-    ///
-    /// # Examples
-    ///
-    /// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
-    /// ownership with `from_raw`:
-    ///
-    /// ```ignore (extern-declaration)
-    /// use std::ffi::CString;
-    /// use std::os::raw::c_char;
-    ///
-    /// extern "C" {
-    ///     fn some_extern_function(s: *mut c_char);
-    /// }
-    ///
-    /// let c_string = CString::new("Hello!").expect("CString::new failed");
-    /// let raw = c_string.into_raw();
-    /// unsafe {
-    ///     some_extern_function(raw);
-    ///     let c_string = CString::from_raw(raw);
-    /// }
-    /// ```
-    #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `CString`"]
-    pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
-        // SAFETY: This is called with a pointer that was obtained from a call
-        // to `CString::into_raw` and the length has not been modified. As such,
-        // we know there is a NUL byte (and only one) at the end and that the
-        // information about the size of the allocation is correct on Rust's
-        // side.
-        let len = c::strlen(ptr) + 1; // Including the NUL byte
-        let slice = slice::from_raw_parts_mut(ptr, len as usize);
-        CString {
-            inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]),
-        }
-    }
-
-    /// Consumes the `CString` and transfers ownership of the string to a C caller.
-    ///
-    /// The pointer which this function returns must be returned to Rust and reconstituted using
-    /// [`CString::from_raw`] to be properly deallocated. Specifically, one
-    /// should *not* use the standard C `free()` function to deallocate
-    /// this string.
-    ///
-    /// Failure to call [`CString::from_raw`] will lead to a memory leak.
-    ///
-    /// The C side must **not** modify the length of the string (by writing a
-    /// `null` somewhere inside the string or removing the final one) before
-    /// it makes it back into Rust using [`CString::from_raw`]. See the safety section
-    /// in [`CString::from_raw`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    ///
-    /// let ptr = c_string.into_raw();
-    ///
-    /// unsafe {
-    ///     assert_eq!(b'f', *ptr as u8);
-    ///     assert_eq!(b'o', *ptr.offset(1) as u8);
-    ///     assert_eq!(b'o', *ptr.offset(2) as u8);
-    ///     assert_eq!(b'\0', *ptr.offset(3) as u8);
-    ///
-    ///     // retake pointer to free memory
-    ///     let _ = CString::from_raw(ptr);
-    /// }
-    /// ```
-    #[inline]
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_raw(self) -> *mut c_char {
-        Box::into_raw(self.into_inner()) as *mut c_char
-    }
-
-    /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data.
-    ///
-    /// On failure, ownership of the original `CString` is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let valid_utf8 = vec![b'f', b'o', b'o'];
-    /// let cstring = CString::new(valid_utf8).expect("CString::new failed");
-    /// assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo");
-    ///
-    /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
-    /// let cstring = CString::new(invalid_utf8).expect("CString::new failed");
-    /// let err = cstring.into_string().err().expect("into_string().err() failed");
-    /// assert_eq!(err.utf8_error().valid_up_to(), 1);
-    /// ```
-    pub fn into_string(self) -> Result<String, IntoStringError> {
-        String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError {
-            error: e.utf8_error(),
-            inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) },
-        })
-    }
-
-    /// Consumes the `CString` and returns the underlying byte buffer.
-    ///
-    /// The returned buffer does **not** contain the trailing nul
-    /// terminator, and it is guaranteed to not have any interior nul
-    /// bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.into_bytes();
-    /// assert_eq!(bytes, vec![b'f', b'o', b'o']);
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_bytes(self) -> Vec<u8> {
-        let mut vec = self.into_inner().into_vec();
-        let _nul = vec.pop();
-        debug_assert_eq!(_nul, Some(0u8));
-        vec
-    }
-
-    /// Equivalent to [`CString::into_bytes()`] except that the
-    /// returned vector includes the trailing nul terminator.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.into_bytes_with_nul();
-    /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_bytes_with_nul(self) -> Vec<u8> {
-        self.into_inner().into_vec()
-    }
-
-    /// Returns the contents of this `CString` as a slice of bytes.
-    ///
-    /// The returned slice does **not** contain the trailing nul
-    /// terminator, and it is guaranteed to not have any interior nul
-    /// bytes. If you need the nul terminator, use
-    /// [`CString::as_bytes_with_nul`] instead.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.as_bytes();
-    /// assert_eq!(bytes, &[b'f', b'o', b'o']);
-    /// ```
-    #[inline]
-    #[must_use]
-    pub fn as_bytes(&self) -> &[u8] {
-        // SAFETY: CString has a length at least 1
-        unsafe { self.inner.get_unchecked(..self.inner.len() - 1) }
-    }
-
-    /// Equivalent to [`CString::as_bytes()`] except that the
-    /// returned slice includes the trailing nul terminator.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.as_bytes_with_nul();
-    /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
-    /// ```
-    #[inline]
-    #[must_use]
-    pub fn as_bytes_with_nul(&self) -> &[u8] {
-        &self.inner
-    }
-
-    /// Extracts a [`CStr`] slice containing the entire string.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::{CString, CStr};
-    ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
-    /// let cstr = c_string.as_c_str();
-    /// assert_eq!(cstr,
-    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
-    /// ```
-    #[inline]
-    #[must_use]
-    pub fn as_c_str(&self) -> &CStr {
-        &*self
-    }
-
-    /// Converts this `CString` into a boxed [`CStr`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::{CString, CStr};
-    ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
-    /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(&*boxed,
-    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_boxed_c_str(self) -> Box<CStr> {
-        unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
-    }
-
-    /// Bypass "move out of struct which implements [`Drop`] trait" restriction.
-    #[inline]
-    fn into_inner(self) -> Box<[u8]> {
-        // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)`
-        // so we use `ManuallyDrop` to ensure `self` is not dropped.
-        // Then we can return the box directly without invalidating it.
-        // See https://github.com/rust-lang/rust/issues/62553.
-        let this = mem::ManuallyDrop::new(self);
-        unsafe { ptr::read(&this.inner) }
-    }
-
-    /// Converts a <code>[Vec]<[u8]></code> to a [`CString`] without checking the
-    /// invariants on the given [`Vec`].
-    ///
-    /// # Safety
-    ///
-    /// The given [`Vec`] **must** have one nul byte as its last element.
-    /// This means it cannot be empty nor have any other nul byte anywhere else.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    /// assert_eq!(
-    ///     unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) },
-    ///     unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
-    /// );
-    /// ```
-    #[must_use]
-    pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
-        debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len());
-        Self::_from_vec_with_nul_unchecked(v)
-    }
-
-    unsafe fn _from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
-        Self {
-            inner: v.into_boxed_slice(),
-        }
-    }
-
-    /// Attempts to converts a <code>[Vec]<[u8]></code> to a [`CString`].
-    ///
-    /// Runtime checks are present to ensure there is only one nul byte in the
-    /// [`Vec`], its last element.
-    ///
-    /// # Errors
-    ///
-    /// If a nul byte is present and not the last element or no nul bytes
-    /// is present, an error will be returned.
-    ///
-    /// # Examples
-    ///
-    /// A successful conversion will produce the same result as [`CString::new`]
-    /// when called without the ending nul byte.
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    /// assert_eq!(
-    ///     CString::from_vec_with_nul(b"abc\0".to_vec())
-    ///         .expect("CString::from_vec_with_nul failed"),
-    ///     CString::new(b"abc".to_vec()).expect("CString::new failed")
-    /// );
-    /// ```
-    ///
-    /// An incorrectly formatted [`Vec`] will produce an error.
-    ///
-    /// ```
-    /// use std::ffi::{CString, FromVecWithNulError};
-    /// // Interior nul byte
-    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err();
-    /// // No nul byte
-    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
-    /// ```
-    pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
-        let nul_pos = memchr::memchr(0, &v);
-        match nul_pos {
-            Some(nul_pos) if nul_pos + 1 == v.len() => {
-                // SAFETY: We know there is only one nul byte, at the end
-                // of the vec.
-                Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) })
-            }
-            Some(nul_pos) => Err(FromVecWithNulError {
-                error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
-                bytes: v,
-            }),
-            None => Err(FromVecWithNulError {
-                error_kind: FromBytesWithNulErrorKind::NotNulTerminated,
-                bytes: v,
-            }),
-        }
-    }
-}
-
-// Turns this `CString` into an empty string to prevent
-// memory-unsafe code from working by accident. Inline
-// to prevent LLVM from optimizing it away in debug builds.
-impl Drop for CString {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            *self.inner.get_unchecked_mut(0) = 0;
-        }
-    }
-}
-
-impl ops::Deref for CString {
-    type Target = CStr;
-
-    #[inline]
-    fn deref(&self) -> &CStr {
-        unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
-    }
-}
-
-impl fmt::Debug for CString {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&**self, f)
-    }
-}
-
-impl From<CString> for Vec<u8> {
-    /// Converts a [`CString`] into a <code>[Vec]<[u8]></code>.
-    ///
-    /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
-    #[inline]
-    fn from(s: CString) -> Vec<u8> {
-        s.into_bytes()
-    }
-}
-
-impl fmt::Debug for CStr {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "\"")?;
-        for byte in self
-            .to_bytes()
-            .iter()
-            .flat_map(|&b| ascii::escape_default(b))
-        {
-            f.write_char(byte as char)?;
-        }
-        write!(f, "\"")
-    }
-}
-
-impl Default for &CStr {
-    fn default() -> Self {
-        const SLICE: &[c_char] = &[0];
-        unsafe { CStr::from_ptr(SLICE.as_ptr()) }
-    }
-}
-
-impl Default for CString {
-    /// Creates an empty `CString`.
-    fn default() -> CString {
-        let a: &CStr = Default::default();
-        a.to_owned()
-    }
-}
-
-impl Borrow<CStr> for CString {
-    #[inline]
-    fn borrow(&self) -> &CStr {
-        self
-    }
-}
-
-impl<'a> From<Cow<'a, CStr>> for CString {
-    /// Converts a `Cow<'a, CStr>` into a `CString`, by copying the contents if they are
-    /// borrowed.
-    #[inline]
-    fn from(s: Cow<'a, CStr>) -> Self {
-        s.into_owned()
-    }
-}
-
-impl From<&CStr> for Box<CStr> {
-    /// Converts a `&CStr` into a `Box<CStr>`,
-    /// by copying the contents into a newly allocated [`Box`].
-    fn from(s: &CStr) -> Box<CStr> {
-        let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
-        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
-    }
-}
-
-impl From<Cow<'_, CStr>> for Box<CStr> {
-    /// Converts a `Cow<'a, CStr>` into a `Box<CStr>`,
-    /// by copying the contents if they are borrowed.
-    #[inline]
-    fn from(cow: Cow<'_, CStr>) -> Box<CStr> {
-        match cow {
-            Cow::Borrowed(s) => Box::from(s),
-            Cow::Owned(s) => Box::from(s),
-        }
-    }
-}
-
-impl From<Box<CStr>> for CString {
-    /// Converts a <code>[Box]<[CStr]></code> into a [`CString`] without copying or allocating.
-    #[inline]
-    fn from(s: Box<CStr>) -> CString {
-        s.into_c_string()
-    }
-}
-
-impl From<Vec<NonZeroU8>> for CString {
-    /// Converts a <code>[Vec]<[NonZeroU8]></code> into a [`CString`] without
-    /// copying nor checking for inner null bytes.
-    #[inline]
-    fn from(v: Vec<NonZeroU8>) -> CString {
-        unsafe {
-            // Transmute `Vec<NonZeroU8>` to `Vec<u8>`.
-            let v: Vec<u8> = {
-                // SAFETY:
-                //   - transmuting between `NonZeroU8` and `u8` is sound;
-                //   - `alloc::Layout<NonZeroU8> == alloc::Layout<u8>`.
-                let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v);
-                Vec::from_raw_parts(ptr.cast::<u8>(), len, cap)
-            };
-            // SAFETY: `v` cannot contain null bytes, given the type-level
-            // invariant of `NonZeroU8`.
-            Self::_from_vec_unchecked(v)
-        }
-    }
-}
-
-impl Clone for Box<CStr> {
-    #[inline]
-    fn clone(&self) -> Self {
-        (**self).into()
-    }
-}
-
-impl From<CString> for Box<CStr> {
-    /// Converts a [`CString`] into a <code>[Box]<[CStr]></code> without copying or allocating.
-    #[inline]
-    fn from(s: CString) -> Box<CStr> {
-        s.into_boxed_c_str()
-    }
-}
-
-impl<'a> From<CString> for Cow<'a, CStr> {
-    /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating.
-    #[inline]
-    fn from(s: CString) -> Cow<'a, CStr> {
-        Cow::Owned(s)
-    }
-}
-
-impl<'a> From<&'a CStr> for Cow<'a, CStr> {
-    /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating.
-    #[inline]
-    fn from(s: &'a CStr) -> Cow<'a, CStr> {
-        Cow::Borrowed(s)
-    }
-}
-
-impl<'a> From<&'a CString> for Cow<'a, CStr> {
-    /// Converts a `&`[`CString`] into a borrowed [`Cow`] without copying or allocating.
-    #[inline]
-    fn from(s: &'a CString) -> Cow<'a, CStr> {
-        Cow::Borrowed(s.as_c_str())
-    }
-}
-
-impl From<CString> for Arc<CStr> {
-    /// Converts a [`CString`] into an <code>[Arc]<[CStr]></code> by moving the [`CString`]
-    /// data into a new [`Arc`] buffer.
-    #[inline]
-    fn from(s: CString) -> Arc<CStr> {
-        let arc: Arc<[u8]> = Arc::from(s.into_inner());
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
-    }
-}
-
-impl From<&CStr> for Arc<CStr> {
-    /// Converts a `&CStr` into a `Arc<CStr>`,
-    /// by copying the contents into a newly allocated [`Arc`].
-    #[inline]
-    fn from(s: &CStr) -> Arc<CStr> {
-        let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
-    }
-}
-
-impl From<CString> for Rc<CStr> {
-    /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> by moving the [`CString`]
-    /// data into a new [`Arc`] buffer.
-    #[inline]
-    fn from(s: CString) -> Rc<CStr> {
-        let rc: Rc<[u8]> = Rc::from(s.into_inner());
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
-    }
-}
-
-impl From<&CStr> for Rc<CStr> {
-    /// Converts a `&CStr` into a `Rc<CStr>`,
-    /// by copying the contents into a newly allocated [`Rc`].
-    #[inline]
-    fn from(s: &CStr) -> Rc<CStr> {
-        let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
-    }
-}
-
-impl Default for Box<CStr> {
-    fn default() -> Box<CStr> {
-        let boxed: Box<[u8]> = Box::from([0]);
-        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
-    }
-}
-
-impl NulError {
-    /// Returns the position of the nul byte in the slice that caused
-    /// [`CString::new`] to fail.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let nul_error = CString::new("foo\0bar").unwrap_err();
-    /// assert_eq!(nul_error.nul_position(), 3);
-    ///
-    /// let nul_error = CString::new("foo bar\0").unwrap_err();
-    /// assert_eq!(nul_error.nul_position(), 7);
-    /// ```
-    #[must_use]
-    pub fn nul_position(&self) -> usize {
-        self.0
-    }
-
-    /// Consumes this error, returning the underlying vector of bytes which
-    /// generated the error in the first place.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let nul_error = CString::new("foo\0bar").unwrap_err();
-    /// assert_eq!(nul_error.into_vec(), b"foo\0bar");
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_vec(self) -> Vec<u8> {
-        self.1
-    }
-}
-
-impl IntoStringError {
-    /// Consumes this error, returning original [`CString`] which generated the
-    /// error.
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_cstring(self) -> CString {
-        self.inner
-    }
-
-    /// Access the underlying UTF-8 error that was the cause of this error.
-    #[must_use]
-    pub fn utf8_error(&self) -> Utf8Error {
-        self.error
-    }
-}
-
-impl CStr {
-    /// Wraps a raw C string with a safe C string wrapper.
-    ///
-    /// This function will wrap the provided `ptr` with a `CStr` wrapper, which
-    /// allows inspection and interoperation of non-owned C strings. The total
-    /// size of the raw C string must be smaller than `isize::MAX` **bytes**
-    /// in memory due to calling the `slice::from_raw_parts` function.
-    /// This method is unsafe for a number of reasons:
-    ///
-    /// * There is no guarantee to the validity of `ptr`.
-    /// * The returned lifetime is not guaranteed to be the actual lifetime of
-    ///   `ptr`.
-    /// * There is no guarantee that the memory pointed to by `ptr` contains a
-    ///   valid nul terminator byte at the end of the string.
-    /// * It is not guaranteed that the memory pointed by `ptr` won't change
-    ///   before the `CStr` has been destroyed.
-    ///
-    /// > **Note**: This operation is intended to be a 0-cost cast but it is
-    /// > currently implemented with an up-front calculation of the length of
-    /// > the string. This is not guaranteed to always be the case.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore (extern-declaration)
-    /// # fn main() {
-    /// use std::ffi::CStr;
-    /// use std::os::raw::c_char;
-    ///
-    /// extern "C" {
-    ///     fn my_string() -> *const c_char;
-    /// }
-    ///
-    /// unsafe {
-    ///     let slice = CStr::from_ptr(my_string());
-    ///     println!("string returned: {}", slice.to_str().unwrap());
-    /// }
-    /// # }
-    /// ```
-    #[inline]
-    #[must_use]
-    pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
-        // SAFETY: The caller has provided a pointer that points to a valid C
-        // string with a NUL terminator of size less than `isize::MAX`, whose
-        // content remain valid and doesn't change for the lifetime of the
-        // returned `CStr`.
-        //
-        // Thus computing the length is fine (a NUL byte exists), the call to
-        // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning
-        // the call to `from_bytes_with_nul_unchecked` is correct.
-        //
-        // The cast from c_char to u8 is ok because a c_char is always one byte.
-        let len = c::strlen(ptr);
-        let ptr = ptr as *const u8;
-        Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
-    }
-
-    /// Creates a C string wrapper from a byte slice.
-    ///
-    /// This function will cast the provided `bytes` to a `CStr`
-    /// wrapper after ensuring that the byte slice is nul-terminated
-    /// and does not contain any interior nul bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
-    /// assert!(cstr.is_ok());
-    /// ```
-    ///
-    /// Creating a `CStr` without a trailing nul terminator is an error:
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"hello");
-    /// assert!(cstr.is_err());
-    /// ```
-    ///
-    /// Creating a `CStr` with an interior nul byte is an error:
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
-    /// assert!(cstr.is_err());
-    /// ```
-    pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
-        let nul_pos = memchr::memchr(0, bytes);
-        match nul_pos {
-            Some(nul_pos) if nul_pos + 1 == bytes.len() => {
-                // SAFETY: We know there is only one nul byte, at the end
-                // of the byte slice.
-                Ok(unsafe { Self::_from_bytes_with_nul_unchecked(bytes) })
-            }
-            Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
-            None => Err(FromBytesWithNulError::not_nul_terminated()),
-        }
-    }
-
-    /// Unsafely creates a C string wrapper from a byte slice.
-    ///
-    /// This function will cast the provided `bytes` to a `CStr` wrapper without
-    /// performing any sanity checks. The provided slice **must** be nul-terminated
-    /// and not contain any interior nul bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::{CStr, CString};
-    ///
-    /// unsafe {
-    ///     let cstring = CString::new("hello").expect("CString::new failed");
-    ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
-    ///     assert_eq!(cstr, &*cstring);
-    /// }
-    /// ```
-    #[inline]
-    #[must_use]
-    pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
-        // We're in a const fn, so this is the best we can do
-        debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
-        Self::_from_bytes_with_nul_unchecked(bytes)
-    }
-
-    #[inline]
-    const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self {
-        // SAFETY: Casting to CStr is safe because its internal representation
-        // is a [u8] too (safe only inside std).
-        // Dereferencing the obtained pointer is safe because it comes from a
-        // reference. Making a reference is then safe because its lifetime
-        // is bound by the lifetime of the given `bytes`.
-        &*(bytes as *const [u8] as *const Self)
-    }
-
-    /// Returns the inner pointer to this C string.
-    ///
-    /// The returned pointer will be valid for as long as `self` is, and points
-    /// to a contiguous region of memory terminated with a 0 byte to represent
-    /// the end of the string.
-    ///
-    /// **WARNING**
-    ///
-    /// The returned pointer is read-only; writing to it (including passing it
-    /// to C code that writes to it) causes undefined behavior.
-    ///
-    /// It is your responsibility to make sure that the underlying memory is not
-    /// freed too early. For example, the following code will cause undefined
-    /// behavior when `ptr` is used inside the `unsafe` block:
-    ///
-    /// ```no_run
-    /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)]
-    /// use std::ffi::CString;
-    ///
-    /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
-    /// unsafe {
-    ///     // `ptr` is dangling
-    ///     *ptr;
-    /// }
-    /// ```
-    ///
-    /// This happens because the pointer returned by `as_ptr` does not carry any
-    /// lifetime information and the [`CString`] is deallocated immediately after
-    /// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
-    /// expression is evaluated.
-    /// To fix the problem, bind the `CString` to a local variable:
-    ///
-    /// ```no_run
-    /// # #![allow(unused_must_use)]
-    /// use std::ffi::CString;
-    ///
-    /// let hello = CString::new("Hello").expect("CString::new failed");
-    /// let ptr = hello.as_ptr();
-    /// unsafe {
-    ///     // `ptr` is valid because `hello` is in scope
-    ///     *ptr;
-    /// }
-    /// ```
-    ///
-    /// This way, the lifetime of the [`CString`] in `hello` encompasses
-    /// the lifetime of `ptr` and the `unsafe` block.
-    #[inline]
-    #[must_use]
-    pub const fn as_ptr(&self) -> *const c_char {
-        self.inner.as_ptr()
-    }
-
-    /// Converts this C string to a byte slice.
-    ///
-    /// The returned slice will **not** contain the trailing nul terminator that this C
-    /// string has.
-    ///
-    /// > **Note**: This method is currently implemented as a constant-time
-    /// > cast, but it is planned to alter its definition in the future to
-    /// > perform the length calculation whenever this method is called.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_bytes(), b"foo");
-    /// ```
-    #[inline]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    pub fn to_bytes(&self) -> &[u8] {
-        let bytes = self.to_bytes_with_nul();
-        // SAFETY: to_bytes_with_nul returns slice with length at least 1
-        unsafe { bytes.get_unchecked(..bytes.len() - 1) }
-    }
-
-    /// Converts this C string to a byte slice containing the trailing 0 byte.
-    ///
-    /// This function is the equivalent of [`CStr::to_bytes`] except that it
-    /// will retain the trailing nul terminator instead of chopping it off.
-    ///
-    /// > **Note**: This method is currently implemented as a 0-cost cast, but
-    /// > it is planned to alter its definition in the future to perform the
-    /// > length calculation whenever this method is called.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");
-    /// ```
-    #[inline]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    pub fn to_bytes_with_nul(&self) -> &[u8] {
-        unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
-    }
-
-    /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8.
-    ///
-    /// If the contents of the `CStr` are valid UTF-8 data, this
-    /// function will return the corresponding <code>&[str]</code> slice. Otherwise,
-    /// it will return an error with details of where UTF-8 validation failed.
-    ///
-    /// [str]: prim@str "str"
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_str(), Ok("foo"));
-    /// ```
-    pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
-        // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
-        // instead of in `from_ptr()`, it may be worth considering if this should
-        // be rewritten to do the UTF-8 check inline with the length calculation
-        // instead of doing it afterwards.
-        str::from_utf8(self.to_bytes())
-    }
-
-    /// Converts a `CStr` into a <code>[Cow]<[str]></code>.
-    ///
-    /// If the contents of the `CStr` are valid UTF-8 data, this
-    /// function will return a <code>[Cow]::[Borrowed]\(&[str])</code>
-    /// with the corresponding <code>&[str]</code> slice. Otherwise, it will
-    /// replace any invalid UTF-8 sequences with
-    /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
-    /// <code>[Cow]::[Owned]\(&[str])</code> with the result.
-    ///
-    /// [str]: prim@str "str"
-    /// [Borrowed]: Cow::Borrowed
-    /// [Owned]: Cow::Owned
-    /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER "std::char::REPLACEMENT_CHARACTER"
-    ///
-    /// # Examples
-    ///
-    /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8:
-    ///
-    /// ```
-    /// use std::borrow::Cow;
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"Hello World\0")
-    ///                  .expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World"));
-    /// ```
-    ///
-    /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8:
-    ///
-    /// ```
-    /// use std::borrow::Cow;
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0")
-    ///                  .expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(
-    ///     cstr.to_string_lossy(),
-    ///     Cow::Owned(String::from("Hello �World")) as Cow<'_, str>
-    /// );
-    /// ```
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    pub fn to_string_lossy(&self) -> Cow<'_, str> {
-        String::from_utf8_lossy(self.to_bytes())
-    }
-
-    /// Converts a <code>[Box]<[CStr]></code> into a [`CString`] without copying or allocating.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
-    /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed"));
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_c_string(self: Box<CStr>) -> CString {
-        let raw = Box::into_raw(self) as *mut [u8];
-        CString {
-            inner: unsafe { Box::from_raw(raw) },
-        }
-    }
-}
-
-impl PartialEq for CStr {
-    fn eq(&self, other: &CStr) -> bool {
-        self.to_bytes().eq(other.to_bytes())
-    }
-}
-
-impl Eq for CStr {}
-
-impl PartialOrd for CStr {
-    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
-        self.to_bytes().partial_cmp(other.to_bytes())
-    }
-}
-
-impl Ord for CStr {
-    fn cmp(&self, other: &CStr) -> Ordering {
-        self.to_bytes().cmp(other.to_bytes())
-    }
-}
-
-impl ToOwned for CStr {
-    type Owned = CString;
-
-    fn to_owned(&self) -> CString {
-        CString {
-            inner: self.to_bytes_with_nul().into(),
-        }
-    }
-
-    fn clone_into(&self, target: &mut CString) {
-        let mut b = Vec::from(mem::take(&mut target.inner));
-        self.to_bytes_with_nul().clone_into(&mut b);
-        target.inner = b.into_boxed_slice();
-    }
-}
-
-impl From<&CStr> for CString {
-    /// Copies the contents of the `&CStr` into a newly allocated `CString`.
-    fn from(s: &CStr) -> CString {
-        s.to_owned()
-    }
-}
-
-impl ops::Index<ops::RangeFull> for CString {
-    type Output = CStr;
-
-    #[inline]
-    fn index(&self, _index: ops::RangeFull) -> &CStr {
-        self
-    }
-}
-
-impl ops::Index<ops::RangeFrom<usize>> for CStr {
-    type Output = CStr;
-
-    fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
-        let bytes = self.to_bytes_with_nul();
-        // we need to manually check the starting index to account for the null
-        // byte, since otherwise we could get an empty string that doesn't end
-        // in a null.
-        if index.start < bytes.len() {
-            unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) }
-        } else {
-            panic!(
-                "index out of bounds: the len is {} but the index is {}",
-                bytes.len(),
-                index.start
-            );
-        }
-    }
-}
-
-impl AsRef<CStr> for CStr {
-    #[inline]
-    fn as_ref(&self) -> &CStr {
-        self
-    }
-}
-
-impl AsRef<CStr> for CString {
-    #[inline]
-    fn as_ref(&self) -> &CStr {
-        self
-    }
-}
-
-mod c {
-    /// # Safety
-    pub unsafe fn strlen(s: *const i8) -> usize {
-        let mut result = 0;
-        let mut p = s;
-        while *p != 0 {
-            p = p.offset(1);
-            result += 1;
-        }
-        result
-    }
-}
+pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError};
+pub use core::ffi::{CStr, FromBytesWithNulError};
diff --git a/sgx_ffi/src/c_str/tests.rs b/sgx_ffi/src/c_str/tests.rs
deleted file mode 100644
index 74098856..00000000
--- a/sgx_ffi/src/c_str/tests.rs
+++ /dev/null
@@ -1,200 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License..
-
-use super::*;
-use alloc::borrow::Cow::{Borrowed, Owned};
-use alloc::rc::Rc;
-use alloc::sync::Arc;
-use sgx_types::types::c_char;
-
-use sgx_test_utils::test_case;
-
-#[test_case]
-fn c_to_rust() {
-    let data = b"123\0";
-    let ptr = data.as_ptr() as *const c_char;
-    unsafe {
-        assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
-        assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
-    }
-}
-
-#[test_case]
-fn simple() {
-    let s = CString::new("1234").unwrap();
-    assert_eq!(s.as_bytes(), b"1234");
-    assert_eq!(s.as_bytes_with_nul(), b"1234\0");
-}
-
-#[test_case]
-fn build_with_zero1() {
-    assert!(CString::new(&b"\0"[..]).is_err());
-}
-
-#[test_case]
-fn build_with_zero2() {
-    assert!(CString::new(vec![0]).is_err());
-}
-
-#[test_case]
-fn formatted() {
-    let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap();
-    assert_eq!(format!("{:?}", s), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#);
-}
-
-#[test_case]
-fn borrowed() {
-    unsafe {
-        let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
-        assert_eq!(s.to_bytes(), b"12");
-        assert_eq!(s.to_bytes_with_nul(), b"12\0");
-    }
-}
-
-#[test_case]
-fn to_str() {
-    let data = b"123\xE2\x80\xA6\0";
-    let ptr = data.as_ptr() as *const c_char;
-    unsafe {
-        assert_eq!(CStr::from_ptr(ptr).to_str(), Ok("123…"));
-        assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Borrowed("123…"));
-    }
-    let data = b"123\xE2\0";
-    let ptr = data.as_ptr() as *const c_char;
-    unsafe {
-        assert!(CStr::from_ptr(ptr).to_str().is_err());
-        assert_eq!(
-            CStr::from_ptr(ptr).to_string_lossy(),
-            Owned::<str>(format!("123\u{FFFD}"))
-        );
-    }
-}
-
-#[test_case]
-fn to_owned() {
-    let data = b"123\0";
-    let ptr = data.as_ptr() as *const c_char;
-
-    let owned = unsafe { CStr::from_ptr(ptr).to_owned() };
-    assert_eq!(owned.as_bytes_with_nul(), data);
-}
-
-#[test_case]
-fn from_bytes_with_nul() {
-    let data = b"123\0";
-    let cstr = CStr::from_bytes_with_nul(data);
-    assert_eq!(cstr.map(CStr::to_bytes), Ok(&b"123"[..]));
-    let cstr = CStr::from_bytes_with_nul(data);
-    assert_eq!(cstr.map(CStr::to_bytes_with_nul), Ok(&b"123\0"[..]));
-
-    unsafe {
-        let cstr = CStr::from_bytes_with_nul(data);
-        let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data);
-        assert_eq!(cstr, Ok(cstr_unchecked));
-    }
-}
-
-#[test_case]
-fn from_bytes_with_nul_unterminated() {
-    let data = b"123";
-    let cstr = CStr::from_bytes_with_nul(data);
-    assert!(cstr.is_err());
-}
-
-#[test_case]
-fn from_bytes_with_nul_interior() {
-    let data = b"1\023\0";
-    let cstr = CStr::from_bytes_with_nul(data);
-    assert!(cstr.is_err());
-}
-
-#[test_case]
-fn into_boxed() {
-    let orig: &[u8] = b"Hello, world!\0";
-    let cstr = CStr::from_bytes_with_nul(orig).unwrap();
-    let boxed: Box<CStr> = Box::from(cstr);
-    let cstring = cstr.to_owned().into_boxed_c_str().into_c_string();
-    assert_eq!(cstr, &*boxed);
-    assert_eq!(&*boxed, &*cstring);
-    assert_eq!(&*cstring, cstr);
-}
-
-#[test_case]
-fn boxed_default() {
-    let boxed = <Box<CStr>>::default();
-    assert_eq!(boxed.to_bytes_with_nul(), &[0]);
-}
-
-#[test_case]
-fn test_c_str_clone_into() {
-    let mut c_string = CString::new("lorem").unwrap();
-    let c_ptr = c_string.as_ptr();
-    let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap();
-    c_str.clone_into(&mut c_string);
-    assert_eq!(c_str, c_string.as_c_str());
-    // The exact same size shouldn't have needed to move its allocation
-    assert_eq!(c_ptr, c_string.as_ptr());
-}
-
-#[test_case]
-fn into_rc() {
-    let orig: &[u8] = b"Hello, world!\0";
-    let cstr = CStr::from_bytes_with_nul(orig).unwrap();
-    let rc: Rc<CStr> = Rc::from(cstr);
-    let arc: Arc<CStr> = Arc::from(cstr);
-
-    assert_eq!(&*rc, cstr);
-    assert_eq!(&*arc, cstr);
-
-    let rc2: Rc<CStr> = Rc::from(cstr.to_owned());
-    let arc2: Arc<CStr> = Arc::from(cstr.to_owned());
-
-    assert_eq!(&*rc2, cstr);
-    assert_eq!(&*arc2, cstr);
-}
-
-#[test_case]
-fn cstr_const_constructor() {
-    const CSTR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"Hello, world!\0") };
-
-    assert_eq!(CSTR.to_str().unwrap(), "Hello, world!");
-}
-
-#[test_case]
-fn cstr_index_from() {
-    let original = b"Hello, world!\0";
-    let cstr = CStr::from_bytes_with_nul(original).unwrap();
-    let result = CStr::from_bytes_with_nul(&original[7..]).unwrap();
-
-    assert_eq!(&cstr[7..], result);
-}
-
-#[test_case]
-fn c_string_from_empty_string() {
-    let original = "";
-    let cstring = CString::new(original).unwrap();
-    assert_eq!(original.as_bytes(), cstring.as_bytes());
-    assert_eq!([b'\0'], cstring.as_bytes_with_nul());
-}
-
-#[test_case]
-fn c_str_from_empty_string() {
-    let original = b"\0";
-    let cstr = CStr::from_bytes_with_nul(original).unwrap();
-    assert_eq!([] as [u8; 0], cstr.to_bytes());
-    assert_eq!([b'\0'], cstr.to_bytes_with_nul());
-}
diff --git a/sgx_ffi/src/lib.rs b/sgx_ffi/src/lib.rs
index d141f7aa..fd8d5dc1 100644
--- a/sgx_ffi/src/lib.rs
+++ b/sgx_ffi/src/lib.rs
@@ -17,19 +17,8 @@
 
 #![no_std]
 #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))]
-#![allow(clippy::derive_hash_xor_eq)]
-#![allow(clippy::missing_safety_doc)]
-#![allow(incomplete_features)]
-#![feature(rustc_attrs)]
-#![feature(specialization)]
-#![feature(toowned_clone_into)]
-#![feature(vec_into_raw_parts)]
-#![cfg_attr(feature = "unit_test", allow(clippy::useless_format))]
 
-#[allow(unused_imports)]
-#[macro_use]
 extern crate alloc;
-
 extern crate sgx_types;
 
 pub mod ascii;
diff --git a/sgx_key_exchange/message/src/message.rs b/sgx_key_exchange/message/src/message.rs
index 231e36e9..20959cd3 100644
--- a/sgx_key_exchange/message/src/message.rs
+++ b/sgx_key_exchange/message/src/message.rs
@@ -199,7 +199,7 @@ impl RaMsg2 {
         raw_msg.kdf_id = self.kdf_id;
         raw_msg.sign_gb_ga = self.sign_gb_ga.into();
         raw_msg.mac = self.mac;
-        raw_msg.sig_rl_size = raw_len - header_len as u32;
+        raw_msg.sig_rl_size = raw_len - header_len;
         if let Some(sig_rl) = self.sig_rl.as_ref() {
             bytes[header_len as usize..].copy_from_slice(sig_rl);
         }
@@ -219,7 +219,7 @@ impl RaMsg2 {
         raw_msg.kdf_id = self.kdf_id;
         raw_msg.sign_gb_ga = self.sign_gb_ga.into();
         raw_msg.mac = self.mac;
-        raw_msg.sig_rl_size = raw_len - header_len as u32;
+        raw_msg.sig_rl_size = raw_len - header_len;
         if let Some(sig_rl) = self.sig_rl.as_ref() {
             bytes[header_len as usize..].copy_from_slice(sig_rl);
         }
diff --git a/sgx_key_exchange/tkey_exchange/src/session/manager.rs b/sgx_key_exchange/tkey_exchange/src/session/manager.rs
index 468230b9..2ada71a9 100644
--- a/sgx_key_exchange/tkey_exchange/src/session/manager.rs
+++ b/sgx_key_exchange/tkey_exchange/src/session/manager.rs
@@ -23,7 +23,7 @@ use core::ops::Deref;
 use core::ptr;
 use core::sync::atomic::{AtomicU32, Ordering};
 use sgx_crypto::ecc::{EcPrivateKey, EcPublicKey, EcShareKey};
-use sgx_sync::{SpinMutex, SpinRwLock, SyncLazy};
+use sgx_sync::{LazyLock, SpinMutex, SpinRwLock};
 use sgx_types::error::SgxResult;
 use sgx_types::types::{AlignKey128bit, Ec256SharedKey, PsSecPropDesc, QuoteNonce, TargetInfo};
 
@@ -119,8 +119,8 @@ impl Session {
     }
 }
 
-pub static SESSION_MAGAGER: SyncLazy<SpinRwLock<SessionManager>> =
-    SyncLazy::new(|| SpinRwLock::new(SessionManager::new()));
+pub static SESSION_MAGAGER: LazyLock<SpinRwLock<SessionManager>> =
+    LazyLock::new(|| SpinRwLock::new(SessionManager::new()));
 
 struct Node {
     sid: u32,
diff --git a/sgx_key_exchange/ukey_exchange/src/capi.rs b/sgx_key_exchange/ukey_exchange/src/capi.rs
index 09fbef36..76b8cd9a 100644
--- a/sgx_key_exchange/ukey_exchange/src/capi.rs
+++ b/sgx_key_exchange/ukey_exchange/src/capi.rs
@@ -22,12 +22,12 @@ use sgx_types::types::{
     AttKeyId, CRaMsg1, CRaMsg2, CRaMsg3, ECallGetGaFn, ECallGetMsg3Fn, ECallProcessMsg2Fn,
     EnclaveId, RaContext,
 };
-use std::lazy::SyncLazy;
 use std::mem::ManuallyDrop;
 use std::slice;
+use std::sync::LazyLock;
 use std::sync::Mutex;
 
-static INITIATOR: SyncLazy<Mutex<Initiator>> = SyncLazy::new(|| Mutex::new(Initiator::new(0, 0)));
+static INITIATOR: LazyLock<Mutex<Initiator>> = LazyLock::new(|| Mutex::new(Initiator::new(0, 0)));
 
 /// # Safety
 #[no_mangle]
diff --git a/sgx_key_exchange/ukey_exchange/src/session.rs b/sgx_key_exchange/ukey_exchange/src/session.rs
index 66fac032..97cec698 100644
--- a/sgx_key_exchange/ukey_exchange/src/session.rs
+++ b/sgx_key_exchange/ukey_exchange/src/session.rs
@@ -187,7 +187,7 @@ impl Initiator {
                     &report as *const _,
                     att_key_id as *const _,
                     &mut qe_report_info as *mut _,
-                    (&mut c_msg3.quote).as_mut_ptr().cast(),
+                    (c_msg3.quote).as_mut_ptr().cast(),
                     quote_size,
                 );
                 ensure!(status.is_success(), status);
@@ -203,7 +203,7 @@ impl Initiator {
                     sig_rl,
                     sig_rl_len,
                     &mut qe_report as *mut _,
-                    (&mut c_msg3.quote).as_mut_ptr().cast(),
+                    (c_msg3.quote).as_mut_ptr().cast(),
                     quote_size,
                 );
                 ensure!(status.is_success(), status);
diff --git a/sgx_libc/Cargo.toml b/sgx_libc/Cargo.toml
index 78c1209d..a737a21e 100644
--- a/sgx_libc/Cargo.toml
+++ b/sgx_libc/Cargo.toml
@@ -32,7 +32,7 @@ crate-type = ["rlib"]
 [features]
 default = ["panic_on_unsupported_syscall"]
 extra_traits = ["sgx_oc/extra_traits"]
-pthread = ["sgx_trts/thread"]
+pthread = ["sgx_trts/thread", "sgx_sync/capi"]
 panic_on_unsupported_syscall = []
 
 [target.'cfg(not(target_vendor = "teaclave"))'.dependencies]
diff --git a/sgx_libc/sgx_tlibc_sys/src/lib.rs b/sgx_libc/sgx_tlibc_sys/src/lib.rs
index f9a7d91e..04bce752 100644
--- a/sgx_libc/sgx_tlibc_sys/src/lib.rs
+++ b/sgx_libc/sgx_tlibc_sys/src/lib.rs
@@ -161,6 +161,7 @@ mod bindings {
 
         #[cfg_attr(target_os = "linux", link_name = "__errno_location")]
         pub fn errno_location() -> *mut c_int;
+        pub fn strerror(errnum: c_int) -> *const c_char;
         pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int;
     }
 }
diff --git a/sgx_libc/src/linux/ocall/fd.rs b/sgx_libc/src/linux/ocall/fd.rs
index 140ac744..3ab67ba0 100644
--- a/sgx_libc/src/linux/ocall/fd.rs
+++ b/sgx_libc/src/linux/ocall/fd.rs
@@ -347,11 +347,7 @@ pub unsafe extern "C" fn close(fd: c_int) -> c_int {
 
 #[no_mangle]
 pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
-    if ocall::isatty(fd).is_ok() {
-        1
-    } else {
-        0
-    }
+    i32::from(ocall::isatty(fd).is_ok())
 }
 
 #[no_mangle]
@@ -371,3 +367,17 @@ pub unsafe extern "C" fn eventfd(initval: c_uint, flags: c_int) -> c_int {
         -1
     }
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn futimens(fd: c_int, times: *const [timespec; 2]) -> c_int {
+    if times.is_null() {
+        set_errno(EINVAL);
+        return -1;
+    }
+
+    if ocall::futimens(fd, &*times).is_ok() {
+        0
+    } else {
+        -1
+    }
+}
diff --git a/sgx_libc/src/linux/ocall/sync.rs b/sgx_libc/src/linux/ocall/sync.rs
index 7e3a1682..a05707a3 100644
--- a/sgx_libc/src/linux/ocall/sync.rs
+++ b/sgx_libc/src/linux/ocall/sync.rs
@@ -18,7 +18,7 @@
 use crate::linux::*;
 use core::convert::TryFrom;
 use core::mem;
-use core::sync::atomic::AtomicI32;
+use core::sync::atomic::AtomicU32;
 use core::time::Duration;
 use sgx_sync::{Futex, FutexFlags, FutexOp, Timespec};
 use sgx_trts::trts::is_within_enclave;
@@ -50,11 +50,11 @@ unsafe fn futex_inernal(
     uaddr2: *const u32,
     val3: u32,
 ) -> OsResult<isize> {
-    let get_addr = |addr: *const u32| -> OsResult<&AtomicI32> {
+    let get_addr = |addr: *const u32| -> OsResult<&AtomicU32> {
         if addr.is_null() || !is_within_enclave(addr as *const u8, mem::size_of::<c_int>()) {
             Err(EINVAL)
         } else {
-            Ok(&*(addr as *const AtomicI32))
+            Ok(&*(addr as *const AtomicU32))
         }
     };
 
@@ -83,11 +83,11 @@ unsafe fn futex_inernal(
                 Some(t) => Duration::try_from(t).map(Some),
                 None => Ok(None),
             })?;
-            futex.wait(val as i32, timeout).map(|_| 0)
+            futex.wait(val, timeout).map(|_| 0)
         }
         FutexOp::WaitBitset => {
             let timeout = get_timeout(timeout)?.map(|ts| (ts, flags.into()));
-            futex.wait_bitset(val as i32, timeout, val3).map(|_| 0)
+            futex.wait_bitset(val, timeout, val3).map(|_| 0)
         }
         FutexOp::Wake => {
             let count = get_val(val)?;
@@ -110,7 +110,7 @@ unsafe fn futex_inernal(
             let nwakes = get_val(val)?;
             let nrequeues = get_val(timeout as u32)?;
             futex
-                .cmp_requeue(nwakes, &new_futex, nrequeues, val3 as i32)
+                .cmp_requeue(nwakes, &new_futex, nrequeues, val3)
                 .map(|total| total as isize)
         }
         _ => {
diff --git a/sgx_libc/src/linux/pthread/mod.rs b/sgx_libc/src/linux/pthread/mod.rs
index 00f1abe2..4d1412a5 100644
--- a/sgx_libc/src/linux/pthread/mod.rs
+++ b/sgx_libc/src/linux/pthread/mod.rs
@@ -123,11 +123,7 @@ pub unsafe extern "C" fn pthread_self() -> pthread_t {
 
 #[no_mangle]
 pub unsafe extern "C" fn pthread_equal(t1: pthread_t, t2: pthread_t) -> c_int {
-    if t1 == t2 {
-        1
-    } else {
-        0
-    }
+    i32::from(t1 == t2)
 }
 
 #[no_mangle]
diff --git a/sgx_oc/src/lib.rs b/sgx_oc/src/lib.rs
index 17743fff..58ec7c98 100644
--- a/sgx_oc/src/lib.rs
+++ b/sgx_oc/src/lib.rs
@@ -18,6 +18,7 @@
 #![no_std]
 #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))]
 #![feature(allocator_api)]
+#![feature(error_in_core)]
 #![feature(const_extern_fn)]
 #![feature(negative_impls)]
 #![feature(nonnull_slice_from_raw_parts)]
diff --git a/sgx_oc/src/linux/edl/fd.rs b/sgx_oc/src/linux/edl/fd.rs
index 45b9ee7d..77a1b30c 100644
--- a/sgx_oc/src/linux/edl/fd.rs
+++ b/sgx_oc/src/linux/edl/fd.rs
@@ -112,4 +112,10 @@ extern "C" {
         initval: c_uint,
         flags: c_int,
     ) -> sgx_status_t;
+    pub fn u_futimens_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        fd: c_int,
+        times: *const [timespec; 2],
+    ) -> sgx_status_t;
 }
diff --git a/sgx_oc/src/linux/mod.rs b/sgx_oc/src/linux/mod.rs
index ca831660..1e0736ef 100644
--- a/sgx_oc/src/linux/mod.rs
+++ b/sgx_oc/src/linux/mod.rs
@@ -110,7 +110,7 @@ f! {
     }
 
     pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr {
-        if (*mhdr).msg_controllen as usize >= mem::size_of::<cmsghdr>() {
+        if (*mhdr).msg_controllen >= mem::size_of::<cmsghdr>() {
             (*mhdr).msg_control as *mut cmsghdr
         } else {
             core::ptr::null_mut::<cmsghdr>()
@@ -130,13 +130,13 @@ f! {
     }
 
     pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr {
-        if ((*cmsg).cmsg_len as usize) < mem::size_of::<cmsghdr>() {
+        if ((*cmsg).cmsg_len) < mem::size_of::<cmsghdr>() {
             return core::ptr::null_mut::<cmsghdr>();
         };
-        let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr;
-        let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize;
+        let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len)) as *mut cmsghdr;
+        let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen;
         if (next.offset(1)) as usize > max
-            || next as usize + CMSG_ALIGN((*next).cmsg_len as usize) > max
+            || next as usize + CMSG_ALIGN((*next).cmsg_len) > max
         {
             core::ptr::null_mut::<cmsghdr>()
         } else {
@@ -255,7 +255,7 @@ unsafe fn __sigdelset(set: *mut sigset_t, sig: c_int) {
 unsafe fn __sigismember(set: *const sigset_t, sig: c_int) -> c_int {
     let mask: u64 = __sigmask(sig);
     let word: u64 = __sigword(sig);
-    let val = if mask != 0 { 1 } else { 0 };
+    let val = u64::from(mask != 0);
     ((*set).__val[word as usize] & val) as c_int
 }
 
diff --git a/sgx_oc/src/linux/ocall/env.rs b/sgx_oc/src/linux/ocall/env.rs
index 590407c1..87257552 100644
--- a/sgx_oc/src/linux/ocall/env.rs
+++ b/sgx_oc/src/linux/ocall/env.rs
@@ -46,7 +46,7 @@ pub unsafe fn getgid() -> OCallResult<gid_t> {
 pub unsafe fn getcwd() -> OCallResult<CString> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let mut buf = Vec::with_capacity(1024);
+    let mut buf = Vec::with_capacity(512);
 
     loop {
         let bufsz = buf.capacity();
diff --git a/sgx_oc/src/linux/ocall/fd.rs b/sgx_oc/src/linux/ocall/fd.rs
index 7c620e33..c09049ee 100644
--- a/sgx_oc/src/linux/ocall/fd.rs
+++ b/sgx_oc/src/linux/ocall/fd.rs
@@ -88,7 +88,7 @@ pub unsafe fn readv(fd: c_int, mut iov: Vec<&mut [u8]>) -> OCallResult<size_t> {
 
     let mut total_size: usize = 0;
     for s in iov.iter() {
-        check_enclave_buffer(*s)?;
+        check_enclave_buffer(s)?;
         total_size = total_size
             .checked_add(s.len())
             .ok_or_else(|| OCallError::from_custom_error("Overflow"))?;
@@ -155,7 +155,7 @@ pub unsafe fn preadv64(fd: c_int, mut iov: Vec<&mut [u8]>, offset: off64_t) -> O
 
     let mut total_size: usize = 0;
     for s in iov.iter() {
-        check_enclave_buffer(*s)?;
+        check_enclave_buffer(s)?;
         total_size = total_size
             .checked_add(s.len())
             .ok_or_else(|| OCallError::from_custom_error("Overflow"))?;
@@ -276,7 +276,7 @@ pub unsafe fn writev(fd: c_int, iov: Vec<&[u8]>) -> OCallResult<size_t> {
 
     let mut total_size: usize = 0;
     for s in iov.iter() {
-        check_enclave_buffer(*s)?;
+        check_enclave_buffer(s)?;
         total_size = total_size
             .checked_add(s.len())
             .ok_or_else(|| OCallError::from_custom_error("Overflow"))?;
@@ -328,7 +328,7 @@ pub unsafe fn pwritev64(fd: c_int, iov: Vec<&[u8]>, offset: off64_t) -> OCallRes
 
     let mut total_size: usize = 0;
     for s in iov.iter() {
-        check_enclave_buffer(*s)?;
+        check_enclave_buffer(s)?;
         total_size = total_size
             .checked_add(s.len())
             .ok_or_else(|| OCallError::from_custom_error("Overflow"))?;
@@ -608,3 +608,20 @@ pub unsafe fn eventfd(initval: c_uint, flags: c_int) -> OCallResult<c_int> {
 
     Ok(result)
 }
+
+pub unsafe fn futimens(fd: c_int, times: &[timespec; 2]) -> OCallResult<c_int> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+
+    let status = u_futimens_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        times as *const [timespec; 2],
+    );
+
+    ensure!(status.is_success(), esgx!(status));
+    ensure!(result >= 0, eos!(error));
+
+    Ok(result)
+}
diff --git a/sgx_oc/src/linux/ocall/mem.rs b/sgx_oc/src/linux/ocall/mem.rs
index 84f409aa..dee68f2c 100644
--- a/sgx_oc/src/linux/ocall/mem.rs
+++ b/sgx_oc/src/linux/ocall/mem.rs
@@ -84,13 +84,13 @@ impl Drop for HeapBuffer {
 
 impl AsRef<[u8]> for HeapBuffer {
     fn as_ref(&self) -> &[u8] {
-        &**self
+        self
     }
 }
 
 impl AsMut<[u8]> for HeapBuffer {
     fn as_mut(&mut self) -> &mut [u8] {
-        &mut **self
+        self
     }
 }
 
@@ -132,7 +132,7 @@ unsafe impl Allocator for HostAlloc {
     #[inline]
     unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
         if layout.size() != 0 && is_within_host(ptr.as_ptr(), layout.size()) {
-            let _ = self.host_free(ptr);
+            self.host_free(ptr);
         }
     }
 }
@@ -153,7 +153,7 @@ impl HostAlloc {
                 &mut error as *mut c_int,
                 size,
                 layout.align(),
-                if zeroed { 1 } else { 0 },
+                i32::from(zeroed),
             )
         } else {
             u_malloc_ocall(
diff --git a/sgx_oc/src/linux/ocall/mod.rs b/sgx_oc/src/linux/ocall/mod.rs
index f77fd035..bfa37a13 100644
--- a/sgx_oc/src/linux/ocall/mod.rs
+++ b/sgx_oc/src/linux/ocall/mod.rs
@@ -21,6 +21,7 @@ use alloc::str;
 use alloc::string::String;
 use alloc::vec::Vec;
 use core::convert::From;
+use core::error::Error;
 use core::fmt;
 use core::num::NonZeroUsize;
 use core::ptr;
@@ -77,7 +78,7 @@ impl OCallError {
 }
 
 impl OCallError {
-    pub fn description(&self) -> String {
+    pub fn error_description(&self) -> String {
         match self {
             Self::SgxError(status) => sgx_error_string(*status),
             Self::OsError(errno) => os_error_string(*errno),
@@ -110,6 +111,28 @@ impl From<&'static str> for OCallError {
     }
 }
 
+impl Error for OCallError {
+    #[allow(deprecated)]
+    fn description(&self) -> &str {
+        match self {
+            OCallError::SgxError(s) => s.description(),
+            OCallError::OsError(code) => os_error_str(*code),
+            OCallError::GaiError(code) => gai_error_str(*code),
+            OCallError::CustomError(s) => s,
+        }
+    }
+
+    #[allow(deprecated)]
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        match self {
+            OCallError::SgxError(ref s) => Some(s),
+            OCallError::OsError(..) => None,
+            OCallError::GaiError(..) => None,
+            OCallError::CustomError(..) => None,
+        }
+    }
+}
+
 pub type OCallResult<T> = Result<T, OCallError>;
 
 pub fn gai_error_cstr(errno: i32) -> &'static CStr {
@@ -161,6 +184,18 @@ pub fn gai_error_str(errno: i32) -> &'static str {
     }
 }
 
+pub fn os_error_str(errno: i32) -> &'static str {
+    extern "C" {
+        pub fn strerror(errnum: c_int) -> *const c_char;
+    }
+
+    unsafe {
+        let p = strerror(errno);
+        assert!(!p.is_null(), "strerror failure");
+        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap()
+    }
+}
+
 pub fn os_error_string(errno: i32) -> String {
     const TMPBUF_SZ: usize = 128;
     extern "C" {
diff --git a/sgx_oc/src/linux/ocall/socket.rs b/sgx_oc/src/linux/ocall/socket.rs
index 5a1c672f..5f9d23f7 100644
--- a/sgx_oc/src/linux/ocall/socket.rs
+++ b/sgx_oc/src/linux/ocall/socket.rs
@@ -468,7 +468,7 @@ impl SockAddr {
                     len as usize >= core::mem::size_of::<sockaddr_in>(),
                     ecust!("Malformed addr_len")
                 );
-                let sockaddr: *const sockaddr_in = core::mem::transmute(addr);
+                let sockaddr: *const sockaddr_in = addr as *const _ as *const sockaddr_in;
                 Ok(SockAddr::from(*sockaddr))
             }
             AF_INET6 => {
@@ -476,11 +476,11 @@ impl SockAddr {
                     len as usize >= core::mem::size_of::<sockaddr_in6>(),
                     ecust!("Malformed addr_len")
                 );
-                let sockaddr: *const sockaddr_in6 = core::mem::transmute(addr);
+                let sockaddr: *const sockaddr_in6 = addr as *const _ as *const sockaddr_in6;
                 Ok(SockAddr::from(*sockaddr))
             }
             AF_UNIX => {
-                let sockaddr: *const sockaddr_un = core::mem::transmute(addr);
+                let sockaddr: *const sockaddr_un = addr as *const _ as *const sockaddr_un;
                 SockAddr::try_from_un(*sockaddr, len)
             }
             _ => {
@@ -499,7 +499,7 @@ impl SockAddr {
                     len as usize == core::mem::size_of::<sockaddr_in>(),
                     ecust!("Malformed addr_len")
                 );
-                let sockaddr: *const sockaddr_in = core::mem::transmute(&storage);
+                let sockaddr: *const sockaddr_in = &storage as *const _ as *const sockaddr_in;
                 Ok(SockAddr::from(*sockaddr))
             }
             AF_INET6 => {
@@ -507,15 +507,15 @@ impl SockAddr {
                     len as usize == core::mem::size_of::<sockaddr_in6>(),
                     ecust!("Malformed addr_len")
                 );
-                let sockaddr: *const sockaddr_in6 = core::mem::transmute(&storage);
+                let sockaddr: *const sockaddr_in6 = &storage as *const _ as *const sockaddr_in6;
                 Ok(SockAddr::from(*sockaddr))
             }
             AF_UNIX => {
-                let sockaddr: *const sockaddr_un = core::mem::transmute(&storage);
+                let sockaddr: *const sockaddr_un = &storage as *const _ as *const sockaddr_un;
                 SockAddr::try_from_un(*sockaddr, len)
             }
             0 if len == 0 => {
-                let sockaddr: *const sockaddr_un = core::mem::transmute(&storage);
+                let sockaddr: *const sockaddr_un = &storage as *const _ as *const sockaddr_un;
                 Ok(SockAddr::UN((*sockaddr, len)))
             }
             _ => {
diff --git a/sgx_oc/src/linux/ocall/socket_msg.rs b/sgx_oc/src/linux/ocall/socket_msg.rs
index 7ed5a985..9d2f3de2 100644
--- a/sgx_oc/src/linux/ocall/socket_msg.rs
+++ b/sgx_oc/src/linux/ocall/socket_msg.rs
@@ -55,11 +55,8 @@ pub struct MsgHdrMut<'a> {
 impl<'a> MsgHdr<'a> {
     pub unsafe fn from_raw(c_msg: &msghdr) -> Self {
         let name = new_optional_slice(c_msg.msg_name as *const u8, c_msg.msg_namelen as usize);
-        let iovs = new_optional_slice(c_msg.msg_iov as *const iovec, c_msg.msg_iovlen as usize);
-        let control = new_optional_slice(
-            c_msg.msg_control as *const u8,
-            c_msg.msg_controllen as usize,
-        );
+        let iovs = new_optional_slice(c_msg.msg_iov as *const iovec, c_msg.msg_iovlen);
+        let control = new_optional_slice(c_msg.msg_control as *const u8, c_msg.msg_controllen);
         let flags = MsgHdrFlags::from_bits_truncate(c_msg.msg_flags);
         let iovs = iovs
             .map(|iovs_slice| {
@@ -82,9 +79,8 @@ impl<'a> MsgHdr<'a> {
 impl<'a> MsgHdrMut<'a> {
     pub unsafe fn from_raw(c_msg: &mut msghdr) -> Self {
         let name = new_optional_slice_mut(c_msg.msg_name as *mut u8, c_msg.msg_namelen as usize);
-        let iovs = new_optional_slice_mut(c_msg.msg_iov as *mut iovec, c_msg.msg_iovlen as usize);
-        let control =
-            new_optional_slice_mut(c_msg.msg_control as *mut u8, c_msg.msg_controllen as usize);
+        let iovs = new_optional_slice_mut(c_msg.msg_iov as *mut iovec, c_msg.msg_iovlen);
+        let control = new_optional_slice_mut(c_msg.msg_control as *mut u8, c_msg.msg_controllen);
         let flags = MsgHdrFlags::from_bits_truncate(c_msg.msg_flags);
         let iovs = iovs
             .map(|iovs_slice| {
@@ -238,7 +234,7 @@ pub unsafe fn recvmsg(sockfd: c_int, msg: &mut MsgHdrMut, flags: c_int) -> OCall
 
     let mut total_size: usize = 0;
     for s in msg.iovs.iter() {
-        check_trusted_enclave_buffer(*s)?;
+        check_trusted_enclave_buffer(s)?;
         total_size = total_size
             .checked_add(s.len())
             .ok_or_else(|| OCallError::from_custom_error("Overflow"))?;
@@ -333,7 +329,7 @@ pub unsafe fn recvmsg(sockfd: c_int, msg: &mut MsgHdrMut, flags: c_int) -> OCall
         }
     }
 
-    msg.name_len = msg_namelen_out as u32;
+    msg.name_len = msg_namelen_out;
     msg.control_len = msg_controllen_out;
     msg.flags = msg_flags;
 
diff --git a/sgx_oc/src/linux/x86_64/mod.rs b/sgx_oc/src/linux/x86_64/mod.rs
index 0c9b8f8f..c7f357c9 100644
--- a/sgx_oc/src/linux/x86_64/mod.rs
+++ b/sgx_oc/src/linux/x86_64/mod.rs
@@ -464,6 +464,9 @@ pub const AT_SYMLINK_NOFOLLOW: c_int = 0x100;
 pub const AT_REMOVEDIR: c_int = 0x200;
 pub const AT_SYMLINK_FOLLOW: c_int = 0x400;
 
+pub const UTIME_OMIT: c_long = 1073741822;
+pub const UTIME_NOW: c_long = 1073741823;
+
 pub const CLOCK_REALTIME: clockid_t = 0;
 pub const CLOCK_MONOTONIC: clockid_t = 1;
 pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
@@ -1279,7 +1282,7 @@ pub const SA_NOCLDWAIT: c_int = 0x0000_0002;
 
 pub const SIG_DFL: sighandler_t = 0_usize;
 pub const SIG_IGN: sighandler_t = 1_usize;
-pub const SIG_ERR: sighandler_t = !0 as usize;
+pub const SIG_ERR: sighandler_t = !0;
 
 pub const SIGHUP: c_int = 1;
 pub const SIGINT: c_int = 2;
diff --git a/sgx_protected_fs/tfs/src/capi.rs b/sgx_protected_fs/tfs/src/capi.rs
index 77fd69f4..70f90c7e 100644
--- a/sgx_protected_fs/tfs/src/capi.rs
+++ b/sgx_protected_fs/tfs/src/capi.rs
@@ -351,11 +351,7 @@ pub unsafe extern "C" fn sgx_feof(file: RawProtectedFile) -> i32 {
     }
 
     let file = ManuallyDrop::new(SgxFile::from_raw(file));
-    if file.is_eof() {
-        1
-    } else {
-        0
-    }
+    i32::from(file.is_eof())
 }
 
 /// # Safety
@@ -533,7 +529,7 @@ pub unsafe extern "C" fn sgx_fimport_auto_key(
         KeyPolicy::MRSIGNER
     };
 
-    match fs_imp::import_key(name, *import_key, key_policy) {
+    match fs_imp::import_key(name, *import_key, Some(key_policy)) {
         Ok(_) => 0,
         Err(_) => -1,
     }
diff --git a/sgx_protected_fs/tfs/src/sys/error.rs b/sgx_protected_fs/tfs/src/sys/error.rs
index df71b95a..6ee72820 100644
--- a/sgx_protected_fs/tfs/src/sys/error.rs
+++ b/sgx_protected_fs/tfs/src/sys/error.rs
@@ -133,13 +133,13 @@ impl Error for FsError {
 #[macro_export]
 macro_rules! esgx {
     ($status:expr) => {
-        crate::sys::error::FsError::from_sgx_error($status)
+        $crate::sys::error::FsError::from_sgx_error($status)
     };
 }
 
 #[macro_export]
 macro_rules! eos {
     ($errno:expr) => {
-        crate::sys::error::FsError::from_os_error($errno)
+        $crate::sys::error::FsError::from_os_error($errno)
     };
 }
diff --git a/sgx_protected_fs/ufs/src/lib.rs b/sgx_protected_fs/ufs/src/lib.rs
index 5054ee78..0ccce906 100644
--- a/sgx_protected_fs/ufs/src/lib.rs
+++ b/sgx_protected_fs/ufs/src/lib.rs
@@ -257,8 +257,8 @@ impl FileStream {
     fn seek(&self, pos: SeekFrom) -> OsResult {
         let (offset, whence) = match pos {
             SeekFrom::Start(off) => (off as i64, libc::SEEK_SET),
-            SeekFrom::End(off) => (off as i64, libc::SEEK_END),
-            SeekFrom::Current(off) => (off as i64, libc::SEEK_CUR),
+            SeekFrom::End(off) => (off, libc::SEEK_END),
+            SeekFrom::Current(off) => (off, libc::SEEK_CUR),
         };
         if unsafe { libc::fseeko(self.stream, offset, whence) } != 0 {
             bail!(errno())
diff --git a/sgx_rand/src/isaac.rs b/sgx_rand/src/isaac.rs
index a4e0e792..b25c40ac 100644
--- a/sgx_rand/src/isaac.rs
+++ b/sgx_rand/src/isaac.rs
@@ -534,7 +534,7 @@ impl Rng for Isaac64Rng {
         // See corresponding location in IsaacRng.next_u32 for
         // explanation.
         debug_assert!(self.cnt < RAND_SIZE_64);
-        self.rsl[(self.cnt % RAND_SIZE_64) as usize].0
+        self.rsl[(self.cnt % RAND_SIZE_64)].0
     }
 }
 
diff --git a/sgx_rsrvmm/src/rsrvmm/area.rs b/sgx_rsrvmm/src/rsrvmm/area.rs
index fe428d18..17765303 100644
--- a/sgx_rsrvmm/src/rsrvmm/area.rs
+++ b/sgx_rsrvmm/src/rsrvmm/area.rs
@@ -356,7 +356,7 @@ impl MmArea {
             let (pe_needed, pr_needed) = self.is_needed_modify_perm(new_perm)?;
 
             if pe_needed || pr_needed {
-                let _ = modpr_ocall(self.start(), count, perm).unwrap();
+                modpr_ocall(self.start(), count, perm).unwrap();
             }
 
             let pages = PageRange::new(
@@ -378,10 +378,10 @@ impl MmArea {
             }
 
             if pr_needed && new_perm == MmPerm::None {
-                let _ = mprotect_ocall(self.start(), count, perm).unwrap();
+                mprotect_ocall(self.start(), count, perm).unwrap();
             }
         } else {
-            let _ = mprotect_ocall(self.start(), count, perm).unwrap();
+            mprotect_ocall(self.start(), count, perm).unwrap();
         }
 
         self.perm = new_perm;
diff --git a/sgx_rsrvmm/src/rsrvmm/manager.rs b/sgx_rsrvmm/src/rsrvmm/manager.rs
index 8ebd5bb8..ec89dcae 100644
--- a/sgx_rsrvmm/src/rsrvmm/manager.rs
+++ b/sgx_rsrvmm/src/rsrvmm/manager.rs
@@ -223,7 +223,7 @@ impl MmManager {
                 }
             }
 
-            if result_free_range == None
+            if result_free_range.is_none()
                 || result_free_range.as_ref().unwrap().size() > free_range.size()
             {
                 // Record the minimal free range that satisfies the contraints
diff --git a/sgx_serialize/src/json.rs b/sgx_serialize/src/json.rs
index b8e4ccf1..bb1ca227 100644
--- a/sgx_serialize/src/json.rs
+++ b/sgx_serialize/src/json.rs
@@ -17,6 +17,7 @@
 
 #![forbid(non_camel_case_types)]
 #![allow(missing_docs)]
+#![allow(clippy::derive_partial_eq_without_eq)]
 
 //! JSON parsing and serialization
 //!
@@ -237,7 +238,7 @@ pub struct AsPrettyJson<'a, T> {
 
 /// The errors that can arise while parsing a JSON stream.
 #[allow(clippy::upper_case_acronyms)]
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum ErrorCode {
     InvalidSyntax,
     InvalidNumber,
@@ -258,7 +259,7 @@ pub enum ErrorCode {
     NotUtf8,
 }
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum ParserError {
     /// msg, line, col
     SyntaxError(ErrorCode, usize, usize),
@@ -268,7 +269,7 @@ pub enum ParserError {
 // Builder and Parser have the same errors.
 pub type BuilderError = ParserError;
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum DecoderError {
     ParseError(ParserError),
     ExpectedError(string::String, string::String),
@@ -1321,7 +1322,7 @@ impl Index<usize> for Json {
 }
 
 /// The output of the streaming parser.
-#[derive(PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum JsonEvent {
     ObjectStart,
     ObjectEnd,
@@ -1370,7 +1371,7 @@ pub struct Stack {
 /// As an example, `StackElement::Key("foo")`, `StackElement::Key("bar")`,
 /// `StackElement::Index(3)`, and `StackElement::Key("x")` are the
 /// StackElements composing the stack that represents `foo.bar[3].x`.
-#[derive(PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum StackElement<'l> {
     Index(u32),
     Key(&'l str),
@@ -1378,7 +1379,7 @@ pub enum StackElement<'l> {
 
 // Internally, Key elements are stored as indices in a buffer to avoid
 // allocating a string for every member of an object.
-#[derive(PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 enum InternalStackElement {
     InternalIndex(u32),
     InternalKey(u16, u16), // start, size
diff --git a/sgx_serialize/src/lib.rs b/sgx_serialize/src/lib.rs
index 02ead6c3..fa8f88ca 100644
--- a/sgx_serialize/src/lib.rs
+++ b/sgx_serialize/src/lib.rs
@@ -25,12 +25,13 @@ Core encoding and decoding interfaces.
 #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))]
 #![feature(box_syntax)]
 #![feature(never_type)]
-#![feature(nll)]
 #![feature(associated_type_bounds)]
 #![feature(min_specialization)]
 #![feature(core_intrinsics)]
 #![feature(maybe_uninit_slice)]
 #![feature(new_uninit)]
+#![allow(clippy::borrow_deref_ref)]
+#![allow(clippy::explicit_auto_deref)]
 
 #[cfg(all(feature = "tserialize", feature = "userialize"))]
 compile_error!(
diff --git a/sgx_serialize/src/opaque.rs b/sgx_serialize/src/opaque.rs
index ba1d2b9c..910f2714 100644
--- a/sgx_serialize/src/opaque.rs
+++ b/sgx_serialize/src/opaque.rs
@@ -147,7 +147,7 @@ impl serialize::Encoder for Encoder {
 
     #[inline]
     fn emit_bool(&mut self, v: bool) -> EncodeResult {
-        self.emit_u8(if v { 1 } else { 0 })
+        self.emit_u8(u8::from(v))
     }
 
     #[inline]
diff --git a/sgx_serialize/src/types.rs b/sgx_serialize/src/types.rs
index 1d35ef6d..9a417616 100644
--- a/sgx_serialize/src/types.rs
+++ b/sgx_serialize/src/types.rs
@@ -1551,7 +1551,6 @@ impl Decodable for TeeTcbSvn {
 }
 
 impl Encodable for TeeInfo {
-    #[allow(unaligned_references)]
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         let TeeInfo {
             attributes: ref _attributes,
@@ -1608,16 +1607,22 @@ impl Decodable for TeeInfo {
 }
 
 impl Encodable for TeeTcbInfo {
-    #[allow(unaligned_references)]
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
-        let TeeTcbInfo {
-            valid: ref _valid,
-            tee_tcb_svn: ref _tee_tcb_svn,
-            mr_seam: ref _mr_seam,
-            mr_seam_signer: ref _mr_seam_signer,
-            attributes: ref _attributes,
-            reserved: ref _reserved,
-        } = *self;
+        // let TeeTcbInfo {
+        //     valid: ref _valid,
+        //     tee_tcb_svn: ref _tee_tcb_svn,
+        //     mr_seam: ref _mr_seam,
+        //     mr_seam_signer: ref _mr_seam_signer,
+        //     attributes: ref _attributes,
+        //     reserved: ref _reserved,
+        // } = *self;
+        let _valid = unsafe { &*core::ptr::addr_of!(self.valid) };
+        let _tee_tcb_svn = unsafe { &*core::ptr::addr_of!(self.tee_tcb_svn) };
+        let _mr_seam = unsafe { &*core::ptr::addr_of!(self.mr_seam) };
+        let _mr_seam_signer = unsafe { &*core::ptr::addr_of!(self.mr_seam_signer) };
+        let _attributes = unsafe { &*core::ptr::addr_of!(self.attributes) };
+        let _reserved = unsafe { &*core::ptr::addr_of!(self.reserved) };
+
         e.emit_struct("TeeTcbInfo", 6usize, |e| -> _ {
             e.emit_struct_field("valid", 0usize, |e| -> _ { Encodable::encode(&*_valid, e) })?;
             e.emit_struct_field("tee_tcb_svn", 1usize, |e| -> _ {
@@ -1655,22 +1660,34 @@ impl Decodable for TeeTcbInfo {
 }
 
 impl Encodable for Report2Body {
-    #[allow(unaligned_references)]
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
-        let Report2Body {
-            tee_tcb_svn: ref _tee_tcb_svn,
-            mr_seam: ref _mr_seam,
-            mrsigner_seam: ref _mrsigner_seam,
-            seam_attributes: ref _seam_attributes,
-            td_attributes: ref _td_attributes,
-            xfam: ref _xfam,
-            mr_td: ref _mr_td,
-            mr_config_id: ref _mr_config_id,
-            mr_owner: ref _mr_owner,
-            mr_owner_config: ref _mr_owner_config,
-            rt_mr: ref _rt_mr,
-            report_data: ref _report_data,
-        } = *self;
+        // let Report2Body {
+        //     tee_tcb_svn: ref _tee_tcb_svn,
+        //     mr_seam: ref _mr_seam,
+        //     mrsigner_seam: ref _mrsigner_seam,
+        //     seam_attributes: ref _seam_attributes,
+        //     td_attributes: ref _td_attributes,
+        //     xfam: ref _xfam,
+        //     mr_td: ref _mr_td,
+        //     mr_config_id: ref _mr_config_id,
+        //     mr_owner: ref _mr_owner,
+        //     mr_owner_config: ref _mr_owner_config,
+        //     rt_mr: ref _rt_mr,
+        //     report_data: ref _report_data,
+        // } = *self;
+        let _tee_tcb_svn = unsafe { &*core::ptr::addr_of!(self.tee_tcb_svn) };
+        let _mr_seam = unsafe { &*core::ptr::addr_of!(self.mr_seam) };
+        let _mrsigner_seam = unsafe { &*core::ptr::addr_of!(self.mrsigner_seam) };
+        let _seam_attributes = unsafe { &*core::ptr::addr_of!(self.seam_attributes) };
+        let _td_attributes = unsafe { &*core::ptr::addr_of!(self.td_attributes) };
+        let _xfam = unsafe { &*core::ptr::addr_of!(self.xfam) };
+        let _mr_td = unsafe { &*core::ptr::addr_of!(self.mr_td) };
+        let _mr_config_id = unsafe { &*core::ptr::addr_of!(self.mr_config_id) };
+        let _mr_owner = unsafe { &*core::ptr::addr_of!(self.mr_owner) };
+        let _mr_owner_config = unsafe { &*core::ptr::addr_of!(self.mr_owner_config) };
+        let _rt_mr = unsafe { &*core::ptr::addr_of!(self.rt_mr) };
+        let _report_data = unsafe { &*core::ptr::addr_of!(self.report_data) };
+
         e.emit_struct("Report2Body", 12usize, |e| -> _ {
             e.emit_struct_field("tee_tcb_svn", 0usize, |e| -> _ {
                 Encodable::encode(&*_tee_tcb_svn, e)
diff --git a/sgx_sync/Cargo.toml b/sgx_sync/Cargo.toml
index c1d0c5d7..7e86c4f8 100644
--- a/sgx_sync/Cargo.toml
+++ b/sgx_sync/Cargo.toml
@@ -31,6 +31,7 @@ crate-type = ["rlib"]
 
 [features]
 default = []
+capi = []
 
 [dependencies]
 sgx_trts = { path = "../sgx_trts" }
diff --git a/sgx_sync/src/capi.rs b/sgx_sync/src/capi.rs
index 4f6bcb1e..9625723a 100644
--- a/sgx_sync/src/capi.rs
+++ b/sgx_sync/src/capi.rs
@@ -17,7 +17,7 @@
 
 use crate::spin::SpinMutex;
 use crate::sys::condvar::{Condvar, MovableCondvar};
-use crate::sys::mutex::{MovableMutex, Mutex, MutexControl};
+use crate::sys::mutex::{MovableMutex, MovableReentrantMutex, Mutex, MutexControl};
 use crate::sys::rwlock::{MovableRwLock, RwLock};
 use alloc::boxed::Box;
 use core::mem;
@@ -126,8 +126,18 @@ pub unsafe extern "C" fn sgx_thread_mutex_init(
         return EINVAL;
     };
 
-    let m = ManuallyDrop::new(MovableMutex::from(Mutex::new_with_control(control)));
-    mutex.mutex = m.as_ref() as *const _ as *mut c_void;
+    let mutex_ptr = match control {
+        MutexControl::NonRecursive => {
+            let m = ManuallyDrop::new(MovableMutex::new());
+            &**m as *const _ as *mut c_void
+        }
+        MutexControl::Recursive => {
+            let m = ManuallyDrop::new(MovableReentrantMutex::new());
+            &**m as *const _ as *mut c_void
+        }
+    };
+
+    mutex.mutex = mutex_ptr;
     0
 }
 
@@ -207,8 +217,8 @@ pub unsafe extern "C" fn sgx_thread_cond_init(
 ) -> c_int {
     check_param!(cond, sgx_thread_cond_t);
 
-    let c = ManuallyDrop::new(MovableCondvar::from(Condvar::new()));
-    (*cond).cond = c.as_ref() as *const _ as *mut c_void;
+    let c = ManuallyDrop::new(MovableCondvar::new());
+    (*cond).cond = &**c as *const _ as *mut c_void;
     0
 }
 
@@ -333,8 +343,8 @@ pub unsafe extern "C" fn sgx_thread_rwlock_init(
 ) -> c_int {
     check_param!(rwlock, sgx_thread_rwlock_t);
 
-    let rw = ManuallyDrop::new(MovableRwLock::from(RwLock::new()));
-    (*rwlock).rwlock = rw.as_ref() as *const _ as *mut c_void;
+    let rw = ManuallyDrop::new(MovableRwLock::new());
+    (*rwlock).rwlock = &**rw as *const _ as *mut c_void;
     0
 }
 
diff --git a/sgx_sync/src/condvar.rs b/sgx_sync/src/condvar.rs
index 835e187c..4c1452fa 100644
--- a/sgx_sync/src/condvar.rs
+++ b/sgx_sync/src/condvar.rs
@@ -33,10 +33,10 @@ pub struct Condvar {
 
 impl Condvar {
     /// Creates a new condition variable for use.
-    pub fn new() -> Condvar {
-        let c = imp::MovableCondvar::from(imp::Condvar::new());
-        Condvar {
-            inner: c,
+    #[inline]
+    pub const fn new() -> Condvar {
+        Self {
+            inner: imp::MovableCondvar::new(),
             check: CondvarCheck::new(),
         }
     }
@@ -63,7 +63,7 @@ impl Condvar {
     #[inline]
     pub unsafe fn wait(&self, mutex: &MovableMutex) {
         self.check.verify(mutex);
-        let r = self.inner.wait(mutex.as_ref());
+        let r = self.inner.wait(mutex.raw());
         debug_assert_eq!(r, Ok(()));
     }
 
@@ -76,19 +76,12 @@ impl Condvar {
     #[inline]
     pub unsafe fn wait_timeout(&self, mutex: &MovableMutex, dur: Duration) -> bool {
         self.check.verify(mutex);
-        let r = self.inner.wait_timeout(mutex.as_ref(), dur);
+        let r = self.inner.wait_timeout(mutex.raw(), dur);
         debug_assert!(r == Err(ETIMEDOUT) || r == Ok(()));
         r == Ok(())
     }
 }
 
-impl Drop for Condvar {
-    fn drop(&mut self) {
-        let r = unsafe { self.inner.destroy() };
-        debug_assert_eq!(r, Ok(()));
-    }
-}
-
 impl Default for Condvar {
     fn default() -> Condvar {
         Condvar::new()
diff --git a/sgx_sync/src/condvar/check.rs b/sgx_sync/src/condvar/check.rs
index 97193af8..0f00e9b7 100644
--- a/sgx_sync/src/condvar/check.rs
+++ b/sgx_sync/src/condvar/check.rs
@@ -15,10 +15,11 @@
 // specific language governing permissions and limitations
 // under the License..
 
+use crate::lazy_box::{LazyBox, LazyInit};
 use crate::mutex::MovableMutex;
-use crate::sys::mutex as mutex_imp;
-use alloc::boxed::Box;
-use core::sync::atomic::{AtomicUsize, Ordering};
+use crate::sys::mutex as imp;
+use core::ptr;
+use core::sync::atomic::{AtomicPtr, Ordering};
 
 pub trait CondvarCheck {
     type Check;
@@ -26,27 +27,31 @@ pub trait CondvarCheck {
 
 /// For boxed mutexes, a `Condvar` will check it's only ever used with the same
 /// mutex, based on its (stable) address.
-impl CondvarCheck for Box<mutex_imp::Mutex> {
+impl<T: LazyInit> CondvarCheck for LazyBox<T> {
     type Check = SameMutexCheck;
 }
 
 pub struct SameMutexCheck {
-    addr: AtomicUsize,
+    addr: AtomicPtr<()>,
 }
 
 #[allow(dead_code)]
 impl SameMutexCheck {
     pub const fn new() -> Self {
         Self {
-            addr: AtomicUsize::new(0),
+            addr: AtomicPtr::new(ptr::null_mut()),
         }
     }
     pub fn verify(&self, mutex: &MovableMutex) {
-        let addr = mutex.as_ref() as *const mutex_imp::Mutex as usize;
-        match self
-            .addr
-            .compare_exchange(0, addr, Ordering::SeqCst, Ordering::SeqCst)
-        {
+        let addr = mutex.raw() as *const imp::Mutex as *const () as *mut _;
+        // Relaxed is okay here because we never read through `self.addr`, and only use it to
+        // compare addresses.
+        match self.addr.compare_exchange(
+            ptr::null_mut(),
+            addr,
+            Ordering::Relaxed,
+            Ordering::Relaxed,
+        ) {
             Ok(_) => {}               // Stored the address
             Err(n) if n == addr => {} // Lost a race to store the same address
             _ => panic!("attempted to use a condition variable with two mutexes"),
@@ -56,7 +61,7 @@ impl SameMutexCheck {
 
 /// Unboxed mutexes may move, so `Condvar` can not require its address to stay
 /// constant.
-impl CondvarCheck for mutex_imp::Mutex {
+impl CondvarCheck for imp::Mutex {
     type Check = NoCheck;
 }
 
diff --git a/sgx_sync/src/futex.rs b/sgx_sync/src/futex.rs
index 3ab44053..06434510 100644
--- a/sgx_sync/src/futex.rs
+++ b/sgx_sync/src/futex.rs
@@ -18,7 +18,7 @@
 use crate::sys::futex as imp;
 use crate::Timespec;
 use core::marker::PhantomData;
-use core::sync::atomic::AtomicI32;
+use core::sync::atomic::AtomicU32;
 use core::time::Duration;
 use sgx_types::error::OsResult;
 
@@ -72,11 +72,11 @@ impl_enum! {
 
 pub struct Futex<'a> {
     futex: imp::Futex,
-    marker: PhantomData<&'a AtomicI32>,
+    marker: PhantomData<&'a AtomicU32>,
 }
 
 impl<'a> Futex<'a> {
-    pub fn new(futex: &AtomicI32) -> Futex<'a> {
+    pub fn new(futex: &AtomicU32) -> Futex<'a> {
         Futex {
             futex: imp::Futex::new(futex as *const _ as usize),
             marker: PhantomData,
@@ -84,14 +84,14 @@ impl<'a> Futex<'a> {
     }
 
     #[inline]
-    pub fn wait(&self, expected: i32, timeout: Option<Duration>) -> OsResult {
+    pub fn wait(&self, expected: u32, timeout: Option<Duration>) -> OsResult {
         self.futex.wait(expected, timeout)
     }
 
     #[inline]
     pub fn wait_bitset(
         &self,
-        expected: i32,
+        expected: u32,
         timeout: Option<(Timespec, FutexClockId)>,
         bitset: u32,
     ) -> OsResult {
@@ -114,7 +114,7 @@ impl<'a> Futex<'a> {
         nwakes: i32,
         new_futex: &Futex,
         nrequeues: i32,
-        expected: i32,
+        expected: u32,
     ) -> OsResult<usize> {
         self.futex.cmp_requeue(
             nwakes as usize,
diff --git a/sgx_sync/src/lazy_box.rs b/sgx_sync/src/lazy_box.rs
new file mode 100644
index 00000000..c26e21f7
--- /dev/null
+++ b/sgx_sync/src/lazy_box.rs
@@ -0,0 +1,118 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License..
+
+#![allow(dead_code)] // Only used on some platforms.
+
+// This is used to wrap pthread {Mutex, Condvar, RwLock} in.
+
+use alloc::boxed::Box;
+use core::marker::PhantomData;
+use core::ops::{Deref, DerefMut};
+use core::ptr::null_mut;
+use core::sync::atomic::{
+    AtomicPtr,
+    Ordering::{AcqRel, Acquire},
+};
+
+pub struct LazyBox<T: LazyInit> {
+    ptr: AtomicPtr<T>,
+    _phantom: PhantomData<T>,
+}
+
+pub trait LazyInit {
+    /// This is called before the box is allocated, to provide the value to
+    /// move into the new box.
+    ///
+    /// It might be called more than once per LazyBox, as multiple threads
+    /// might race to initialize it concurrently, each constructing and initializing
+    /// their own box. All but one of them will be passed to `cancel_init` right after.
+    fn init() -> Box<Self>;
+
+    /// Any surplus boxes from `init()` that lost the initialization race
+    /// are passed to this function for disposal.
+    ///
+    /// The default implementation calls destroy().
+    fn cancel_init(x: Box<Self>) {
+        Self::destroy(x);
+    }
+
+    /// This is called to destroy a used box.
+    ///
+    /// The default implementation just drops it.
+    fn destroy(_: Box<Self>) {}
+}
+
+impl<T: LazyInit> LazyBox<T> {
+    #[inline]
+    pub const fn new() -> Self {
+        Self {
+            ptr: AtomicPtr::new(null_mut()),
+            _phantom: PhantomData,
+        }
+    }
+
+    #[inline]
+    fn get_pointer(&self) -> *mut T {
+        let ptr = self.ptr.load(Acquire);
+        if ptr.is_null() {
+            self.initialize()
+        } else {
+            ptr
+        }
+    }
+
+    #[cold]
+    fn initialize(&self) -> *mut T {
+        let new_ptr = Box::into_raw(T::init());
+        match self
+            .ptr
+            .compare_exchange(null_mut(), new_ptr, AcqRel, Acquire)
+        {
+            Ok(_) => new_ptr,
+            Err(ptr) => {
+                // Lost the race to another thread.
+                // Drop the box we created, and use the one from the other thread instead.
+                T::cancel_init(unsafe { Box::from_raw(new_ptr) });
+                ptr
+            }
+        }
+    }
+}
+
+impl<T: LazyInit> Deref for LazyBox<T> {
+    type Target = T;
+    #[inline]
+    fn deref(&self) -> &T {
+        unsafe { &*self.get_pointer() }
+    }
+}
+
+impl<T: LazyInit> DerefMut for LazyBox<T> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.get_pointer() }
+    }
+}
+
+impl<T: LazyInit> Drop for LazyBox<T> {
+    fn drop(&mut self) {
+        let ptr = *self.ptr.get_mut();
+        if !ptr.is_null() {
+            T::destroy(unsafe { Box::from_raw(ptr) });
+        }
+    }
+}
diff --git a/sgx_sync/src/lazy_lock.rs b/sgx_sync/src/lazy_lock.rs
new file mode 100644
index 00000000..bbdffe6a
--- /dev/null
+++ b/sgx_sync/src/lazy_lock.rs
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License..
+
+use crate::once_lock::OnceLock;
+use core::cell::Cell;
+use core::fmt;
+use core::ops::Deref;
+use core::panic::{RefUnwindSafe, UnwindSafe};
+
+/// A value which is initialized on the first access.
+///
+/// This type is a thread-safe `Lazy`, and can be used in statics.
+///
+pub struct LazyLock<T, F = fn() -> T> {
+    cell: OnceLock<T>,
+    init: Cell<Option<F>>,
+}
+
+impl<T, F> LazyLock<T, F> {
+    /// Creates a new lazy value with the given initializing
+    /// function.
+    pub const fn new(f: F) -> LazyLock<T, F> {
+        LazyLock {
+            cell: OnceLock::new(),
+            init: Cell::new(Some(f)),
+        }
+    }
+}
+
+impl<T, F: FnOnce() -> T> LazyLock<T, F> {
+    /// Forces the evaluation of this lazy value and
+    /// returns a reference to result. This is equivalent
+    /// to the `Deref` impl, but is explicit.
+    ///
+    pub fn force(this: &LazyLock<T, F>) -> &T {
+        this.cell.get_or_init(|| match this.init.take() {
+            Some(f) => f(),
+            None => panic!("Lazy instance has previously been poisoned"),
+        })
+    }
+}
+
+impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        LazyLock::force(self)
+    }
+}
+
+impl<T: Default> Default for LazyLock<T> {
+    /// Creates a new lazy value using `Default` as the initializing function.
+    fn default() -> LazyLock<T> {
+        LazyLock::new(T::default)
+    }
+}
+
+impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Lazy")
+            .field("cell", &self.cell)
+            .finish_non_exhaustive()
+    }
+}
+
+// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
+// to not impl `Sync` for `F`
+// we do create a `&mut Option<F>` in `force`, but this is
+// properly synchronized, so it only happens once
+// so it also does not contribute to this impl.
+unsafe impl<T, F: Send> Sync for LazyLock<T, F> where OnceLock<T>: Sync {}
+// auto-derived `Send` impl is OK.
+
+impl<T, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> where OnceLock<T>: RefUnwindSafe {}
+impl<T, F: UnwindSafe> UnwindSafe for LazyLock<T, F> where OnceLock<T>: UnwindSafe {}
diff --git a/sgx_sync/src/lib.rs b/sgx_sync/src/lib.rs
index c57ac470..76d3818a 100644
--- a/sgx_sync/src/lib.rs
+++ b/sgx_sync/src/lib.rs
@@ -18,6 +18,7 @@
 #![no_std]
 #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))]
 #![deny(unused_features)]
+#![feature(const_trait_impl)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(hashmap_internals)]
@@ -36,25 +37,30 @@ extern crate sgx_types;
 mod barrier;
 mod condvar;
 mod futex;
-mod lazy;
+mod lazy_box;
+mod lazy_lock;
 mod lock_api;
 mod mutex;
 mod once;
+mod once_lock;
 mod remutex;
 mod rwlock;
 mod spin;
 mod sys;
 
+#[cfg(feature = "capi")]
 pub mod capi;
+
 pub use sys::ocall::Timespec;
 
 pub use barrier::{Barrier, BarrierWaitResult};
 pub use condvar::Condvar;
 pub use futex::{Futex, FutexClockId, FutexFlags, FutexOp};
-pub use lazy::{SyncLazy, SyncOnceCell};
+pub use lazy_lock::LazyLock;
 pub use lock_api::{RawMutex, RawRwLock};
 pub use mutex::{MovableMutex, StaticMutex, StaticMutexGuard};
 pub use once::{Once, OnceState, ONCE_INIT};
+pub use once_lock::OnceLock;
 pub use remutex::{ReentrantMutex, ReentrantMutexGuard};
 pub use rwlock::{MovableRwLock, StaticRwLock, StaticRwLockReadGuard, StaticRwLockWriteGuard};
 pub use spin::{SpinMutex, SpinMutexGuard, SpinRwLock, SpinRwLockReadGuard, SpinRwLockWriteGuard};
diff --git a/sgx_sync/src/mutex.rs b/sgx_sync/src/mutex.rs
index 76b1f943..922e7d50 100644
--- a/sgx_sync/src/mutex.rs
+++ b/sgx_sync/src/mutex.rs
@@ -34,6 +34,7 @@ unsafe impl Sync for StaticMutex {}
 
 impl StaticMutex {
     /// Creates a new mutex for use.
+    #[inline]
     pub const fn new() -> StaticMutex {
         StaticMutex(imp::Mutex::new())
     }
@@ -65,13 +66,12 @@ impl Drop for StaticMutexGuard {
 
 /// An SGX-based mutual exclusion lock.
 ///
-/// This mutex does *not* have a const constructor, cleans up its resources in
-/// its `Drop` implementation, may safely be moved (when not borrowed), and
-/// does not cause UB when used reentrantly.
+/// This mutex cleans up its resources in its `Drop` implementation, may safely
+/// be moved (when not borrowed), and does not cause UB when used reentrantly.
 ///
 /// This mutex does not implement poisoning.
 ///
-/// This is either a wrapper around `Box<imp::Mutex>` or `imp::Mutex`,
+/// This is either a wrapper around `LazyBox<imp::Mutex>` or `imp::Mutex`,
 /// depending on the platform. It is boxed on platforms where `imp::Mutex` may
 /// not be moved.
 pub struct MovableMutex(imp::MovableMutex);
@@ -80,11 +80,12 @@ unsafe impl Sync for MovableMutex {}
 
 impl MovableMutex {
     /// Creates a new mutex.
-    pub fn new() -> MovableMutex {
-        MovableMutex(imp::MovableMutex::from(imp::Mutex::new()))
+    #[inline]
+    pub const fn new() -> MovableMutex {
+        MovableMutex(imp::MovableMutex::new())
     }
 
-    pub(crate) fn as_ref(&self) -> &imp::Mutex {
+    pub(crate) fn raw(&self) -> &imp::Mutex {
         &self.0
     }
 
@@ -115,13 +116,6 @@ impl MovableMutex {
     }
 }
 
-impl Drop for MovableMutex {
-    fn drop(&mut self) {
-        let r = unsafe { self.0.destroy() };
-        debug_assert_eq!(r, Ok(()));
-    }
-}
-
 impl Default for MovableMutex {
     fn default() -> MovableMutex {
         MovableMutex::new()
diff --git a/sgx_sync/src/lazy.rs b/sgx_sync/src/once_lock.rs
similarity index 64%
rename from sgx_sync/src/lazy.rs
rename to sgx_sync/src/once_lock.rs
index 03b5b067..bd54de13 100644
--- a/sgx_sync/src/lazy.rs
+++ b/sgx_sync/src/once_lock.rs
@@ -16,72 +16,30 @@
 // under the License..
 
 use crate::once::Once;
-use core::cell::{Cell, UnsafeCell};
+use core::cell::UnsafeCell;
 use core::fmt;
 use core::marker::PhantomData;
 use core::mem::MaybeUninit;
-use core::ops::{Deref, Drop};
+use core::ops::Drop;
+use core::panic::{RefUnwindSafe, UnwindSafe};
 
-pub struct SyncOnceCell<T> {
+/// A synchronization primitive which can be written to only once.
+///
+/// This type is a thread-safe `OnceCell`.
+///
+pub struct OnceLock<T> {
     once: Once,
+    // Whether or not the value is initialized is tracked by `state_and_queue`.
     value: UnsafeCell<MaybeUninit<T>>,
-    // `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
+    /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
     _marker: PhantomData<T>,
 }
 
-unsafe impl<T: Sync + Send> Sync for SyncOnceCell<T> {}
-unsafe impl<T: Send> Send for SyncOnceCell<T> {}
-
-impl<T> Default for SyncOnceCell<T> {
-    fn default() -> SyncOnceCell<T> {
-        SyncOnceCell::new()
-    }
-}
-
-impl<T: fmt::Debug> fmt::Debug for SyncOnceCell<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.get() {
-            Some(v) => f.debug_tuple("Once").field(v).finish(),
-            None => f.write_str("Once(Uninit)"),
-        }
-    }
-}
-
-impl<T: Clone> Clone for SyncOnceCell<T> {
-    fn clone(&self) -> SyncOnceCell<T> {
-        let cell = SyncOnceCell::new();
-        if let Some(value) = self.get() {
-            match cell.set(value.clone()) {
-                Ok(()) => (),
-                Err(_) => unreachable!(),
-            }
-        }
-        cell
-    }
-}
-
-impl<T> From<T> for SyncOnceCell<T> {
-    fn from(value: T) -> SyncOnceCell<T> {
-        let cell = SyncOnceCell::new();
-        match cell.set(value) {
-            Ok(()) => cell,
-            Err(_) => unreachable!(),
-        }
-    }
-}
-
-impl<T: PartialEq> PartialEq for SyncOnceCell<T> {
-    fn eq(&self, other: &SyncOnceCell<T>) -> bool {
-        self.get() == other.get()
-    }
-}
-
-impl<T: Eq> Eq for SyncOnceCell<T> {}
-
-impl<T> SyncOnceCell<T> {
+impl<T> OnceLock<T> {
     /// Creates a new empty cell.
-    pub const fn new() -> SyncOnceCell<T> {
-        SyncOnceCell {
+    #[must_use]
+    pub const fn new() -> OnceLock<T> {
+        OnceLock {
             once: Once::new(),
             value: UnsafeCell::new(MaybeUninit::uninit()),
             _marker: PhantomData,
@@ -92,6 +50,7 @@ impl<T> SyncOnceCell<T> {
     ///
     /// Returns `None` if the cell is empty, or being initialized. This
     /// method never blocks.
+    ///
     pub fn get(&self) -> Option<&T> {
         if self.is_initialized() {
             // Safe b/c checked is_initialized
@@ -115,7 +74,10 @@ impl<T> SyncOnceCell<T> {
 
     /// Sets the contents of this cell to `value`.
     ///
-    /// Returns `Ok(())` if the cell's value was updated.
+    /// May block if another thread is currently attempting to initialize the cell. The cell is
+    /// guaranteed to contain a value when set returns, though not necessarily the one provided.
+    ///
+    /// Returns `Ok(())` if the cell's value was set by this call.
     ///
     pub fn set(&self, value: T) -> Result<(), T> {
         let mut value = Some(value);
@@ -171,7 +133,7 @@ impl<T> SyncOnceCell<T> {
     {
         // Fast path check
         // NOTE: We need to perform an acquire on the state in this method
-        // in order to correctly synchronize `SyncLazy::force`. This is
+        // in order to correctly synchronize `LazyLock::force`. This is
         // currently done by calling `self.get()`, which in turn calls
         // `self.is_initialized()`, which in turn performs the acquire.
         if let Some(value) = self.get() {
@@ -185,16 +147,16 @@ impl<T> SyncOnceCell<T> {
         Ok(unsafe { self.get_unchecked() })
     }
 
-    /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns
+    /// Consumes the `OnceLock`, returning the wrapped value. Returns
     /// `None` if the cell was empty.
     ///
     pub fn into_inner(mut self) -> Option<T> {
         self.take()
     }
 
-    /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
+    /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
     ///
-    /// Has no effect and returns `None` if the `SyncOnceCell` hasn't been initialized.
+    /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized.
     ///
     /// Safety is guaranteed by requiring a mutable reference.
     ///
@@ -204,7 +166,7 @@ impl<T> SyncOnceCell<T> {
             // SAFETY: `self.value` is initialized and contains a valid `T`.
             // `self.once` is reset, so `is_initialized()` will be false again
             // which prevents the value from being read twice.
-            unsafe { Some((&*self.value.get()).assume_init_read()) }
+            unsafe { Some((*self.value.get()).assume_init_read()) }
         } else {
             None
         }
@@ -228,7 +190,7 @@ impl<T> SyncOnceCell<T> {
         self.once.call_once_force(|p| {
             match f() {
                 Ok(value) => {
-                    unsafe { (&mut *slot.get()).write(value) };
+                    unsafe { (*slot.get()).write(value) };
                 }
                 Err(e) => {
                     res = Err(e);
@@ -242,90 +204,86 @@ impl<T> SyncOnceCell<T> {
         res
     }
 
-    /// Safety: The value must be initialized
+    /// # Safety
+    ///
+    /// The value must be initialized
     unsafe fn get_unchecked(&self) -> &T {
         debug_assert!(self.is_initialized());
-        (&*self.value.get()).assume_init_ref()
+        (*self.value.get()).assume_init_ref()
     }
 
-    /// Safety: The value must be initialized
+    /// # Safety
+    ///
+    /// The value must be initialized
     unsafe fn get_unchecked_mut(&mut self) -> &mut T {
         debug_assert!(self.is_initialized());
-        (&mut *self.value.get()).assume_init_mut()
+        (*self.value.get()).assume_init_mut()
     }
 }
 
-unsafe impl<#[may_dangle] T> Drop for SyncOnceCell<T> {
-    fn drop(&mut self) {
-        if self.is_initialized() {
-            // Safety: The cell is initialized and being dropped, so it can't
-            // be accessed again. We also don't touch the `T` other than
-            // dropping it, which validates our usage of #[may_dangle].
-            unsafe { (&mut *self.value.get()).assume_init_drop() };
-        }
-    }
-}
+unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
+unsafe impl<T: Send> Send for OnceLock<T> {}
 
-/// A value which is initialized on the first access.
-///
-/// This type is a thread-safe `Lazy`, and can be used in statics.
-///
-pub struct SyncLazy<T, F = fn() -> T> {
-    cell: SyncOnceCell<T>,
-    init: Cell<Option<F>>,
+impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
+impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
+
+impl<T> const Default for OnceLock<T> {
+    /// Creates a new empty cell.
+    ///
+    fn default() -> OnceLock<T> {
+        OnceLock::new()
+    }
 }
 
-impl<T: fmt::Debug, F> fmt::Debug for SyncLazy<T, F> {
+impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Lazy")
-            .field("cell", &self.cell)
-            .field("init", &"..")
-            .finish()
+        match self.get() {
+            Some(v) => f.debug_tuple("Once").field(v).finish(),
+            None => f.write_str("Once(Uninit)"),
+        }
     }
 }
 
-// We never create a `&F` from a `&SyncLazy<T, F>` so it is fine
-// to not impl `Sync` for `F`
-// we do create a `&mut Option<F>` in `force`, but this is
-// properly synchronized, so it only happens once
-// so it also does not contribute to this impl.
-unsafe impl<T, F: Send> Sync for SyncLazy<T, F> where SyncOnceCell<T>: Sync {}
-// auto-derived `Send` impl is OK.
-
-impl<T, F> SyncLazy<T, F> {
-    /// Creates a new lazy value with the given initializing
-    /// function.
-    pub const fn new(f: F) -> SyncLazy<T, F> {
-        SyncLazy {
-            cell: SyncOnceCell::new(),
-            init: Cell::new(Some(f)),
+impl<T: Clone> Clone for OnceLock<T> {
+    fn clone(&self) -> OnceLock<T> {
+        let cell = Self::new();
+        if let Some(value) = self.get() {
+            match cell.set(value.clone()) {
+                Ok(()) => (),
+                Err(_) => unreachable!(),
+            }
         }
+        cell
     }
 }
 
-impl<T, F: FnOnce() -> T> SyncLazy<T, F> {
-    /// Forces the evaluation of this lazy value and
-    /// returns a reference to result. This is equivalent
-    /// to the `Deref` impl, but is explicit.
+impl<T> From<T> for OnceLock<T> {
+    /// Create a new cell with its contents set to `value`.
     ///
-    pub fn force(this: &SyncLazy<T, F>) -> &T {
-        this.cell.get_or_init(|| match this.init.take() {
-            Some(f) => f(),
-            None => panic!("Lazy instance has previously been poisoned"),
-        })
+    fn from(value: T) -> Self {
+        let cell = Self::new();
+        match cell.set(value) {
+            Ok(()) => cell,
+            Err(_) => unreachable!(),
+        }
     }
 }
 
-impl<T, F: FnOnce() -> T> Deref for SyncLazy<T, F> {
-    type Target = T;
-    fn deref(&self) -> &T {
-        SyncLazy::force(self)
+impl<T: PartialEq> PartialEq for OnceLock<T> {
+    fn eq(&self, other: &OnceLock<T>) -> bool {
+        self.get() == other.get()
     }
 }
 
-impl<T: Default> Default for SyncLazy<T> {
-    /// Creates a new lazy value using `Default` as the initializing function.
-    fn default() -> SyncLazy<T> {
-        SyncLazy::new(T::default)
+impl<T: Eq> Eq for OnceLock<T> {}
+
+unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
+    fn drop(&mut self) {
+        if self.is_initialized() {
+            // SAFETY: The cell is initialized and being dropped, so it can't
+            // be accessed again. We also don't touch the `T` other than
+            // dropping it, which validates our usage of #[may_dangle].
+            unsafe { (*self.value.get()).assume_init_drop() };
+        }
     }
 }
diff --git a/sgx_sync/src/remutex.rs b/sgx_sync/src/remutex.rs
index 411fe530..c0f692c8 100644
--- a/sgx_sync/src/remutex.rs
+++ b/sgx_sync/src/remutex.rs
@@ -17,10 +17,8 @@
 
 use crate::sys::mutex as sys;
 use core::fmt;
-use core::marker::PhantomPinned;
 use core::ops::Deref;
 use core::panic::{RefUnwindSafe, UnwindSafe};
-use core::pin::Pin;
 
 /// A re-entrant mutual exclusion
 ///
@@ -28,9 +26,8 @@ use core::pin::Pin;
 /// available. The thread which has already locked the mutex can lock it
 /// multiple times without blocking, preventing a common source of deadlocks.
 pub struct ReentrantMutex<T> {
-    inner: sys::ReentrantMutex,
+    inner: sys::MovableReentrantMutex,
     data: T,
-    _pinned: PhantomPinned,
 }
 
 unsafe impl<T: Send> Send for ReentrantMutex<T> {}
@@ -53,7 +50,7 @@ impl<T> RefUnwindSafe for ReentrantMutex<T> {}
 /// guarded data.
 #[must_use = "if unused the ReentrantMutex will immediately unlock"]
 pub struct ReentrantMutexGuard<'a, T: 'a> {
-    lock: Pin<&'a ReentrantMutex<T>>,
+    lock: &'a ReentrantMutex<T>,
 }
 
 impl<T> !Send for ReentrantMutexGuard<'_, T> {}
@@ -63,9 +60,8 @@ impl<T> ReentrantMutex<T> {
     ///
     pub const fn new(t: T) -> ReentrantMutex<T> {
         ReentrantMutex {
-            inner: sys::ReentrantMutex::new(),
+            inner: sys::MovableReentrantMutex::new(),
             data: t,
-            _pinned: PhantomPinned,
         }
     }
 
@@ -81,11 +77,11 @@ impl<T> ReentrantMutex<T> {
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
+    pub fn lock(&self) -> ReentrantMutexGuard<'_, T> {
         unsafe {
             let _ = self.inner.lock();
         }
-        ReentrantMutexGuard::new(self)
+        ReentrantMutexGuard { lock: self }
     }
 
     /// Attempts to acquire this lock.
@@ -100,30 +96,18 @@ impl<T> ReentrantMutex<T> {
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {
+    pub fn try_lock(&self) -> Option<ReentrantMutexGuard<'_, T>> {
         if unsafe { self.inner.try_lock().is_ok() } {
-            Some(ReentrantMutexGuard::new(self))
+            Some(ReentrantMutexGuard { lock: self })
         } else {
             None
         }
     }
 }
 
-impl<T> Drop for ReentrantMutex<T> {
-    fn drop(&mut self) {
-        // This is actually safe b/c we know that there is no further usage of
-        // this mutex (it's up to the user to arrange for a mutex to get
-        // dropped, that's not our job)
-        unsafe {
-            let _ = self.inner.destroy();
-        }
-    }
-}
-
 impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let pin_lock = unsafe { Pin::new_unchecked(self) };
-        match pin_lock.try_lock() {
+        match self.try_lock() {
             Some(guard) => f
                 .debug_struct("ReentrantMutex")
                 .field("data", &*guard)
@@ -144,12 +128,6 @@ impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
     }
 }
 
-impl<'mutex, T> ReentrantMutexGuard<'mutex, T> {
-    fn new(lock: Pin<&'mutex ReentrantMutex<T>>) -> ReentrantMutexGuard<'mutex, T> {
-        ReentrantMutexGuard { lock }
-    }
-}
-
 impl<T> Deref for ReentrantMutexGuard<'_, T> {
     type Target = T;
 
diff --git a/sgx_sync/src/rwlock.rs b/sgx_sync/src/rwlock.rs
index c047dc7d..c417ce75 100644
--- a/sgx_sync/src/rwlock.rs
+++ b/sgx_sync/src/rwlock.rs
@@ -28,6 +28,7 @@ pub struct StaticRwLock(imp::RwLock);
 unsafe impl Sync for StaticRwLock {}
 
 impl StaticRwLock {
+    #[inline]
     pub const fn new() -> StaticRwLock {
         StaticRwLock(imp::RwLock::new())
     }
@@ -83,17 +84,23 @@ impl Drop for StaticRwLockWriteGuard {
 
 /// An SGX-based reader-writer lock.
 ///
-/// This structure is entirely unsafe and serves as the lowest layer of a
-/// cross-platform binding of system rwlocks. It is recommended to use the
-/// safer types at the top level of this crate instead of this type.
+/// This rwlock cleans up its resources in its `Drop` implementation and may
+/// safely be moved (when not borrowed).
+///
+/// This rwlock does not implement poisoning.
+///
+/// This is either a wrapper around `LazyBox<imp::RwLock>` or `imp::RwLock`,
+/// depending on the platform. It is boxed on platforms where `imp::RwLock` may
+/// not be moved.
 pub struct MovableRwLock(imp::MovableRwLock);
 
 unsafe impl Sync for MovableRwLock {}
 
 impl MovableRwLock {
     /// Creates a new reader-writer lock for use.
-    pub fn new() -> MovableRwLock {
-        MovableRwLock(imp::MovableRwLock::from(imp::RwLock::new()))
+    #[inline]
+    pub const fn new() -> MovableRwLock {
+        MovableRwLock(imp::MovableRwLock::new())
     }
 
     /// Acquires shared access to the underlying lock, blocking the current
@@ -160,13 +167,6 @@ impl MovableRwLock {
     }
 }
 
-impl Drop for MovableRwLock {
-    fn drop(&mut self) {
-        let r = unsafe { self.0.destroy() };
-        debug_assert_eq!(r, Ok(()));
-    }
-}
-
 impl Default for MovableRwLock {
     fn default() -> MovableRwLock {
         MovableRwLock::new()
diff --git a/sgx_sync/src/sys/condvar.rs b/sgx_sync/src/sys/condvar.rs
index 6eb8e5da..95bcf275 100644
--- a/sgx_sync/src/sys/condvar.rs
+++ b/sgx_sync/src/sys/condvar.rs
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
+use crate::lazy_box::{LazyBox, LazyInit};
 use crate::sys::mutex::Mutex;
 use crate::sys::ocall;
 use alloc::boxed::Box;
@@ -28,6 +29,70 @@ use sgx_trts::tcs::{self, TcsId};
 use sgx_types::error::errno::{EBUSY, ETIMEDOUT};
 use sgx_types::error::OsResult;
 
+pub struct Condvar {
+    inner: UnsafeCell<CondvarInner>,
+}
+
+pub type MovableCondvar = LazyBox<Condvar>;
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+impl LazyInit for Condvar {
+    fn init() -> Box<Self> {
+        Box::new(Self::new())
+    }
+}
+
+impl Condvar {
+    pub const fn new() -> Self {
+        Condvar {
+            inner: UnsafeCell::new(CondvarInner::new()),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) -> OsResult {
+        let condvar = &mut *self.inner.get();
+        condvar.wait(mutex)
+    }
+
+    #[inline]
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> OsResult {
+        let condvar = &mut *self.inner.get();
+        condvar.wait_timeout(mutex, dur)
+    }
+
+    #[inline]
+    pub unsafe fn notify_one(&self) -> OsResult {
+        let condvar = &mut *self.inner.get();
+        condvar.notify_one()
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) -> OsResult {
+        let condvar = &mut *self.inner.get();
+        condvar.notify_all()
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) -> OsResult {
+        let condvar = &mut *self.inner.get();
+        condvar.destroy()
+    }
+}
+
+impl Drop for Condvar {
+    #[inline]
+    fn drop(&mut self) {
+        let r = unsafe { self.destroy() };
+        debug_assert_eq!(r, Ok(()));
+    }
+}
+
+struct CondvarInner {
+    inner: SpinMutex<Inner>,
+}
 struct Inner {
     queue: LinkedList<TcsId>,
 }
@@ -40,10 +105,6 @@ impl Inner {
     }
 }
 
-struct CondvarInner {
-    inner: SpinMutex<Inner>,
-}
-
 impl CondvarInner {
     pub const fn new() -> CondvarInner {
         CondvarInner {
@@ -156,50 +217,3 @@ impl CondvarInner {
         }
     }
 }
-
-pub type MovableCondvar = Box<Condvar>;
-
-unsafe impl Send for Condvar {}
-unsafe impl Sync for Condvar {}
-
-pub struct Condvar {
-    inner: UnsafeCell<CondvarInner>,
-}
-
-impl Condvar {
-    pub const fn new() -> Self {
-        Condvar {
-            inner: UnsafeCell::new(CondvarInner::new()),
-        }
-    }
-
-    #[inline]
-    pub unsafe fn wait(&self, mutex: &Mutex) -> OsResult {
-        let condvar = &mut *self.inner.get();
-        condvar.wait(mutex)
-    }
-
-    #[inline]
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> OsResult {
-        let condvar = &mut *self.inner.get();
-        condvar.wait_timeout(mutex, dur)
-    }
-
-    #[inline]
-    pub unsafe fn notify_one(&self) -> OsResult {
-        let condvar = &mut *self.inner.get();
-        condvar.notify_one()
-    }
-
-    #[inline]
-    pub unsafe fn notify_all(&self) -> OsResult {
-        let condvar = &mut *self.inner.get();
-        condvar.notify_all()
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) -> OsResult {
-        let condvar = &mut *self.inner.get();
-        condvar.destroy()
-    }
-}
diff --git a/sgx_sync/src/sys/futex.rs b/sgx_sync/src/sys/futex.rs
index 44dce0ca..0fb732f6 100644
--- a/sgx_sync/src/sys/futex.rs
+++ b/sgx_sync/src/sys/futex.rs
@@ -18,7 +18,7 @@
 #![allow(deprecated)]
 
 use crate::futex::FutexClockId;
-use crate::lazy::SyncLazy;
+use crate::lazy_lock::LazyLock;
 use crate::sys::ocall::{self, Timeout, Timespec};
 use alloc::collections::VecDeque;
 use alloc::sync::Arc;
@@ -45,7 +45,7 @@ impl Futex {
     }
 
     #[inline]
-    pub fn wait(&self, expected: i32, timeout: Option<Duration>) -> OsResult {
+    pub fn wait(&self, expected: u32, timeout: Option<Duration>) -> OsResult {
         let timeout =
             timeout.map(|dur| Timeout::new(dur.into(), FutexClockId::Monotonic as u32, false));
         self.wait_with_timeout(expected, timeout, Self::FUTEX_BITSET_MATCH_ANY)
@@ -53,7 +53,7 @@ impl Futex {
 
     pub fn wait_bitset(
         &self,
-        expected: i32,
+        expected: u32,
         timeout: Option<(Timespec, FutexClockId)>,
         bitset: u32,
     ) -> OsResult {
@@ -61,7 +61,7 @@ impl Futex {
         self.wait_with_timeout(expected, timeout, bitset)
     }
 
-    fn wait_with_timeout(&self, expected: i32, timeout: Option<Timeout>, bitset: u32) -> OsResult {
+    fn wait_with_timeout(&self, expected: u32, timeout: Option<Timeout>, bitset: u32) -> OsResult {
         let (_, bucket) = FUTEX_BUCKETS.get_bucket(self);
         let mut futex_bucket = bucket.lock();
 
@@ -102,7 +102,7 @@ impl Futex {
         max_nwakes: usize,
         new_futex: &Futex,
         max_nrequeues: usize,
-        expected: i32,
+        expected: u32,
     ) -> OsResult<usize> {
         self.requeue_internal(max_nwakes, new_futex, max_nrequeues, Some(expected))
             .map(|(nwakes, nrequeues)| nwakes + nrequeues)
@@ -124,7 +124,7 @@ impl Futex {
         max_nwakes: usize,
         new_futex: &Futex,
         max_nrequeues: usize,
-        expected: Option<i32>,
+        expected: Option<u32>,
     ) -> OsResult<(usize, usize)> {
         if max_nwakes > i32::MAX as usize || max_nrequeues > i32::MAX as usize {
             bail!(EINVAL);
@@ -178,8 +178,8 @@ impl Futex {
         Ok(total_number)
     }
 
-    fn load_val(&self) -> i32 {
-        unsafe { intrinsics::atomic_load(self.0 as *const i32) }
+    fn load_val(&self) -> u32 {
+        unsafe { intrinsics::atomic_load_seqcst(self.0 as *const u32) }
     }
 
     fn addr(&self) -> usize {
@@ -272,10 +272,10 @@ impl Bucket {
     }
 }
 
-static BUCKET_COUNT: SyncLazy<usize> =
-    SyncLazy::new(|| ((1 << 8) * (trts::cpu_core_num())).next_power_of_two() as usize);
-static BUCKET_MASK: SyncLazy<usize> = SyncLazy::new(|| *BUCKET_COUNT - 1);
-static FUTEX_BUCKETS: SyncLazy<FutexBuckets> = SyncLazy::new(|| FutexBuckets::new(*BUCKET_COUNT));
+static BUCKET_COUNT: LazyLock<usize> =
+    LazyLock::new(|| ((1 << 8) * (trts::cpu_core_num())).next_power_of_two() as usize);
+static BUCKET_MASK: LazyLock<usize> = LazyLock::new(|| *BUCKET_COUNT - 1);
+static FUTEX_BUCKETS: LazyLock<FutexBuckets> = LazyLock::new(|| FutexBuckets::new(*BUCKET_COUNT));
 
 #[derive(Debug)]
 struct FutexBuckets {
diff --git a/sgx_sync/src/sys/mod.rs b/sgx_sync/src/sys/mod.rs
index d52ecc01..89b6ad2a 100644
--- a/sgx_sync/src/sys/mod.rs
+++ b/sgx_sync/src/sys/mod.rs
@@ -16,8 +16,7 @@
 // under the License..
 
 pub mod condvar;
+pub mod futex;
 pub mod mutex;
+pub mod ocall;
 pub mod rwlock;
-
-pub(crate) mod futex;
-pub(crate) mod ocall;
diff --git a/sgx_sync/src/sys/mutex.rs b/sgx_sync/src/sys/mutex.rs
index 56a076b5..85cc835d 100644
--- a/sgx_sync/src/sys/mutex.rs
+++ b/sgx_sync/src/sys/mutex.rs
@@ -15,15 +15,190 @@
 // specific language governing permissions and limitations
 // under the License..
 
+use crate::lazy_box::{LazyBox, LazyInit};
 use crate::sys::ocall;
 use alloc::boxed::Box;
 use alloc::collections::LinkedList;
 use core::cell::UnsafeCell;
+use core::mem;
 use sgx_trts::sync::SpinMutex;
 use sgx_trts::tcs::{self, TcsId};
 use sgx_types::error::errno::{EBUSY, EPERM};
 use sgx_types::error::OsResult;
 
+pub struct Mutex {
+    inner: UnsafeCell<MutexInner>,
+}
+
+pub type MovableMutex = LazyBox<Mutex>;
+
+unsafe impl Send for Mutex {}
+unsafe impl Sync for Mutex {}
+
+impl LazyInit for Mutex {
+    fn init() -> Box<Self> {
+        Box::new(Self::new())
+    }
+
+    fn destroy(mutex: Box<Self>) {
+        // We're not allowed to pthread_mutex_destroy a locked mutex,
+        // so check first if it's unlocked.
+        if unsafe { !mutex.is_locked() } {
+            drop(mutex);
+        } else {
+            // The mutex is locked. This happens if a MutexGuard is leaked.
+            // In this case, we just leak the Mutex too.
+            mem::forget(mutex);
+        }
+    }
+
+    fn cancel_init(_: Box<Self>) {
+        // In this case, we can just drop it without any checks,
+        // since it cannot have been locked yet.
+    }
+}
+
+impl Mutex {
+    pub const fn new() -> Mutex {
+        Mutex {
+            inner: UnsafeCell::new(MutexInner::new(MutexControl::NonRecursive)),
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn new_with_control(control: MutexControl) -> Mutex {
+        Mutex {
+            inner: UnsafeCell::new(MutexInner::new(control)),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn lock(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.lock()
+    }
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.try_lock()
+    }
+
+    #[inline]
+    pub unsafe fn unlock(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.unlock()
+    }
+
+    #[inline]
+    pub unsafe fn unlock_lazy(&self) -> OsResult<Option<TcsId>> {
+        let mutex = &mut *self.inner.get();
+        mutex.unlock_lazy()
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.destroy()
+    }
+
+    #[inline]
+    unsafe fn is_locked(&self) -> bool {
+        let mutex = &*self.inner.get();
+        mutex.is_locked()
+    }
+}
+
+impl Drop for Mutex {
+    #[inline]
+    fn drop(&mut self) {
+        let r = unsafe { self.destroy() };
+        debug_assert_eq!(r, Ok(()));
+    }
+}
+
+pub struct ReentrantMutex {
+    inner: UnsafeCell<MutexInner>,
+}
+
+pub type MovableReentrantMutex = LazyBox<ReentrantMutex>;
+
+unsafe impl Send for ReentrantMutex {}
+unsafe impl Sync for ReentrantMutex {}
+
+impl LazyInit for ReentrantMutex {
+    fn init() -> Box<Self> {
+        Box::new(Self::new())
+    }
+
+    fn destroy(mutex: Box<Self>) {
+        // We're not allowed to pthread_mutex_destroy a locked mutex,
+        // so check first if it's unlocked.
+        if unsafe { !mutex.is_locked() } {
+            drop(mutex);
+        } else {
+            // The mutex is locked. This happens if a MutexGuard is leaked.
+            // In this case, we just leak the Mutex too.
+            mem::forget(mutex);
+        }
+    }
+
+    fn cancel_init(_: Box<Self>) {
+        // In this case, we can just drop it without any checks,
+        // since it cannot have been locked yet.
+    }
+}
+
+impl ReentrantMutex {
+    pub const fn new() -> ReentrantMutex {
+        ReentrantMutex {
+            inner: UnsafeCell::new(MutexInner::new(MutexControl::Recursive)),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn lock(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.lock()
+    }
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.try_lock()
+    }
+
+    #[inline]
+    pub unsafe fn unlock(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.unlock()
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) -> OsResult {
+        let mutex = &mut *self.inner.get();
+        mutex.destroy()
+    }
+
+    #[inline]
+    unsafe fn is_locked(&self) -> bool {
+        let mutex = &*self.inner.get();
+        mutex.is_locked()
+    }
+}
+
+impl Drop for ReentrantMutex {
+    #[inline]
+    fn drop(&mut self) {
+        let r = unsafe { self.destroy() };
+        debug_assert_eq!(r, Ok(()));
+    }
+}
+
+struct MutexInner {
+    inner: SpinMutex<Inner>,
+}
+
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum MutexControl {
     NonRecursive,
@@ -48,10 +223,6 @@ impl Inner {
     }
 }
 
-struct MutexInner {
-    inner: SpinMutex<Inner>,
-}
-
 impl MutexInner {
     const fn new(control: MutexControl) -> MutexInner {
         MutexInner {
@@ -160,93 +331,9 @@ impl MutexInner {
             Err(EBUSY)
         }
     }
-}
-
-pub type MovableMutex = Box<Mutex>;
-
-unsafe impl Send for Mutex {}
-unsafe impl Sync for Mutex {}
-
-pub struct Mutex {
-    inner: UnsafeCell<MutexInner>,
-}
-
-impl Mutex {
-    pub const fn new() -> Mutex {
-        Mutex {
-            inner: UnsafeCell::new(MutexInner::new(MutexControl::NonRecursive)),
-        }
-    }
-
-    pub fn new_with_control(control: MutexControl) -> Mutex {
-        Mutex {
-            inner: UnsafeCell::new(MutexInner::new(control)),
-        }
-    }
-
-    #[inline]
-    pub unsafe fn lock(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.lock()
-    }
-
-    #[inline]
-    pub unsafe fn try_lock(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.try_lock()
-    }
-
-    #[inline]
-    pub unsafe fn unlock(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.unlock()
-    }
-
-    #[inline]
-    pub unsafe fn unlock_lazy(&self) -> OsResult<Option<TcsId>> {
-        let mutex = &mut *self.inner.get();
-        mutex.unlock_lazy()
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.destroy()
-    }
-}
-
-pub struct ReentrantMutex {
-    inner: UnsafeCell<MutexInner>,
-}
-
-impl ReentrantMutex {
-    pub const fn new() -> ReentrantMutex {
-        ReentrantMutex {
-            inner: UnsafeCell::new(MutexInner::new(MutexControl::Recursive)),
-        }
-    }
-
-    #[inline]
-    pub unsafe fn lock(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.lock()
-    }
 
-    #[inline]
-    pub unsafe fn try_lock(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.try_lock()
-    }
-
-    #[inline]
-    pub unsafe fn unlock(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.unlock()
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) -> OsResult {
-        let mutex = &mut *self.inner.get();
-        mutex.destroy()
+    unsafe fn is_locked(&self) -> bool {
+        let inner_guard = self.inner.lock();
+        inner_guard.owner.is_some() || !inner_guard.queue.is_empty()
     }
 }
diff --git a/sgx_sync/src/sys/ocall/mod.rs b/sgx_sync/src/sys/ocall/mod.rs
index 85f4419b..7683b717 100644
--- a/sgx_sync/src/sys/ocall/mod.rs
+++ b/sgx_sync/src/sys/ocall/mod.rs
@@ -388,7 +388,7 @@ pub fn thread_wait_event_ex(tcs: TcsId, timeout: Option<Timeout>) -> OsResult {
         timeout.as_ref().map_or((ptr::null(), 0, 0), |timeout| {
             let ts_ptr = &timeout.ts.t as *const timespec;
             let clockid = timeout.clockid as i32;
-            let absolute_time = if timeout.absolute_time { 1 } else { 0 };
+            let absolute_time = i32::from(timeout.absolute_time);
             (ts_ptr, clockid, absolute_time)
         });
 
diff --git a/sgx_sync/src/sys/rwlock.rs b/sgx_sync/src/sys/rwlock.rs
index 21c75fcf..5532eef9 100644
--- a/sgx_sync/src/sys/rwlock.rs
+++ b/sgx_sync/src/sys/rwlock.rs
@@ -15,16 +15,122 @@
 // specific language governing permissions and limitations
 // under the License..
 
+use crate::lazy_box::{LazyBox, LazyInit};
 use crate::sys::ocall;
 use alloc::boxed::Box;
 use alloc::collections::LinkedList;
 use alloc::vec::Vec;
 use core::cell::UnsafeCell;
+use core::mem;
 use sgx_trts::sync::SpinMutex;
 use sgx_trts::tcs::{self, TcsId};
 use sgx_types::error::errno::{EBUSY, EDEADLK, EPERM};
 use sgx_types::error::OsResult;
 
+pub struct RwLock {
+    inner: UnsafeCell<RwLockInner>,
+}
+
+pub type MovableRwLock = LazyBox<RwLock>;
+
+unsafe impl Send for RwLock {}
+unsafe impl Sync for RwLock {}
+
+impl LazyInit for RwLock {
+    fn init() -> Box<Self> {
+        Box::new(Self::new())
+    }
+
+    fn destroy(rwlock: Box<Self>) {
+        // We're not allowed to pthread_rwlock_destroy a locked rwlock,
+        // so check first if it's unlocked.
+        if unsafe { rwlock.is_locked() } {
+            // The rwlock is locked. This happens if a RwLock{Read,Write}Guard is leaked.
+            // In this case, we just leak the RwLock too.
+            mem::forget(rwlock);
+        }
+    }
+
+    fn cancel_init(_: Box<Self>) {
+        // In this case, we can just drop it without any checks,
+        // since it cannot have been locked yet.
+    }
+}
+
+impl RwLock {
+    pub const fn new() -> RwLock {
+        RwLock {
+            inner: UnsafeCell::new(RwLockInner::new()),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn read(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.read()
+    }
+
+    #[inline]
+    pub unsafe fn try_read(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.try_read()
+    }
+
+    #[inline]
+    pub unsafe fn write(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.write()
+    }
+
+    #[inline]
+    pub unsafe fn try_write(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.try_write()
+    }
+
+    #[inline]
+    pub unsafe fn read_unlock(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.read_unlock()
+    }
+
+    #[inline]
+    pub unsafe fn write_unlock(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.write_unlock()
+    }
+
+    #[allow(dead_code)]
+    #[inline]
+    pub unsafe fn unlock(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.unlock()
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) -> OsResult {
+        let rwlock = &mut *self.inner.get();
+        rwlock.destroy()
+    }
+
+    #[inline]
+    unsafe fn is_locked(&self) -> bool {
+        let rwlock = &*self.inner.get();
+        rwlock.is_locked()
+    }
+}
+
+impl Drop for RwLock {
+    fn drop(&mut self) {
+        let r = unsafe { self.destroy() };
+        debug_assert_eq!(r, Ok(()));
+    }
+}
+
+struct RwLockInner {
+    inner: SpinMutex<Inner>,
+}
+
 struct Inner {
     reader_count: u32,
     writer_waiting: u32,
@@ -45,10 +151,6 @@ impl Inner {
     }
 }
 
-struct RwLockInner {
-    inner: SpinMutex<Inner>,
-}
-
 impl RwLockInner {
     const fn new() -> RwLockInner {
         RwLockInner {
@@ -199,81 +301,19 @@ impl RwLockInner {
     }
 
     unsafe fn destroy(&mut self) -> OsResult {
-        let inner_guard = self.inner.lock();
-        if inner_guard.owner.is_some()
-            || inner_guard.reader_count != 0
-            || inner_guard.writer_waiting != 0
-            || !inner_guard.reader_queue.is_empty()
-            || !inner_guard.writer_queue.is_empty()
-        {
+        if self.is_locked() {
             Err(EBUSY)
         } else {
             Ok(())
         }
     }
-}
-
-pub type MovableRwLock = Box<RwLock>;
-
-unsafe impl Send for RwLock {}
-unsafe impl Sync for RwLock {}
-
-pub struct RwLock {
-    inner: UnsafeCell<RwLockInner>,
-}
-
-impl RwLock {
-    pub const fn new() -> RwLock {
-        RwLock {
-            inner: UnsafeCell::new(RwLockInner::new()),
-        }
-    }
-
-    #[inline]
-    pub unsafe fn read(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.read()
-    }
-
-    #[inline]
-    pub unsafe fn try_read(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.try_read()
-    }
 
-    #[inline]
-    pub unsafe fn write(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.write()
-    }
-
-    #[inline]
-    pub unsafe fn try_write(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.try_write()
-    }
-
-    #[inline]
-    pub unsafe fn read_unlock(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.read_unlock()
-    }
-
-    #[inline]
-    pub unsafe fn write_unlock(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.write_unlock()
-    }
-
-    #[inline]
-    pub unsafe fn unlock(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.unlock()
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) -> OsResult {
-        let rwlock = &mut *self.inner.get();
-        rwlock.destroy()
+    unsafe fn is_locked(&self) -> bool {
+        let inner_guard = self.inner.lock();
+        inner_guard.owner.is_some()
+            || inner_guard.reader_count != 0
+            || inner_guard.writer_waiting != 0
+            || !inner_guard.reader_queue.is_empty()
+            || !inner_guard.writer_queue.is_empty()
     }
 }
diff --git a/sgx_tdh/src/capi.rs b/sgx_tdh/src/capi.rs
index 9ec3d42a..db7c1a6b 100644
--- a/sgx_tdh/src/capi.rs
+++ b/sgx_tdh/src/capi.rs
@@ -35,7 +35,7 @@ pub unsafe extern "C" fn sgx_dh_init_session(
     if session.is_null() {
         return SgxStatus::InvalidParameter;
     }
-    if !(&*session).is_enclave_range() {
+    if !(*session).is_enclave_range() {
         return SgxStatus::InvalidParameter;
     }
 
@@ -69,7 +69,7 @@ pub unsafe extern "C" fn sgx_dh_responder_gen_msg1(
     if session.is_null() || msg1.is_null() {
         return SgxStatus::InvalidParameter;
     }
-    if !(&*session).is_enclave_range() {
+    if !(*session).is_enclave_range() {
         return SgxStatus::InvalidParameter;
     }
 
@@ -107,7 +107,7 @@ pub unsafe extern "C" fn sgx_dh_responder_proc_msg2(
     {
         return SgxStatus::InvalidParameter;
     }
-    if !(&*session).is_enclave_range() {
+    if !(*session).is_enclave_range() {
         return SgxStatus::InvalidParameter;
     }
 
@@ -190,7 +190,7 @@ where
         return SgxStatus::InvalidParameter;
     }
 
-    if !(&*session).is_enclave_range() {
+    if !(*session).is_enclave_range() {
         return SgxStatus::InvalidParameter;
     }
 
@@ -260,7 +260,7 @@ where
     if session.is_null() || msg3.is_null() || aek.is_null() || responder_identity.is_null() {
         return SgxStatus::InvalidParameter;
     }
-    if !(&*session).is_enclave_range() {
+    if !(*session).is_enclave_range() {
         return SgxStatus::InvalidParameter;
     }
 
diff --git a/sgx_tests/cov/src/lib.rs b/sgx_tests/cov/src/lib.rs
index 61256476..eff7f227 100644
--- a/sgx_tests/cov/src/lib.rs
+++ b/sgx_tests/cov/src/lib.rs
@@ -31,9 +31,9 @@ use sgx_types::types::c_char;
 use std::ffi::CStr;
 use std::io::Write;
 use std::io::{Error, ErrorKind};
-use std::lazy::SyncLazy;
 use std::slice;
 use std::string::String;
+use std::sync::LazyLock;
 use std::sync::{Mutex, Once};
 use std::untrusted::fs::{copy, File, OpenOptions};
 use std::vec::Vec;
@@ -45,10 +45,10 @@ const GCOV_TAG_COUNTER_ARCS: u32 = 0x01a1_0000;
 const GCOV_TAG_OBJECT_SUMMARY: u32 = 0xa100_0000;
 const GCOV_TAG_PROGRAM_SUMMARY: u32 = 0xa300_0000;
 
-static GCDA_FILE: SyncLazy<Mutex<(Option<File>, u32)>> =
-    SyncLazy::new(|| Mutex::new((None, u32::MAX)));
-static WROUT_FNS: SyncLazy<Mutex<Vec<extern "C" fn()>>> = SyncLazy::new(|| Mutex::new(Vec::new()));
-static RND: SyncLazy<Mutex<u32>> = SyncLazy::new(|| Mutex::new(0));
+static GCDA_FILE: LazyLock<Mutex<(Option<File>, u32)>> =
+    LazyLock::new(|| Mutex::new((None, u32::MAX)));
+static WROUT_FNS: LazyLock<Mutex<Vec<extern "C" fn()>>> = LazyLock::new(|| Mutex::new(Vec::new()));
+static RND: LazyLock<Mutex<u32>> = LazyLock::new(|| Mutex::new(0));
 
 pub fn cov_writeout() {
     for f in WROUT_FNS.lock().unwrap().iter() {
diff --git a/sgx_tests/utils/src/lib.rs b/sgx_tests/utils/src/lib.rs
index 15854d2b..8cd222a5 100644
--- a/sgx_tests/utils/src/lib.rs
+++ b/sgx_tests/utils/src/lib.rs
@@ -17,9 +17,7 @@
 
 #![no_std]
 #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))]
-#![feature(bench_black_box)]
 #![feature(core_intrinsics)]
-#![feature(total_cmp)]
 
 #[macro_use]
 extern crate alloc;
diff --git a/sgx_tests/utils/src/stats.rs b/sgx_tests/utils/src/stats.rs
index f808eb8e..4fb17b8a 100644
--- a/sgx_tests/utils/src/stats.rs
+++ b/sgx_tests/utils/src/stats.rs
@@ -306,11 +306,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) {
     let hundred = 100_f64;
     let hi = percentile_of_sorted(&tmp, hundred - pct);
     for samp in samples {
-        if *samp > hi {
-            *samp = hi
-        } else if *samp < lo {
-            *samp = lo
-        }
+        *samp = (*samp).clamp(lo, hi);
     }
 }
 #[inline]
diff --git a/sgx_trts/src/arch.rs b/sgx_trts/src/arch.rs
index a788248f..c1d695a5 100644
--- a/sgx_trts/src/arch.rs
+++ b/sgx_trts/src/arch.rs
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License..
 
+#![allow(clippy::enum_variant_names)]
+
 use crate::edmm::{PageInfo, PageType};
 use crate::tcs::tc;
 use crate::version::*;
diff --git a/sgx_trts/src/call/ocalloc.rs b/sgx_trts/src/call/ocalloc.rs
index e4be53ab..34be0448 100644
--- a/sgx_trts/src/call/ocalloc.rs
+++ b/sgx_trts/src/call/ocalloc.rs
@@ -101,13 +101,13 @@ impl Drop for OcBuffer {
 
 impl AsRef<[u8]> for OcBuffer {
     fn as_ref(&self) -> &[u8] {
-        &**self
+        self
     }
 }
 
 impl AsMut<[u8]> for OcBuffer {
     fn as_mut(&mut self) -> &mut [u8] {
-        &mut **self
+        self
     }
 }
 
diff --git a/sgx_trts/src/capi.rs b/sgx_trts/src/capi.rs
index babc4e99..12f23921 100644
--- a/sgx_trts/src/capi.rs
+++ b/sgx_trts/src/capi.rs
@@ -53,11 +53,7 @@ pub unsafe extern "C" fn sgx_register_exception_handler(
 pub unsafe extern "C" fn sgx_unregister_exception_handler(handle: *const c_void) -> i32 {
     let handle = Handle::from_raw(handle as u64);
     let result = unregister(handle);
-    if result {
-        1
-    } else {
-        0
-    }
+    i32::from(result)
 }
 
 #[inline]
@@ -129,11 +125,7 @@ pub extern "C" fn sgx_get_rsrvmm_default_perm() -> u32 {
 #[link_section = ".nipx"]
 #[no_mangle]
 pub extern "C" fn sgx_is_enclave_crashed() -> i32 {
-    if enclave::state::is_crashed() {
-        1
-    } else {
-        0
-    }
+    i32::from(enclave::state::is_crashed())
 }
 
 #[inline]
@@ -169,21 +161,13 @@ pub extern "C" fn sgx_is_supported_edmm() -> bool {
 #[inline]
 #[no_mangle]
 pub unsafe extern "C" fn sgx_is_within_enclave(p: *const u8, len: usize) -> i32 {
-    if enclave::is_within_enclave(p, len) {
-        1
-    } else {
-        0
-    }
+    i32::from(enclave::is_within_enclave(p, len))
 }
 
 #[inline]
 #[no_mangle]
 pub unsafe extern "C" fn sgx_is_outside_enclave(p: *const u8, len: usize) -> i32 {
-    if enclave::is_within_host(p, len) {
-        1
-    } else {
-        0
-    }
+    i32::from(enclave::is_within_host(p, len))
 }
 
 #[inline]
@@ -304,11 +288,7 @@ pub unsafe extern "C" fn sgx_thread_self() -> sgx_thread_t {
 #[inline]
 #[no_mangle]
 pub unsafe extern "C" fn sgx_thread_equal(a: sgx_thread_t, b: sgx_thread_t) -> i32 {
-    if a == b {
-        1
-    } else {
-        0
-    }
+    i32::from(a == b)
 }
 
 #[cfg(not(feature = "hyper"))]
diff --git a/sgx_trts/src/elf/control_flow.rs b/sgx_trts/src/elf/control_flow.rs
index ba84d608..887ff67d 100644
--- a/sgx_trts/src/elf/control_flow.rs
+++ b/sgx_trts/src/elf/control_flow.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum ControlFlow<C, B> {
     Continue(C),
     Break(B),
diff --git a/sgx_trts/src/elf/header.rs b/sgx_trts/src/elf/header.rs
index a5a5d821..91011fa2 100644
--- a/sgx_trts/src/elf/header.rs
+++ b/sgx_trts/src/elf/header.rs
@@ -428,7 +428,7 @@ impl fmt::Debug for Machine_ {
     }
 }
 
-#[allow(non_camel_case_types)]
+#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
 pub enum Machine {
     None,
diff --git a/sgx_trts/src/elf/program.rs b/sgx_trts/src/elf/program.rs
index eeebbc13..8907c9f5 100644
--- a/sgx_trts/src/elf/program.rs
+++ b/sgx_trts/src/elf/program.rs
@@ -236,7 +236,7 @@ macro_rules! ph_impl {
 
             pub fn raw_data<'a>(&self, elf_file: &ElfFile<'a>) -> &'a [u8] {
                 assert!(match self.get_type() {
-                    Ok(typ) => typ != Type::Null,
+                    Ok(_) => self.type_.0 != 0,
                     Err(_) => false,
                 });
                 unsafe {
diff --git a/sgx_trts/src/elf/slice.rs b/sgx_trts/src/elf/slice.rs
index 3807bde5..59defb9d 100644
--- a/sgx_trts/src/elf/slice.rs
+++ b/sgx_trts/src/elf/slice.rs
@@ -46,6 +46,7 @@ pub trait AsSlice<T> {
 }
 
 impl<T> AsSlice<T> for [T] {
+    #[inline(always)]
     fn as_slice(&self) -> Slice<T> {
         Slice { rust: self }
     }
diff --git a/sgx_trts/src/enclave/parse.rs b/sgx_trts/src/enclave/parse.rs
index 7ded28dc..f1fe6175 100644
--- a/sgx_trts/src/enclave/parse.rs
+++ b/sgx_trts/src/enclave/parse.rs
@@ -317,21 +317,20 @@ unsafe fn relocate_elf_rela(elf: &ElfFile, sym_offset: u64, rel_offset: u64, rel
             }
             sections::R_X86_64_GLOB_DAT | sections::R_X86_64_JMP_SLOT | sections::R_X86_64_64 => {
                 if let Some(sym) = get_sym(sym_table, rel.get_symbol_table_index()) {
-                    *reloc_addr = elf.input.as_slice().as_ptr() as u64
-                        + sym.value()
-                        + rel.get_addend() as u64;
+                    *reloc_addr =
+                        elf.input.as_slice().as_ptr() as u64 + sym.value() + rel.get_addend();
                 }
             }
             sections::R_X86_64_DTPMOD64 => *reloc_addr = 1_u64,
             sections::R_X86_64_DTPOFF64 => {
                 if let Some(sym) = get_sym(sym_table, rel.get_symbol_table_index()) {
-                    *reloc_addr = sym.value() + rel.get_addend() as u64;
+                    *reloc_addr = sym.value() + rel.get_addend();
                 }
             }
             sections::R_X86_64_TPOFF64 => {
                 if let Some(sym) = get_sym(sym_table, rel.get_symbol_table_index()) {
                     if let Some(tls_size) = tls_size(elf) {
-                        *reloc_addr = sym.value() + rel.get_addend() as u64 - tls_size;
+                        *reloc_addr = sym.value() + rel.get_addend() - tls_size;
                     }
                 }
             }
diff --git a/sgx_trts/src/enclave/state.rs b/sgx_trts/src/enclave/state.rs
index 5f65477e..7bfcdf4c 100644
--- a/sgx_trts/src/enclave/state.rs
+++ b/sgx_trts/src/enclave/state.rs
@@ -77,8 +77,11 @@ pub fn lock_state() -> State {
     const IN_PROGRESS: u32 = 1;
 
     let state = unsafe {
-        let (state, _) =
-            core::intrinsics::atomic_cxchg(&mut ENCLAVE_STATE, NOT_STARTED, IN_PROGRESS);
+        let (state, _) = core::intrinsics::atomic_cxchg_seqcst_seqcst(
+            &mut ENCLAVE_STATE,
+            NOT_STARTED,
+            IN_PROGRESS,
+        );
         state
     };
     match state {
diff --git a/sgx_trts/src/feature/sys.rs b/sgx_trts/src/feature/sys.rs
index 61404f7b..537b5a5b 100644
--- a/sgx_trts/src/feature/sys.rs
+++ b/sgx_trts/src/feature/sys.rs
@@ -73,7 +73,8 @@ impl SystemFeatures {
         #[cfg(feature = "hyper")]
         {
             use crate::inst::GlobalHyper;
-            GlobalHyper::get_mut().set_msbuf_info(&features.msbuf_info)?;
+            let msbuf_info = ptr::addr_of!(features.msbuf_info);
+            GlobalHyper::get_mut().set_msbuf_info(&ptr::read_unaligned(msbuf_info))?;
         }
 
         Ok(features)
@@ -85,7 +86,7 @@ impl SystemFeatures {
                 cmp::min(self.size, mem::size_of::<Self>())
             } else {
                 let b = self as *const _ as usize;
-                let p = &self.size as *const _ as usize;
+                let p = ptr::addr_of!(self.size) as usize;
                 p - b
             };
 
diff --git a/sgx_trts/src/inst/hyper/inst.rs b/sgx_trts/src/inst/hyper/inst.rs
index ba5ffa80..be4c2da5 100644
--- a/sgx_trts/src/inst/hyper/inst.rs
+++ b/sgx_trts/src/inst/hyper/inst.rs
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License..
 
+#![allow(clippy::enum_variant_names)]
+
 use crate::arch::Secinfo;
 use crate::inst::INVALID_LEAF;
 use crate::se::{
diff --git a/sgx_trts/src/inst/sim/tls/gnu.rs b/sgx_trts/src/inst/sim/tls/gnu.rs
index 11f156bf..357381a0 100644
--- a/sgx_trts/src/inst/sim/tls/gnu.rs
+++ b/sgx_trts/src/inst/sim/tls/gnu.rs
@@ -25,6 +25,7 @@ pub union Dtv {
 }
 
 #[repr(C)]
+#[derive(Clone, Copy, Debug)]
 struct Pointer {
     value: usize,
     is_static: i32,
diff --git a/sgx_trts/src/lib.rs b/sgx_trts/src/lib.rs
index 9bfabe7c..2a1babfc 100644
--- a/sgx_trts/src/lib.rs
+++ b/sgx_trts/src/lib.rs
@@ -20,24 +20,20 @@
 #![no_std]
 #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))]
 #![feature(allocator_api)]
-#![feature(atomic_from_mut)]
+#![feature(const_trait_impl)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
-#![feature(linkage)]
+#![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
 #![feature(negative_impls)]
+#![feature(never_type)]
 #![feature(nonnull_slice_from_raw_parts)]
-#![feature(once_cell)]
 #![feature(ptr_internals)]
 #![feature(thread_local)]
-#![feature(untagged_unions)]
 #![cfg_attr(feature = "sim", feature(unchecked_math))]
-#![allow(clippy::enum_variant_names)]
 #![allow(clippy::missing_safety_doc)]
-#![allow(clippy::upper_case_acronyms)]
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
-#![allow(unaligned_references)]
 
 #[cfg(all(feature = "sim", feature = "hyper"))]
 compile_error!("feature \"sim\" and feature \"hyper\" cannot be enabled at the same time");
diff --git a/sgx_trts/src/sync/lazy.rs b/sgx_trts/src/sync/lazy.rs
new file mode 100644
index 00000000..10aa1b2b
--- /dev/null
+++ b/sgx_trts/src/sync/lazy.rs
@@ -0,0 +1,257 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License..
+
+use core::cell::{Cell, UnsafeCell};
+use core::fmt;
+use core::mem;
+use core::ops::Deref;
+
+/// A cell which can be written to only once.
+///
+/// Unlike `RefCell`, a `OnceCell` only provides shared `&T` references to its value.
+/// Unlike `Cell`, a `OnceCell` doesn't require copying or replacing the value to access it.
+///
+pub struct OnceCell<T> {
+    // Invariant: written to at most once.
+    inner: UnsafeCell<Option<T>>,
+}
+
+impl<T> Default for OnceCell<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.get() {
+            Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
+            None => f.write_str("OnceCell(Uninit)"),
+        }
+    }
+}
+
+impl<T: Clone> Clone for OnceCell<T> {
+    fn clone(&self) -> OnceCell<T> {
+        let res = OnceCell::new();
+        if let Some(value) = self.get() {
+            match res.set(value.clone()) {
+                Ok(()) => (),
+                Err(_) => unreachable!(),
+            }
+        }
+        res
+    }
+}
+
+impl<T: PartialEq> PartialEq for OnceCell<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.get() == other.get()
+    }
+}
+
+impl<T: Eq> Eq for OnceCell<T> {}
+
+impl<T> const From<T> for OnceCell<T> {
+    /// Creates a new `OnceCell<T>` which already contains the given `value`.
+    fn from(value: T) -> Self {
+        OnceCell {
+            inner: UnsafeCell::new(Some(value)),
+        }
+    }
+}
+
+impl<T> OnceCell<T> {
+    /// Creates a new empty cell.
+    #[must_use]
+    pub const fn new() -> OnceCell<T> {
+        OnceCell {
+            inner: UnsafeCell::new(None),
+        }
+    }
+
+    /// Gets the reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty.
+    pub fn get(&self) -> Option<&T> {
+        // SAFETY: Safe due to `inner`'s invariant
+        unsafe { &*self.inner.get() }.as_ref()
+    }
+
+    /// Gets the mutable reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty.
+    pub fn get_mut(&mut self) -> Option<&mut T> {
+        self.inner.get_mut().as_mut()
+    }
+
+    /// Sets the contents of the cell to `value`.
+    ///
+    /// # Errors
+    ///
+    /// This method returns `Ok(())` if the cell was empty and `Err(value)` if
+    /// it was full.
+    ///
+    pub fn set(&self, value: T) -> Result<(), T> {
+        // SAFETY: Safe because we cannot have overlapping mutable borrows
+        let slot = unsafe { &*self.inner.get() };
+        if slot.is_some() {
+            return Err(value);
+        }
+
+        // SAFETY: This is the only place where we set the slot, no races
+        // due to reentrancy/concurrency are possible, and we've
+        // checked that slot is currently `None`, so this write
+        // maintains the `inner`'s invariant.
+        let slot = unsafe { &mut *self.inner.get() };
+        *slot = Some(value);
+        Ok(())
+    }
+
+    /// Gets the contents of the cell, initializing it with `f`
+    /// if the cell was empty.
+    ///
+    /// # Panics
+    ///
+    /// If `f` panics, the panic is propagated to the caller, and the cell
+    /// remains uninitialized.
+    ///
+    /// It is an error to reentrantly initialize the cell from `f`. Doing
+    /// so results in a panic.
+    ///
+    pub fn get_or_init<F>(&self, f: F) -> &T
+    where
+        F: FnOnce() -> T,
+    {
+        match self.get_or_try_init(|| Ok::<T, !>(f())) {
+            Ok(val) => val,
+            Err(_) => unreachable!(),
+        }
+    }
+
+    /// Gets the contents of the cell, initializing it with `f` if
+    /// the cell was empty. If the cell was empty and `f` failed, an
+    /// error is returned.
+    ///
+    /// # Panics
+    ///
+    /// If `f` panics, the panic is propagated to the caller, and the cell
+    /// remains uninitialized.
+    ///
+    /// It is an error to reentrantly initialize the cell from `f`. Doing
+    /// so results in a panic.
+    ///
+    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        if let Some(val) = self.get() {
+            return Ok(val);
+        }
+        /// Avoid inlining the initialization closure into the common path that fetches
+        /// the already initialized value
+        #[cold]
+        fn outlined_call<F, T, E>(f: F) -> Result<T, E>
+        where
+            F: FnOnce() -> Result<T, E>,
+        {
+            f()
+        }
+        let val = outlined_call(f)?;
+        // Note that *some* forms of reentrant initialization might lead to
+        // UB (see `reentrant_init` test). I believe that just removing this
+        // `assert`, while keeping `set/get` would be sound, but it seems
+        // better to panic, rather than to silently use an old value.
+        assert!(self.set(val).is_ok(), "reentrant init");
+        Ok(self.get().unwrap())
+    }
+
+    /// Consumes the cell, returning the wrapped value.
+    ///
+    /// Returns `None` if the cell was empty.
+    ///
+    pub fn into_inner(self) -> Option<T> {
+        // Because `into_inner` takes `self` by value, the compiler statically verifies
+        // that it is not currently borrowed. So it is safe to move out `Option<T>`.
+        self.inner.into_inner()
+    }
+
+    /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
+    ///
+    /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
+    ///
+    /// Safety is guaranteed by requiring a mutable reference.
+    ///
+    pub fn take(&mut self) -> Option<T> {
+        mem::take(self).into_inner()
+    }
+}
+
+/// A value which is initialized on the first access.
+///
+pub struct Lazy<T, F = fn() -> T> {
+    cell: OnceCell<T>,
+    init: Cell<Option<F>>,
+}
+
+impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Lazy")
+            .field("cell", &self.cell)
+            .field("init", &"..")
+            .finish()
+    }
+}
+
+impl<T, F> Lazy<T, F> {
+    /// Creates a new lazy value with the given initializing function.
+    ///
+    pub const fn new(init: F) -> Lazy<T, F> {
+        Lazy {
+            cell: OnceCell::new(),
+            init: Cell::new(Some(init)),
+        }
+    }
+}
+
+impl<T, F: FnOnce() -> T> Lazy<T, F> {
+    /// Forces the evaluation of this lazy value and returns a reference to
+    /// the result.
+    ///
+    /// This is equivalent to the `Deref` impl, but is explicit.
+    ///
+    pub fn force(this: &Lazy<T, F>) -> &T {
+        this.cell.get_or_init(|| match this.init.take() {
+            Some(f) => f(),
+            None => panic!("`Lazy` instance has previously been poisoned"),
+        })
+    }
+}
+
+impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        Lazy::force(self)
+    }
+}
+
+impl<T: Default> Default for Lazy<T> {
+    /// Creates a new lazy value using `Default` as the initializing function.
+    fn default() -> Lazy<T> {
+        Lazy::new(T::default)
+    }
+}
diff --git a/sgx_trts/src/sync/mod.rs b/sgx_trts/src/sync/mod.rs
index 1644daf4..92193b80 100644
--- a/sgx_trts/src/sync/mod.rs
+++ b/sgx_trts/src/sync/mod.rs
@@ -15,12 +15,16 @@
 // specific language governing permissions and limitations
 // under the License..
 
+mod lazy;
 mod lock_api;
 mod mutex;
 mod once;
 mod rwlock;
 
+#[allow(unused_imports)]
+pub(crate) use lazy::{Lazy, OnceCell};
+pub(crate) use once::Once;
+
 pub use lock_api::{RawMutex, RawRwLock};
 pub use mutex::{SpinMutex, SpinMutexGuard};
-pub(crate) use once::Once;
 pub use rwlock::{SpinRwLock, SpinRwLockReadGuard, SpinRwLockWriteGuard};
diff --git a/sgx_trts/src/sync/mutex.rs b/sgx_trts/src/sync/mutex.rs
index 4d3f0d96..0b909ac8 100644
--- a/sgx_trts/src/sync/mutex.rs
+++ b/sgx_trts/src/sync/mutex.rs
@@ -118,7 +118,7 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for SpinMutex<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_lock() {
             Some(guard) => write!(f, "SpinMutex {{ value: ")
-                .and_then(|()| (&*guard).fmt(f))
+                .and_then(|()| (*guard).fmt(f))
                 .and_then(|()| write!(f, "}}")),
             None => write!(f, "SpinMutex {{ <locked> }}"),
         }
diff --git a/sgx_trts/src/sync/rwlock.rs b/sgx_trts/src/sync/rwlock.rs
index 1dbded74..5f4d9ccc 100644
--- a/sgx_trts/src/sync/rwlock.rs
+++ b/sgx_trts/src/sync/rwlock.rs
@@ -155,7 +155,7 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for SpinRwLock<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_read() {
             Some(guard) => write!(f, "SpinRwLock {{ value: ")
-                .and_then(|()| (&*guard).fmt(f))
+                .and_then(|()| (*guard).fmt(f))
                 .and_then(|()| write!(f, "}}")),
             None => write!(f, "SpinRwLock {{ <locked> }}"),
         }
diff --git a/sgx_trts/src/tcs/list.rs b/sgx_trts/src/tcs/list.rs
index c83913e5..2111ec19 100644
--- a/sgx_trts/src/tcs/list.rs
+++ b/sgx_trts/src/tcs/list.rs
@@ -17,10 +17,10 @@
 
 use crate::arch::Tcs;
 use crate::rand::Rng;
+use crate::sync::OnceCell;
 use crate::sync::SpinMutex;
 use alloc::collections::linked_list::{Iter, LinkedList};
 use core::fmt;
-use core::lazy::OnceCell;
 use core::num::NonZeroUsize;
 use core::ptr::NonNull;
 
diff --git a/sgx_trts/src/tcs/tc.rs b/sgx_trts/src/tcs/tc.rs
index cff18f8d..09e4bcfc 100644
--- a/sgx_trts/src/tcs/tc.rs
+++ b/sgx_trts/src/tcs/tc.rs
@@ -20,8 +20,8 @@ use crate::enclave::parse;
 use crate::error;
 use crate::feature::SysFeatures;
 use crate::rand::Rng;
+use crate::sync::OnceCell;
 use core::convert::From;
-use core::lazy::OnceCell;
 use core::mem;
 use core::num::NonZeroUsize;
 use core::ptr;
diff --git a/sgx_trts/src/thread/tls/bitset.rs b/sgx_trts/src/thread/tls/bitset.rs
index 7a93ed8c..7441dea4 100644
--- a/sgx_trts/src/thread/tls/bitset.rs
+++ b/sgx_trts/src/thread/tls/bitset.rs
@@ -50,7 +50,8 @@ impl Bitset {
         self.0[hi].fetch_and(!lo, Ordering::Relaxed);
     }
 
-    // Sets any unset bit. Not atomic. Returns `None` if all bits were observed to be set.
+    /// Sets any unset bit. Not atomic. Returns `None` if all bits were
+    /// observed to be set.
     pub fn set(&self) -> Option<usize> {
         'elems: for (idx, elem) in self.0.iter().enumerate() {
             let mut current = elem.load(Ordering::Relaxed);
diff --git a/sgx_trts/src/thread/tls/mod.rs b/sgx_trts/src/thread/tls/mod.rs
index 8d4802e4..cb77ef5d 100644
--- a/sgx_trts/src/thread/tls/mod.rs
+++ b/sgx_trts/src/thread/tls/mod.rs
@@ -160,7 +160,9 @@ impl<'a> !Send for ActiveTls<'a> {}
 
 impl<'a> Drop for ActiveTls<'a> {
     fn drop(&mut self) {
-        let value_with_destructor = |storage: &'a StorageNode| {
+        fn value_with_destructor(
+            storage: &StorageNode,
+        ) -> Option<(&Cell<*mut u8>, unsafe extern "C" fn(*mut u8))> {
             let index = storage.key.to_index();
             if TLS_KEY_IN_USE.get(index) {
                 let ptr = TLS_DESTRUCTOR[index].load(Ordering::Relaxed);
@@ -169,13 +171,13 @@ impl<'a> Drop for ActiveTls<'a> {
             } else {
                 None
             }
-        };
+        }
         let tls_storage = self.tls.data.borrow();
 
         let mut any_non_null_dtor = true;
         while any_non_null_dtor {
             any_non_null_dtor = false;
-            for (value, dtor) in tls_storage.iter().filter_map(&value_with_destructor) {
+            for (value, dtor) in tls_storage.iter().filter_map(value_with_destructor) {
                 let value = value.replace(ptr::null_mut());
                 if !value.is_null() {
                     any_non_null_dtor = true;
diff --git a/sgx_trts/src/veh/exception.rs b/sgx_trts/src/veh/exception.rs
index 0c8c82fd..92d5fb85 100644
--- a/sgx_trts/src/veh/exception.rs
+++ b/sgx_trts/src/veh/exception.rs
@@ -26,6 +26,7 @@ use crate::veh::MAX_REGISTER_COUNT;
 use crate::veh::{ExceptionHandler, ExceptionInfo, ExceptionType, ExceptionVector, HandleResult};
 use core::convert::TryFrom;
 use core::mem;
+use core::mem::MaybeUninit;
 use sgx_types::error::{SgxResult, SgxStatus};
 
 macro_rules! try_error {
@@ -232,10 +233,13 @@ extern "C" fn internal_handle(info: &mut ExceptionInfo) {
             error::abort();
         }
 
-        let mut handlers: [ExceptionHandler; MAX_REGISTER_COUNT] = unsafe { mem::zeroed() };
+        let mut handlers: [MaybeUninit<ExceptionHandler>; MAX_REGISTER_COUNT] =
+            MaybeUninit::uninit_array();
+
+        // let mut handlers: [ExceptionHandler; MAX_REGISTER_COUNT] = unsafe { mem::zeroed() };
         let mut len = 0_usize;
         for (i, f) in list_guard.iter().enumerate().take(MAX_REGISTER_COUNT) {
-            handlers[i] = f;
+            handlers[i].write(f);
             len += 1;
         }
         (handlers, len)
@@ -245,7 +249,7 @@ extern "C" fn internal_handle(info: &mut ExceptionInfo) {
 
     let mut result = HandleResult::Search;
     for f in &handlers[..len] {
-        result = (*f)(info);
+        result = (unsafe { f.assume_init_ref() })(info);
         if result == HandleResult::Execution {
             break;
         }
diff --git a/sgx_trts/src/veh/list.rs b/sgx_trts/src/veh/list.rs
index ffbafeff..2cc2eb76 100644
--- a/sgx_trts/src/veh/list.rs
+++ b/sgx_trts/src/veh/list.rs
@@ -33,11 +33,11 @@
 // under the License..
 
 use crate::rand::Rng;
+use crate::sync::OnceCell;
 use crate::sync::SpinMutex;
 use crate::veh::{ExceptionHandler, Handle};
 use alloc::collections::linked_list::{Iter, LinkedList};
 use core::fmt;
-use core::lazy::OnceCell;
 use core::mem;
 use core::num::NonZeroUsize;
 
diff --git a/sgx_trts/src/xsave.rs b/sgx_trts/src/xsave.rs
index 1e4adb58..6dd6d597 100644
--- a/sgx_trts/src/xsave.rs
+++ b/sgx_trts/src/xsave.rs
@@ -34,11 +34,7 @@ pub fn get_xfrm() -> u64 {
         }
     }
 
-    let enbaled = if xfrm == types::XFRM_LEGACY {
-        0_i32
-    } else {
-        1_i32
-    };
+    let enbaled = i32::from(xfrm != types::XFRM_LEGACY);
     unsafe {
         set_xsave_enabled(enbaled);
     }
diff --git a/sgx_tse/src/capi.rs b/sgx_tse/src/capi.rs
index 62593699..617a731f 100644
--- a/sgx_tse/src/capi.rs
+++ b/sgx_tse/src/capi.rs
@@ -52,7 +52,7 @@ pub unsafe extern "C" fn sgx_verify_report(report: *const Report) -> SgxStatus {
         return SgxStatus::InvalidParameter;
     }
 
-    match (&*report).verify() {
+    match (*report).verify() {
         Ok(_) => SgxStatus::Success,
         Err(e) => e,
     }
@@ -84,7 +84,7 @@ pub unsafe extern "C" fn sgx_get_key(
         return SgxStatus::InvalidParameter;
     }
 
-    match (&*key_request).get_key() {
+    match (*key_request).get_key() {
         Ok(k) => {
             *key = k;
             SgxStatus::Success
@@ -100,7 +100,7 @@ pub unsafe extern "C" fn sgx_verify_report2(report_mac: *const Report2Mac) -> Sg
         return SgxStatus::InvalidParameter;
     }
 
-    match (&*report_mac).verify() {
+    match (*report_mac).verify() {
         Ok(_) => SgxStatus::Success,
         Err(e) => e,
     }
diff --git a/sgx_tse/src/se.rs b/sgx_tse/src/se.rs
index f92f2034..af55bb10 100644
--- a/sgx_tse/src/se.rs
+++ b/sgx_tse/src/se.rs
@@ -188,7 +188,7 @@ impl LAv2ProtoSpec {
 
         let mut to = 0_i32;
         for i in 1..(self.ts_count() + 1) as usize {
-            let size = (1 << (self.target_spec[i] & 0xF)) as i32;
+            let size = 1 << (self.target_spec[i] & 0xF);
             to += size - 1;
             to &= -size;
 
diff --git a/sgx_tstd/src/alloc.rs b/sgx_tstd/src/alloc.rs
index c07dea5a..6d6569d0 100644
--- a/sgx_tstd/src/alloc.rs
+++ b/sgx_tstd/src/alloc.rs
@@ -59,8 +59,6 @@
 //! [`GlobalAlloc`] trait. This type can be provided by an external library:
 //!
 //! ```rust,ignore (demonstrates crates.io usage)
-//! extern crate jemallocator;
-//!
 //! use jemallocator::Jemalloc;
 //!
 //! #[global_allocator]
@@ -93,6 +91,20 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
 /// about the allocation that failed.
 ///
 /// The allocation error hook is a global resource.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(alloc_error_hook)]
+///
+/// use std::alloc::{Layout, set_alloc_error_hook};
+///
+/// fn custom_alloc_error_hook(layout: Layout) {
+///    panic!("memory allocation of {} bytes failed", layout.size());
+/// }
+///
+/// set_alloc_error_hook(custom_alloc_error_hook);
+/// ```
 pub fn set_alloc_error_hook(hook: fn(Layout)) {
     HOOK.store(hook as *mut (), Ordering::SeqCst);
 }
@@ -108,7 +120,18 @@ pub fn take_alloc_error_hook() -> fn(Layout) {
 }
 
 fn default_alloc_error_hook(layout: Layout) {
-    rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
+    extern "Rust" {
+        // This symbol is emitted by rustc next to __rust_alloc_error_handler.
+        // Its value depends on the -Zoom={panic,abort} compiler option.
+        static __rust_alloc_error_handler_should_panic: u8;
+    }
+
+    #[allow(unused_unsafe)]
+    if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
+        panic!("memory allocation of {} bytes failed\n", layout.size());
+    } else {
+        rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
+    }
 }
 
 #[doc(hidden)]
diff --git a/sgx_tstd/src/backtrace.rs b/sgx_tstd/src/backtrace.rs
index 12e65edf..5f6266d6 100644
--- a/sgx_tstd/src/backtrace.rs
+++ b/sgx_tstd/src/backtrace.rs
@@ -26,19 +26,13 @@
 //! implementing `std::error::Error`) to get a causal chain of where an error
 //! was generated.
 //!
-//! > **Note**: this module is unstable and is designed in [RFC 2504], and you
-//! > can learn more about its status in the [tracking issue].
-//!
-//! [RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
-//! [tracking issue]: https://github.com/rust-lang/rust/issues/53487
-//!
 //! ## Accuracy
 //!
 //! Backtraces are attempted to be as accurate as possible, but no guarantees
 //! are provided about the exact accuracy of a backtrace. Instruction pointers,
 //! symbol names, filenames, line numbers, etc, may all be incorrect when
-//! reported. Accuracy is attempted on a best-effort basis, however, and bugs
-//! are always welcome to indicate areas of improvement!
+//! reported. Accuracy is attempted on a best-effort basis, however, any bug
+//! reports are always welcome to indicate areas of improvement!
 //!
 //! For most platforms a backtrace with a filename/line number requires that
 //! programs be compiled with debug information. Without debug information
@@ -303,7 +297,7 @@ impl Backtrace {
     // `ip`
     fn create(ip: usize) -> Backtrace {
         // SAFETY: We don't attempt to lock this reentrantly.
-        let _lock = unsafe { lock() };
+        let _lock = lock();
         let mut frames = Vec::new();
         let mut actual_start = None;
         unsafe {
@@ -444,8 +438,7 @@ impl Capture {
         // Use the global backtrace lock to synchronize this as it's a
         // requirement of the `backtrace` crate, and then actually resolve
         // everything.
-        // SAFETY: We don't attempt to lock this reentrantly.
-        let _lock = unsafe { lock() };
+        let _lock = lock();
         for frame in self.frames.iter_mut() {
             let symbols = &mut frame.symbols;
             let frame = match &frame.frame {
diff --git a/sgx_tstd/src/backtrace/tests.rs b/sgx_tstd/src/backtrace/tests.rs
index 07f67657..cc8dc5f6 100644
--- a/sgx_tstd/src/backtrace/tests.rs
+++ b/sgx_tstd/src/backtrace/tests.rs
@@ -76,10 +76,10 @@ fn test_debug() {
     \n    { fn: \"std::rt::lang_start\", file: \"rust/rt.rs\", line: 400 },\
     \n]";
 
-    assert_eq!(format!("{:#?}", backtrace), expected);
+    assert_eq!(format!("{backtrace:#?}"), expected);
 
     // Format the backtrace a second time, just to make sure lazily resolved state is stable
-    assert_eq!(format!("{:#?}", backtrace), expected);
+    assert_eq!(format!("{backtrace:#?}"), expected);
 }
 
 #[test_case]
@@ -110,5 +110,5 @@ fn test_frames() {
 
     let mut iter = frames.iter().zip(expected.iter());
 
-    assert!(iter.all(|(f, e)| format!("{:#?}", f) == *e));
+    assert!(iter.all(|(f, e)| format!("{f:#?}") == *e));
 }
diff --git a/sgx_tstd/src/collections/hash/benches/map.rs b/sgx_tstd/src/collections/hash/benches/map.rs
index 79fe4e31..932c3686 100644
--- a/sgx_tstd/src/collections/hash/benches/map.rs
+++ b/sgx_tstd/src/collections/hash/benches/map.rs
@@ -60,12 +60,10 @@ fn find_existing(b: &mut Bencher) {
         m.insert(i, i);
     }
 
-    let mut k = 1;
     b.iter(|| {
         for i in 1..1001 {
             m.contains_key(&i);
         }
-        k += 1;
     });
 }
 
diff --git a/sgx_tstd/src/collections/hash/map.rs b/sgx_tstd/src/collections/hash/map.rs
index 3eb7f883..3f7580f9 100644
--- a/sgx_tstd/src/collections/hash/map.rs
+++ b/sgx_tstd/src/collections/hash/map.rs
@@ -26,10 +26,11 @@ use crate::borrow::Borrow;
 use crate::cell::Cell;
 use crate::collections::TryReserveError;
 use crate::collections::TryReserveErrorKind;
+use crate::error::Error;
 use crate::fmt::{self, Debug};
 #[allow(deprecated)]
 use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13};
-use crate::iter::{FromIterator, FusedIterator};
+use crate::iter::FusedIterator;
 use crate::ops::Index;
 use crate::sys;
 
@@ -71,7 +72,8 @@ use crate::sys;
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
 /// The behavior resulting from such a logic error is not specified, but will
-/// not result in undefined behavior. This could include panics, incorrect results,
+/// be encapsulated to the `HashMap` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
 ///
 /// The hash table implementation is a Rust port of Google's [SwissTable].
@@ -126,8 +128,8 @@ use crate::sys;
 /// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
 /// for &book in &to_find {
 ///     match book_reviews.get(book) {
-///         Some(review) => println!("{}: {}", book, review),
-///         None => println!("{} is unreviewed.", book)
+///         Some(review) => println!("{book}: {review}"),
+///         None => println!("{book} is unreviewed.")
 ///     }
 /// }
 ///
@@ -136,7 +138,7 @@ use crate::sys;
 ///
 /// // Iterate over everything.
 /// for (book, review) in &book_reviews {
-///     println!("{}: \"{}\"", book, review);
+///     println!("{book}: \"{review}\"");
 /// }
 /// ```
 ///
@@ -153,7 +155,7 @@ use crate::sys;
 /// ]);
 /// ```
 ///
-/// `HashMap` implements an [`Entry API`](#method.entry), which allows
+/// `HashMap` implements an [`Entry` API](#method.entry), which allows
 /// for complex methods of getting, setting, updating and removing keys and
 /// their values:
 ///
@@ -180,6 +182,9 @@ use crate::sys;
 /// // update a key, guarding against the key possibly not being set
 /// let stat = player_stats.entry("attack").or_insert(100);
 /// *stat += random_stat_buff();
+///
+/// // modify an entry before an insert with in-place mutation
+/// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100);
 /// ```
 ///
 /// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`].
@@ -216,7 +221,7 @@ use crate::sys;
 ///
 /// // Use derived implementation to print the status of the vikings.
 /// for (viking, health) in &vikings {
-///     println!("{:?} has {} hp", viking, health);
+///     println!("{viking:?} has {health} hp");
 /// }
 /// ```
 
@@ -244,10 +249,11 @@ impl<K, V> HashMap<K, V, RandomState> {
         Default::default()
     }
 
-    /// Creates an empty `HashMap` with the specified capacity.
+    /// Creates an empty `HashMap` with at least the specified capacity.
     ///
     /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
     ///
     /// # Examples
     ///
@@ -287,22 +293,23 @@ impl<K, V, S> HashMap<K, V, S> {
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
+    pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap { base: base::HashMap::with_hasher(hash_builder) }
     }
 
-    /// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
-    /// to hash the keys.
+    /// Creates an empty `HashMap` with at least the specified capacity, using
+    /// `hasher` to hash the keys.
     ///
     /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash map will not allocate.
     ///
-    /// Warning: `hash_builder` is normally randomly generated, and
+    /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow HashMaps to be resistant to attacks that
     /// cause many collisions and very poor performance. Setting it
     /// manually using this function can expose a DoS attack vector.
     ///
-    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
+    /// The `hasher` passed should implement the [`BuildHasher`] trait for
     /// the HashMap to be useful, see its documentation for details.
     ///
     /// # Examples
@@ -316,8 +323,8 @@ impl<K, V, S> HashMap<K, V, S> {
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
-        HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
+    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashMap<K, V, S> {
+        HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hasher) }
     }
 
     /// Returns the number of elements the map can hold without reallocating.
@@ -352,9 +359,14 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ]);
     ///
     /// for key in map.keys() {
-    ///     println!("{}", key);
+    ///     println!("{key}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over keys takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     pub fn keys(&self) -> Keys<'_, K, V> {
         Keys { inner: self.iter() }
     }
@@ -380,8 +392,13 @@ impl<K, V, S> HashMap<K, V, S> {
     /// vec.sort_unstable();
     /// assert_eq!(vec, ["a", "b", "c"]);
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over keys takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn into_keys(self) -> IntoKeys<K, V> {
         IntoKeys { inner: self.into_iter() }
     }
@@ -401,9 +418,14 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ]);
     ///
     /// for val in map.values() {
-    ///     println!("{}", val);
+    ///     println!("{val}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over values takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     pub fn values(&self) -> Values<'_, K, V> {
         Values { inner: self.iter() }
     }
@@ -427,9 +449,14 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     ///
     /// for val in map.values() {
-    ///     println!("{}", val);
+    ///     println!("{val}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over values takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
         ValuesMut { inner: self.iter_mut() }
     }
@@ -455,8 +482,13 @@ impl<K, V, S> HashMap<K, V, S> {
     /// vec.sort_unstable();
     /// assert_eq!(vec, [1, 2, 3]);
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over values takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn into_values(self) -> IntoValues<K, V> {
         IntoValues { inner: self.into_iter() }
     }
@@ -476,10 +508,15 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ]);
     ///
     /// for (key, val) in map.iter() {
-    ///     println!("key: {} val: {}", key, val);
+    ///     println!("key: {key} val: {val}");
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over map takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
+    #[rustc_lint_query_instability]
     pub fn iter(&self) -> Iter<'_, K, V> {
         Iter { base: self.base.iter() }
     }
@@ -505,10 +542,15 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     ///
     /// for (key, val) in &map {
-    ///     println!("key: {} val: {}", key, val);
+    ///     println!("key: {key} val: {val}");
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over map takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
+    #[rustc_lint_query_instability]
     pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
         IterMut { base: self.base.iter_mut() }
     }
@@ -551,7 +593,7 @@ impl<K, V, S> HashMap<K, V, S> {
     ///
     /// If the returned iterator is dropped before being fully consumed, it
     /// drops the remaining key-value pairs. The returned iterator keeps a
-    /// mutable borrow on the vector to optimize its implementation.
+    /// mutable borrow on the map to optimize its implementation.
     ///
     /// # Examples
     ///
@@ -570,7 +612,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert!(a.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain(&mut self) -> Drain<'_, K, V> {
         Drain { base: self.base.drain() }
     }
@@ -611,7 +653,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
     where
         F: FnMut(&K, &mut V) -> bool,
@@ -621,7 +663,7 @@ impl<K, V, S> HashMap<K, V, S> {
 
     /// Retains only the elements specified by the predicate.
     ///
-    /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
+    /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)` returns `false`.
     /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
@@ -633,8 +675,13 @@ impl<K, V, S> HashMap<K, V, S> {
     /// map.retain(|&k, _| k % 2 == 0);
     /// assert_eq!(map.len(), 4);
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, this operation takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn retain<F>(&mut self, f: F)
     where
         F: FnMut(&K, &mut V) -> bool,
@@ -684,8 +731,10 @@ where
     S: BuildHasher,
 {
     /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashMap`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashMap`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Panics
     ///
@@ -704,8 +753,11 @@ where
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashMap<K, V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashMap`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional` if
+    /// it returns `Ok(())`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Errors
     ///
@@ -718,7 +770,7 @@ where
     /// use std::collections::HashMap;
     ///
     /// let mut map: HashMap<&str, isize> = HashMap::new();
-    /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
+    /// map.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?");
     /// ```
     #[inline]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
@@ -781,8 +833,7 @@ where
     /// let mut letters = HashMap::new();
     ///
     /// for ch in "a short treatise on fungi".chars() {
-    ///     let counter = letters.entry(ch).or_insert(0);
-    ///     *counter += 1;
+    ///     letters.entry(ch).and_modify(|counter| *counter += 1).or_insert(1);
     /// }
     ///
     /// assert_eq!(letters[&'s'], 2);
@@ -845,6 +896,117 @@ where
         self.base.get_key_value(k)
     }
 
+    /// Attempts to get mutable references to `N` values in the map at once.
+    ///
+    /// Returns an array of length `N` with the results of each query. For soundness, at most one
+    /// mutable reference will be returned to any value. `None` will be returned if any of the
+    /// keys are duplicates or missing.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_many_mut)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut libraries = HashMap::new();
+    /// libraries.insert("Bodleian Library".to_string(), 1602);
+    /// libraries.insert("Athenæum".to_string(), 1807);
+    /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
+    /// libraries.insert("Library of Congress".to_string(), 1800);
+    ///
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Library of Congress",
+    /// ]);
+    /// assert_eq!(
+    ///     got,
+    ///     Some([
+    ///         &mut 1807,
+    ///         &mut 1800,
+    ///     ]),
+    /// );
+    ///
+    /// // Missing keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "New York Public Library",
+    /// ]);
+    /// assert_eq!(got, None);
+    ///
+    /// // Duplicate keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Athenæum",
+    /// ]);
+    /// assert_eq!(got, None);
+    /// ```
+    #[inline]
+    pub fn get_many_mut<Q: ?Sized, const N: usize>(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get_many_mut(ks)
+    }
+
+    /// Attempts to get mutable references to `N` values in the map at once, without validating that
+    /// the values are unique.
+    ///
+    /// Returns an array of length `N` with the results of each query. `None` will be returned if
+    /// any of the keys are missing.
+    ///
+    /// For a safe alternative see [`get_many_mut`](Self::get_many_mut).
+    ///
+    /// # Safety
+    ///
+    /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
+    /// references are not used.
+    ///
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_many_mut)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut libraries = HashMap::new();
+    /// libraries.insert("Bodleian Library".to_string(), 1602);
+    /// libraries.insert("Athenæum".to_string(), 1807);
+    /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
+    /// libraries.insert("Library of Congress".to_string(), 1800);
+    ///
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Library of Congress",
+    /// ]);
+    /// assert_eq!(
+    ///     got,
+    ///     Some([
+    ///         &mut 1807,
+    ///         &mut 1800,
+    ///     ]),
+    /// );
+    ///
+    /// // Missing keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "New York Public Library",
+    /// ]);
+    /// assert_eq!(got, None);
+    /// ```
+    #[inline]
+    pub unsafe fn get_many_unchecked_mut<Q: ?Sized, const N: usize>(
+        &mut self,
+        ks: [&Q; N],
+    ) -> Option<[&'_ mut V; N]>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get_many_unchecked_mut(ks)
+    }
+
     /// Returns `true` if the map contains a value for the specified key.
     ///
     /// The key may be any borrowed form of the map's key type, but
@@ -1910,6 +2072,13 @@ impl<'a, K: Debug, V: Debug> fmt::Display for OccupiedError<'a, K, V> {
     }
 }
 
+impl<'a, K: fmt::Debug, V: fmt::Debug> Error for OccupiedError<'a, K, V> {
+    #[allow(deprecated)]
+    fn description(&self) -> &str {
+        "key already exists"
+    }
+}
+
 impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
     type Item = (&'a K, &'a V);
     type IntoIter = Iter<'a, K, V>;
@@ -1953,7 +2122,7 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S> {
     /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> IntoIter<K, V> {
         IntoIter { base: self.base.into_iter() }
     }
@@ -2692,6 +2861,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(entry_insert)]
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::Entry;
     ///
@@ -2849,6 +3019,7 @@ impl DefaultHasher {
     /// This hasher is not guaranteed to be the same as all other
     /// `DefaultHasher` instances, but is the same as all other `DefaultHasher`
     /// instances created through `new` or `default`.
+    #[inline]
     #[allow(deprecated)]
     #[must_use]
     pub fn new() -> DefaultHasher {
@@ -2861,17 +3032,26 @@ impl Default for DefaultHasher {
     /// See its documentation for more.
     ///
     /// [`new`]: DefaultHasher::new
+    #[inline]
     fn default() -> DefaultHasher {
         DefaultHasher::new()
     }
 }
 
 impl Hasher for DefaultHasher {
+    // The underlying `SipHasher13` doesn't override the other
+    // `write_*` methods, so it's ok not to forward them here.
+
     #[inline]
     fn write(&mut self, msg: &[u8]) {
         self.0.write(msg)
     }
 
+    #[inline]
+    fn write_str(&mut self, s: &str) {
+        self.0.write_str(s);
+    }
+
     #[inline]
     fn finish(&self) -> u64 {
         self.0.finish()
diff --git a/sgx_tstd/src/collections/hash/map/tests.rs b/sgx_tstd/src/collections/hash/map/tests.rs
index 105c3947..f2f0d5e8 100644
--- a/sgx_tstd/src/collections/hash/map/tests.rs
+++ b/sgx_tstd/src/collections/hash/map/tests.rs
@@ -286,10 +286,13 @@ fn test_lots_of_insertions() {
 
     // Try this a few times to make sure we never screw up the hashmap's
     // internal state.
-    for _ in 0..10 {
+    let loops = 10;
+    for _ in 0..loops {
         assert!(m.is_empty());
 
-        for i in 1..1001 {
+        let count = 1001;
+
+        for i in 1..count {
             assert!(m.insert(i, i).is_none());
 
             for j in 1..=i {
@@ -297,42 +300,42 @@ fn test_lots_of_insertions() {
                 assert_eq!(r, Some(&j));
             }
 
-            for j in i + 1..1001 {
+            for j in i + 1..count {
                 let r = m.get(&j);
                 assert_eq!(r, None);
             }
         }
 
-        for i in 1001..2001 {
+        for i in count..(2 * count) {
             assert!(!m.contains_key(&i));
         }
 
         // remove forwards
-        for i in 1..1001 {
+        for i in 1..count {
             assert!(m.remove(&i).is_some());
 
             for j in 1..=i {
                 assert!(!m.contains_key(&j));
             }
 
-            for j in i + 1..1001 {
+            for j in i + 1..count {
                 assert!(m.contains_key(&j));
             }
         }
 
-        for i in 1..1001 {
+        for i in 1..count {
             assert!(!m.contains_key(&i));
         }
 
-        for i in 1..1001 {
+        for i in 1..count {
             assert!(m.insert(i, i).is_none());
         }
 
         // remove backwards
-        for i in (1..1001).rev() {
+        for i in (1..count).rev() {
             assert!(m.remove(&i).is_some());
 
-            for j in i..1001 {
+            for j in i..count {
                 assert!(!m.contains_key(&j));
             }
 
@@ -534,10 +537,10 @@ fn test_show() {
     map.insert(1, 2);
     map.insert(3, 4);
 
-    let map_str = format!("{:?}", map);
+    let map_str = format!("{map:?}");
 
     assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
-    assert_eq!(format!("{:?}", empty), "{}");
+    assert_eq!(format!("{empty:?}"), "{}");
 }
 
 #[test_case]
@@ -1098,3 +1101,9 @@ fn from_array() {
     // that's a problem!
     let _must_not_require_type_annotation = HashMap::from([(1, 2)]);
 }
+
+#[test_case]
+fn const_with_hasher() {
+    const X: HashMap<(), (), ()> = HashMap::with_hasher(());
+    assert_eq!(X.len(), 0);
+}
diff --git a/sgx_tstd/src/collections/hash/set.rs b/sgx_tstd/src/collections/hash/set.rs
index f31c6963..05fac8a1 100644
--- a/sgx_tstd/src/collections/hash/set.rs
+++ b/sgx_tstd/src/collections/hash/set.rs
@@ -24,7 +24,7 @@ use crate::borrow::Borrow;
 use crate::collections::TryReserveError;
 use crate::fmt;
 use crate::hash::{BuildHasher, Hash};
-use crate::iter::{Chain, FromIterator, FusedIterator};
+use crate::iter::{Chain, FusedIterator};
 use crate::ops::{BitAnd, BitOr, BitXor, Sub};
 
 use super::map::{map_try_reserve_error, RandomState};
@@ -50,13 +50,14 @@ use super::map::{map_try_reserve_error, RandomState};
 /// In other words, if two keys are equal, their hashes must be equal.
 ///
 ///
-/// It is a logic error for an item to be modified in such a way that the
-/// item's hash, as determined by the [`Hash`] trait, or its equality, as
-/// determined by the [`Eq`] trait, changes while it is in the set. This is
-/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
-/// unsafe code. The behavior resulting from such a logic error is not
-/// specified (it could include panics, incorrect results, aborts, memory
-/// leaks, or non-termination) but will not be undefined behavior.
+/// It is a logic error for a key to be modified in such a way that the key's
+/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
+/// the [`Eq`] trait, changes while it is in the map. This is normally only
+/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will
+/// be encapsulated to the `HashSet` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
+/// aborts, memory leaks, and non-termination.
 ///
 /// # Examples
 ///
@@ -83,7 +84,7 @@ use super::map::{map_try_reserve_error, RandomState};
 ///
 /// // Iterate over everything.
 /// for book in &books {
-///     println!("{}", book);
+///     println!("{book}");
 /// }
 /// ```
 ///
@@ -108,7 +109,7 @@ use super::map::{map_try_reserve_error, RandomState};
 ///
 /// // Use derived implementation to print the vikings.
 /// for x in &vikings {
-///     println!("{:?}", x);
+///     println!("{x:?}");
 /// }
 /// ```
 ///
@@ -147,10 +148,11 @@ impl<T> HashSet<T, RandomState> {
         Default::default()
     }
 
-    /// Creates an empty `HashSet` with the specified capacity.
+    /// Creates an empty `HashSet` with at least the specified capacity.
     ///
     /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
     ///
     /// # Examples
     ///
@@ -194,11 +196,16 @@ impl<T, S> HashSet<T, S> {
     ///
     /// // Will print in an arbitrary order.
     /// for x in set.iter() {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over set takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { base: self.base.iter() }
     }
@@ -242,7 +249,7 @@ impl<T, S> HashSet<T, S> {
     ///
     /// If the returned iterator is dropped before being fully consumed, it
     /// drops the remaining elements. The returned iterator keeps a mutable
-    /// borrow on the vector to optimize its implementation.
+    /// borrow on the set to optimize its implementation.
     ///
     /// # Examples
     ///
@@ -254,13 +261,13 @@ impl<T, S> HashSet<T, S> {
     ///
     /// // print 1, 2, 3 in an arbitrary order
     /// for i in set.drain() {
-    ///     println!("{}", i);
+    ///     println!("{i}");
     /// }
     ///
     /// assert!(set.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain(&mut self) -> Drain<'_, T> {
         Drain { base: self.base.drain() }
     }
@@ -298,7 +305,7 @@ impl<T, S> HashSet<T, S> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F>
     where
         F: FnMut(&T) -> bool,
@@ -308,7 +315,7 @@ impl<T, S> HashSet<T, S> {
 
     /// Retains only the elements specified by the predicate.
     ///
-    /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+    /// In other words, remove all elements `e` for which `f(&e)` returns `false`.
     /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
@@ -320,7 +327,12 @@ impl<T, S> HashSet<T, S> {
     /// set.retain(|&k| k % 2 == 0);
     /// assert_eq!(set.len(), 3);
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, this operation takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
+    #[rustc_lint_query_instability]
     pub fn retain<F>(&mut self, f: F)
     where
         F: FnMut(&T) -> bool,
@@ -369,15 +381,16 @@ impl<T, S> HashSet<T, S> {
     /// set.insert(2);
     /// ```
     #[inline]
-    pub fn with_hasher(hasher: S) -> HashSet<T, S> {
+    pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
         HashSet { base: base::HashSet::with_hasher(hasher) }
     }
 
-    /// Creates an empty `HashSet` with the specified capacity, using
+    /// Creates an empty `HashSet` with at least the specified capacity, using
     /// `hasher` to hash the keys.
     ///
     /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
     ///
     /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow `HashSet`s to be resistant to attacks that
@@ -426,8 +439,10 @@ where
     S: BuildHasher,
 {
     /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashSet`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashSet`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Panics
     ///
@@ -447,8 +462,11 @@ where
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashSet<K, V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashSet`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional` if
+    /// it returns `Ok(())`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Errors
     ///
@@ -460,7 +478,7 @@ where
     /// ```
     /// use std::collections::HashSet;
     /// let mut set: HashSet<i32> = HashSet::new();
-    /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
+    /// set.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?");
     /// ```
     #[inline]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
@@ -524,7 +542,7 @@ where
     ///
     /// // Can be seen as `a - b`.
     /// for x in a.difference(&b) {
-    ///     println!("{}", x); // Print 1
+    ///     println!("{x}"); // Print 1
     /// }
     ///
     /// let diff: HashSet<_> = a.difference(&b).collect();
@@ -536,7 +554,7 @@ where
     /// assert_eq!(diff, [4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference { iter: self.iter(), other }
     }
@@ -553,7 +571,7 @@ where
     ///
     /// // Print 1, 4 in arbitrary order.
     /// for x in a.symmetric_difference(&b) {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     ///
     /// let diff1: HashSet<_> = a.symmetric_difference(&b).collect();
@@ -563,7 +581,7 @@ where
     /// assert_eq!(diff1, [1, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn symmetric_difference<'a>(
         &'a self,
         other: &'a HashSet<T, S>,
@@ -574,6 +592,12 @@ where
     /// Visits the values representing the intersection,
     /// i.e., the values that are both in `self` and `other`.
     ///
+    /// When an equal element is present in `self` and `other`
+    /// then the resulting `Intersection` may yield references to
+    /// one or the other. This can be relevant if `T` contains fields which
+    /// are not compared by its `Eq` implementation, and may hold different
+    /// value between the two equal copies of `T` in the two sets.
+    ///
     /// # Examples
     ///
     /// ```
@@ -583,14 +607,14 @@ where
     ///
     /// // Print 2, 3 in arbitrary order.
     /// for x in a.intersection(&b) {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     ///
     /// let intersection: HashSet<_> = a.intersection(&b).collect();
     /// assert_eq!(intersection, [2, 3].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         if self.len() <= other.len() {
             Intersection { iter: self.iter(), other }
@@ -611,14 +635,14 @@ where
     ///
     /// // Print 1, 2, 3, 4 in arbitrary order.
     /// for x in a.union(&b) {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     ///
     /// let union: HashSet<_> = a.union(&b).collect();
     /// assert_eq!(union, [1, 2, 3, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
         if self.len() >= other.len() {
             Union { iter: self.iter().chain(other.difference(self)) }
@@ -834,9 +858,10 @@ where
 
     /// Adds a value to the set.
     ///
-    /// If the set did not have this value present, `true` is returned.
+    /// Returns whether the value was newly inserted. That is:
     ///
-    /// If the set did have this value present, `false` is returned.
+    /// - If the set did not previously contain this value, `true` is returned.
+    /// - If the set already contained this value, `false` is returned.
     ///
     /// # Examples
     ///
@@ -1384,7 +1409,7 @@ impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
     type IntoIter = Iter<'a, T>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> Iter<'a, T> {
         self.iter()
     }
@@ -1411,11 +1436,11 @@ impl<T, S> IntoIterator for HashSet<T, S> {
     ///
     /// // Will print in an arbitrary order.
     /// for x in &v {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { base: self.base.into_iter() }
     }
diff --git a/sgx_tstd/src/collections/hash/set/tests.rs b/sgx_tstd/src/collections/hash/set/tests.rs
index 89dad83a..352143fa 100644
--- a/sgx_tstd/src/collections/hash/set/tests.rs
+++ b/sgx_tstd/src/collections/hash/set/tests.rs
@@ -320,10 +320,10 @@ fn test_show() {
     set.insert(1);
     set.insert(2);
 
-    let set_str = format!("{:?}", set);
+    let set_str = format!("{set:?}");
 
     assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
-    assert_eq!(format!("{:?}", empty), "{}");
+    assert_eq!(format!("{empty:?}"), "{}");
 }
 
 #[test_case]
@@ -516,3 +516,9 @@ fn from_array() {
     // that's a problem!
     let _must_not_require_type_annotation = HashSet::from([1, 2]);
 }
+
+#[test_case]
+fn const_with_hasher() {
+    const X: HashSet<(), ()> = HashSet::with_hasher(());
+    assert_eq!(X.len(), 0);
+}
diff --git a/sgx_tstd/src/collections/mod.rs b/sgx_tstd/src/collections/mod.rs
index 5b2dcbd1..4b8c5a14 100644
--- a/sgx_tstd/src/collections/mod.rs
+++ b/sgx_tstd/src/collections/mod.rs
@@ -216,7 +216,7 @@
 //! ```
 //! let vec = vec![1, 2, 3, 4];
 //! for x in vec.iter() {
-//!    println!("vec contained {}", x);
+//!    println!("vec contained {x:?}");
 //! }
 //! ```
 //!
@@ -263,7 +263,7 @@
 //! ```
 //! let vec = vec![1, 2, 3, 4];
 //! for x in vec.iter().rev() {
-//!    println!("vec contained {}", x);
+//!    println!("vec contained {x:?}");
 //! }
 //! ```
 //!
@@ -323,7 +323,7 @@
 //!
 //! println!("Number of occurrences of each character");
 //! for (char, count) in &count {
-//!     println!("{}: {}", char, count);
+//!     println!("{char}: {count}");
 //! }
 //! ```
 //!
@@ -356,7 +356,7 @@
 //!     // Check if they're sober enough to have another beer.
 //!     if person.blood_alcohol > 0.3 {
 //!         // Too drunk... for now.
-//!         println!("Sorry {}, I have to cut you off", id);
+//!         println!("Sorry {id}, I have to cut you off");
 //!     } else {
 //!         // Have another!
 //!         person.blood_alcohol += 0.1;
@@ -415,6 +415,7 @@
 //!
 //! [IntoIterator]: crate::iter::IntoIterator "iter::IntoIterator"
 
+#[doc(hidden)]
 pub use crate::ops::Bound;
 pub use alloc_crate::collections::{binary_heap, btree_map, btree_set};
 pub use alloc_crate::collections::{linked_list, vec_deque};
diff --git a/sgx_tstd/src/env.rs b/sgx_tstd/src/env.rs
index 9a4b3da0..46de970c 100644
--- a/sgx_tstd/src/env.rs
+++ b/sgx_tstd/src/env.rs
@@ -45,9 +45,11 @@ use crate::sys::os as os_imp;
 ///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to the `getcwd` function on Unix
+/// This function [currently] corresponds to the `getcwd` function on Unix
 /// and the `GetCurrentDirectoryW` function on Windows.
 ///
+/// [currently]: crate::io#platform-specific-behavior
+///
 /// # Errors
 ///
 /// Returns an [`Err`] if the current working directory value is invalid.
@@ -76,11 +78,13 @@ pub fn current_dir() -> io::Result<PathBuf> {
 ///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to the `chdir` function on Unix
+/// This function [currently] corresponds to the `chdir` function on Unix
 /// and the `SetCurrentDirectoryW` function on Windows.
 ///
 /// Returns an [`Err`] if the operation fails.
 ///
+/// [currently]: crate::io#platform-specific-behavior
+///
 /// # Examples
 ///
 /// ```
@@ -135,7 +139,7 @@ pub struct VarsOs {
 /// // We will iterate through the references to the element returned by
 /// // env::vars();
 /// for (key, value) in env::vars() {
-///     println!("{}: {}", key, value);
+///     println!("{key}: {value}");
 /// }
 /// ```
 ///
@@ -164,7 +168,7 @@ pub fn vars() -> Vars {
 /// // We will iterate through the references to the element returned by
 /// // env::vars_os();
 /// for (key, value) in env::vars_os() {
-///     println!("{:?}: {:?}", key, value);
+///     println!("{key:?}: {value:?}");
 /// }
 /// ```
 #[must_use]
@@ -223,8 +227,8 @@ impl fmt::Debug for VarsOs {
 ///
 /// let key = "HOME";
 /// match env::var(key) {
-///     Ok(val) => println!("{}: {:?}", key, val),
-///     Err(e) => println!("couldn't interpret {}: {}", key, e),
+///     Ok(val) => println!("{key}: {val:?}"),
+///     Err(e) => println!("couldn't interpret {key}: {e}"),
 /// }
 /// ```
 pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> {
@@ -262,8 +266,8 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 ///
 /// let key = "HOME";
 /// match env::var_os(key) {
-///     Some(val) => println!("{}: {:?}", key, val),
-///     None => println!("{} is not defined in the environment.", key)
+///     Some(val) => println!("{key}: {val:?}"),
+///     None => println!("{key} is not defined in the environment.")
 /// }
 /// ```
 #[must_use]
@@ -273,7 +277,7 @@ pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
 
 fn _var_os(key: &OsStr) -> Option<OsString> {
     os_imp::getenv(key)
-        .unwrap_or_else(|e| panic!("failed to get environment variable `{:?}`: {}", key, e))
+        .unwrap_or_else(|e| panic!("failed to get environment variable `{key:?}`: {e}"))
 }
 
 /// The error type for operations interacting with environment variables.
@@ -347,7 +351,7 @@ pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
 
 fn _set_var(key: &OsStr, value: &OsStr) {
     os_imp::setenv(key, value).unwrap_or_else(|e| {
-        panic!("failed to set environment variable `{:?}` to `{:?}`: {}", key, value, e)
+        panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
     })
 }
 
@@ -388,7 +392,7 @@ pub fn remove_var<K: AsRef<OsStr>>(key: K) {
 
 fn _remove_var(key: &OsStr) {
     os_imp::unsetenv(key)
-        .unwrap_or_else(|e| panic!("failed to remove environment variable `{:?}`: {}", key, e))
+        .unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}"))
 }
 
 /// An iterator that splits an environment variable into paths according to
@@ -423,7 +427,7 @@ pub struct SplitPaths<'a> {
 ///             println!("'{}'", path.display());
 ///         }
 ///     }
-///     None => println!("{} is not defined in the environment.", key)
+///     None => println!("{key} is not defined in the environment.")
 /// }
 /// ```
 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
@@ -585,7 +589,7 @@ pub fn home_dir() -> Option<PathBuf> {
 /// # Platform-specific behavior
 ///
 /// On Unix, returns the value of the `TMPDIR` environment variable if it is
-/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
+/// set, otherwise for non-Android it returns `/tmp`. On Android, since there
 /// is no global temporary folder (it is usually allocated per-app), it returns
 /// `/data/local/tmp`.
 /// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
@@ -628,36 +632,23 @@ pub fn temp_dir() -> PathBuf {
 ///
 /// # Security
 ///
-/// The output of this function should not be used in anything that might have
-/// security implications. For example:
+/// The output of this function should not be trusted for anything
+/// that might have security implications. Basically, if users can run
+/// the executable, they can change the output arbitrarily.
 ///
-/// ```
-/// fn main() {
-///     println!("{:?}", std::env::current_exe());
-/// }
-/// ```
+/// As an example, you can easily introduce a race condition. It goes
+/// like this:
 ///
-/// On Linux systems, if this is compiled as `foo`:
+/// 1. You get the path to the current executable using `current_exe()`, and
+///    store it in a variable.
+/// 2. Time passes. A malicious actor removes the current executable, and
+///    replaces it with a malicious one.
+/// 3. You then use the stored path to re-execute the current
+///    executable.
 ///
-/// ```bash
-/// $ rustc foo.rs
-/// $ ./foo
-/// Ok("/home/alex/foo")
-/// ```
-///
-/// And you make a hard link of the program:
-///
-/// ```bash
-/// $ ln foo bar
-/// ```
-///
-/// When you run it, you won’t get the path of the original executable, you’ll
-/// get the path of the hard link:
-///
-/// ```bash
-/// $ ./bar
-/// Ok("/home/alex/bar")
-/// ```
+/// You expected to safely execute the current executable, but you're
+/// instead executing something completely different. The code you
+/// just executed run with your privileges.
 ///
 /// This sort of behavior has been known to [lead to privilege escalation] when
 /// used incorrectly.
@@ -672,7 +663,7 @@ pub fn temp_dir() -> PathBuf {
 /// match env::current_exe() {
 ///     Ok(exe_path) => println!("Path of this executable is: {}",
 ///                              exe_path.display()),
-///     Err(e) => println!("failed to get current exe path: {}", e),
+///     Err(e) => println!("failed to get current exe path: {e}"),
 /// };
 /// ```
 #[cfg(feature = "env")]
@@ -741,7 +732,7 @@ pub struct ArgsOs {
 ///
 /// // Prints each argument on a separate line
 /// for argument in env::args() {
-///     println!("{}", argument);
+///     println!("{argument}");
 /// }
 /// ```
 pub fn args() -> Args {
@@ -775,7 +766,7 @@ pub fn args() -> Args {
 ///
 /// // Prints each argument on a separate line
 /// for argument in env::args_os() {
-///     println!("{:?}", argument);
+///     println!("{argument:?}");
 /// }
 /// ```
 pub fn args_os() -> ArgsOs {
diff --git a/sgx_tstd/src/error.rs b/sgx_tstd/src/error.rs
index da666a8f..ec182b39 100644
--- a/sgx_tstd/src/error.rs
+++ b/sgx_tstd/src/error.rs
@@ -20,152 +20,11 @@
 #[cfg(feature = "unit_test")]
 mod tests;
 
-// A note about crates and the facade:
-//
-// Originally, the `Error` trait was defined in libcore, and the impls
-// were scattered about. However, coherence objected to this
-// arrangement, because to create the blanket impls for `Box` required
-// knowing that `&str: !Error`, and we have no means to deal with that
-// sort of conflict just now. Therefore, for the time being, we have
-// moved the `Error` trait into libstd. As we evolve a sol'n to the
-// coherence challenge (e.g., specialization, neg impls, etc) we can
-// reconsider what crate these items belong in.
-
-use core::array;
-use core::convert::Infallible;
-
-use crate::alloc::{AllocError, LayoutError};
-use crate::any::TypeId;
 #[cfg(feature = "backtrace")]
 use crate::backtrace::Backtrace;
-use crate::borrow::Cow;
-use crate::cell;
-use crate::char;
-use crate::fmt::{self, Debug, Display};
-#[cfg(feature = "backtrace")]
-use crate::fmt::Write;
-use crate::mem::transmute;
-use crate::num;
-use crate::str;
-use crate::string;
-use crate::sync::Arc;
-use crate::sys;
-use crate::time;
-
-use sgx_oc::ocall::{self, OCallError};
-use sgx_types::error::SgxStatus;
-
-/// `Error` is a trait representing the basic expectations for error values,
-/// i.e., values of type `E` in [`Result<T, E>`].
-///
-/// Errors must describe themselves through the [`Display`] and [`Debug`]
-/// traits. Error messages are typically concise lowercase sentences without
-/// trailing punctuation:
-///
-/// ```
-/// let err = "NaN".parse::<u32>().unwrap_err();
-/// assert_eq!(err.to_string(), "invalid digit found in string");
-/// ```
-///
-/// Errors may provide cause chain information. [`Error::source()`] is generally
-/// used when errors cross "abstraction boundaries". If one module must report
-/// an error that is caused by an error from a lower-level module, it can allow
-/// accessing that error via [`Error::source()`]. This makes it possible for the
-/// high-level module to provide its own errors while also revealing some of the
-/// implementation for debugging via `source` chains.
-pub trait Error: Debug + Display {
-    /// The lower-level source of this error, if any.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    ///
-    /// #[derive(Debug)]
-    /// struct SuperError {
-    ///     source: SuperErrorSideKick,
-    /// }
-    ///
-    /// impl fmt::Display for SuperError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "SuperError is here!")
-    ///     }
-    /// }
-    ///
-    /// impl Error for SuperError {
-    ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
-    ///         Some(&self.source)
-    ///     }
-    /// }
-    ///
-    /// #[derive(Debug)]
-    /// struct SuperErrorSideKick;
-    ///
-    /// impl fmt::Display for SuperErrorSideKick {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "SuperErrorSideKick is here!")
-    ///     }
-    /// }
-    ///
-    /// impl Error for SuperErrorSideKick {}
-    ///
-    /// fn get_super_error() -> Result<(), SuperError> {
-    ///     Err(SuperError { source: SuperErrorSideKick })
-    /// }
-    ///
-    /// fn main() {
-    ///     match get_super_error() {
-    ///         Err(e) => {
-    ///             println!("Error: {}", e);
-    ///             println!("Caused by: {}", e.source().unwrap());
-    ///         }
-    ///         _ => println!("No error"),
-    ///     }
-    /// }
-    /// ```
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        None
-    }
+use crate::fmt::{self, Write};
 
-    /// Gets the `TypeId` of `self`.
-    #[doc(hidden)]
-    fn type_id(&self, _: private::Internal) -> TypeId
-    where
-        Self: 'static,
-    {
-        TypeId::of::<Self>()
-    }
-
-    /// Returns a stack backtrace, if available, of where this error occurred.
-    ///
-    /// This function allows inspecting the location, in code, of where an error
-    /// happened. The returned `Backtrace` contains information about the stack
-    /// trace of the OS thread of execution of where the error originated from.
-    ///
-    /// Note that not all errors contain a `Backtrace`. Also note that a
-    /// `Backtrace` may actually be empty. For more information consult the
-    /// `Backtrace` type itself.
-    #[cfg(feature = "backtrace")]
-    fn backtrace(&self) -> Option<&Backtrace> {
-        None
-    }
-
-    /// ```
-    /// if let Err(e) = "xc".parse::<u32>() {
-    ///     // Print `e` itself, no need for description().
-    ///     eprintln!("Error: {}", e);
-    /// }
-    /// ```
-    fn description(&self) -> &str {
-        "description() is deprecated; use Display"
-    }
-
-    #[allow(missing_docs)]
-    fn cause(&self) -> Option<&dyn Error> {
-        self.source()
-    }
-}
+pub use core::error::Error;
 
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
@@ -174,634 +33,12 @@ mod private {
     pub struct Internal;
 }
 
-impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
-    /// Converts a type of [`Error`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    /// use std::mem;
-    ///
-    /// #[derive(Debug)]
-    /// struct AnError;
-    ///
-    /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "An error")
-    ///     }
-    /// }
-    ///
-    /// impl Error for AnError {}
-    ///
-    /// let an_error = AnError;
-    /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<dyn Error>::from(an_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: E) -> Box<dyn Error + 'a> {
-        Box::new(err)
-    }
-}
-
-impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
-    /// dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    /// use std::mem;
-    ///
-    /// #[derive(Debug)]
-    /// struct AnError;
-    ///
-    /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "An error")
-    ///     }
-    /// }
-    ///
-    /// impl Error for AnError {}
-    ///
-    /// unsafe impl Send for AnError {}
-    ///
-    /// unsafe impl Sync for AnError {}
-    ///
-    /// let an_error = AnError;
-    /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
-        Box::new(err)
-    }
-}
-
-impl From<String> for Box<dyn Error + Send + Sync> {
-    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    #[inline]
-    fn from(err: String) -> Box<dyn Error + Send + Sync> {
-        struct StringError(String);
-
-        impl Error for StringError {
-            #[allow(deprecated)]
-            fn description(&self) -> &str {
-                &self.0
-            }
-        }
-
-        impl Display for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                Display::fmt(&self.0, f)
-            }
-        }
-
-        // Purposefully skip printing "StringError(..)"
-        impl Debug for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                Debug::fmt(&self.0, f)
-            }
-        }
-
-        Box::new(StringError(err))
-    }
-}
-
-impl From<String> for Box<dyn Error> {
-    /// Converts a [`String`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(str_err: String) -> Box<dyn Error> {
-        let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
-        let err2: Box<dyn Error> = err1;
-        err2
-    }
-}
-
-impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// [`str`]: prim@str
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    #[inline]
-    fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
-        From::from(String::from(err))
-    }
-}
-
-impl From<&str> for Box<dyn Error> {
-    /// Converts a [`str`] into a box of dyn [`Error`].
-    ///
-    /// [`str`]: prim@str
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: &str) -> Box<dyn Error> {
-        From::from(String::from(err))
-    }
-}
-
-impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    /// use std::borrow::Cow;
-    ///
-    /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
-        From::from(String::from(err))
-    }
-}
-
-impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    /// use std::borrow::Cow;
-    ///
-    /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: Cow<'a, str>) -> Box<dyn Error> {
-        From::from(String::from(err))
-    }
-}
-
-impl Error for ! {}
-
-impl Error for AllocError {}
-
-impl Error for LayoutError {}
-
-impl Error for str::ParseBoolError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "failed to parse bool"
-    }
-}
-
-impl Error for str::Utf8Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-8: corrupt contents"
-    }
-}
-
-impl Error for num::ParseIntError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for num::TryFromIntError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for array::TryFromSliceError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for num::ParseFloatError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for string::FromUtf8Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-8"
-    }
-}
-
-impl Error for string::FromUtf16Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-16"
-    }
-}
-
-impl Error for Infallible {
-    fn description(&self) -> &str {
-        match *self {}
-    }
-}
-
-impl Error for char::DecodeUtf16Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "unpaired surrogate found"
-    }
-}
-
-impl Error for char::TryFromCharError {}
-
-impl<'a, K: Debug + Ord, V: Debug> Error
-    for crate::collections::btree_map::OccupiedError<'a, K, V>
-{
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "key already exists"
-    }
-}
-
-impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "key already exists"
-    }
-}
-
-impl Error for SgxStatus {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for OCallError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match self {
-            OCallError::SgxError(s) => s.description(),
-            OCallError::OsError(code) => sys::decode_error_kind(*code).as_str(),
-            OCallError::GaiError(code) => ocall::gai_error_str(*code),
-            OCallError::CustomError(s) => s,
-        }
-    }
-
-    #[allow(deprecated)]
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        match self {
-            OCallError::SgxError(ref s) => Some(s),
-            OCallError::OsError(..) => None,
-            OCallError::GaiError(..) => None,
-            OCallError::CustomError(..) => None,
-        }
-    }
-}
-
-impl<T: Error> Error for Box<T> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
-    #[allow(deprecated)]
-    fn cause(&self) -> Option<&dyn Error> {
-        Error::cause(&**self)
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Error::source(&**self)
-    }
-}
-
-impl<'a, T: Error + ?Sized> Error for &'a T {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
-    #[allow(deprecated)]
-    fn cause(&self) -> Option<&dyn Error> {
-        Error::cause(&**self)
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Error::source(&**self)
-    }
-
-    #[cfg(feature = "backtrace")]
-    fn backtrace(&self) -> Option<&Backtrace> {
-        Error::backtrace(&**self)
-    }
-}
-
-impl<T: Error + ?Sized> Error for Arc<T> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
-    #[allow(deprecated)]
-    fn cause(&self) -> Option<&dyn Error> {
-        Error::cause(&**self)
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Error::source(&**self)
-    }
-
-    #[cfg(feature = "backtrace")]
-    fn backtrace(&self) -> Option<&Backtrace> {
-        Error::backtrace(&**self)
-    }
-}
-
-impl Error for fmt::Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "an error occurred when formatting an argument"
-    }
-}
-
-impl Error for cell::BorrowError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "already mutably borrowed"
-    }
-}
-
-impl Error for cell::BorrowMutError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "already borrowed"
-    }
-}
-
-impl Error for char::CharTryFromError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "converted integer out of range for `char`"
-    }
-}
-
-impl Error for char::ParseCharError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for alloc_crate::collections::TryReserveError {}
-
-impl Error for time::FromFloatSecsError {}
-
-// Copied from `any.rs`.
-impl dyn Error + 'static {
-    /// Returns `true` if the inner type is the same as `T`.
-    #[inline]
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        // Get `TypeId` of the type this function is instantiated with.
-        let t = TypeId::of::<T>();
-
-        // Get `TypeId` of the type in the trait object (`self`).
-        let concrete = self.type_id(private::Internal);
-
-        // Compare both `TypeId`s on equality.
-        t == concrete
-    }
-
-    /// Returns some reference to the inner value if it is of type `T`, or
-    /// `None` if it isn't.
-    #[inline]
-    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        if self.is::<T>() {
-            unsafe { Some(&*(self as *const dyn Error as *const T)) }
-        } else {
-            None
-        }
-    }
-
-    /// Returns some mutable reference to the inner value if it is of type `T`, or
-    /// `None` if it isn't.
-    #[inline]
-    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        if self.is::<T>() {
-            unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) }
-        } else {
-            None
-        }
-    }
-}
-
-impl dyn Error + 'static + Send {
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        <dyn Error + 'static>::is::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        <dyn Error + 'static>::downcast_ref::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        <dyn Error + 'static>::downcast_mut::<T>(self)
-    }
-}
-
-impl dyn Error + 'static + Send + Sync {
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        <dyn Error + 'static>::is::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        <dyn Error + 'static>::downcast_ref::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        <dyn Error + 'static>::downcast_mut::<T>(self)
-    }
-}
-
-impl dyn Error {
-    #[inline]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
-        if self.is::<T>() {
-            unsafe {
-                let raw: *mut dyn Error = Box::into_raw(self);
-                Ok(Box::from_raw(raw as *mut T))
-            }
-        } else {
-            Err(self)
-        }
-    }
-
-    /// Returns an iterator starting with the current error and continuing with
-    /// recursively calling [`Error::source`].
-    ///
-    /// If you want to omit the current error and only use its sources,
-    /// use `skip(1)`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(error_iter)]
-    /// use std::error::Error;
-    /// use std::fmt;
-    ///
-    /// #[derive(Debug)]
-    /// struct A;
-    ///
-    /// #[derive(Debug)]
-    /// struct B(Option<Box<dyn Error + 'static>>);
-    ///
-    /// impl fmt::Display for A {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "A")
-    ///     }
-    /// }
-    ///
-    /// impl fmt::Display for B {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "B")
-    ///     }
-    /// }
-    ///
-    /// impl Error for A {}
-    ///
-    /// impl Error for B {
-    ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
-    ///         self.0.as_ref().map(|e| e.as_ref())
-    ///     }
-    /// }
-    ///
-    /// let b = B(Some(Box::new(A)));
-    ///
-    /// // let err : Box<Error> = b.into(); // or
-    /// let err = &b as &(dyn Error);
-    ///
-    /// let mut iter = err.chain();
-    ///
-    /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
-    /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
-    /// assert!(iter.next().is_none());
-    /// assert!(iter.next().is_none());
-    /// ```
-    #[inline]
-    pub fn chain(&self) -> Chain<'_> {
-        Chain { current: Some(self) }
-    }
-}
-
-/// An iterator over an [`Error`] and its sources.
+/// An error reporter that prints an error and its sources.
 ///
-/// If you want to omit the initial error and only process
-/// its sources, use `skip(1)`.
-#[derive(Clone, Debug)]
-pub struct Chain<'a> {
-    current: Option<&'a (dyn Error + 'static)>,
-}
-
-impl<'a> Iterator for Chain<'a> {
-    type Item = &'a (dyn Error + 'static);
-
-    fn next(&mut self) -> Option<Self::Item> {
-        let current = self.current;
-        self.current = self.current.and_then(Error::source);
-        current
-    }
-}
-
-impl dyn Error + Send {
-    #[inline]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
-        let err: Box<dyn Error> = self;
-        <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // Reapply the `Send` marker.
-            transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
-        })
-    }
-}
-
-impl dyn Error + Send + Sync {
-    #[inline]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
-        let err: Box<dyn Error> = self;
-        <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // Reapply the `Send + Sync` marker.
-            transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
-        })
-    }
-}
-
-/// An error reporter that print's an error and its sources.
-///
-/// Report also exposes configuration options for formatting the error chain, either entirely on a
-/// single line, or in multi-line format with each cause in the error chain on a new line.
+/// Report also exposes configuration options for formatting the error sources, either entirely on a
+/// single line, or in multi-line format with each source on a new line.
 ///
-/// `Report` only requires that the wrapped error implements `Error`. It doesn't require that the
+/// `Report` only requires that the wrapped error implement `Error`. It doesn't require that the
 /// wrapped error be `Send`, `Sync`, or `'static`.
 ///
 /// # Examples
@@ -905,7 +142,7 @@ impl dyn Error + Send + Sync {
 ///
 /// ## Return from `main`
 ///
-/// `Report` also implements `From` for all types that implement [`Error`], this when combined with
+/// `Report` also implements `From` for all types that implement [`Error`]; this when combined with
 /// the `Debug` output means `Report` is an ideal starting place for formatting errors returned
 /// from `main`.
 ///
@@ -940,7 +177,7 @@ impl dyn Error + Send + Sync {
 /// #     Err(SuperError { source: SuperErrorSideKick })
 /// # }
 ///
-/// fn main() -> Result<(), Report> {
+/// fn main() -> Result<(), Report<SuperError>> {
 ///     get_super_error()?;
 ///     Ok(())
 /// }
@@ -953,7 +190,7 @@ impl dyn Error + Send + Sync {
 /// ```
 ///
 /// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line
-/// output format, if you want to make sure your `Report`s are pretty printed and include backtrace
+/// output format. If you want to make sure your `Report`s are pretty printed and include backtrace
 /// you will need to manually convert and enable those flags.
 ///
 /// ```should_panic
@@ -987,7 +224,7 @@ impl dyn Error + Send + Sync {
 /// #     Err(SuperError { source: SuperErrorSideKick })
 /// # }
 ///
-/// fn main() -> Result<(), Report> {
+/// fn main() -> Result<(), Report<SuperError>> {
 ///     get_super_error()
 ///         .map_err(Report::from)
 ///         .map_err(|r| r.pretty(true).show_backtrace(true))?;
@@ -1003,7 +240,6 @@ impl dyn Error + Send + Sync {
 /// Caused by:
 ///       SuperErrorSideKick is here!
 /// ```
-#[cfg(feature = "backtrace")]
 pub struct Report<E = Box<dyn Error>> {
     /// The error being reported.
     error: E,
@@ -1013,7 +249,6 @@ pub struct Report<E = Box<dyn Error>> {
     pretty: bool,
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> Report<E>
 where
     Report<E>: From<E>,
@@ -1024,7 +259,6 @@ where
     }
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> Report<E> {
     /// Enable pretty-printing the report across multiple lines.
     ///
@@ -1060,7 +294,7 @@ impl<E> Report<E> {
     ///
     /// let error = SuperError { source: SuperErrorSideKick };
     /// let report = Report::new(error).pretty(true);
-    /// eprintln!("Error: {:?}", report);
+    /// eprintln!("Error: {report:?}");
     /// ```
     ///
     /// This example produces the following output:
@@ -1121,7 +355,7 @@ impl<E> Report<E> {
     /// let source = SuperErrorSideKick { source };
     /// let error = SuperError { source };
     /// let report = Report::new(error).pretty(true);
-    /// eprintln!("Error: {:?}", report);
+    /// eprintln!("Error: {report:?}");
     /// ```
     ///
     /// This example produces the following output:
@@ -1144,13 +378,15 @@ impl<E> Report<E> {
     ///
     /// **Note**: Report will search for the first `Backtrace` it can find starting from the
     /// outermost error. In this example it will display the backtrace from the second error in the
-    /// chain, `SuperErrorSideKick`.
+    /// sources, `SuperErrorSideKick`.
     ///
     /// ```rust
     /// #![feature(error_reporter)]
-    /// #![feature(backtrace)]
+    /// #![feature(provide_any)]
+    /// #![feature(error_generic_member_access)]
     /// # use std::error::Error;
     /// # use std::fmt;
+    /// use std::any::Demand;
     /// use std::error::Report;
     /// use std::backtrace::Backtrace;
     ///
@@ -1180,8 +416,8 @@ impl<E> Report<E> {
     /// }
     ///
     /// impl Error for SuperErrorSideKick {
-    ///     fn backtrace(&self) -> Option<&Backtrace> {
-    ///         Some(&self.backtrace)
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         demand.provide_ref::<Backtrace>(&self.backtrace);
     ///     }
     /// }
     ///
@@ -1195,7 +431,7 @@ impl<E> Report<E> {
     /// let source = SuperErrorSideKick::new();
     /// let error = SuperError { source };
     /// let report = Report::new(error).pretty(true).show_backtrace(true);
-    /// eprintln!("Error: {:?}", report);
+    /// eprintln!("Error: {report:?}");
     /// ```
     ///
     /// This example produces something similar to the following output:
@@ -1226,82 +462,21 @@ impl<E> Report<E> {
     }
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> Report<E>
 where
     E: Error,
 {
+    #[cfg(feature = "backtrace")]
+    #[allow(clippy::map_flatten)]
     fn backtrace(&self) -> Option<&Backtrace> {
         // have to grab the backtrace on the first error directly since that error may not be
         // 'static
-        let backtrace = self.error.backtrace();
-        backtrace.or_else(|| {
-            self.error
-                .source()
-                .and_then(|source| source.chain().find_map(|source| source.backtrace()))
-        })
-    }
-
-    /// Format the report as a single line.
-    fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.error)?;
-
-        let sources = self.error.source().into_iter().flat_map(<dyn Error>::chain);
-
-        for cause in sources {
-            write!(f, ": {}", cause)?;
-        }
-
-        Ok(())
-    }
-
-    /// Format the report as multiple lines, with each error cause on its own line.
-    fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let error = &self.error;
-
-        write!(f, "{}", error)?;
-
-        if let Some(cause) = error.source() {
-            write!(f, "\n\nCaused by:")?;
-
-            let multiple = cause.source().is_some();
-
-            for (ind, error) in cause.chain().enumerate() {
-                writeln!(f)?;
-                let mut indented = Indented { inner: f };
-                if multiple {
-                    write!(indented, "{: >4}: {}", ind, error)?;
-                } else {
-                    write!(indented, "      {}", error)?;
-                }
-            }
-        }
-
-        if self.show_backtrace {
-            let backtrace = self.backtrace();
-
-            if let Some(backtrace) = backtrace {
-                let backtrace = backtrace.to_string();
-
-                f.write_str("\n\nStack backtrace:\n")?;
-                f.write_str(backtrace.trim_end())?;
-            }
-        }
-
-        Ok(())
-    }
-}
-
-#[cfg(feature = "backtrace")]
-impl Report<Box<dyn Error>> {
-    fn backtrace(&self) -> Option<&Backtrace> {
-        // have to grab the backtrace on the first error directly since that error may not be
-        // 'static
-        let backtrace = self.error.backtrace();
+        let backtrace = (&self.error as &dyn Error).request_ref();
         backtrace.or_else(|| {
             self.error
                 .source()
-                .and_then(|source| source.chain().find_map(|source| source.backtrace()))
+                .map(|source| source.sources().find_map(|source| source.request_ref()))
+                .flatten()
         })
     }
 
@@ -1309,10 +484,10 @@ impl Report<Box<dyn Error>> {
     fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.error)?;
 
-        let sources = self.error.source().into_iter().flat_map(<dyn Error>::chain);
+        let sources = self.error.source().into_iter().flat_map(<dyn Error>::sources);
 
         for cause in sources {
-            write!(f, ": {}", cause)?;
+            write!(f, ": {cause}")?;
         }
 
         Ok(())
@@ -1322,24 +497,25 @@ impl Report<Box<dyn Error>> {
     fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let error = &self.error;
 
-        write!(f, "{}", error)?;
+        write!(f, "{error}")?;
 
         if let Some(cause) = error.source() {
             write!(f, "\n\nCaused by:")?;
 
             let multiple = cause.source().is_some();
 
-            for (ind, error) in cause.chain().enumerate() {
+            for (ind, error) in cause.sources().enumerate() {
                 writeln!(f)?;
                 let mut indented = Indented { inner: f };
                 if multiple {
-                    write!(indented, "{: >4}: {}", ind, error)?;
+                    write!(indented, "{ind: >4}: {error}")?;
                 } else {
-                    write!(indented, "      {}", error)?;
+                    write!(indented, "      {error}")?;
                 }
             }
         }
 
+        #[cfg(feature = "backtrace")]
         if self.show_backtrace {
             let backtrace = self.backtrace();
 
@@ -1355,7 +531,6 @@ impl Report<Box<dyn Error>> {
     }
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> From<E> for Report<E>
 where
     E: Error,
@@ -1365,18 +540,6 @@ where
     }
 }
 
-#[cfg(feature = "backtrace")]
-impl<'a, E> From<E> for Report<Box<dyn Error + 'a>>
-where
-    E: Error + 'a,
-{
-    fn from(error: E) -> Self {
-        let error = box error;
-        Report { error, show_backtrace: false, pretty: false }
-    }
-}
-
-#[cfg(feature = "backtrace")]
 impl<E> fmt::Display for Report<E>
 where
     E: Error,
@@ -1386,16 +549,8 @@ where
     }
 }
 
-#[cfg(feature = "backtrace")]
-impl fmt::Display for Report<Box<dyn Error>> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) }
-    }
-}
-
 // This type intentionally outputs the same format for `Display` and `Debug`for
 // situations where you unwrap a `Report` or return it from main.
-#[cfg(feature = "backtrace")]
 impl<E> fmt::Debug for Report<E>
 where
     Report<E>: fmt::Display,
@@ -1406,12 +561,10 @@ where
 }
 
 /// Wrapper type for indenting the inner source.
-#[cfg(feature = "backtrace")]
 struct Indented<'a, D> {
     inner: &'a mut D,
 }
 
-#[cfg(feature = "backtrace")]
 impl<T> Write for Indented<'_, T>
 where
     T: Write,
diff --git a/sgx_tstd/src/error/tests.rs b/sgx_tstd/src/error/tests.rs
index 2f5c49a2..b9f99138 100644
--- a/sgx_tstd/src/error/tests.rs
+++ b/sgx_tstd/src/error/tests.rs
@@ -17,6 +17,7 @@
 
 use super::Error;
 use crate::fmt;
+use core::any::Demand;
 
 use sgx_test_utils::test_case;
 
@@ -149,7 +150,7 @@ Stack backtrace:
     error.backtrace = Some(trace);
     let report = Report::new(error).pretty(true).show_backtrace(true);
 
-    println!("Error: {}", report);
+    println!("Error: {report}");
     assert_eq!(expected.trim_end(), report.to_string());
 }
 
@@ -174,7 +175,7 @@ Stack backtrace:
     let error = GenericError::new_with_source("Error with two sources", error);
     let report = Report::new(error).pretty(true).show_backtrace(true);
 
-    println!("Error: {}", report);
+    println!("Error: {report}");
     assert_eq!(expected.trim_end(), report.to_string());
 }
 
@@ -217,8 +218,8 @@ where
         self.source.as_deref()
     }
 
-    fn backtrace(&self) -> Option<&Backtrace> {
-        self.backtrace.as_ref()
+    fn provide<'a>(&'a self, req: &mut Demand<'a>) {
+        self.backtrace.as_ref().map(|bt| req.provide_ref::<Backtrace>(bt));
     }
 }
 
@@ -374,7 +375,7 @@ Caused by:
    1: The message goes on and on.";
 
     let actual = report.to_string();
-    println!("{}", actual);
+    println!("{actual}");
     assert_eq!(expected, actual);
 }
 
diff --git a/sgx_tstd/src/f32.rs b/sgx_tstd/src/f32.rs
index 6906080e..0f116a06 100644
--- a/sgx_tstd/src/f32.rs
+++ b/sgx_tstd/src/f32.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
-//! Constants specific to the `f32` single-precision floating point type.
+//! Constants for the `f32` single-precision floating point type.
 //!
 //! *[See also the `f32` primitive type](primitive@f32).*
 //!
@@ -40,9 +40,8 @@ pub use core::f32::{
     MIN_EXP, MIN_POSITIVE, NAN, NEG_INFINITY, RADIX,
 };
 
-#[lang = "f32_runtime"]
 impl f32 {
-    /// Returns the largest integer less than or equal to a number.
+    /// Returns the largest integer less than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -55,13 +54,14 @@ impl f32 {
     /// assert_eq!(g.floor(), 3.0);
     /// assert_eq!(h.floor(), -4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn floor(self) -> f32 {
         unsafe { intrinsics::floorf32(self) }
     }
 
-    /// Returns the smallest integer greater than or equal to a number.
+    /// Returns the smallest integer greater than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -72,13 +72,14 @@ impl f32 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ceil(self) -> f32 {
         unsafe { intrinsics::ceilf32(self) }
     }
 
-    /// Returns the nearest integer to a number. Round half-way cases away from
+    /// Returns the nearest integer to `self`. Round half-way cases away from
     /// `0.0`.
     ///
     /// # Examples
@@ -90,13 +91,15 @@ impl f32 {
     /// assert_eq!(f.round(), 3.0);
     /// assert_eq!(g.round(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn round(self) -> f32 {
         unsafe { intrinsics::roundf32(self) }
     }
 
-    /// Returns the integer part of a number.
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
     ///
     /// # Examples
     ///
@@ -109,13 +112,14 @@ impl f32 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn trunc(self) -> f32 {
         unsafe { intrinsics::truncf32(self) }
     }
 
-    /// Returns the fractional part of a number.
+    /// Returns the fractional part of `self`.
     ///
     /// # Examples
     ///
@@ -128,14 +132,14 @@ impl f32 {
     /// assert!(abs_difference_x <= f32::EPSILON);
     /// assert!(abs_difference_y <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn fract(self) -> f32 {
         self - self.trunc()
     }
 
-    /// Computes the absolute value of `self`. Returns `NAN` if the
-    /// number is `NAN`.
+    /// Computes the absolute value of `self`.
     ///
     /// # Examples
     ///
@@ -151,6 +155,7 @@ impl f32 {
     ///
     /// assert!(f32::NAN.abs().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs(self) -> f32 {
@@ -161,7 +166,7 @@ impl f32 {
     ///
     /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
-    /// - `NAN` if the number is `NAN`
+    /// - NaN if the number is NaN
     ///
     /// # Examples
     ///
@@ -173,6 +178,7 @@ impl f32 {
     ///
     /// assert!(f32::NAN.signum().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn signum(self) -> f32 {
@@ -183,8 +189,10 @@ impl f32 {
     /// `sign`.
     ///
     /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
-    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `sign` is returned.
+    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+    /// across arithmetical operations is not generally guaranteed.
+    /// See [explanation of NaN as a special value](primitive@f32) for more info.
     ///
     /// # Examples
     ///
@@ -198,6 +206,7 @@ impl f32 {
     ///
     /// assert!(f32::NAN.copysign(1.0).is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn copysign(self, sign: f32) -> f32 {
@@ -224,6 +233,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn mul_add(self, a: f32, b: f32) -> f32 {
@@ -247,6 +257,7 @@ impl f32 {
     /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn div_euclid(self, rhs: f32) -> f32 {
@@ -280,6 +291,7 @@ impl f32 {
     /// // limitation due to round-off error
     /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn rem_euclid(self, rhs: f32) -> f32 {
@@ -289,7 +301,9 @@ impl f32 {
 
     /// Raises a number to an integer power.
     ///
-    /// Using this function is generally faster than using `powf`
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
     ///
     /// # Examples
     ///
@@ -299,6 +313,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powi(self, n: i32) -> f32 {
@@ -315,6 +330,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powf(self, n: f32) -> f32 {
@@ -338,6 +354,7 @@ impl f32 {
     /// assert!(negative.sqrt().is_nan());
     /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sqrt(self) -> f32 {
@@ -358,6 +375,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp(self) -> f32 {
@@ -376,6 +394,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp2(self) -> f32 {
@@ -396,6 +415,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln(self) -> f32 {
@@ -418,6 +438,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log(self, base: f32) -> f32 {
@@ -436,6 +457,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log2(self) -> f32 {
@@ -457,6 +479,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log10(self) -> f32 {
@@ -480,6 +503,7 @@ impl f32 {
     /// assert!(abs_difference_x <= f32::EPSILON);
     /// assert!(abs_difference_y <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs_sub(self, other: f32) -> f32 {
@@ -498,6 +522,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cbrt(self) -> f32 {
@@ -518,6 +543,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn hypot(self, other: f32) -> f32 {
@@ -535,6 +561,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sin(self) -> f32 {
@@ -552,6 +579,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cos(self) -> f32 {
@@ -568,6 +596,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tan(self) -> f32 {
@@ -588,6 +617,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asin(self) -> f32 {
@@ -608,6 +638,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acos(self) -> f32 {
@@ -627,6 +658,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan(self) -> f32 {
@@ -659,6 +691,7 @@ impl f32 {
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// assert!(abs_difference_2 <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan2(self, other: f32) -> f32 {
@@ -680,6 +713,7 @@ impl f32 {
     /// assert!(abs_difference_0 <= f32::EPSILON);
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[inline]
     pub fn sin_cos(self) -> (f32, f32) {
         (self.sin(), self.cos())
@@ -699,6 +733,7 @@ impl f32 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp_m1(self) -> f32 {
@@ -719,6 +754,7 @@ impl f32 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln_1p(self) -> f32 {
@@ -740,6 +776,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sinh(self) -> f32 {
@@ -761,6 +798,7 @@ impl f32 {
     /// // Same result
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cosh(self) -> f32 {
@@ -782,6 +820,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tanh(self) -> f32 {
@@ -800,6 +839,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asinh(self) -> f32 {
@@ -818,6 +858,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acosh(self) -> f32 {
@@ -836,6 +877,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= 1e-5);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atanh(self) -> f32 {
diff --git a/sgx_tstd/src/f64.rs b/sgx_tstd/src/f64.rs
index 68b772eb..d80a295a 100644
--- a/sgx_tstd/src/f64.rs
+++ b/sgx_tstd/src/f64.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
-//! Constants specific to the `f64` double-precision floating point type.
+//! Constants for the `f64` double-precision floating point type.
 //!
 //! *[See also the `f64` primitive type](primitive@f64).*
 //!
@@ -40,9 +40,8 @@ pub use core::f64::{
     MIN_EXP, MIN_POSITIVE, NAN, NEG_INFINITY, RADIX,
 };
 
-#[lang = "f64_runtime"]
 impl f64 {
-    /// Returns the largest integer less than or equal to a number.
+    /// Returns the largest integer less than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -55,13 +54,14 @@ impl f64 {
     /// assert_eq!(g.floor(), 3.0);
     /// assert_eq!(h.floor(), -4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn floor(self) -> f64 {
         unsafe { intrinsics::floorf64(self) }
     }
 
-    /// Returns the smallest integer greater than or equal to a number.
+    /// Returns the smallest integer greater than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -72,13 +72,14 @@ impl f64 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ceil(self) -> f64 {
         unsafe { intrinsics::ceilf64(self) }
     }
 
-    /// Returns the nearest integer to a number. Round half-way cases away from
+    /// Returns the nearest integer to `self`. Round half-way cases away from
     /// `0.0`.
     ///
     /// # Examples
@@ -90,13 +91,15 @@ impl f64 {
     /// assert_eq!(f.round(), 3.0);
     /// assert_eq!(g.round(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn round(self) -> f64 {
         unsafe { intrinsics::roundf64(self) }
     }
 
-    /// Returns the integer part of a number.
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
     ///
     /// # Examples
     ///
@@ -109,13 +112,14 @@ impl f64 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn trunc(self) -> f64 {
         unsafe { intrinsics::truncf64(self) }
     }
 
-    /// Returns the fractional part of a number.
+    /// Returns the fractional part of `self`.
     ///
     /// # Examples
     ///
@@ -128,14 +132,14 @@ impl f64 {
     /// assert!(abs_difference_x < 1e-10);
     /// assert!(abs_difference_y < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn fract(self) -> f64 {
         self - self.trunc()
     }
 
-    /// Computes the absolute value of `self`. Returns `NAN` if the
-    /// number is `NAN`.
+    /// Computes the absolute value of `self`.
     ///
     /// # Examples
     ///
@@ -151,6 +155,7 @@ impl f64 {
     ///
     /// assert!(f64::NAN.abs().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs(self) -> f64 {
@@ -161,7 +166,7 @@ impl f64 {
     ///
     /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
-    /// - `NAN` if the number is `NAN`
+    /// - NaN if the number is NaN
     ///
     /// # Examples
     ///
@@ -173,6 +178,7 @@ impl f64 {
     ///
     /// assert!(f64::NAN.signum().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn signum(self) -> f64 {
@@ -183,8 +189,10 @@ impl f64 {
     /// `sign`.
     ///
     /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
-    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `sign` is returned.
+    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+    /// across arithmetical operations is not generally guaranteed.
+    /// See [explanation of NaN as a special value](primitive@f32) for more info.
     ///
     /// # Examples
     ///
@@ -198,6 +206,7 @@ impl f64 {
     ///
     /// assert!(f64::NAN.copysign(1.0).is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn copysign(self, sign: f64) -> f64 {
@@ -224,6 +233,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn mul_add(self, a: f64, b: f64) -> f64 {
@@ -247,6 +257,7 @@ impl f64 {
     /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn div_euclid(self, rhs: f64) -> f64 {
@@ -280,6 +291,7 @@ impl f64 {
     /// // limitation due to round-off error
     /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn rem_euclid(self, rhs: f64) -> f64 {
@@ -289,7 +301,9 @@ impl f64 {
 
     /// Raises a number to an integer power.
     ///
-    /// Using this function is generally faster than using `powf`
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
     ///
     /// # Examples
     ///
@@ -299,6 +313,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powi(self, n: i32) -> f64 {
@@ -315,6 +330,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powf(self, n: f64) -> f64 {
@@ -338,6 +354,7 @@ impl f64 {
     /// assert!(negative.sqrt().is_nan());
     /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sqrt(self) -> f64 {
@@ -358,6 +375,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp(self) -> f64 {
@@ -376,6 +394,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp2(self) -> f64 {
@@ -396,6 +415,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln(self) -> f64 {
@@ -418,6 +438,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log(self, base: f64) -> f64 {
@@ -436,6 +457,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log2(self) -> f64 {
@@ -459,6 +481,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log10(self) -> f64 {
@@ -482,6 +505,7 @@ impl f64 {
     /// assert!(abs_difference_x < 1e-10);
     /// assert!(abs_difference_y < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs_sub(self, other: f64) -> f64 {
@@ -500,6 +524,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cbrt(self) -> f64 {
@@ -520,6 +545,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn hypot(self, other: f64) -> f64 {
@@ -537,6 +563,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sin(self) -> f64 {
@@ -554,6 +581,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cos(self) -> f64 {
@@ -570,6 +598,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-14);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tan(self) -> f64 {
@@ -590,6 +619,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asin(self) -> f64 {
@@ -610,6 +640,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acos(self) -> f64 {
@@ -629,6 +660,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan(self) -> f64 {
@@ -661,6 +693,7 @@ impl f64 {
     /// assert!(abs_difference_1 < 1e-10);
     /// assert!(abs_difference_2 < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan2(self, other: f64) -> f64 {
@@ -682,6 +715,7 @@ impl f64 {
     /// assert!(abs_difference_0 < 1e-10);
     /// assert!(abs_difference_1 < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[inline]
     pub fn sin_cos(self) -> (f64, f64) {
         (self.sin(), self.cos())
@@ -701,6 +735,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-20);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp_m1(self) -> f64 {
@@ -721,6 +756,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-20);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln_1p(self) -> f64 {
@@ -742,6 +778,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sinh(self) -> f64 {
@@ -763,6 +800,7 @@ impl f64 {
     /// // Same result
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cosh(self) -> f64 {
@@ -784,6 +822,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tanh(self) -> f64 {
@@ -802,6 +841,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asinh(self) -> f64 {
@@ -820,6 +860,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acosh(self) -> f64 {
@@ -838,6 +879,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atanh(self) -> f64 {
@@ -848,6 +890,7 @@ impl f64 {
     // because of their non-standard behavior (e.g., log(-n) returns -Inf instead
     // of expected NaN).
     #[allow(clippy::if_same_then_else)]
+    #[rustc_allow_incoherent_impl]
     fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
         if !cfg!(any(target_os = "solaris", target_os = "illumos")) {
             log_fn(self)
diff --git a/sgx_tstd/src/ffi/c_str.rs b/sgx_tstd/src/ffi/c_str.rs
deleted file mode 100644
index b31e2fff..00000000
--- a/sgx_tstd/src/ffi/c_str.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License..
-
-#[cfg(feature = "unit_test")]
-mod tests;
-
-pub use sgx_ffi::c_str::*;
-
-use crate::error::Error;
-use crate::io;
-
-impl Error for NulError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "nul byte found in data"
-    }
-}
-
-impl From<NulError> for io::Error {
-    /// Converts a [`NulError`] into a [`io::Error`].
-    fn from(_: NulError) -> io::Error {
-        io::const_io_error!(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
-    }
-}
-
-impl Error for FromBytesWithNulError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for FromVecWithNulError {}
-
-impl Error for IntoStringError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Some(self.__source())
-    }
-}
diff --git a/sgx_tstd/src/ffi/mod.rs b/sgx_tstd/src/ffi/mod.rs
index 1c6152af..7e72f121 100644
--- a/sgx_tstd/src/ffi/mod.rs
+++ b/sgx_tstd/src/ffi/mod.rs
@@ -121,7 +121,7 @@
 //! On Unix, [`OsStr`] implements the
 //! <code>std::os::unix::ffi::[OsStrExt][unix.OsStrExt]</code> trait, which
 //! augments it with two methods, [`from_bytes`] and [`as_bytes`].
-//! These do inexpensive conversions from and to UTF-8 byte slices.
+//! These do inexpensive conversions from and to byte slices.
 //!
 //! Additionally, on Unix [`OsString`] implements the
 //! <code>std::os::unix::ffi::[OsStringExt][unix.OsStringExt]</code> trait,
@@ -161,13 +161,18 @@
 //! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt "os::windows::ffi::OsStringExt"
 //! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide "os::windows::ffi::OsStringExt::from_wide"
 
-pub use self::c_str::FromBytesWithNulError;
-pub use self::c_str::FromVecWithNulError;
-pub use self::c_str::{CStr, CString, IntoStringError, NulError};
+pub use alloc_crate::ffi::{CString, FromVecWithNulError, IntoStringError, NulError};
+pub use core::ffi::{CStr, FromBytesWithNulError};
+
 pub use self::os_str::{OsStr, OsString};
 
+pub use core::ffi::{
+    c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
+    c_ulong, c_ulonglong, c_ushort,
+};
+
 pub use core::ffi::c_void;
+
 pub use core::ffi::{VaList, VaListImpl};
 
-mod c_str;
 mod os_str;
diff --git a/sgx_tstd/src/ffi/os_str.rs b/sgx_tstd/src/ffi/os_str.rs
index eb9b8bbe..8a2d359f 100644
--- a/sgx_tstd/src/ffi/os_str.rs
+++ b/sgx_tstd/src/ffi/os_str.rs
@@ -25,7 +25,7 @@ use crate::cmp;
 use crate::collections::TryReserveError;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::iter::{Extend, FromIterator};
+use crate::iter::Extend;
 use crate::ops;
 use crate::rc::Rc;
 use crate::str::FromStr;
@@ -64,6 +64,22 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// values, encoded in a less-strict variant of UTF-8. This is useful to
 /// understand when handling capacity and length values.
 ///
+/// # Capacity of `OsString`
+///
+/// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
+/// uses units of bytes in an unspecified encoding for other contents. On a given target, all
+/// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
+/// ```
+/// use std::ffi::{OsStr, OsString};
+///
+/// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
+///     let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
+///     ret.push(a); // This will not allocate further
+///     ret.push(b); // This will not allocate further
+///     ret
+/// }
+/// ```
+///
 /// # Creating an `OsString`
 ///
 /// **From a Rust string**: `OsString` implements
@@ -191,13 +207,14 @@ impl OsString {
         self.inner.push_slice(&s.as_ref().inner)
     }
 
-    /// Creates a new `OsString` with the given capacity.
+    /// Creates a new `OsString` with at least the given capacity.
     ///
-    /// The string will be able to hold exactly `capacity` length units of other
-    /// OS strings without reallocating. If `capacity` is 0, the string will not
+    /// The string will be able to hold at least `capacity` length units of other
+    /// OS strings without reallocating. This method is allowed to allocate for
+    /// more units than `capacity`. If `capacity` is 0, the string will not
     /// allocate.
     ///
-    /// See main `OsString` documentation information about encoding.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -238,7 +255,7 @@ impl OsString {
 
     /// Returns the capacity this `OsString` can hold without reallocating.
     ///
-    /// See `OsString` introduction for information about encoding.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -255,9 +272,12 @@ impl OsString {
     }
 
     /// Reserves capacity for at least `additional` more capacity to be inserted
-    /// in the given `OsString`.
+    /// in the given `OsString`. Does nothing if the capacity is
+    /// already sufficient.
+    ///
+    /// The collection may reserve more space to speculatively avoid frequent reallocations.
     ///
-    /// The collection may reserve more space to avoid frequent reallocations.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -274,10 +294,13 @@ impl OsString {
     }
 
     /// Tries to reserve capacity for at least `additional` more length units
-    /// in the given `OsString`. The string may reserve more space to avoid
+    /// in the given `OsString`. The string may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
-    /// greater than or equal to `self.len() + additional`. Does nothing if
-    /// capacity is already sufficient.
+    /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
+    /// Does nothing if capacity is already sufficient. This method preserves
+    /// the contents even if an error occurs.
+    ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Errors
     ///
@@ -287,7 +310,6 @@ impl OsString {
     /// # Examples
     ///
     /// ```
-    /// #![feature(try_reserve_2)]
     /// use std::ffi::{OsStr, OsString};
     /// use std::collections::TryReserveError;
     ///
@@ -309,7 +331,7 @@ impl OsString {
         self.inner.try_reserve(additional)
     }
 
-    /// Reserves the minimum capacity for exactly `additional` more capacity to
+    /// Reserves the minimum capacity for at least `additional` more capacity to
     /// be inserted in the given `OsString`. Does nothing if the capacity is
     /// already sufficient.
     ///
@@ -319,6 +341,8 @@ impl OsString {
     ///
     /// [`reserve`]: OsString::reserve
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -333,7 +357,7 @@ impl OsString {
         self.inner.reserve_exact(additional)
     }
 
-    /// Tries to reserve the minimum capacity for exactly `additional`
+    /// Tries to reserve the minimum capacity for at least `additional`
     /// more length units in the given `OsString`. After calling
     /// `try_reserve_exact`, capacity will be greater than or equal to
     /// `self.len() + additional` if it returns `Ok(())`.
@@ -345,6 +369,8 @@ impl OsString {
     ///
     /// [`try_reserve`]: OsString::try_reserve
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Errors
     ///
     /// If the capacity overflows, or the allocator reports a failure, then an error
@@ -353,7 +379,6 @@ impl OsString {
     /// # Examples
     ///
     /// ```
-    /// #![feature(try_reserve_2)]
     /// use std::ffi::{OsStr, OsString};
     /// use std::collections::TryReserveError;
     ///
@@ -377,6 +402,8 @@ impl OsString {
 
     /// Shrinks the capacity of the `OsString` to match its length.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -402,6 +429,8 @@ impl OsString {
     ///
     /// If the current capacity is less than the lower limit, this is a no-op.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -597,6 +626,13 @@ impl Hash for OsString {
     }
 }
 
+impl fmt::Write for OsString {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.push(s);
+        Ok(())
+    }
+}
+
 impl OsStr {
     /// Coerces into an `OsStr` slice.
     ///
@@ -750,6 +786,8 @@ impl OsStr {
     /// This number is simply useful for passing to other methods, like
     /// [`OsString::with_capacity`] to avoid reallocations.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1163,6 +1201,22 @@ impl OsStr {
     }
 }
 
+impl<S: Borrow<OsStr>> alloc_crate::slice::Join<&OsStr> for [S] {
+    type Output = OsString;
+
+    fn join(slice: &Self, sep: &OsStr) -> OsString {
+        let Some((first, suffix)) = slice.split_first() else {
+            return OsString::new();
+        };
+        let first_owned = first.borrow().to_owned();
+        suffix.iter().fold(first_owned, |mut a, b| {
+            a.push(sep);
+            a.push(b.borrow());
+            a
+        })
+    }
+}
+
 impl Borrow<OsStr> for OsString {
     #[inline]
     fn borrow(&self) -> &OsStr {
diff --git a/sgx_tstd/src/ffi/os_str/tests.rs b/sgx_tstd/src/ffi/os_str/tests.rs
index 376be81f..33fbb40f 100644
--- a/sgx_tstd/src/ffi/os_str/tests.rs
+++ b/sgx_tstd/src/ffi/os_str/tests.rs
@@ -103,6 +103,20 @@ fn test_os_string_reserve_exact() {
     assert!(os_string.capacity() >= 33)
 }
 
+#[test_case]
+fn test_os_string_join() {
+    let strings = [OsStr::new("hello"), OsStr::new("dear"), OsStr::new("world")];
+    assert_eq!("hello", strings[..1].join(OsStr::new(" ")));
+    assert_eq!("hello dear world", strings.join(OsStr::new(" ")));
+    assert_eq!("hellodearworld", strings.join(OsStr::new("")));
+    assert_eq!("hello.\n dear.\n world", strings.join(OsStr::new(".\n ")));
+
+    assert_eq!("dear world", strings[1..].join(&OsString::from(" ")));
+
+    let strings_abc = [OsString::from("a"), OsString::from("b"), OsString::from("c")];
+    assert_eq!("a b c", strings_abc.join(OsStr::new(" ")));
+}
+
 #[test_case]
 fn test_os_string_default() {
     let os_string: OsString = Default::default();
diff --git a/sgx_tstd/src/fs.rs b/sgx_tstd/src/fs.rs
index 8de50199..6a9afafd 100644
--- a/sgx_tstd/src/fs.rs
+++ b/sgx_tstd/src/fs.rs
@@ -24,7 +24,7 @@ mod tests;
 
 use crate::ffi::OsString;
 use crate::fmt;
-use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write};
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
 use crate::path::{Path, PathBuf};
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
@@ -32,7 +32,7 @@ use crate::time::SystemTime;
 #[cfg(not(feature = "untrusted_fs"))]
 use crate::untrusted::path::PathEx;
 
-/// A reference to an open file on the filesystem.
+/// An object providing access to an open file on the filesystem.
 ///
 /// An instance of a `File` can be read and/or written depending on what options
 /// it was opened with. Files also implement [`Seek`] to alter the logical cursor
@@ -98,6 +98,12 @@ use crate::untrusted::path::PathEx;
 /// by different processes. Avoid assuming that holding a `&File` means that the
 /// file will not change.
 ///
+/// # Platform-specific behavior
+///
+/// On Windows, the implementation of [`Read`] and [`Write`] traits for `File`
+/// perform synchronous I/O operations. Therefore the underlying file must not
+/// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`).
+///
 /// [`BufReader<R>`]: io::BufReader
 /// [`sync_all`]: File::sync_all
 #[cfg_attr(not(test), rustc_diagnostic_item = "File")]
@@ -136,6 +142,16 @@ pub struct ReadDir(fs_imp::ReadDir);
 /// An instance of `DirEntry` represents an entry inside of a directory on the
 /// filesystem. Each entry can be inspected via methods to learn about the full
 /// path or possibly other metadata through per-platform extension traits.
+///
+/// # Platform-specific behavior
+///
+/// On Unix, the `DirEntry` struct contains an internal reference to the open
+/// directory. Holding `DirEntry` objects will consume a file handle even
+/// after the `ReadDir` iterator is dropped.
+///
+/// Note that this [may change in the future][changes].
+///
+/// [changes]: io#platform-specific-behavior
... 18252 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org