about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorSayan Nandan <17377258+sntdevco@users.noreply.github.com>2019-08-09 13:01:05 +0530
committerGitHub <noreply@github.com>2019-08-09 13:01:05 +0530
commitfb3a01354ffecc41d7a189e4dd225d706387a522 (patch)
tree41492dfe93f1dccba847dadb56ac6aa079edaaa9 /src/libstd
parent33445aea509cadcd715009c79795d289268daa7c (diff)
parent5aa3d9a7b5d3a46a7f158e8881146331a6bc9243 (diff)
downloadrust-fb3a01354ffecc41d7a189e4dd225d706387a522.tar.gz
rust-fb3a01354ffecc41d7a189e4dd225d706387a522.zip
Merge pull request #1 from rust-lang/master
Merge recent changes into master
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/Cargo.toml43
-rw-r--r--src/libstd/alloc.rs7
-rw-r--r--src/libstd/build.rs9
-rw-r--r--src/libstd/collections/hash/map.rs1720
-rw-r--r--src/libstd/collections/hash/mod.rs9
-rw-r--r--src/libstd/collections/hash/set.rs172
-rw-r--r--src/libstd/collections/hash/table.rs1131
-rw-r--r--src/libstd/collections/mod.rs7
-rw-r--r--src/libstd/env.rs37
-rw-r--r--src/libstd/error.rs106
-rw-r--r--src/libstd/f32.rs72
-rw-r--r--src/libstd/f64.rs71
-rw-r--r--src/libstd/ffi/c_str.rs38
-rw-r--r--src/libstd/ffi/mod.rs2
-rw-r--r--src/libstd/ffi/os_str.rs18
-rw-r--r--src/libstd/fs.rs87
-rw-r--r--src/libstd/future.rs68
-rw-r--r--src/libstd/io/buffered.rs131
-rw-r--r--src/libstd/io/cursor.rs91
-rw-r--r--src/libstd/io/error.rs10
-rw-r--r--src/libstd/io/impls.rs22
-rw-r--r--src/libstd/io/mod.rs493
-rw-r--r--src/libstd/io/stdio.rs95
-rw-r--r--src/libstd/io/util.rs30
-rw-r--r--src/libstd/keyword_docs.rs415
-rw-r--r--src/libstd/lib.rs90
-rw-r--r--src/libstd/macros.rs706
-rw-r--r--src/libstd/net/addr.rs33
-rw-r--r--src/libstd/net/ip.rs956
-rw-r--r--src/libstd/net/parser.rs44
-rw-r--r--src/libstd/net/tcp.rs88
-rw-r--r--src/libstd/net/test.rs10
-rw-r--r--src/libstd/net/udp.rs55
-rw-r--r--src/libstd/num.rs8
-rw-r--r--src/libstd/os/android/fs.rs1
-rw-r--r--src/libstd/os/android/raw.rs1
-rw-r--r--src/libstd/os/dragonfly/fs.rs1
-rw-r--r--src/libstd/os/fortanix_sgx/mod.rs5
-rw-r--r--src/libstd/os/freebsd/fs.rs1
-rw-r--r--src/libstd/os/ios/fs.rs1
-rw-r--r--src/libstd/os/linux/fs.rs7
-rw-r--r--src/libstd/os/linux/raw.rs56
-rw-r--r--src/libstd/os/macos/fs.rs1
-rw-r--r--src/libstd/os/mod.rs8
-rw-r--r--src/libstd/os/netbsd/fs.rs1
-rw-r--r--src/libstd/os/openbsd/fs.rs1
-rw-r--r--src/libstd/os/raw/mod.rs58
-rw-r--r--src/libstd/os/redox/fs.rs383
-rw-r--r--src/libstd/os/redox/mod.rs (renamed from src/libstd/os/bitrig/mod.rs)2
-rw-r--r--src/libstd/os/redox/raw.rs (renamed from src/libstd/os/bitrig/raw.rs)68
-rw-r--r--src/libstd/os/vxworks/fs.rs (renamed from src/libstd/os/bitrig/fs.rs)61
-rw-r--r--src/libstd/os/vxworks/mod.rs6
-rw-r--r--src/libstd/os/vxworks/raw.rs7
-rw-r--r--src/libstd/os/wasi.rs6
-rw-r--r--src/libstd/panic.rs16
-rw-r--r--src/libstd/panicking.rs27
-rw-r--r--src/libstd/path.rs52
-rw-r--r--src/libstd/prelude/mod.rs3
-rw-r--r--src/libstd/prelude/v1.rs64
-rw-r--r--src/libstd/primitive_docs.rs55
-rw-r--r--src/libstd/process.rs80
-rw-r--r--src/libstd/sync/barrier.rs4
-rw-r--r--src/libstd/sync/condvar.rs54
-rw-r--r--src/libstd/sync/mod.rs2
-rw-r--r--src/libstd/sync/mpsc/mod.rs136
-rw-r--r--src/libstd/sync/mpsc/oneshot.rs72
-rw-r--r--src/libstd/sync/mpsc/select.rs352
-rw-r--r--src/libstd/sync/mpsc/select_tests.rs413
-rw-r--r--src/libstd/sync/mpsc/shared.rs39
-rw-r--r--src/libstd/sync/mpsc/stream.rs53
-rw-r--r--src/libstd/sync/mpsc/sync.rs61
-rw-r--r--src/libstd/sync/mutex.rs16
-rw-r--r--src/libstd/sync/once.rs7
-rw-r--r--src/libstd/sync/rwlock.rs24
-rw-r--r--src/libstd/sys/cloudabi/abi/cloudabi.rs4
-rw-r--r--src/libstd/sys/cloudabi/backtrace.rs115
-rw-r--r--src/libstd/sys/cloudabi/condvar.rs29
-rw-r--r--src/libstd/sys/cloudabi/io.rs30
-rw-r--r--src/libstd/sys/cloudabi/mod.rs17
-rw-r--r--src/libstd/sys/cloudabi/mutex.rs26
-rw-r--r--src/libstd/sys/cloudabi/shims/fs.rs18
-rw-r--r--src/libstd/sys/cloudabi/shims/net.rs16
-rw-r--r--src/libstd/sys/cloudabi/shims/os.rs4
-rw-r--r--src/libstd/sys/cloudabi/shims/pipe.rs10
-rw-r--r--src/libstd/sys/cloudabi/shims/process.rs6
-rw-r--r--src/libstd/sys/cloudabi/thread.rs3
-rw-r--r--src/libstd/sys/cloudabi/time.rs20
-rw-r--r--src/libstd/sys/mod.rs19
-rw-r--r--src/libstd/sys/redox/backtrace/mod.rs32
-rw-r--r--src/libstd/sys/redox/backtrace/printing.rs1
-rw-r--r--src/libstd/sys/redox/backtrace/tracing.rs99
-rw-r--r--src/libstd/sys/redox/condvar.rs111
-rw-r--r--src/libstd/sys/redox/ext/ffi.rs55
-rw-r--r--src/libstd/sys/redox/ext/fs.rs339
-rw-r--r--src/libstd/sys/redox/ext/mod.rs45
-rw-r--r--src/libstd/sys/redox/ext/net.rs759
-rw-r--r--src/libstd/sys/redox/ext/thread.rs39
-rw-r--r--src/libstd/sys/redox/fast_thread_local.rs111
-rw-r--r--src/libstd/sys/redox/fd.rs88
-rw-r--r--src/libstd/sys/redox/fs.rs473
-rw-r--r--src/libstd/sys/redox/io.rs32
-rw-r--r--src/libstd/sys/redox/memchr.rs4
-rw-r--r--src/libstd/sys/redox/mod.rs97
-rw-r--r--src/libstd/sys/redox/mutex.rs169
-rw-r--r--src/libstd/sys/redox/net/dns/answer.rs12
-rw-r--r--src/libstd/sys/redox/net/dns/mod.rs205
-rw-r--r--src/libstd/sys/redox/net/dns/query.rs8
-rw-r--r--src/libstd/sys/redox/net/mod.rs140
-rw-r--r--src/libstd/sys/redox/net/netc.rs47
-rw-r--r--src/libstd/sys/redox/net/tcp.rs257
-rw-r--r--src/libstd/sys/redox/net/udp.rs232
-rw-r--r--src/libstd/sys/redox/os_str.rs180
-rw-r--r--src/libstd/sys/redox/path.rs29
-rw-r--r--src/libstd/sys/redox/pipe.rs93
-rw-r--r--src/libstd/sys/redox/process.rs614
-rw-r--r--src/libstd/sys/redox/rand.rs3
-rw-r--r--src/libstd/sys/redox/rwlock.rs51
-rw-r--r--src/libstd/sys/redox/syscall/arch/arm.rs73
-rw-r--r--src/libstd/sys/redox/syscall/arch/x86.rs73
-rw-r--r--src/libstd/sys/redox/syscall/arch/x86_64.rs74
-rw-r--r--src/libstd/sys/redox/syscall/call.rs348
-rw-r--r--src/libstd/sys/redox/syscall/data.rs191
-rw-r--r--src/libstd/sys/redox/syscall/error.rs315
-rw-r--r--src/libstd/sys/redox/syscall/flag.rs148
-rw-r--r--src/libstd/sys/redox/syscall/mod.rs33
-rw-r--r--src/libstd/sys/redox/syscall/number.rs73
-rw-r--r--src/libstd/sys/redox/thread.rs85
-rw-r--r--src/libstd/sys/redox/thread_local.rs61
-rw-r--r--src/libstd/sys/redox/time.rs209
-rw-r--r--src/libstd/sys/sgx/abi/entry.S14
-rw-r--r--src/libstd/sys/sgx/abi/mem.rs12
-rw-r--r--src/libstd/sys/sgx/abi/mod.rs19
-rw-r--r--src/libstd/sys/sgx/abi/panic.rs8
-rw-r--r--src/libstd/sys/sgx/abi/reloc.rs2
-rw-r--r--src/libstd/sys/sgx/abi/thread.rs1
-rw-r--r--src/libstd/sys/sgx/abi/tls.rs53
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/alloc.rs41
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/mod.rs49
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/raw.rs29
-rw-r--r--src/libstd/sys/sgx/alloc.rs16
-rw-r--r--src/libstd/sys/sgx/args.rs3
-rw-r--r--src/libstd/sys/sgx/backtrace.rs97
-rw-r--r--src/libstd/sys/sgx/condvar.rs2
-rw-r--r--src/libstd/sys/sgx/ext/arch.rs8
-rw-r--r--src/libstd/sys/sgx/ext/ffi.rs137
-rw-r--r--src/libstd/sys/sgx/fd.rs14
-rw-r--r--src/libstd/sys/sgx/fs.rs18
-rw-r--r--src/libstd/sys/sgx/io.rs30
-rw-r--r--src/libstd/sys/sgx/mod.rs18
-rw-r--r--src/libstd/sys/sgx/net.rs86
-rw-r--r--src/libstd/sys/sgx/os.rs8
-rw-r--r--src/libstd/sys/sgx/os_str.rs180
-rw-r--r--src/libstd/sys/sgx/path.rs2
-rw-r--r--src/libstd/sys/sgx/pipe.rs15
-rw-r--r--src/libstd/sys/sgx/process.rs6
-rw-r--r--src/libstd/sys/sgx/rwlock.rs89
-rw-r--r--src/libstd/sys/sgx/stack_overflow.rs1
-rw-r--r--src/libstd/sys/sgx/stdio.rs18
-rw-r--r--src/libstd/sys/sgx/thread.rs27
-rw-r--r--src/libstd/sys/sgx/time.rs4
-rw-r--r--src/libstd/sys/sgx/waitqueue.rs44
-rw-r--r--src/libstd/sys/unix/alloc.rs12
-rw-r--r--src/libstd/sys/unix/args.rs4
-rw-r--r--src/libstd/sys/unix/condvar.rs18
-rw-r--r--src/libstd/sys/unix/env.rs22
-rw-r--r--src/libstd/sys/unix/ext/ffi.rs137
-rw-r--r--src/libstd/sys/unix/ext/fs.rs2
-rw-r--r--src/libstd/sys/unix/ext/io.rs15
-rw-r--r--src/libstd/sys/unix/ext/net.rs43
-rw-r--r--src/libstd/sys/unix/fast_thread_local.rs6
-rw-r--r--src/libstd/sys/unix/fd.rs14
-rw-r--r--src/libstd/sys/unix/fs.rs325
-rw-r--r--src/libstd/sys/unix/io.rs41
-rw-r--r--src/libstd/sys/unix/l4re.rs21
-rw-r--r--src/libstd/sys/unix/mod.rs7
-rw-r--r--src/libstd/sys/unix/mutex.rs24
-rw-r--r--src/libstd/sys/unix/net.rs6
-rw-r--r--src/libstd/sys/unix/os.rs39
-rw-r--r--src/libstd/sys/unix/path.rs2
-rw-r--r--src/libstd/sys/unix/pipe.rs13
-rw-r--r--src/libstd/sys/unix/process/process_common.rs28
-rw-r--r--src/libstd/sys/unix/process/process_unix.rs115
-rw-r--r--src/libstd/sys/unix/rand.rs29
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs7
-rw-r--r--src/libstd/sys/unix/stdio.rs30
-rw-r--r--src/libstd/sys/unix/thread.rs30
-rw-r--r--src/libstd/sys/unix/time.rs67
-rw-r--r--src/libstd/sys/vxworks/alloc.rs53
-rw-r--r--src/libstd/sys/vxworks/args.rs (renamed from src/libstd/sys/redox/args.rs)49
-rw-r--r--src/libstd/sys/vxworks/backtrace/mod.rs (renamed from src/libstd/sys/unix/backtrace/mod.rs)0
-rw-r--r--src/libstd/sys/vxworks/backtrace/printing/dladdr.rs (renamed from src/libstd/sys/unix/backtrace/printing/dladdr.rs)1
-rw-r--r--src/libstd/sys/vxworks/backtrace/printing/mod.rs (renamed from src/libstd/sys/unix/backtrace/printing/mod.rs)0
-rw-r--r--src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs (renamed from src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs)0
-rw-r--r--src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs (renamed from src/libstd/sys/unix/backtrace/tracing/gcc_s.rs)6
-rw-r--r--src/libstd/sys/vxworks/backtrace/tracing/mod.rs (renamed from src/libstd/sys/unix/backtrace/tracing/mod.rs)0
-rw-r--r--src/libstd/sys/vxworks/cmath.rs (renamed from src/libstd/sys/redox/cmath.rs)0
-rw-r--r--src/libstd/sys/vxworks/condvar.rs96
-rw-r--r--src/libstd/sys/vxworks/env.rs (renamed from src/libstd/sys/redox/env.rs)4
-rw-r--r--src/libstd/sys/vxworks/ext/ffi.rs38
-rw-r--r--src/libstd/sys/vxworks/ext/fs.rs801
-rw-r--r--src/libstd/sys/vxworks/ext/io.rs (renamed from src/libstd/sys/redox/ext/io.rs)79
-rw-r--r--src/libstd/sys/vxworks/ext/mod.rs20
-rw-r--r--src/libstd/sys/vxworks/ext/net.rs1825
-rw-r--r--src/libstd/sys/vxworks/ext/process.rs (renamed from src/libstd/sys/redox/ext/process.rs)32
-rw-r--r--src/libstd/sys/vxworks/ext/raw.rs5
-rw-r--r--src/libstd/sys/vxworks/fast_thread_local.rs36
-rw-r--r--src/libstd/sys/vxworks/fd.rs188
-rw-r--r--src/libstd/sys/vxworks/fs.rs575
-rw-r--r--src/libstd/sys/vxworks/io.rs86
-rw-r--r--src/libstd/sys/vxworks/memchr.rs24
-rw-r--r--src/libstd/sys/vxworks/mod.rs125
-rw-r--r--src/libstd/sys/vxworks/mutex.rs127
-rw-r--r--src/libstd/sys/vxworks/net.rs357
-rw-r--r--src/libstd/sys/vxworks/os.rs (renamed from src/libstd/sys/redox/os.rs)195
-rw-r--r--src/libstd/sys/vxworks/path.rs19
-rw-r--r--src/libstd/sys/vxworks/pipe.rs95
-rw-r--r--src/libstd/sys/vxworks/process/mod.rs7
-rw-r--r--src/libstd/sys/vxworks/process/process_common.rs405
-rw-r--r--src/libstd/sys/vxworks/process/process_vxworks.rs156
-rw-r--r--src/libstd/sys/vxworks/process/rtp.rs298
-rw-r--r--src/libstd/sys/vxworks/rand.rs31
-rw-r--r--src/libstd/sys/vxworks/rwlock.rs113
-rw-r--r--src/libstd/sys/vxworks/stack_overflow.rs41
-rw-r--r--src/libstd/sys/vxworks/stdio.rs (renamed from src/libstd/sys/redox/stdio.rs)19
-rw-r--r--src/libstd/sys/vxworks/thread.rs143
-rw-r--r--src/libstd/sys/vxworks/thread_local.rs34
-rw-r--r--src/libstd/sys/vxworks/time.rs224
-rw-r--r--src/libstd/sys/vxworks/weak.rs60
-rw-r--r--src/libstd/sys/wasi/alloc.rs43
-rw-r--r--src/libstd/sys/wasi/args.rs76
-rw-r--r--src/libstd/sys/wasi/env.rs9
-rw-r--r--src/libstd/sys/wasi/ext/ffi.rs6
-rw-r--r--src/libstd/sys/wasi/ext/fs.rs412
-rw-r--r--src/libstd/sys/wasi/ext/io.rs142
-rw-r--r--src/libstd/sys/wasi/ext/mod.rs18
-rw-r--r--src/libstd/sys/wasi/fd.rs350
-rw-r--r--src/libstd/sys/wasi/fs.rs691
-rw-r--r--src/libstd/sys/wasi/io.rs87
-rw-r--r--src/libstd/sys/wasi/mod.rs128
-rw-r--r--src/libstd/sys/wasi/net.rs426
-rw-r--r--src/libstd/sys/wasi/os.rs184
-rw-r--r--src/libstd/sys/wasi/path.rs19
-rw-r--r--src/libstd/sys/wasi/pipe.rs33
-rw-r--r--src/libstd/sys/wasi/process.rs152
-rw-r--r--src/libstd/sys/wasi/stdio.rs81
-rw-r--r--src/libstd/sys/wasi/thread.rs56
-rw-r--r--src/libstd/sys/wasi/time.rs76
-rw-r--r--src/libstd/sys/wasm/alloc.rs95
-rw-r--r--src/libstd/sys/wasm/backtrace.rs27
-rw-r--r--src/libstd/sys/wasm/fast_thread_local.rs9
-rw-r--r--src/libstd/sys/wasm/fs.rs18
-rw-r--r--src/libstd/sys/wasm/io.rs30
-rw-r--r--src/libstd/sys/wasm/mod.rs12
-rw-r--r--src/libstd/sys/wasm/net.rs16
-rw-r--r--src/libstd/sys/wasm/os.rs4
-rw-r--r--src/libstd/sys/wasm/os_str.rs180
-rw-r--r--src/libstd/sys/wasm/path.rs2
-rw-r--r--src/libstd/sys/wasm/pipe.rs10
-rw-r--r--src/libstd/sys/wasm/process.rs6
-rw-r--r--src/libstd/sys/wasm/thread.rs79
-rw-r--r--src/libstd/sys/wasm/thread_local.rs32
-rw-r--r--src/libstd/sys/wasm/thread_local_atomics.rs61
-rw-r--r--src/libstd/sys/wasm/time.rs4
-rw-r--r--src/libstd/sys/windows/args.rs4
-rw-r--r--src/libstd/sys/windows/backtrace/backtrace_gnu.rs53
-rw-r--r--src/libstd/sys/windows/backtrace/mod.rs355
-rw-r--r--src/libstd/sys/windows/backtrace/printing/mod.rs24
-rw-r--r--src/libstd/sys/windows/backtrace/printing/msvc.rs208
-rw-r--r--src/libstd/sys/windows/c.rs592
-rw-r--r--src/libstd/sys/windows/compat.rs2
-rw-r--r--src/libstd/sys/windows/dynamic_lib.rs44
-rw-r--r--src/libstd/sys/windows/ext/ffi.rs4
-rw-r--r--src/libstd/sys/windows/ext/fs.rs30
-rw-r--r--src/libstd/sys/windows/ext/io.rs21
-rw-r--r--src/libstd/sys/windows/fast_thread_local.rs4
-rw-r--r--src/libstd/sys/windows/fs.rs102
-rw-r--r--src/libstd/sys/windows/handle.rs14
-rw-r--r--src/libstd/sys/windows/io.rs41
-rw-r--r--src/libstd/sys/windows/mod.rs19
-rw-r--r--src/libstd/sys/windows/mutex.rs2
-rw-r--r--src/libstd/sys/windows/net.rs57
-rw-r--r--src/libstd/sys/windows/os.rs27
-rw-r--r--src/libstd/sys/windows/os_str.rs10
-rw-r--r--src/libstd/sys/windows/path.rs2
-rw-r--r--src/libstd/sys/windows/pipe.rs27
-rw-r--r--src/libstd/sys/windows/process.rs11
-rw-r--r--src/libstd/sys/windows/rand.rs18
-rw-r--r--src/libstd/sys/windows/stack_overflow_uwp.rs (renamed from src/libstd/sys/redox/stack_overflow.rs)10
-rw-r--r--src/libstd/sys/windows/stdio_uwp.rs85
-rw-r--r--src/libstd/sys/windows/thread.rs3
-rw-r--r--src/libstd/sys/windows/time.rs34
-rw-r--r--src/libstd/sys_common/alloc.rs3
-rw-r--r--src/libstd/sys_common/at_exit_imp.rs5
-rw-r--r--src/libstd/sys_common/backtrace.rs305
-rw-r--r--src/libstd/sys_common/bytestring.rs6
-rw-r--r--src/libstd/sys_common/fs.rs41
-rw-r--r--src/libstd/sys_common/gnu/libbacktrace.rs175
-rw-r--r--src/libstd/sys_common/gnu/mod.rs5
-rw-r--r--src/libstd/sys_common/io.rs2
-rw-r--r--src/libstd/sys_common/mod.rs28
-rw-r--r--src/libstd/sys_common/mutex.rs2
-rw-r--r--src/libstd/sys_common/net.rs22
-rw-r--r--src/libstd/sys_common/os_str_bytes.rs (renamed from src/libstd/sys/unix/os_str.rs)87
-rw-r--r--src/libstd/sys_common/poison.rs8
-rw-r--r--src/libstd/sys_common/remutex.rs10
-rw-r--r--src/libstd/sys_common/thread.rs3
-rw-r--r--src/libstd/sys_common/util.rs4
-rw-r--r--src/libstd/sys_common/wtf8.rs28
-rw-r--r--src/libstd/thread/local.rs313
-rw-r--r--src/libstd/thread/mod.rs39
-rw-r--r--src/libstd/time.rs50
311 files changed, 15709 insertions, 14683 deletions
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 1a6b58f35b3..5334c4dfc68 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -3,7 +3,7 @@ authors = ["The Rust Project Developers"]
 name = "std"
 version = "0.0.0"
 build = "build.rs"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust.git"
 description = "The Rust Standard Library"
 edition = "2018"
@@ -15,15 +15,27 @@ crate-type = ["dylib", "rlib"]
 
 [dependencies]
 alloc = { path = "../liballoc" }
+cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
 core = { path = "../libcore" }
-libc = { version = "0.2.44", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.1" }
+libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.16" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
-rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] }
-backtrace-sys = { version = "0.1.24", features = ["rustc-dep-of-std"], optional = true }
+hashbrown = { version = "0.4.0", features = ['rustc-dep-of-std'] }
+
+[dependencies.backtrace]
+version = "0.3.34"
+default-features = false # don't use coresymbolication on OSX
+features = [
+  "rustc-dep-of-std", # enable build support for integrating into libstd
+  "dbghelp",          # backtrace/symbolize on MSVC
+  "libbacktrace",     # symbolize on most platforms
+  "libunwind",        # backtrace on most platforms
+  "dladdr",           # symbolize on platforms w/o libbacktrace
+]
+optional = true
 
 [dev-dependencies]
 rand = "0.6.1"
@@ -48,12 +60,12 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 cc = "1.0"
 
 [features]
-default = ["compiler_builtins_c", "std_detect_file_io", "std_detect_dlsym_getauxval"]
+default = ["std_detect_file_io", "std_detect_dlsym_getauxval"]
 
-backtrace = ["backtrace-sys"]
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
-compiler_builtins_c = ["compiler_builtins/c"]
+compiler-builtins-c = ["alloc/compiler-builtins-c"]
+llvm-libunwind = ["unwind/llvm-libunwind"]
 
 # Make panics and failed asserts immediately abort without formatting any message
 panic_immediate_abort = ["core/panic_immediate_abort"]
@@ -63,12 +75,13 @@ panic_immediate_abort = ["core/panic_immediate_abort"]
 # requires rebuilding the standard library to use it.
 wasm_syscall = []
 
-# An off-by-default features to enable libstd to assume that wasm-bindgen is in
-# the environment for hooking up some thread-related information like the
-# current thread id and accessing/getting the current thread's TCB
-wasm-bindgen-threads = []
-
-# Enable std_detect default features for stdsimd:
-# https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/std_detect/Cargo.toml
+# Enable std_detect default features for stdarch/crates/std_detect:
+# https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
 std_detect_file_io = []
 std_detect_dlsym_getauxval = []
+
+[package.metadata.fortanix-sgx]
+# Maximum possible number of threads when testing
+threads = 125
+# Maximum heap size
+heap_size = 0x8000000
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
index a13da2901df..ff52974775b 100644
--- a/src/libstd/alloc.rs
+++ b/src/libstd/alloc.rs
@@ -130,7 +130,7 @@ pub use alloc_crate::alloc::*;
 /// program opts in to using jemalloc as the global allocator, `System` will
 /// still allocate memory using `malloc` and `HeapAlloc`.
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Default, Copy, Clone)]
 pub struct System;
 
 // The Alloc impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`.
@@ -173,6 +173,9 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
 /// about the allocation that failed.
 ///
 /// The allocation error hook is a global resource.
+///
+/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html
+/// [`take_alloc_error_hook`]: fn.take_alloc_error_hook.html
 #[unstable(feature = "alloc_error_hook", issue = "51245")]
 pub fn set_alloc_error_hook(hook: fn(Layout)) {
     HOOK.store(hook as *mut (), Ordering::SeqCst);
@@ -183,6 +186,8 @@ pub fn set_alloc_error_hook(hook: fn(Layout)) {
 /// *See also the function [`set_alloc_error_hook`].*
 ///
 /// If no custom hook is registered, the default hook will be returned.
+///
+/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html
 #[unstable(feature = "alloc_error_hook", issue = "51245")]
 pub fn take_alloc_error_hook() -> fn(Layout) {
     let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 726c2732153..8db7bc12cd3 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -1,5 +1,3 @@
-#![deny(warnings)]
-
 use std::env;
 
 fn main() {
@@ -20,8 +18,7 @@ fn main() {
     } else if target.contains("netbsd") {
         println!("cargo:rustc-link-lib=pthread");
         println!("cargo:rustc-link-lib=rt");
-    } else if target.contains("dragonfly") || target.contains("bitrig") ||
-              target.contains("openbsd") {
+    } else if target.contains("dragonfly") || target.contains("openbsd") {
         println!("cargo:rustc-link-lib=pthread");
     } else if target.contains("solaris") {
         println!("cargo:rustc-link-lib=socket");
@@ -40,6 +37,10 @@ fn main() {
         println!("cargo:rustc-link-lib=framework=Security");
         println!("cargo:rustc-link-lib=framework=Foundation");
         println!("cargo:rustc-link-lib=resolv");
+    } else if target.contains("uwp") {
+        println!("cargo:rustc-link-lib=ws2_32");
+        // For BCryptGenRandom
+        println!("cargo:rustc-link-lib=bcrypt");
     } else if target.contains("windows") {
         println!("cargo:rustc-link-lib=advapi32");
         println!("cargo:rustc-link-lib=ws2_32");
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 928de29b297..1e28ee8da26 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1,222 +1,20 @@
+// ignore-tidy-filelength
+
 use self::Entry::*;
-use self::VacantEntryState::*;
 
-use crate::intrinsics::unlikely;
-use crate::collections::CollectionAllocErr;
-use crate::cell::Cell;
+use hashbrown::hash_map as base;
+
 use crate::borrow::Borrow;
-use crate::cmp::max;
+use crate::cell::Cell;
+use crate::collections::CollectionAllocErr;
 use crate::fmt::{self, Debug};
 #[allow(deprecated)]
-use crate::hash::{Hash, Hasher, BuildHasher, SipHasher13};
+use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13};
 use crate::iter::{FromIterator, FusedIterator};
-use crate::mem::{self, replace};
-use crate::ops::{Deref, DerefMut, Index};
+use crate::ops::Index;
 use crate::sys;
 
-use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucketMut, RawTable,
-                   SafeHash};
-use super::table::BucketState::{Empty, Full};
-use super::table::Fallibility::{Fallible, Infallible};
-
-const MIN_NONZERO_RAW_CAPACITY: usize = 32;     // must be a power of two
-
-/// The default behavior of HashMap implements a maximum load factor of 90.9%.
-#[derive(Clone)]
-struct DefaultResizePolicy;
-
-impl DefaultResizePolicy {
-    #[inline]
-    fn new() -> DefaultResizePolicy {
-        DefaultResizePolicy
-    }
-
-    /// A hash map's "capacity" is the number of elements it can hold without
-    /// being resized. Its "raw capacity" is the number of slots required to
-    /// provide that capacity, accounting for maximum loading. The raw capacity
-    /// is always zero or a power of two.
-    #[inline]
-    fn try_raw_capacity(&self, len: usize) -> Result<usize, CollectionAllocErr> {
-        if len == 0 {
-            Ok(0)
-        } else {
-            // 1. Account for loading: `raw_capacity >= len * 1.1`.
-            // 2. Ensure it is a power of two.
-            // 3. Ensure it is at least the minimum size.
-            let mut raw_cap = len.checked_mul(11)
-                .map(|l| l / 10)
-                .and_then(|l| l.checked_next_power_of_two())
-                .ok_or(CollectionAllocErr::CapacityOverflow)?;
-
-            raw_cap = max(MIN_NONZERO_RAW_CAPACITY, raw_cap);
-            Ok(raw_cap)
-        }
-    }
-
-    #[inline]
-    fn raw_capacity(&self, len: usize) -> usize {
-        self.try_raw_capacity(len).expect("raw_capacity overflow")
-    }
-
-    /// The capacity of the given raw capacity.
-    #[inline]
-    fn capacity(&self, raw_cap: usize) -> usize {
-        // This doesn't have to be checked for overflow since allocation size
-        // in bytes will overflow earlier than multiplication by 10.
-        //
-        // As per https://github.com/rust-lang/rust/pull/30991 this is updated
-        // to be: (raw_cap * den + den - 1) / num
-        (raw_cap * 10 + 10 - 1) / 11
-    }
-}
-
-// The main performance trick in this hashmap is called Robin Hood Hashing.
-// It gains its excellent performance from one essential operation:
-//
-//    If an insertion collides with an existing element, and that element's
-//    "probe distance" (how far away the element is from its ideal location)
-//    is higher than how far we've already probed, swap the elements.
-//
-// This massively lowers variance in probe distance, and allows us to get very
-// high load factors with good performance. The 90% load factor I use is rather
-// conservative.
-//
-// > Why a load factor of approximately 90%?
-//
-// In general, all the distances to initial buckets will converge on the mean.
-// At a load factor of α, the odds of finding the target bucket after k
-// probes is approximately 1-α^k. If we set this equal to 50% (since we converge
-// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round
-// this down to make the math easier on the CPU and avoid its FPU.
-// Since on average we start the probing in the middle of a cache line, this
-// strategy pulls in two cache lines of hashes on every lookup. I think that's
-// pretty good, but if you want to trade off some space, it could go down to one
-// cache line on average with an α of 0.84.
-//
-// > Wait, what? Where did you get 1-α^k from?
-//
-// On the first probe, your odds of a collision with an existing element is α.
-// The odds of doing this twice in a row is approximately α^2. For three times,
-// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT
-// colliding after k tries is 1-α^k.
-//
-// The paper from 1986 cited below mentions an implementation which keeps track
-// of the distance-to-initial-bucket histogram. This approach is not suitable
-// for modern architectures because it requires maintaining an internal data
-// structure. This allows very good first guesses, but we are most concerned
-// with guessing entire cache lines, not individual indexes. Furthermore, array
-// accesses are no longer linear and in one direction, as we have now. There
-// is also memory and cache pressure that this would entail that would be very
-// difficult to properly see in a microbenchmark.
-//
-// ## Future Improvements (FIXME!)
-//
-// Allow the load factor to be changed dynamically and/or at initialization.
-//
-// Also, would it be possible for us to reuse storage when growing the
-// underlying table? This is exactly the use case for 'realloc', and may
-// be worth exploring.
-//
-// ## Future Optimizations (FIXME!)
-//
-// Another possible design choice that I made without any real reason is
-// parameterizing the raw table over keys and values. Technically, all we need
-// is the size and alignment of keys and values, and the code should be just as
-// efficient (well, we might need one for power-of-two size and one for not...).
-// This has the potential to reduce code bloat in rust executables, without
-// really losing anything except 4 words (key size, key alignment, val size,
-// val alignment) which can be passed in to every call of a `RawTable` function.
-// This would definitely be an avenue worth exploring if people start complaining
-// about the size of rust executables.
-//
-// Annotate exceedingly likely branches in `table::make_hash`
-// and `search_hashed` to reduce instruction cache pressure
-// and mispredictions once it becomes possible (blocked on issue #11092).
-//
-// Shrinking the table could simply reallocate in place after moving buckets
-// to the first half.
-//
-// The growth algorithm (fragment of the Proof of Correctness)
-// --------------------
-//
-// The growth algorithm is basically a fast path of the naive reinsertion-
-// during-resize algorithm. Other paths should never be taken.
-//
-// Consider growing a robin hood hashtable of capacity n. Normally, we do this
-// by allocating a new table of capacity `2n`, and then individually reinsert
-// each element in the old table into the new one. This guarantees that the
-// new table is a valid robin hood hashtable with all the desired statistical
-// properties. Remark that the order we reinsert the elements in should not
-// matter. For simplicity and efficiency, we will consider only linear
-// reinsertions, which consist of reinserting all elements in the old table
-// into the new one by increasing order of index. However we will not be
-// starting our reinsertions from index 0 in general. If we start from index
-// i, for the purpose of reinsertion we will consider all elements with real
-// index j < i to have virtual index n + j.
-//
-// Our hash generation scheme consists of generating a 64-bit hash and
-// truncating the most significant bits. When moving to the new table, we
-// simply introduce a new bit to the front of the hash. Therefore, if an
-// element has ideal index i in the old table, it can have one of two ideal
-// locations in the new table. If the new bit is 0, then the new ideal index
-// is i. If the new bit is 1, then the new ideal index is n + i. Intuitively,
-// we are producing two independent tables of size n, and for each element we
-// independently choose which table to insert it into with equal probability.
-// However, rather than wrapping around themselves on overflowing their
-// indexes, the first table overflows into the second, and the second into the
-// first. Visually, our new table will look something like:
-//
-// [yy_xxx_xxxx_xxx|xx_yyy_yyyy_yyy]
-//
-// Where x's are elements inserted into the first table, y's are elements
-// inserted into the second, and _'s are empty sections. We now define a few
-// key concepts that we will use later. Note that this is a very abstract
-// perspective of the table. A real resized table would be at least half
-// empty.
-//
-// Theorem: A linear robin hood reinsertion from the first ideal element
-// produces identical results to a linear naive reinsertion from the same
-// element.
-//
-// FIXME(Gankro, pczarn): review the proof and put it all in a separate README.md
-//
-// Adaptive early resizing
-// ----------------------
-// To protect against degenerate performance scenarios (including DOS attacks),
-// the implementation includes an adaptive behavior that can resize the map
-// early (before its capacity is exceeded) when suspiciously long probe sequences
-// are encountered.
-//
-// With this algorithm in place it would be possible to turn a CPU attack into
-// a memory attack due to the aggressive resizing. To prevent that the
-// adaptive behavior only triggers when the map is at least half full.
-// This reduces the effectiveness of the algorithm but also makes it completely safe.
-//
-// The previous safety measure also prevents degenerate interactions with
-// really bad quality hash algorithms that can make normal inputs look like a
-// DOS attack.
-//
-const DISPLACEMENT_THRESHOLD: usize = 128;
-//
-// The threshold of 128 is chosen to minimize the chance of exceeding it.
-// In particular, we want that chance to be less than 10^-8 with a load of 90%.
-// For displacement, the smallest constant that fits our needs is 90,
-// so we round that up to 128.
-//
-// At a load factor of α, the odds of finding the target bucket after exactly n
-// unsuccessful probes[1] are
-//
-// Pr_α{displacement = n} =
-// (1 - α) / α * ∑_{k≥1} e^(-kα) * (kα)^(k+n) / (k + n)! * (1 - kα / (k + n + 1))
-//
-// We use this formula to find the probability of triggering the adaptive behavior
-//
-// Pr_0.909{displacement > 128} = 1.601 * 10^-11
-//
-// 1. Alfredo Viola (2005). Distributional analysis of Robin Hood linear probing
-//    hashing with buckets.
-
-/// A hash map implemented with linear probing and Robin Hood bucket stealing.
+/// A hash map implemented with quadratic probing and SIMD lookup.
 ///
 /// By default, `HashMap` uses a hashing algorithm selected to provide
 /// resistance against HashDoS attacks. The algorithm is randomly seeded, and a
@@ -254,13 +52,13 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
 /// 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.
 ///
-/// Relevant papers/articles:
+/// The hash table implementation is a Rust port of Google's [SwissTable].
+/// The original C++ version of SwissTable can be found [here], and this
+/// [CppCon talk] gives an overview of how the algorithm works.
 ///
-/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf)
-/// 2. Emmanuel Goossaert. ["Robin Hood
-///    hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/)
-/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift
-///    deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/)
+/// [SwissTable]: https://abseil.io/blog/20180927-swisstables
+/// [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
+/// [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4
 ///
 /// # Examples
 ///
@@ -407,277 +205,7 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashMap<K, V, S = RandomState> {
-    // All hashes are keyed on these values, to prevent hash collision attacks.
-    hash_builder: S,
-
-    table: RawTable<K, V>,
-
-    resize_policy: DefaultResizePolicy,
-}
-
-/// Search for a pre-hashed key.
-/// If you don't already know the hash, use search or search_mut instead
-#[inline]
-fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, is_match: F) -> InternalEntry<K, V, M>
-    where M: Deref<Target = RawTable<K, V>>,
-          F: FnMut(&K) -> bool
-{
-    // This is the only function where capacity can be zero. To avoid
-    // undefined behavior when Bucket::new gets the raw bucket in this
-    // case, immediately return the appropriate search result.
-    if table.capacity() == 0 {
-        return InternalEntry::TableIsEmpty;
-    }
-
-    search_hashed_nonempty(table, hash, is_match, true)
-}
-
-/// Search for a pre-hashed key when the hash map is known to be non-empty.
-#[inline]
-fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F,
-                                      compare_hashes: bool)
-    -> InternalEntry<K, V, M>
-    where M: Deref<Target = RawTable<K, V>>,
-          F: FnMut(&K) -> bool
-{
-    // Do not check the capacity as an extra branch could slow the lookup.
-
-    let size = table.size();
-    let mut probe = Bucket::new(table, hash);
-    let mut displacement = 0;
-
-    loop {
-        let full = match probe.peek() {
-            Empty(bucket) => {
-                // Found a hole!
-                return InternalEntry::Vacant {
-                    hash,
-                    elem: NoElem(bucket, displacement),
-                };
-            }
-            Full(bucket) => bucket,
-        };
-
-        let probe_displacement = full.displacement();
-
-        if probe_displacement < displacement {
-            // Found a luckier bucket than me.
-            // We can finish the search early if we hit any bucket
-            // with a lower distance to initial bucket than we've probed.
-            return InternalEntry::Vacant {
-                hash,
-                elem: NeqElem(full, probe_displacement),
-            };
-        }
-
-        // If the hash doesn't match, it can't be this one..
-        if !compare_hashes || hash == full.hash() {
-            // If the key doesn't match, it can't be this one..
-            if is_match(full.read().0) {
-                return InternalEntry::Occupied { elem: full };
-            }
-        }
-        displacement += 1;
-        probe = full.next();
-        debug_assert!(displacement <= size);
-    }
-}
-
-/// Same as `search_hashed_nonempty` but for mutable access.
-#[inline]
-fn search_hashed_nonempty_mut<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F,
-                                          compare_hashes: bool)
-    -> InternalEntry<K, V, M>
-    where M: DerefMut<Target = RawTable<K, V>>,
-          F: FnMut(&K) -> bool
-{
-    // Do not check the capacity as an extra branch could slow the lookup.
-
-    let size = table.size();
-    let mut probe = Bucket::new(table, hash);
-    let mut displacement = 0;
-
-    loop {
-        let mut full = match probe.peek() {
-            Empty(bucket) => {
-                // Found a hole!
-                return InternalEntry::Vacant {
-                    hash,
-                    elem: NoElem(bucket, displacement),
-                };
-            }
-            Full(bucket) => bucket,
-        };
-
-        let probe_displacement = full.displacement();
-
-        if probe_displacement < displacement {
-            // Found a luckier bucket than me.
-            // We can finish the search early if we hit any bucket
-            // with a lower distance to initial bucket than we've probed.
-            return InternalEntry::Vacant {
-                hash,
-                elem: NeqElem(full, probe_displacement),
-            };
-        }
-
-        // If the hash doesn't match, it can't be this one..
-        if hash == full.hash() || !compare_hashes {
-            // If the key doesn't match, it can't be this one..
-            if is_match(full.read_mut().0) {
-                return InternalEntry::Occupied { elem: full };
-            }
-        }
-        displacement += 1;
-        probe = full.next();
-        debug_assert!(displacement <= size);
-    }
-}
-
-fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>)
-    -> (K, V, &mut RawTable<K, V>)
-{
-    let (empty, retkey, retval) = starting_bucket.take();
-    let mut gap = match empty.gap_peek() {
-        Ok(b) => b,
-        Err(b) => return (retkey, retval, b.into_table()),
-    };
-
-    while gap.full().displacement() != 0 {
-        gap = match gap.shift() {
-            Ok(b) => b,
-            Err(b) => {
-                return (retkey, retval, b.into_table());
-            },
-        };
-    }
-
-    // Now we've done all our shifting. Return the value we grabbed earlier.
-    (retkey, retval, gap.into_table())
-}
-
-/// Performs robin hood bucket stealing at the given `bucket`. You must
-/// also pass that bucket's displacement so we don't have to recalculate it.
-///
-/// `hash`, `key`, and `val` are the elements to "robin hood" into the hashtable.
-fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
-                                mut displacement: usize,
-                                mut hash: SafeHash,
-                                mut key: K,
-                                mut val: V)
-                                -> FullBucketMut<'a, K, V> {
-    let size = bucket.table().size();
-    let raw_capacity = bucket.table().capacity();
-    // There can be at most `size - dib` buckets to displace, because
-    // in the worst case, there are `size` elements and we already are
-    // `displacement` buckets away from the initial one.
-    let idx_end = (bucket.index() + size - bucket.displacement()) % raw_capacity;
-    // Save the *starting point*.
-    let mut bucket = bucket.stash();
-
-    loop {
-        let (old_hash, old_key, old_val) = bucket.replace(hash, key, val);
-        hash = old_hash;
-        key = old_key;
-        val = old_val;
-
-        loop {
-            displacement += 1;
-            let probe = bucket.next();
-            debug_assert!(probe.index() != idx_end);
-
-            let full_bucket = match probe.peek() {
-                Empty(bucket) => {
-                    // Found a hole!
-                    let bucket = bucket.put(hash, key, val);
-                    // Now that it's stolen, just read the value's pointer
-                    // right out of the table! Go back to the *starting point*.
-                    //
-                    // This use of `into_table` is misleading. It turns the
-                    // bucket, which is a FullBucket on top of a
-                    // FullBucketMut, into just one FullBucketMut. The "table"
-                    // refers to the inner FullBucketMut in this context.
-                    return bucket.into_table();
-                }
-                Full(bucket) => bucket,
-            };
-
-            let probe_displacement = full_bucket.displacement();
-
-            bucket = full_bucket;
-
-            // Robin hood! Steal the spot.
-            if probe_displacement < displacement {
-                displacement = probe_displacement;
-                break;
-            }
-        }
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash,
-          S: BuildHasher
-{
-    fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash
-        where X: Hash
-    {
-        table::make_hash(&self.hash_builder, x)
-    }
-
-    /// Search for a key, yielding the index if it's found in the hashtable.
-    /// If you already have the hash for the key lying around, or if you need an
-    /// InternalEntry, use search_hashed or search_hashed_nonempty.
-    #[inline]
-    fn search<'a, Q: ?Sized>(&'a self, q: &Q)
-        -> Option<FullBucket<K, V, &'a RawTable<K, V>>>
-        where K: Borrow<Q>,
-              Q: Eq + Hash
-    {
-        if self.is_empty() {
-            return None;
-        }
-
-        let hash = self.make_hash(q);
-        search_hashed_nonempty(&self.table, hash, |k| q.eq(k.borrow()), true)
-            .into_occupied_bucket()
-    }
-
-    #[inline]
-    fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q)
-        -> Option<FullBucket<K, V, &'a mut RawTable<K, V>>>
-        where K: Borrow<Q>,
-              Q: Eq + Hash
-    {
-        if self.is_empty() {
-            return None;
-        }
-
-        let hash = self.make_hash(q);
-        search_hashed_nonempty(&mut self.table, hash, |k| q.eq(k.borrow()), true)
-            .into_occupied_bucket()
-    }
-
-    // The caller should ensure that invariants by Robin Hood Hashing hold
-    // and that there's space in the underlying table.
-    fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
-        let mut buckets = Bucket::new(&mut self.table, hash);
-        let start_index = buckets.index();
-
-        loop {
-            // We don't need to compare hashes for value swap.
-            // Not even DIBs for Robin Hood.
-            buckets = match buckets.peek() {
-                Empty(empty) => {
-                    empty.put(hash, k, v);
-                    return;
-                }
-                Full(b) => b.into_bucket(),
-            };
-            buckets.next();
-            debug_assert!(buckets.index() != start_index);
-        }
-    }
+    base: base::HashMap<K, V, S>,
 }
 
 impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
@@ -732,13 +260,7 @@ impl<K, V, S> HashMap<K, V, S> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> usize {
-        self.resize_policy.capacity(self.raw_capacity())
-    }
-
-    /// Returns the hash map's raw capacity.
-    #[inline]
-    fn raw_capacity(&self) -> usize {
-        self.table.capacity()
+        self.base.capacity()
     }
 
     /// An iterator visiting all keys in arbitrary order.
@@ -759,7 +281,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn keys(&self) -> Keys<K, V> {
+    pub fn keys(&self) -> Keys<'_, K, V> {
         Keys { inner: self.iter() }
     }
 
@@ -781,7 +303,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn values(&self) -> Values<K, V> {
+    pub fn values(&self) -> Values<'_, K, V> {
         Values { inner: self.iter() }
     }
 
@@ -808,7 +330,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     /// ```
     #[stable(feature = "map_values_mut", since = "1.10.0")]
-    pub fn values_mut(&mut self) -> ValuesMut<K, V> {
+    pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
         ValuesMut { inner: self.iter_mut() }
     }
 
@@ -830,8 +352,8 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter<K, V> {
-        Iter { inner: self.table.iter() }
+    pub fn iter(&self) -> Iter<'_, K, V> {
+        Iter { base: self.base.iter() }
     }
 
     /// An iterator visiting all key-value pairs in arbitrary order,
@@ -858,8 +380,8 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter_mut(&mut self) -> IterMut<K, V> {
-        IterMut { inner: self.table.iter_mut() }
+    pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
+        IterMut { base: self.base.iter_mut() }
     }
 
     /// Returns the number of elements in the map.
@@ -876,7 +398,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
-        self.table.size()
+        self.base.len()
     }
 
     /// Returns `true` if the map contains no elements.
@@ -894,7 +416,7 @@ impl<K, V, S> HashMap<K, V, S> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
-        self.len() == 0
+        self.base.is_empty()
     }
 
     /// Clears the map, returning all key-value pairs as an iterator. Keeps the
@@ -918,8 +440,8 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ```
     #[inline]
     #[stable(feature = "drain", since = "1.6.0")]
-    pub fn drain(&mut self) -> Drain<K, V> {
-        Drain { inner: self.table.drain() }
+    pub fn drain(&mut self) -> Drain<'_, K, V> {
+        Drain { base: self.base.drain() }
     }
 
     /// Clears the map, removing all key-value pairs. Keeps the allocated memory
@@ -938,13 +460,14 @@ impl<K, V, S> HashMap<K, V, S> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn clear(&mut self) {
-        self.drain();
+        self.base.clear();
     }
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash,
-          S: BuildHasher
+where
+    K: Eq + Hash,
+    S: BuildHasher,
 {
     /// Creates an empty `HashMap` which will use the given hash builder to hash
     /// keys.
@@ -970,9 +493,7 @@ impl<K, V, S> HashMap<K, V, S>
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap {
-            hash_builder,
-            resize_policy: DefaultResizePolicy::new(),
-            table: RawTable::new(0),
+            base: base::HashMap::with_hasher(hash_builder),
         }
     }
 
@@ -1000,12 +521,8 @@ impl<K, V, S> HashMap<K, V, S>
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
-        let resize_policy = DefaultResizePolicy::new();
-        let raw_cap = resize_policy.raw_capacity(capacity);
         HashMap {
-            hash_builder,
-            resize_policy,
-            table: RawTable::new(raw_cap),
+            base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder),
         }
     }
 
@@ -1023,9 +540,10 @@ impl<K, V, S> HashMap<K, V, S>
     /// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
     /// let hasher: &RandomState = map.hasher();
     /// ```
+    #[inline]
     #[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
     pub fn hasher(&self) -> &S {
-        &self.hash_builder
+        self.base.hasher()
     }
 
     /// Reserves capacity for at least `additional` more elements to be inserted
@@ -1048,11 +566,7 @@ impl<K, V, S> HashMap<K, V, S>
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: usize) {
-        match self.reserve_internal(additional, Infallible) {
-            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => unreachable!(),
-            Ok(()) => { /* yay */ }
-        }
+        self.base.reserve(additional)
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
@@ -1072,92 +586,12 @@ impl<K, V, S> HashMap<K, V, S>
     /// let mut map: HashMap<&str, isize> = HashMap::new();
     /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
     /// ```
-    #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
-        self.reserve_internal(additional, Fallible)
-    }
-
     #[inline]
-    fn reserve_internal(&mut self, additional: usize, fallibility: Fallibility)
-        -> Result<(), CollectionAllocErr> {
-
-        let remaining = self.capacity() - self.len(); // this can't overflow
-        if remaining < additional {
-            let min_cap = self.len()
-                .checked_add(additional)
-                .ok_or(CollectionAllocErr::CapacityOverflow)?;
-            let raw_cap = self.resize_policy.try_raw_capacity(min_cap)?;
-            self.try_resize(raw_cap, fallibility)?;
-        } else if self.table.tag() && remaining <= self.len() {
-            // Probe sequence is too long and table is half full,
-            // resize early to reduce probing length.
-            let new_capacity = self.table.capacity() * 2;
-            self.try_resize(new_capacity, fallibility)?;
-        }
-        Ok(())
-    }
-
-    /// Resizes the internal vectors to a new capacity. It's your
-    /// responsibility to:
-    ///   1) Ensure `new_raw_cap` is enough for all the elements, accounting
-    ///      for the load factor.
-    ///   2) Ensure `new_raw_cap` is a power of two or zero.
-    #[inline(never)]
-    #[cold]
-    fn try_resize(
-        &mut self,
-        new_raw_cap: usize,
-        fallibility: Fallibility,
-    ) -> Result<(), CollectionAllocErr> {
-        assert!(self.table.size() <= new_raw_cap);
-        assert!(new_raw_cap.is_power_of_two() || new_raw_cap == 0);
-
-        let mut old_table = replace(
-            &mut self.table,
-            match fallibility {
-                Infallible => RawTable::new(new_raw_cap),
-                Fallible => RawTable::try_new(new_raw_cap)?,
-            }
-        );
-        let old_size = old_table.size();
-
-        if old_table.size() == 0 {
-            return Ok(());
-        }
-
-        let mut bucket = Bucket::head_bucket(&mut old_table);
-
-        // This is how the buckets might be laid out in memory:
-        // ($ marks an initialized bucket)
-        //  ________________
-        // |$$$_$$$$$$_$$$$$|
-        //
-        // But we've skipped the entire initial cluster of buckets
-        // and will continue iteration in this order:
-        //  ________________
-        //     |$$$$$$_$$$$$
-        //                  ^ wrap around once end is reached
-        //  ________________
-        //  $$$_____________|
-        //    ^ exit once table.size == 0
-        loop {
-            bucket = match bucket.peek() {
-                Full(bucket) => {
-                    let h = bucket.hash();
-                    let (b, k, v) = bucket.take();
-                    self.insert_hashed_ordered(h, k, v);
-                    if b.table().size() == 0 {
-                        break;
-                    }
-                    b.into_bucket()
-                }
-                Empty(b) => b.into_bucket(),
-            };
-            bucket.next();
-        }
-
-        assert_eq!(self.table.size(), old_size);
-        Ok(())
+    #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+        self.base
+            .try_reserve(additional)
+            .map_err(map_collection_alloc_err)
     }
 
     /// Shrinks the capacity of the map as much as possible. It will drop
@@ -1176,20 +610,10 @@ impl<K, V, S> HashMap<K, V, S>
     /// map.shrink_to_fit();
     /// assert!(map.capacity() >= 2);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
-        let new_raw_cap = self.resize_policy.raw_capacity(self.len());
-        if self.raw_capacity() != new_raw_cap {
-            let old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
-            let old_size = old_table.size();
-
-            // Shrink the table. Naive algorithm for resizing:
-            for (h, k, v) in old_table.into_iter() {
-                self.insert_hashed_nocheck(h, k, v);
-            }
-
-            debug_assert_eq!(self.table.size(), old_size);
-        }
+        self.base.shrink_to_fit();
     }
 
     /// Shrinks the capacity of the map with a lower limit. It will drop
@@ -1214,40 +638,14 @@ impl<K, V, S> HashMap<K, V, S>
     /// map.shrink_to(0);
     /// assert!(map.capacity() >= 2);
     /// ```
-    #[unstable(feature = "shrink_to", reason = "new API", issue="56431")]
+    #[inline]
+    #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
     pub fn shrink_to(&mut self, min_capacity: usize) {
-        assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity");
-
-        let new_raw_cap = self.resize_policy.raw_capacity(max(self.len(), min_capacity));
-        if self.raw_capacity() != new_raw_cap {
-            let old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
-            let old_size = old_table.size();
-
-            // Shrink the table. Naive algorithm for resizing:
-            for (h, k, v) in old_table.into_iter() {
-                self.insert_hashed_nocheck(h, k, v);
-            }
-
-            debug_assert_eq!(self.table.size(), old_size);
-        }
-    }
-
-    /// Insert a pre-hashed key-value pair, without first checking
-    /// that there's enough room in the buckets. Returns a reference to the
-    /// newly insert value.
-    ///
-    /// If the key already exists, the hashtable will be returned untouched
-    /// and a reference to the existing element will be returned.
-    fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> Option<V> {
-        let entry = search_hashed(&mut self.table, hash, |key| *key == k).into_entry(k);
-        match entry {
-            Some(Occupied(mut elem)) => Some(elem.insert(v)),
-            Some(Vacant(elem)) => {
-                elem.insert(v);
-                None
-            }
-            None => unreachable!(),
-        }
+        assert!(
+            self.capacity() >= min_capacity,
+            "Tried to shrink to a larger capacity"
+        );
+        self.base.shrink_to(min_capacity);
     }
 
     /// Gets the given key's corresponding entry in the map for in-place manipulation.
@@ -1269,13 +667,10 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(letters[&'u'], 1);
     /// assert_eq!(letters.get(&'y'), None);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn entry(&mut self, key: K) -> Entry<K, V> {
-        // Gotta resize now.
-        self.reserve(1);
-        let hash = self.make_hash(&key);
-        search_hashed(&mut self.table, hash, |q| q.eq(&key))
-            .into_entry(key).expect("unreachable")
+    pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
+        map_entry(self.base.rustc_entry(key))
     }
 
     /// Returns a reference to the value corresponding to the key.
@@ -1300,10 +695,11 @@ impl<K, V, S> HashMap<K, V, S>
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        self.search(k).map(|bucket| bucket.into_refs().1)
+        self.base.get(k)
     }
 
     /// Returns the key-value pair corresponding to the supplied key.
@@ -1327,11 +723,13 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map.get_key_value(&2), None);
     /// ```
     #[unstable(feature = "map_get_key_value", issue = "49347")]
+    #[inline]
     pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        self.search(k).map(|bucket| bucket.into_refs())
+        self.base.get_key_value(k)
     }
 
     /// Returns `true` if the map contains a value for the specified key.
@@ -1354,11 +752,13 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        self.search(k).is_some()
+        self.base.contains_key(k)
     }
 
     /// Returns a mutable reference to the value corresponding to the key.
@@ -1383,11 +783,13 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map[&1], "b");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
+        self.base.get_mut(k)
     }
 
     /// Inserts a key-value pair into the map.
@@ -1416,10 +818,9 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map[&37], "c");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
-        let hash = self.make_hash(&k);
-        self.reserve(1);
-        self.insert_hashed_nocheck(hash, k, v)
+        self.base.insert(k, v)
     }
 
     /// Removes a key from the map, returning the value at the key if the key
@@ -1443,11 +844,13 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map.remove(&1), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        self.search_mut(k).map(|bucket| pop_internal(bucket).1)
+        self.base.remove(k)
     }
 
     /// Removes a key from the map, returning the stored key and value if the
@@ -1473,15 +876,13 @@ impl<K, V, S> HashMap<K, V, S>
     /// # }
     /// ```
     #[stable(feature = "hash_map_remove_entry", since = "1.27.0")]
+    #[inline]
     pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        self.search_mut(k)
-            .map(|bucket| {
-                let (k, v, _) = pop_internal(bucket);
-                (k, v)
-            })
+        self.base.remove_entry(k)
     }
 
     /// Retains only the elements specified by the predicate.
@@ -1498,45 +899,18 @@ impl<K, V, S> HashMap<K, V, S>
     /// assert_eq!(map.len(), 4);
     /// ```
     #[stable(feature = "retain_hash_collection", since = "1.18.0")]
-    pub fn retain<F>(&mut self, mut f: F)
-        where F: FnMut(&K, &mut V) -> bool
+    #[inline]
+    pub fn retain<F>(&mut self, f: F)
+    where
+        F: FnMut(&K, &mut V) -> bool,
     {
-        if self.table.size() == 0 {
-            return;
-        }
-        let mut elems_left = self.table.size();
-        let mut bucket = Bucket::head_bucket(&mut self.table);
-        bucket.prev();
-        let start_index = bucket.index();
-        while elems_left != 0 {
-            bucket = match bucket.peek() {
-                Full(mut full) => {
-                    elems_left -= 1;
-                    let should_remove = {
-                        let (k, v) = full.read_mut();
-                        !f(k, v)
-                    };
-                    if should_remove {
-                        let prev_raw = full.raw();
-                        let (_, _, t) = pop_internal(full);
-                        Bucket::new_from(prev_raw, t)
-                    } else {
-                        full.into_bucket()
-                    }
-                },
-                Empty(b) => {
-                    b.into_bucket()
-                }
-            };
-            bucket.prev();  // reverse iteration
-            debug_assert!(elems_left == 0 || bucket.index() != start_index);
-        }
+        self.base.retain(f)
     }
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash,
-          S: BuildHasher
+where
+    S: BuildHasher,
 {
     /// Creates a raw entry builder for the HashMap.
     ///
@@ -1569,10 +943,9 @@ impl<K, V, S> HashMap<K, V, S>
     /// so that the map now contains keys which compare equal, search may start
     /// acting erratically, with two keys randomly masking each other. Implementations
     /// are free to assume this doesn't happen (within the limits of memory-safety).
-    #[inline(always)]
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<K, V, S> {
-        self.reserve(1);
+    pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> {
         RawEntryBuilderMut { map: self }
     }
 
@@ -1591,52 +964,59 @@ impl<K, V, S> HashMap<K, V, S>
     /// `get` should be preferred.
     ///
     /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn raw_entry(&self) -> RawEntryBuilder<K, V, S> {
+    pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> {
         RawEntryBuilder { map: self }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> PartialEq for HashMap<K, V, S>
-    where K: Eq + Hash,
-          V: PartialEq,
-          S: BuildHasher
+where
+    K: Eq + Hash,
+    V: PartialEq,
+    S: BuildHasher,
 {
     fn eq(&self, other: &HashMap<K, V, S>) -> bool {
         if self.len() != other.len() {
             return false;
         }
 
-        self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
+        self.iter()
+            .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Eq for HashMap<K, V, S>
-    where K: Eq + Hash,
-          V: Eq,
-          S: BuildHasher
+where
+    K: Eq + Hash,
+    V: Eq,
+    S: BuildHasher,
 {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Debug for HashMap<K, V, S>
-    where K: Eq + Hash + Debug,
-          V: Debug,
-          S: BuildHasher
+where
+    K: Eq + Hash + Debug,
+    V: Debug,
+    S: BuildHasher,
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_map().entries(self.iter()).finish()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Default for HashMap<K, V, S>
-    where K: Eq + Hash,
-          S: BuildHasher + Default
+where
+    K: Eq + Hash,
+    S: BuildHasher + Default,
 {
     /// Creates an empty `HashMap<K, V, S>`, with the `Default` value for the hasher.
+    #[inline]
     fn default() -> HashMap<K, V, S> {
         HashMap::with_hasher(Default::default())
     }
@@ -1644,9 +1024,10 @@ impl<K, V, S> Default for HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, Q: ?Sized, V, S> Index<&Q> for HashMap<K, V, S>
-    where K: Eq + Hash + Borrow<Q>,
-          Q: Eq + Hash,
-          S: BuildHasher
+where
+    K: Eq + Hash + Borrow<Q>,
+    Q: Eq + Hash,
+    S: BuildHasher,
 {
     type Output = V;
 
@@ -1670,23 +1051,24 @@ impl<K, Q: ?Sized, V, S> Index<&Q> for HashMap<K, V, S>
 /// [`HashMap`]: struct.HashMap.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
-    inner: table::Iter<'a, K, V>,
+    base: base::Iter<'a, K, V>,
 }
 
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> Clone for Iter<'_, K, V> {
+    #[inline]
     fn clone(&self) -> Self {
-        Iter { inner: self.inner.clone() }
+        Iter {
+            base: self.base.clone(),
+        }
     }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1699,7 +1081,17 @@ impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
 /// [`HashMap`]: struct.HashMap.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
-    inner: table::IterMut<'a, K, V>,
+    base: base::IterMut<'a, K, V>,
+}
+
+impl<'a, K, V> IterMut<'a, K, V> {
+    /// Returns a iterator of references over the remaining items.
+    #[inline]
+    pub(super) fn iter(&self) -> Iter<'_, K, V> {
+        Iter {
+            base: self.base.rustc_iter(),
+        }
+    }
 }
 
 /// An owning iterator over the entries of a `HashMap`.
@@ -1711,7 +1103,17 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
 /// [`HashMap`]: struct.HashMap.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
-    pub(super) inner: table::IntoIter<K, V>,
+    base: base::IntoIter<K, V>,
+}
+
+impl<K, V> IntoIter<K, V> {
+    /// Returns a iterator of references over the remaining items.
+    #[inline]
+    pub(super) fn iter(&self) -> Iter<'_, K, V> {
+        Iter {
+            base: self.base.rustc_iter(),
+        }
+    }
 }
 
 /// An iterator over the keys of a `HashMap`.
@@ -1729,17 +1131,18 @@ pub struct Keys<'a, K: 'a, V: 'a> {
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> Clone for Keys<'_, K, V> {
+    #[inline]
     fn clone(&self) -> Self {
-        Keys { inner: self.inner.clone() }
+        Keys {
+            inner: self.inner.clone(),
+        }
     }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1758,17 +1161,18 @@ pub struct Values<'a, K: 'a, V: 'a> {
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> Clone for Values<'_, K, V> {
+    #[inline]
     fn clone(&self) -> Self {
-        Values { inner: self.inner.clone() }
+        Values {
+            inner: self.inner.clone(),
+        }
     }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1781,7 +1185,17 @@ impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
 /// [`HashMap`]: struct.HashMap.html
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, K: 'a, V: 'a> {
-    pub(super) inner: table::Drain<'a, K, V>,
+    base: base::Drain<'a, K, V>,
+}
+
+impl<'a, K, V> Drain<'a, K, V> {
+    /// Returns a iterator of references over the remaining items.
+    #[inline]
+    pub(super) fn iter(&self) -> Iter<'_, K, V> {
+        Iter {
+            base: self.base.rustc_iter(),
+        }
+    }
 }
 
 /// A mutable iterator over the values of a `HashMap`.
@@ -1796,47 +1210,6 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> {
     inner: IterMut<'a, K, V>,
 }
 
-enum InternalEntry<K, V, M> {
-    Occupied { elem: FullBucket<K, V, M> },
-    Vacant {
-        hash: SafeHash,
-        elem: VacantEntryState<K, V, M>,
-    },
-    TableIsEmpty,
-}
-
-impl<K, V, M> InternalEntry<K, V, M> {
-    #[inline]
-    fn into_occupied_bucket(self) -> Option<FullBucket<K, V, M>> {
-        match self {
-            InternalEntry::Occupied { elem } => Some(elem),
-            _ => None,
-        }
-    }
-}
-
-impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
-    #[inline]
-    fn into_entry(self, key: K) -> Option<Entry<'a, K, V>> {
-        match self {
-            InternalEntry::Occupied { elem } => {
-                Some(Occupied(OccupiedEntry {
-                    key: Some(key),
-                    elem,
-                }))
-            }
-            InternalEntry::Vacant { hash, elem } => {
-                Some(Vacant(VacantEntry {
-                    hash,
-                    key,
-                    elem,
-                }))
-            }
-            InternalEntry::TableIsEmpty => None,
-        }
-    }
-}
-
 /// A builder for computing where in a HashMap a key-value pair would be stored.
 ///
 /// See the [`HashMap::raw_entry_mut`] docs for usage examples.
@@ -1852,11 +1225,13 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
 ///
 /// This is a lower-level version of [`Entry`].
 ///
-/// This `enum` is constructed from the [`raw_entry`] method on [`HashMap`].
+/// This `enum` is constructed through the [`raw_entry_mut`] method on [`HashMap`],
+/// then calling one of the methods of that [`RawEntryBuilderMut`].
 ///
 /// [`HashMap`]: struct.HashMap.html
 /// [`Entry`]: enum.Entry.html
-/// [`raw_entry`]: struct.HashMap.html#method.raw_entry
+/// [`raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut
+/// [`RawEntryBuilderMut`]: struct.RawEntryBuilderMut.html
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
     /// An occupied entry.
@@ -1871,7 +1246,7 @@ pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
 /// [`RawEntryMut`]: enum.RawEntryMut.html
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> {
-    elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
+    base: base::RawOccupiedEntryMut<'a, K, V>,
 }
 
 /// A view into a vacant entry in a `HashMap`.
@@ -1880,8 +1255,7 @@ pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> {
 /// [`RawEntryMut`]: enum.RawEntryMut.html
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> {
-    elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
-    hash_builder: &'a S,
+    base: base::RawVacantEntryMut<'a, K, V, S>,
 }
 
 /// A builder for computing where in a HashMap a key-value pair would be stored.
@@ -1895,128 +1269,81 @@ pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> {
 }
 
 impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S>
-    where S: BuildHasher,
-          K: Eq + Hash,
+where
+    S: BuildHasher,
 {
     /// Creates a `RawEntryMut` from the given key.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn from_key<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        let mut hasher = self.map.hash_builder.build_hasher();
-        k.hash(&mut hasher);
-        self.from_key_hashed_nocheck(hasher.finish(), k)
+        map_raw_entry(self.map.base.raw_entry_mut().from_key(k))
     }
 
     /// Creates a `RawEntryMut` from the given key and its hash.
     #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S>
-        where K: Borrow<Q>,
-              Q: Eq
+    where
+        K: Borrow<Q>,
+        Q: Eq,
     {
-        self.from_hash(hash, |q| q.borrow().eq(k))
+        map_raw_entry(
+            self.map
+                .base
+                .raw_entry_mut()
+                .from_key_hashed_nocheck(hash, k),
+        )
     }
 
-    #[inline]
-    fn search<F>(self, hash: u64, is_match: F, compare_hashes: bool)  -> RawEntryMut<'a, K, V, S>
-        where for<'b> F: FnMut(&'b K) -> bool,
-    {
-        match search_hashed_nonempty_mut(&mut self.map.table,
-                                         SafeHash::new(hash),
-                                         is_match,
-                                         compare_hashes) {
-            InternalEntry::Occupied { elem } => {
-                RawEntryMut::Occupied(RawOccupiedEntryMut { elem })
-            }
-            InternalEntry::Vacant { elem, .. } => {
-                RawEntryMut::Vacant(RawVacantEntryMut {
-                    elem,
-                    hash_builder: &self.map.hash_builder,
-                })
-            }
-            InternalEntry::TableIsEmpty => {
-                unreachable!()
-            }
-        }
-    }
     /// Creates a `RawEntryMut` from the given hash.
     #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn from_hash<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
-        where for<'b> F: FnMut(&'b K) -> bool,
-    {
-        self.search(hash, is_match, true)
-    }
-
-    /// Search possible locations for an element with hash `hash` until `is_match` returns true for
-    /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided
-    /// hash.
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn search_bucket<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
-        where for<'b> F: FnMut(&'b K) -> bool,
+    where
+        for<'b> F: FnMut(&'b K) -> bool,
     {
-        self.search(hash, is_match, false)
+        map_raw_entry(self.map.base.raw_entry_mut().from_hash(hash, is_match))
     }
 }
 
 impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S>
-    where S: BuildHasher,
+where
+    S: BuildHasher,
 {
     /// Access an entry by key.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        let mut hasher = self.map.hash_builder.build_hasher();
-        k.hash(&mut hasher);
-        self.from_key_hashed_nocheck(hasher.finish(), k)
+        self.map.base.raw_entry().from_key(k)
     }
 
     /// Access an entry by a key and its hash.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)>
-        where K: Borrow<Q>,
-              Q: Hash + Eq
-
-    {
-        self.from_hash(hash, |q| q.borrow().eq(k))
-    }
-
-    fn search<F>(self, hash: u64, is_match: F, compare_hashes: bool) -> Option<(&'a K, &'a V)>
-        where F: FnMut(&K) -> bool
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
     {
-        if unsafe { unlikely(self.map.table.size() == 0) } {
-            return None;
-        }
-        match search_hashed_nonempty(&self.map.table,
-                                     SafeHash::new(hash),
-                                     is_match,
-                                     compare_hashes) {
-            InternalEntry::Occupied { elem } => Some(elem.into_refs()),
-            InternalEntry::Vacant { .. } => None,
-            InternalEntry::TableIsEmpty => unreachable!(),
-        }
+        self.map.base.raw_entry().from_key_hashed_nocheck(hash, k)
     }
 
     /// Access an entry by hash.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
-        where F: FnMut(&K) -> bool
-    {
-        self.search(hash, is_match, true)
-    }
-
-    /// Search possible locations for an element with hash `hash` until `is_match` returns true for
-    /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided
-    /// hash.
-    #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn search_bucket<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
-        where F: FnMut(&K) -> bool
+    where
+        F: FnMut(&K) -> bool,
     {
-        self.search(hash, is_match, false)
+        self.map.base.raw_entry().from_hash(hash, is_match)
     }
 }
 
@@ -2038,10 +1365,12 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
     /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2;
     /// assert_eq!(map["poneyland"], 6);
     /// ```
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V)
-        where K: Hash,
-              S: BuildHasher,
+    where
+        K: Hash,
+        S: BuildHasher,
     {
         match self {
             RawEntryMut::Occupied(entry) => entry.into_key_value(),
@@ -2066,11 +1395,13 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
     ///
     /// assert_eq!(map["poneyland"], "hoho".to_string());
     /// ```
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V)
-        where F: FnOnce() -> (K, V),
-              K: Hash,
-              S: BuildHasher,
+    where
+        F: FnOnce() -> (K, V),
+        K: Hash,
+        S: BuildHasher,
     {
         match self {
             RawEntryMut::Occupied(entry) => entry.into_key_value(),
@@ -2104,9 +1435,11 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
     ///    .or_insert("poneyland", 0);
     /// assert_eq!(map["poneyland"], 43);
     /// ```
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn and_modify<F>(self, f: F) -> Self
-        where F: FnOnce(&mut K, &mut V)
+    where
+        F: FnOnce(&mut K, &mut V),
     {
         match self {
             RawEntryMut::Occupied(mut entry) => {
@@ -2115,7 +1448,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
                     f(k, v);
                 }
                 RawEntryMut::Occupied(entry)
-            },
+            }
             RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry),
         }
     }
@@ -2123,174 +1456,164 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
 
 impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> {
     /// Gets a reference to the key in the entry.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn key(&self) -> &K {
-        self.elem.read().0
+        self.base.key()
     }
 
     /// Gets a mutable reference to the key in the entry.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn key_mut(&mut self) -> &mut K {
-        self.elem.read_mut().0
+        self.base.key_mut()
     }
 
     /// Converts the entry into a mutable reference to the key in the entry
     /// with a lifetime bound to the map itself.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn into_key(self) -> &'a mut K {
-        self.elem.into_mut_refs().0
+        self.base.into_key()
     }
 
     /// Gets a reference to the value in the entry.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn get(&self) -> &V {
-        self.elem.read().1
+        self.base.get()
     }
 
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
     /// with a lifetime bound to the map itself.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn into_mut(self) -> &'a mut V {
-        self.elem.into_mut_refs().1
+        self.base.into_mut()
     }
 
     /// Gets a mutable reference to the value in the entry.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn get_mut(&mut self) -> &mut V {
-        self.elem.read_mut().1
+        self.base.get_mut()
     }
 
     /// Gets a reference to the key and value in the entry.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn get_key_value(&mut self) -> (&K, &V) {
-        self.elem.read()
+        self.base.get_key_value()
     }
 
     /// Gets a mutable reference to the key and value in the entry.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) {
-        self.elem.read_mut()
+        self.base.get_key_value_mut()
     }
 
     /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry
     /// with a lifetime bound to the map itself.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn into_key_value(self) -> (&'a mut K, &'a mut V) {
-        self.elem.into_mut_refs()
+        self.base.into_key_value()
     }
 
     /// Sets the value of the entry, and returns the entry's old value.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn insert(&mut self, value: V) -> V {
-        mem::replace(self.get_mut(), value)
+        self.base.insert(value)
     }
 
     /// Sets the value of the entry, and returns the entry's old value.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn insert_key(&mut self, key: K) -> K {
-        mem::replace(self.key_mut(), key)
+        self.base.insert_key(key)
     }
 
     /// Takes the value out of the entry, and returns it.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn remove(self) -> V {
-        pop_internal(self.elem).1
+        self.base.remove()
     }
 
     /// Take the ownership of the key and value from the map.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn remove_entry(self) -> (K, V) {
-        let (k, v, _) = pop_internal(self.elem);
-        (k, v)
+        self.base.remove_entry()
     }
 }
 
 impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it.
+    #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
     pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V)
-        where K: Hash,
-              S: BuildHasher,
+    where
+        K: Hash,
+        S: BuildHasher,
     {
-        let mut hasher = self.hash_builder.build_hasher();
-        key.hash(&mut hasher);
-        self.insert_hashed_nocheck(hasher.finish(), key, value)
+        self.base.insert(key, value)
     }
 
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it.
     #[inline]
     #[unstable(feature = "hash_raw_entry", issue = "56167")]
-    pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) {
-        let hash = SafeHash::new(hash);
-        let b = match self.elem {
-            NeqElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                robin_hood(bucket, disp, hash, key, value)
-            },
-            NoElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                bucket.put(hash, key, value)
-            },
-        };
-        b.into_mut_refs()
+    pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V)
+    where
+        K: Hash,
+        S: BuildHasher,
+    {
+        self.base.insert_hashed_nocheck(hash, key, value)
     }
 }
 
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 impl<K, V, S> Debug for RawEntryBuilderMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder")
-         .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("RawEntryBuilder").finish()
     }
 }
 
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 impl<K: Debug, V: Debug, S> Debug for RawEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            RawEntryMut::Vacant(ref v) => {
-                f.debug_tuple("RawEntry")
-                    .field(v)
-                    .finish()
-            }
-            RawEntryMut::Occupied(ref o) => {
-                f.debug_tuple("RawEntry")
-                    .field(o)
-                    .finish()
-            }
+            RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(),
+            RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(),
         }
     }
 }
 
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 impl<K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RawOccupiedEntryMut")
-         .field("key", self.key())
-         .field("value", self.get())
-         .finish()
+            .field("key", self.key())
+            .field("value", self.get())
+            .finish()
     }
 }
 
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 impl<K, V, S> Debug for RawVacantEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("RawVacantEntryMut")
-         .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("RawVacantEntryMut").finish()
     }
 }
 
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 impl<K, V, S> Debug for RawEntryBuilder<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder")
-         .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("RawEntryBuilder").finish()
     }
 }
 
@@ -2304,29 +1627,19 @@ impl<K, V, S> Debug for RawEntryBuilder<'_, K, V, S> {
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// An occupied entry.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Occupied(#[stable(feature = "rust1", since = "1.0.0")]
-             OccupiedEntry<'a, K, V>),
+    Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>),
 
     /// A vacant entry.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Vacant(#[stable(feature = "rust1", since = "1.0.0")]
-           VacantEntry<'a, K, V>),
+    Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>),
 }
 
-#[stable(feature= "debug_hash_map", since = "1.12.0")]
+#[stable(feature = "debug_hash_map", since = "1.12.0")]
 impl<K: Debug, V: Debug> Debug for Entry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            Vacant(ref v) => {
-                f.debug_tuple("Entry")
-                    .field(v)
-                    .finish()
-            }
-            Occupied(ref o) => {
-                f.debug_tuple("Entry")
-                    .field(o)
-                    .finish()
-            }
+            Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
+            Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
         }
     }
 }
@@ -2337,18 +1650,12 @@ impl<K: Debug, V: Debug> Debug for Entry<'_, K, V> {
 /// [`Entry`]: enum.Entry.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
-    key: Option<K>,
-    elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
+    base: base::RustcOccupiedEntry<'a, K, V>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, K: 'a + Send, V: 'a + Send> Send for OccupiedEntry<'a, K, V> {}
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, K: 'a + Sync, V: 'a + Sync> Sync for OccupiedEntry<'a, K, V> {}
-
-#[stable(feature= "debug_hash_map", since = "1.12.0")]
+#[stable(feature = "debug_hash_map", since = "1.12.0")]
 impl<K: Debug, V: Debug> Debug for OccupiedEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("OccupiedEntry")
             .field("key", self.key())
             .field("value", self.get())
@@ -2362,39 +1669,22 @@ impl<K: Debug, V: Debug> Debug for OccupiedEntry<'_, K, V> {
 /// [`Entry`]: enum.Entry.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct VacantEntry<'a, K: 'a, V: 'a> {
-    hash: SafeHash,
-    key: K,
-    elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
+    base: base::RustcVacantEntry<'a, K, V>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, K: 'a + Send, V: 'a + Send> Send for VacantEntry<'a, K, V> {}
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, K: 'a + Sync, V: 'a + Sync> Sync for VacantEntry<'a, K, V> {}
-
-#[stable(feature= "debug_hash_map", since = "1.12.0")]
+#[stable(feature = "debug_hash_map", since = "1.12.0")]
 impl<K: Debug, V> Debug for VacantEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_tuple("VacantEntry")
-            .field(self.key())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("VacantEntry").field(self.key()).finish()
     }
 }
 
-/// Possible states of a VacantEntry.
-enum VacantEntryState<K, V, M> {
-    /// The index is occupied, but the key to insert has precedence,
-    /// and will kick the current one out on insertion.
-    NeqElem(FullBucket<K, V, M>, usize),
-    /// The index is genuinely vacant.
-    NoElem(EmptyBucket<K, V, M>, usize),
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
     type Item = (&'a K, &'a V);
     type IntoIter = Iter<'a, K, V>;
 
+    #[inline]
     fn into_iter(self) -> Iter<'a, K, V> {
         self.iter()
     }
@@ -2405,6 +1695,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
     type Item = (&'a K, &'a mut V);
     type IntoIter = IterMut<'a, K, V>;
 
+    #[inline]
     fn into_iter(self) -> IterMut<'a, K, V> {
         self.iter_mut()
     }
@@ -2432,8 +1723,11 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S> {
     /// // Not possible with .iter()
     /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
     /// ```
+    #[inline]
     fn into_iter(self) -> IntoIter<K, V> {
-        IntoIter { inner: self.table.into_iter() }
+        IntoIter {
+            base: self.base.into_iter(),
+        }
     }
 }
 
@@ -2443,18 +1737,18 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
 
     #[inline]
     fn next(&mut self) -> Option<(&'a K, &'a V)> {
-        self.inner.next()
+        self.base.next()
     }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
+        self.base.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
     #[inline]
     fn len(&self) -> usize {
-        self.inner.len()
+        self.base.len()
     }
 }
 
@@ -2467,18 +1761,18 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
 
     #[inline]
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
-        self.inner.next()
+        self.base.next()
     }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
+        self.base.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
     #[inline]
     fn len(&self) -> usize {
-        self.inner.len()
+        self.base.len()
     }
 }
 #[stable(feature = "fused", since = "1.26.0")]
@@ -2486,13 +1780,12 @@ impl<K, V> FusedIterator for IterMut<'_, K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K, V> fmt::Debug for IterMut<'_, K, V>
-    where K: fmt::Debug,
-          V: fmt::Debug,
+where
+    K: fmt::Debug,
+    V: fmt::Debug,
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.inner.iter())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
     }
 }
 
@@ -2502,18 +1795,18 @@ impl<K, V> Iterator for IntoIter<K, V> {
 
     #[inline]
     fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next().map(|(_, k, v)| (k, v))
+        self.base.next()
     }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
+        self.base.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> ExactSizeIterator for IntoIter<K, V> {
     #[inline]
     fn len(&self) -> usize {
-        self.inner.len()
+        self.base.len()
     }
 }
 #[stable(feature = "fused", since = "1.26.0")]
@@ -2521,10 +1814,8 @@ impl<K, V> FusedIterator for IntoIter<K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.inner.iter())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
     }
 }
 
@@ -2599,13 +1890,12 @@ impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K, V> fmt::Debug for ValuesMut<'_, K, V>
-    where K: fmt::Debug,
-          V: fmt::Debug,
+where
+    K: fmt::Debug,
+    V: fmt::Debug,
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.inner.inner.iter())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.inner.iter()).finish()
     }
 }
 
@@ -2615,18 +1905,18 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> {
 
     #[inline]
     fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next().map(|(_, k, v)| (k, v))
+        self.base.next()
     }
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
+        self.base.size_hint()
     }
 }
 #[stable(feature = "drain", since = "1.6.0")]
 impl<K, V> ExactSizeIterator for Drain<'_, K, V> {
     #[inline]
     fn len(&self) -> usize {
-        self.inner.len()
+        self.base.len()
     }
 }
 #[stable(feature = "fused", since = "1.26.0")]
@@ -2634,13 +1924,12 @@ impl<K, V> FusedIterator for Drain<'_, K, V> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K, V> fmt::Debug for Drain<'_, K, V>
-    where K: fmt::Debug,
-          V: fmt::Debug,
+where
+    K: fmt::Debug,
+    V: fmt::Debug,
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.inner.iter())
-            .finish()
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
     }
 }
 
@@ -2662,6 +1951,7 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// *map.entry("poneyland").or_insert(10) *= 2;
     /// assert_eq!(map["poneyland"], 6);
     /// ```
+    #[inline]
     pub fn or_insert(self, default: V) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
@@ -2685,6 +1975,7 @@ impl<'a, K, V> Entry<'a, K, V> {
     ///
     /// assert_eq!(map["poneyland"], "hoho".to_string());
     /// ```
+    #[inline]
     pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
@@ -2702,6 +1993,7 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// let mut map: HashMap<&str, u32> = HashMap::new();
     /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
     /// ```
+    #[inline]
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         match *self {
@@ -2730,19 +2022,20 @@ impl<'a, K, V> Entry<'a, K, V> {
     ///    .or_insert(42);
     /// assert_eq!(map["poneyland"], 43);
     /// ```
+    #[inline]
     #[stable(feature = "entry_and_modify", since = "1.26.0")]
     pub fn and_modify<F>(self, f: F) -> Self
-        where F: FnOnce(&mut V)
+    where
+        F: FnOnce(&mut V),
     {
         match self {
             Occupied(mut entry) => {
                 f(entry.get_mut());
                 Occupied(entry)
-            },
+            }
             Vacant(entry) => Vacant(entry),
         }
     }
-
 }
 
 impl<'a, K, V: Default> Entry<'a, K, V> {
@@ -2762,6 +2055,7 @@ impl<'a, K, V: Default> Entry<'a, K, V> {
     /// assert_eq!(map["poneyland"], None);
     /// # }
     /// ```
+    #[inline]
     pub fn or_default(self) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
@@ -2782,9 +2076,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// map.entry("poneyland").or_insert(12);
     /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
     /// ```
+    #[inline]
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
-        self.elem.read().0
+        self.base.key()
     }
 
     /// Take the ownership of the key and value from the map.
@@ -2805,10 +2100,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// assert_eq!(map.contains_key("poneyland"), false);
     /// ```
+    #[inline]
     #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")]
     pub fn remove_entry(self) -> (K, V) {
-        let (k, v, _) = pop_internal(self.elem);
-        (k, v)
+        self.base.remove_entry()
     }
 
     /// Gets a reference to the value in the entry.
@@ -2826,9 +2121,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///     assert_eq!(o.get(), &12);
     /// }
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> &V {
-        self.elem.read().1
+        self.base.get()
     }
 
     /// Gets a mutable reference to the value in the entry.
@@ -2858,9 +2154,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// assert_eq!(map["poneyland"], 24);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut V {
-        self.elem.read_mut().1
+        self.base.get_mut()
     }
 
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
@@ -2886,9 +2183,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// assert_eq!(map["poneyland"], 22);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_mut(self) -> &'a mut V {
-        self.elem.into_mut_refs().1
+        self.base.into_mut()
     }
 
     /// Sets the value of the entry, and returns the entry's old value.
@@ -2908,11 +2206,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// assert_eq!(map["poneyland"], 15);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn insert(&mut self, mut value: V) -> V {
-        let old_value = self.get_mut();
-        mem::swap(&mut value, old_value);
-        value
+    pub fn insert(&mut self, value: V) -> V {
+        self.base.insert(value)
     }
 
     /// Takes the value out of the entry, and returns it.
@@ -2932,16 +2229,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// assert_eq!(map.contains_key("poneyland"), false);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(self) -> V {
-        pop_internal(self.elem).1
-    }
-
-    /// Returns a key that was used for search.
-    ///
-    /// The key was retained for further use.
-    fn take_key(&mut self) -> Option<K> {
-        self.key.take()
+        self.base.remove()
     }
 
     /// Replaces the entry, returning the old key and value. The new key in the hash map will be
@@ -2965,14 +2256,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// }
     ///
     /// ```
+    #[inline]
     #[unstable(feature = "map_entry_replace", issue = "44286")]
-    pub fn replace_entry(mut self, value: V) -> (K, V) {
-        let (old_key, old_value) = self.elem.read_mut();
-
-        let old_key = mem::replace(old_key, self.key.unwrap());
-        let old_value = mem::replace(old_value, value);
-
-        (old_key, old_value)
+    pub fn replace_entry(self, value: V) -> (K, V) {
+        self.base.replace_entry(value)
     }
 
     /// Replaces the key in the hash map with the key used to create this entry.
@@ -3000,10 +2287,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///     }
     /// }
     /// ```
+    #[inline]
     #[unstable(feature = "map_entry_replace", issue = "44286")]
-    pub fn replace_key(mut self) -> K {
-        let (old_key, _) = self.elem.read_mut();
-        mem::replace(old_key, self.key.unwrap())
+    pub fn replace_key(self) -> K {
+        self.base.replace_key()
     }
 }
 
@@ -3019,9 +2306,10 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     /// let mut map: HashMap<&str, u32> = HashMap::new();
     /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
     /// ```
+    #[inline]
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
-        &self.key
+        self.base.key()
     }
 
     /// Take ownership of the key.
@@ -3038,9 +2326,10 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     ///     v.into_key();
     /// }
     /// ```
+    #[inline]
     #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")]
     pub fn into_key(self) -> K {
-        self.key
+        self.base.into_key()
     }
 
     /// Sets the value of the entry with the VacantEntry's key,
@@ -3059,30 +2348,18 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     /// }
     /// assert_eq!(map["poneyland"], 37);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(self, value: V) -> &'a mut V {
-        let b = match self.elem {
-            NeqElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                robin_hood(bucket, disp, self.hash, self.key, value)
-            },
-            NoElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                bucket.put(self.hash, self.key, value)
-            },
-        };
-        b.into_mut_refs().1
+        self.base.insert(value)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash,
-          S: BuildHasher + Default
+where
+    K: Eq + Hash,
+    S: BuildHasher + Default,
 {
     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> HashMap<K, V, S> {
         let mut map = HashMap::with_hasher(Default::default());
@@ -3093,35 +2370,26 @@ impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash,
-          S: BuildHasher
+where
+    K: Eq + Hash,
+    S: BuildHasher,
 {
+    #[inline]
     fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
-        // Keys may be already present or show multiple times in the iterator.
-        // Reserve the entire hint lower bound if the map is empty.
-        // Otherwise reserve half the hint (rounded up), so the map
-        // will only resize twice in the worst case.
-        let iter = iter.into_iter();
-        let reserve = if self.is_empty() {
-            iter.size_hint().0
-        } else {
-            (iter.size_hint().0 + 1) / 2
-        };
-        self.reserve(reserve);
-        for (k, v) in iter {
-            self.insert(k, v);
-        }
+        self.base.extend(iter)
     }
 }
 
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
-    where K: Eq + Hash + Copy,
-          V: Copy,
-          S: BuildHasher
+where
+    K: Eq + Hash + Copy,
+    V: Copy,
+    S: BuildHasher,
 {
+    #[inline]
     fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
-        self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
+        self.base.extend(iter)
     }
 }
 
@@ -3226,7 +2494,10 @@ impl DefaultHasher {
 
 #[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
 impl Default for DefaultHasher {
-    /// Creates a new `DefaultHasher` using [`new`][DefaultHasher::new].
+    // FIXME: here should link `new` to [DefaultHasher::new], but it occurs intra-doc link
+    // resolution failure when re-exporting libstd items. When #56922 fixed,
+    // link `new` to [DefaultHasher::new] again.
+    /// Creates a new `DefaultHasher` using `new`.
     /// See its documentation for more.
     fn default() -> DefaultHasher {
         DefaultHasher::new()
@@ -3257,41 +2528,34 @@ impl Default for RandomState {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for RandomState {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("RandomState { .. }")
     }
 }
 
-impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
-    where K: Eq + Hash + Borrow<Q>,
-          S: BuildHasher,
-          Q: Eq + Hash
-{
-    type Key = K;
-
-    #[inline]
-    fn get(&self, key: &Q) -> Option<&K> {
-        self.search(key).map(|bucket| bucket.into_refs().0)
+#[inline]
+fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, V> {
+    match raw {
+        base::RustcEntry::Occupied(base) => Entry::Occupied(OccupiedEntry { base }),
+        base::RustcEntry::Vacant(base) => Entry::Vacant(VacantEntry { base }),
     }
+}
 
-    fn take(&mut self, key: &Q) -> Option<K> {
-        self.search_mut(key).map(|bucket| pop_internal(bucket).0)
+#[inline]
+fn map_collection_alloc_err(err: hashbrown::CollectionAllocErr) -> CollectionAllocErr {
+    match err {
+        hashbrown::CollectionAllocErr::CapacityOverflow => CollectionAllocErr::CapacityOverflow,
+        hashbrown::CollectionAllocErr::AllocErr => CollectionAllocErr::AllocErr,
     }
+}
 
-    #[inline]
-    fn replace(&mut self, key: K) -> Option<K> {
-        self.reserve(1);
-
-        match self.entry(key) {
-            Occupied(mut occupied) => {
-                let key = occupied.take_key().unwrap();
-                Some(mem::replace(occupied.elem.read_mut().0, key))
-            }
-            Vacant(vacant) => {
-                vacant.insert(());
-                None
-            }
-        }
+#[inline]
+fn map_raw_entry<'a, K: 'a, V: 'a, S: 'a>(
+    raw: base::RawEntryMut<'a, K, V, S>,
+) -> RawEntryMut<'a, K, V, S> {
+    match raw {
+        base::RawEntryMut::Occupied(base) => RawEntryMut::Occupied(RawOccupiedEntryMut { base }),
+        base::RawEntryMut::Vacant(base) => RawEntryMut::Vacant(RawVacantEntryMut { base }),
     }
 }
 
@@ -3327,23 +2591,29 @@ fn assert_covariance() {
     fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> {
         v
     }
-    fn drain<'new>(d: Drain<'static, &'static str, &'static str>)
-                   -> Drain<'new, &'new str, &'new str> {
+    fn drain<'new>(
+        d: Drain<'static, &'static str, &'static str>,
+    ) -> Drain<'new, &'new str, &'new str> {
         d
     }
 }
 
 #[cfg(test)]
 mod test_map {
-    use super::HashMap;
     use super::Entry::{Occupied, Vacant};
+    use super::HashMap;
     use super::RandomState;
     use crate::cell::RefCell;
     use rand::{thread_rng, Rng};
     use realstd::collections::CollectionAllocErr::*;
-    use realstd::mem::size_of;
     use realstd::usize;
 
+    // https://github.com/rust-lang/rust/issues/62301
+    fn _assert_hashmap_is_unwind_safe() {
+        fn assert_unwind_safe<T: crate::panic::UnwindSafe>() {}
+        assert_unwind_safe::<HashMap<(), crate::cell::UnsafeCell<()>>>();
+    }
+
     #[test]
     fn test_zero_capacities() {
         type HM = HashMap<i32, i32>;
@@ -3478,19 +2748,19 @@ mod test_map {
 
                 DROP_VECTOR.with(|v| {
                     assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i+100], 1);
+                    assert_eq!(v.borrow()[i + 100], 1);
                 });
             }
 
             DROP_VECTOR.with(|v| {
                 for i in 0..50 {
                     assert_eq!(v.borrow()[i], 0);
-                    assert_eq!(v.borrow()[i+100], 0);
+                    assert_eq!(v.borrow()[i + 100], 0);
                 }
 
                 for i in 50..100 {
                     assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i+100], 1);
+                    assert_eq!(v.borrow()[i + 100], 1);
                 }
             });
         }
@@ -3547,13 +2817,9 @@ mod test_map {
             for _ in half.by_ref() {}
 
             DROP_VECTOR.with(|v| {
-                let nk = (0..100)
-                    .filter(|&i| v.borrow()[i] == 1)
-                    .count();
+                let nk = (0..100).filter(|&i| v.borrow()[i] == 1).count();
 
-                let nv = (0..100)
-                    .filter(|&i| v.borrow()[i + 100] == 1)
-                    .count();
+                let nv = (0..100).filter(|&i| v.borrow()[i + 100] == 1).count();
 
                 assert_eq!(nk, 50);
                 assert_eq!(nv, 50);
@@ -3741,7 +3007,7 @@ mod test_map {
     fn test_iterate() {
         let mut m = HashMap::with_capacity(4);
         for i in 0..32 {
-            assert!(m.insert(i, i*2).is_none());
+            assert!(m.insert(i, i * 2).is_none());
         }
         assert_eq!(m.len(), 32);
 
@@ -3829,86 +3095,11 @@ mod test_map {
 
         let map_str = format!("{:?}", map);
 
-        assert!(map_str == "{1: 2, 3: 4}" ||
-                map_str == "{3: 4, 1: 2}");
+        assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
         assert_eq!(format!("{:?}", empty), "{}");
     }
 
     #[test]
-    fn test_expand() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-
-        let mut i = 0;
-        let old_raw_cap = m.raw_capacity();
-        while old_raw_cap == m.raw_capacity() {
-            m.insert(i, i);
-            i += 1;
-        }
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-    }
-
-    #[test]
-    fn test_behavior_resize_policy() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert_eq!(m.raw_capacity(), 0);
-        assert!(m.is_empty());
-
-        m.insert(0, 0);
-        m.remove(&0);
-        assert!(m.is_empty());
-        let initial_raw_cap = m.raw_capacity();
-        m.reserve(initial_raw_cap);
-        let raw_cap = m.raw_capacity();
-
-        assert_eq!(raw_cap, initial_raw_cap * 2);
-
-        let mut i = 0;
-        for _ in 0..raw_cap * 3 / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // three quarters full
-
-        assert_eq!(m.len(), i);
-        assert_eq!(m.raw_capacity(), raw_cap);
-
-        for _ in 0..raw_cap / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // half full
-
-        let new_raw_cap = m.raw_capacity();
-        assert_eq!(new_raw_cap, raw_cap * 2);
-
-        for _ in 0..raw_cap / 2 - 1 {
-            i -= 1;
-            m.remove(&i);
-            assert_eq!(m.raw_capacity(), new_raw_cap);
-        }
-        // A little more than one quarter full.
-        m.shrink_to_fit();
-        assert_eq!(m.raw_capacity(), raw_cap);
-        // again, a little more than half full
-        for _ in 0..raw_cap / 2 - 1 {
-            i -= 1;
-            m.remove(&i);
-        }
-        m.shrink_to_fit();
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-        assert_eq!(m.raw_capacity(), initial_raw_cap);
-    }
-
-    #[test]
     fn test_reserve_shrink_to_fit() {
         let mut m = HashMap::new();
         m.insert(0, 0);
@@ -3947,13 +3138,15 @@ mod test_map {
 
     #[test]
     fn test_from_iter() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+        let xs = [(1, 1), (2, 2), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
         let map: HashMap<_, _> = xs.iter().cloned().collect();
 
         for &(k, v) in &xs {
             assert_eq!(map.get(&k), Some(&v));
         }
+
+        assert_eq!(map.iter().len(), xs.len() - 1);
     }
 
     #[test]
@@ -4048,7 +3241,6 @@ mod test_map {
         assert_eq!(map.get(&1).unwrap(), &100);
         assert_eq!(map.len(), 6);
 
-
         // Existing key (update)
         match map.entry(2) {
             Vacant(_) => unreachable!(),
@@ -4071,7 +3263,6 @@ mod test_map {
         assert_eq!(map.get(&3), None);
         assert_eq!(map.len(), 5);
 
-
         // Inexistent key (insert)
         match map.entry(10) {
             Occupied(_) => unreachable!(),
@@ -4086,11 +3277,10 @@ mod test_map {
     #[test]
     fn test_entry_take_doesnt_corrupt() {
         #![allow(deprecated)] //rand
-        // Test for #19292
+                              // Test for #19292
         fn check(m: &HashMap<i32, ()>) {
             for k in m.keys() {
-                assert!(m.contains_key(k),
-                        "{} is in keys() but not in the map?", k);
+                assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
             }
         }
 
@@ -4195,7 +3385,7 @@ mod test_map {
 
     #[test]
     fn test_retain() {
-        let mut map: HashMap<i32, i32> = (0..100).map(|x|(x, x*10)).collect();
+        let mut map: HashMap<i32, i32> = (0..100).map(|x| (x, x * 10)).collect();
 
         map.retain(|&k, _| k % 2 == 0);
         assert_eq!(map.len(), 50);
@@ -4205,50 +3395,19 @@ mod test_map {
     }
 
     #[test]
-    fn test_adaptive() {
-        const TEST_LEN: usize = 5000;
-        // by cloning we get maps with the same hasher seed
-        let mut first = HashMap::new();
-        let mut second = first.clone();
-        first.extend((0..TEST_LEN).map(|i| (i, i)));
-        second.extend((TEST_LEN..TEST_LEN * 2).map(|i| (i, i)));
-
-        for (&k, &v) in &second {
-            let prev_cap = first.capacity();
-            let expect_grow = first.len() == prev_cap;
-            first.insert(k, v);
-            if !expect_grow && first.capacity() != prev_cap {
-                return;
-            }
-        }
-        panic!("Adaptive early resize failed");
-    }
-
-    #[test]
     fn test_try_reserve() {
-
-        let mut empty_bytes: HashMap<u8,u8> = HashMap::new();
+        let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
 
         const MAX_USIZE: usize = usize::MAX;
 
-        // HashMap and RawTables use complicated size calculations
-        // hashes_size is sizeof(HashUint) * capacity;
-        // pairs_size is sizeof((K. V)) * capacity;
-        // alignment_hashes_size is 8
-        // alignment_pairs size is 4
-        let size_of_multiplier = (size_of::<usize>() + size_of::<(u8, u8)>()).next_power_of_two();
-        // The following formula is used to calculate the new capacity
-        let max_no_ovf = ((MAX_USIZE / 11) * 10) / size_of_multiplier - 1;
-
         if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
-        } else { panic!("usize::MAX should trigger an overflow!"); }
+        } else {
+            panic!("usize::MAX should trigger an overflow!");
+        }
 
-        if size_of::<usize>() < 8 {
-            if let Err(CapacityOverflow) = empty_bytes.try_reserve(max_no_ovf) {
-            } else { panic!("isize::MAX + 1 should trigger a CapacityOverflow!") }
+        if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE / 8) {
         } else {
-            if let Err(AllocErr) = empty_bytes.try_reserve(max_no_ovf) {
-            } else { panic!("isize::MAX + 1 should trigger an OOM!") }
+            panic!("usize::MAX / 8 should trigger an OOM!")
         }
     }
 
@@ -4278,9 +3437,14 @@ mod test_map {
         }
         let hash1 = compute_hash(&map, 1);
         assert_eq!(map.raw_entry().from_key(&1).unwrap(), (&1, &100));
-        assert_eq!(map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(), (&1, &100));
-        assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(), (&1, &100));
-        assert_eq!(map.raw_entry().search_bucket(hash1, |k| *k == 1).unwrap(), (&1, &100));
+        assert_eq!(
+            map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(),
+            (&1, &100)
+        );
+        assert_eq!(
+            map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(),
+            (&1, &100)
+        );
         assert_eq!(map.len(), 6);
 
         // Existing key (update)
@@ -4294,9 +3458,14 @@ mod test_map {
         }
         let hash2 = compute_hash(&map, 2);
         assert_eq!(map.raw_entry().from_key(&2).unwrap(), (&2, &200));
-        assert_eq!(map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(), (&2, &200));
-        assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(), (&2, &200));
-        assert_eq!(map.raw_entry().search_bucket(hash2, |k| *k == 2).unwrap(), (&2, &200));
+        assert_eq!(
+            map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(),
+            (&2, &200)
+        );
+        assert_eq!(
+            map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(),
+            (&2, &200)
+        );
         assert_eq!(map.len(), 6);
 
         // Existing key (take)
@@ -4310,10 +3479,8 @@ mod test_map {
         assert_eq!(map.raw_entry().from_key(&3), None);
         assert_eq!(map.raw_entry().from_hash(hash3, |k| *k == 3), None);
         assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash3, &3), None);
-        assert_eq!(map.raw_entry().search_bucket(hash3, |k| *k == 3), None);
         assert_eq!(map.len(), 5);
 
-
         // Nonexistent key (insert)
         match map.raw_entry_mut().from_key(&10) {
             Occupied(_) => unreachable!(),
@@ -4333,7 +3500,6 @@ mod test_map {
             assert_eq!(map.raw_entry().from_key(&k), kv);
             assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv);
             assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv);
-            assert_eq!(map.raw_entry().search_bucket(hash, |q| *q == k), kv);
 
             match map.raw_entry_mut().from_key(&k) {
                 Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
@@ -4347,10 +3513,6 @@ mod test_map {
                 Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
                 Vacant(_) => assert_eq!(v, None),
             }
-            match map.raw_entry_mut().search_bucket(hash, |q| *q == k) {
-                Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-                Vacant(_) => assert_eq!(v, None),
-            }
         }
     }
 
diff --git a/src/libstd/collections/hash/mod.rs b/src/libstd/collections/hash/mod.rs
index 0d1bbb590db..a6d89a4d32a 100644
--- a/src/libstd/collections/hash/mod.rs
+++ b/src/libstd/collections/hash/mod.rs
@@ -1,14 +1,5 @@
 //! Unordered containers, implemented as hash-tables
 
 mod bench;
-mod table;
 pub mod map;
 pub mod set;
-
-trait Recover<Q: ?Sized> {
-    type Key;
-
-    fn get(&self, key: &Q) -> Option<&Self::Key>;
-    fn take(&mut self, key: &Q) -> Option<Self::Key>;
-    fn replace(&mut self, key: Self::Key) -> Option<Self::Key>;
-}
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index f2111f2d9e0..d243412405a 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -1,14 +1,14 @@
 use crate::borrow::Borrow;
+use crate::collections::CollectionAllocErr;
 use crate::fmt;
 use crate::hash::{Hash, BuildHasher};
 use crate::iter::{Chain, FromIterator, FusedIterator};
 use crate::ops::{BitOr, BitAnd, BitXor, Sub};
 
-use super::Recover;
 use super::map::{self, HashMap, Keys, RandomState};
 
 // Future Optimization (FIXME!)
-// =============================
+// ============================
 //
 // Iteration over zero sized values is a noop. There is no need
 // for `bucket.val` in the case of HashSet. I suppose we would need HKT
@@ -181,8 +181,9 @@ impl<T, S> HashSet<T, S> {
     ///     println!("{}", x);
     /// }
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter<T> {
+    pub fn iter(&self) -> Iter<'_, T> {
         Iter { iter: self.map.keys() }
     }
 
@@ -198,6 +199,7 @@ impl<T, S> HashSet<T, S> {
     /// v.insert(1);
     /// assert_eq!(v.len(), 1);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> usize {
         self.map.len()
@@ -215,6 +217,7 @@ impl<T, S> HashSet<T, S> {
     /// v.insert(1);
     /// assert!(!v.is_empty());
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
         self.map.is_empty()
@@ -239,7 +242,7 @@ impl<T, S> HashSet<T, S> {
     /// ```
     #[inline]
     #[stable(feature = "drain", since = "1.6.0")]
-    pub fn drain(&mut self) -> Drain<T> {
+    pub fn drain(&mut self) -> Drain<'_, T> {
         Drain { iter: self.map.drain() }
     }
 
@@ -255,6 +258,7 @@ impl<T, S> HashSet<T, S> {
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         self.map.clear()
@@ -332,6 +336,7 @@ impl<T, S> HashSet<T, S>
     /// let set: HashSet<i32> = HashSet::with_hasher(hasher);
     /// let hasher: &RandomState = set.hasher();
     /// ```
+    #[inline]
     #[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
     pub fn hasher(&self) -> &S {
         self.map.hasher()
@@ -353,11 +358,35 @@ impl<T, S> HashSet<T, S>
     /// set.reserve(10);
     /// assert!(set.capacity() >= 10);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: usize) {
         self.map.reserve(additional)
     }
 
+    /// 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.
+    ///
+    /// # Errors
+    ///
+    /// If the capacity overflows, or the allocator reports a failure, then an error
+    /// is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(try_reserve)]
+    /// 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?");
+    /// ```
+    #[inline]
+    #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
+        self.map.try_reserve(additional)
+    }
+
     /// Shrinks the capacity of the set as much as possible. It will drop
     /// down as much as possible while maintaining the internal rules
     /// and possibly leaving some space in accordance with the resize policy.
@@ -374,6 +403,7 @@ impl<T, S> HashSet<T, S>
     /// set.shrink_to_fit();
     /// assert!(set.capacity() >= 2);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         self.map.shrink_to_fit()
@@ -430,6 +460,7 @@ impl<T, S> HashSet<T, S>
     /// let diff: HashSet<_> = b.difference(&a).collect();
     /// assert_eq!(diff, [4].iter().collect());
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference {
@@ -459,6 +490,7 @@ impl<T, S> HashSet<T, S>
     /// assert_eq!(diff1, diff2);
     /// assert_eq!(diff1, [1, 4].iter().collect());
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(&'a self,
                                     other: &'a HashSet<T, S>)
@@ -484,6 +516,7 @@ impl<T, S> HashSet<T, S>
     /// let intersection: HashSet<_> = a.intersection(&b).collect();
     /// assert_eq!(intersection, [2, 3].iter().collect());
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         if self.len() <= other.len() {
@@ -517,6 +550,7 @@ impl<T, S> HashSet<T, S>
     /// let union: HashSet<_> = a.union(&b).collect();
     /// assert_eq!(union, [1, 2, 3, 4].iter().collect());
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
         if self.len() <= other.len() {
@@ -548,6 +582,7 @@ impl<T, S> HashSet<T, S>
     ///
     /// [`Eq`]: ../../std/cmp/trait.Eq.html
     /// [`Hash`]: ../../std/hash/trait.Hash.html
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
         where T: Borrow<Q>,
@@ -574,12 +609,69 @@ impl<T, S> HashSet<T, S>
     ///
     /// [`Eq`]: ../../std/cmp/trait.Eq.html
     /// [`Hash`]: ../../std/hash/trait.Hash.html
+    #[inline]
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
         where T: Borrow<Q>,
               Q: Hash + Eq
     {
-        Recover::get(&self.map, value)
+        self.map.get_key_value(value).map(|(k, _)| k)
+    }
+
+    /// Inserts the given `value` into the set if it is not present, then
+    /// returns a reference to the value in the set.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(hash_set_entry)]
+    ///
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+    /// assert_eq!(set.len(), 3);
+    /// assert_eq!(set.get_or_insert(2), &2);
+    /// assert_eq!(set.get_or_insert(100), &100);
+    /// assert_eq!(set.len(), 4); // 100 was inserted
+    /// ```
+    #[inline]
+    #[unstable(feature = "hash_set_entry", issue = "60896")]
+    pub fn get_or_insert(&mut self, value: T) -> &T {
+        // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
+        // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
+        self.map.raw_entry_mut().from_key(&value).or_insert(value, ()).0
+    }
+
+    /// Inserts a value computed from `f` into the set if the given `value` is
+    /// not present, then returns a reference to the value in the set.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(hash_set_entry)]
+    ///
+    /// use std::collections::HashSet;
+    ///
+    /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
+    ///     .iter().map(|&pet| pet.to_owned()).collect();
+    ///
+    /// assert_eq!(set.len(), 3);
+    /// for &pet in &["cat", "dog", "fish"] {
+    ///     let value = set.get_or_insert_with(pet, str::to_owned);
+    ///     assert_eq!(value, pet);
+    /// }
+    /// assert_eq!(set.len(), 4); // a new "fish" was inserted
+    /// ```
+    #[inline]
+    #[unstable(feature = "hash_set_entry", issue = "60896")]
+    pub fn get_or_insert_with<Q: ?Sized, F>(&mut self, value: &Q, f: F) -> &T
+        where T: Borrow<Q>,
+              Q: Hash + Eq,
+              F: FnOnce(&Q) -> T
+    {
+        // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
+        // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
+        self.map.raw_entry_mut().from_key(value).or_insert_with(|| (f(value), ())).0
     }
 
     /// Returns `true` if `self` has no elements in common with `other`.
@@ -627,7 +719,11 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_subset(&self, other: &HashSet<T, S>) -> bool {
-        self.iter().all(|v| other.contains(v))
+        if self.len() <= other.len() {
+            self.iter().all(|v| other.contains(v))
+        } else {
+            false
+        }
     }
 
     /// Returns `true` if the set is a superset of another,
@@ -673,6 +769,7 @@ impl<T, S> HashSet<T, S>
     /// assert_eq!(set.insert(2), false);
     /// assert_eq!(set.len(), 1);
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, value: T) -> bool {
         self.map.insert(value, ()).is_none()
@@ -693,9 +790,16 @@ impl<T, S> HashSet<T, S>
     /// set.replace(Vec::with_capacity(10));
     /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
     /// ```
+    #[inline]
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn replace(&mut self, value: T) -> Option<T> {
-        Recover::replace(&mut self.map, value)
+        match self.map.entry(value) {
+            map::Entry::Occupied(occupied) => Some(occupied.replace_key()),
+            map::Entry::Vacant(vacant) => {
+                vacant.insert(());
+                None
+            }
+        }
     }
 
     /// Removes a value from the set. Returns whether the value was
@@ -719,6 +823,7 @@ impl<T, S> HashSet<T, S>
     ///
     /// [`Eq`]: ../../std/cmp/trait.Eq.html
     /// [`Hash`]: ../../std/hash/trait.Hash.html
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
         where T: Borrow<Q>,
@@ -745,12 +850,13 @@ impl<T, S> HashSet<T, S>
     ///
     /// [`Eq`]: ../../std/cmp/trait.Eq.html
     /// [`Hash`]: ../../std/hash/trait.Hash.html
+    #[inline]
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
         where T: Borrow<Q>,
               Q: Hash + Eq
     {
-        Recover::take(&mut self.map, value)
+        self.map.remove_entry(value).map(|(k, _)| k)
     }
 
     /// Retains only the elements specified by the predicate.
@@ -801,7 +907,7 @@ impl<T, S> fmt::Debug for HashSet<T, S>
     where T: Eq + Hash + fmt::Debug,
           S: BuildHasher
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_set().entries(self.iter()).finish()
     }
 }
@@ -811,6 +917,7 @@ impl<T, S> FromIterator<T> for HashSet<T, S>
     where T: Eq + Hash,
           S: BuildHasher + Default
 {
+    #[inline]
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> HashSet<T, S> {
         let mut set = HashSet::with_hasher(Default::default());
         set.extend(iter);
@@ -823,6 +930,7 @@ impl<T, S> Extend<T> for HashSet<T, S>
     where T: Eq + Hash,
           S: BuildHasher
 {
+    #[inline]
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         self.map.extend(iter.into_iter().map(|k| (k, ())));
     }
@@ -833,6 +941,7 @@ impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
     where T: 'a + Eq + Hash + Copy,
           S: BuildHasher
 {
+    #[inline]
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
@@ -844,6 +953,7 @@ impl<T, S> Default for HashSet<T, S>
           S: BuildHasher + Default
 {
     /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
+    #[inline]
     fn default() -> HashSet<T, S> {
         HashSet { map: HashMap::default() }
     }
@@ -1072,6 +1182,7 @@ impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
 
+    #[inline]
     fn into_iter(self) -> Iter<'a, T> {
         self.iter()
     }
@@ -1102,6 +1213,7 @@ impl<T, S> IntoIterator for HashSet<T, S> {
     ///     println!("{}", x);
     /// }
     /// ```
+    #[inline]
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { iter: self.map.into_iter() }
     }
@@ -1109,6 +1221,7 @@ impl<T, S> IntoIterator for HashSet<T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> Clone for Iter<'_, K> {
+    #[inline]
     fn clone(&self) -> Self {
         Iter { iter: self.iter.clone() }
     }
@@ -1117,15 +1230,18 @@ impl<K> Clone for Iter<'_, K> {
 impl<'a, K> Iterator for Iter<'a, K> {
     type Item = &'a K;
 
+    #[inline]
     fn next(&mut self) -> Option<&'a K> {
         self.iter.next()
     }
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for Iter<'_, K> {
+    #[inline]
     fn len(&self) -> usize {
         self.iter.len()
     }
@@ -1135,7 +1251,7 @@ impl<K> FusedIterator for Iter<'_, K> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: fmt::Debug> fmt::Debug for Iter<'_, K> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_list().entries(self.clone()).finish()
     }
 }
@@ -1144,15 +1260,18 @@ impl<K: fmt::Debug> fmt::Debug for Iter<'_, K> {
 impl<K> Iterator for IntoIter<K> {
     type Item = K;
 
+    #[inline]
     fn next(&mut self) -> Option<K> {
         self.iter.next().map(|(k, _)| k)
     }
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for IntoIter<K> {
+    #[inline]
     fn len(&self) -> usize {
         self.iter.len()
     }
@@ -1162,9 +1281,8 @@ impl<K> FusedIterator for IntoIter<K> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let entries_iter = self.iter
-            .inner
             .iter()
             .map(|(k, _)| k);
         f.debug_list().entries(entries_iter).finish()
@@ -1175,15 +1293,18 @@ impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
 impl<'a, K> Iterator for Drain<'a, K> {
     type Item = K;
 
+    #[inline]
     fn next(&mut self) -> Option<K> {
         self.iter.next().map(|(k, _)| k)
     }
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for Drain<'_, K> {
+    #[inline]
     fn len(&self) -> usize {
         self.iter.len()
     }
@@ -1193,9 +1314,8 @@ impl<K> FusedIterator for Drain<'_, K> {}
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let entries_iter = self.iter
-            .inner
             .iter()
             .map(|(k, _)| k);
         f.debug_list().entries(entries_iter).finish()
@@ -1204,6 +1324,7 @@ impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Clone for Intersection<'_, T, S> {
+    #[inline]
     fn clone(&self) -> Self {
         Intersection { iter: self.iter.clone(), ..*self }
     }
@@ -1216,6 +1337,7 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S>
 {
     type Item = &'a T;
 
+    #[inline]
     fn next(&mut self) -> Option<&'a T> {
         loop {
             let elt = self.iter.next()?;
@@ -1225,6 +1347,7 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S>
         }
     }
 
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper)
@@ -1236,7 +1359,7 @@ impl<T, S> fmt::Debug for Intersection<'_, T, S>
     where T: fmt::Debug + Eq + Hash,
           S: BuildHasher
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_list().entries(self.clone()).finish()
     }
 }
@@ -1250,6 +1373,7 @@ impl<T, S> FusedIterator for Intersection<'_, T, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Clone for Difference<'_, T, S> {
+    #[inline]
     fn clone(&self) -> Self {
         Difference { iter: self.iter.clone(), ..*self }
     }
@@ -1262,6 +1386,7 @@ impl<'a, T, S> Iterator for Difference<'a, T, S>
 {
     type Item = &'a T;
 
+    #[inline]
     fn next(&mut self) -> Option<&'a T> {
         loop {
             let elt = self.iter.next()?;
@@ -1271,6 +1396,7 @@ impl<'a, T, S> Iterator for Difference<'a, T, S>
         }
     }
 
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper)
@@ -1289,13 +1415,14 @@ impl<T, S> fmt::Debug for Difference<'_, T, S>
     where T: fmt::Debug + Eq + Hash,
           S: BuildHasher
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_list().entries(self.clone()).finish()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Clone for SymmetricDifference<'_, T, S> {
+    #[inline]
     fn clone(&self) -> Self {
         SymmetricDifference { iter: self.iter.clone() }
     }
@@ -1308,9 +1435,11 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
 {
     type Item = &'a T;
 
+    #[inline]
     fn next(&mut self) -> Option<&'a T> {
         self.iter.next()
     }
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
@@ -1328,13 +1457,14 @@ impl<T, S> fmt::Debug for SymmetricDifference<'_, T, S>
     where T: fmt::Debug + Eq + Hash,
           S: BuildHasher
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_list().entries(self.clone()).finish()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Clone for Union<'_, T, S> {
+    #[inline]
     fn clone(&self) -> Self {
         Union { iter: self.iter.clone() }
     }
@@ -1352,7 +1482,7 @@ impl<T, S> fmt::Debug for Union<'_, T, S>
     where T: fmt::Debug + Eq + Hash,
           S: BuildHasher
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_list().entries(self.clone()).finish()
     }
 }
@@ -1364,9 +1494,11 @@ impl<'a, T, S> Iterator for Union<'a, T, S>
 {
     type Item = &'a T;
 
+    #[inline]
     fn next(&mut self) -> Option<&'a T> {
         self.iter.next()
     }
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
@@ -1650,13 +1782,15 @@ mod test_set {
 
     #[test]
     fn test_from_iter() {
-        let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+        let xs = [1, 2, 2, 3, 4, 5, 6, 7, 8, 9];
 
         let set: HashSet<_> = xs.iter().cloned().collect();
 
         for x in &xs {
             assert!(set.contains(x));
         }
+
+        assert_eq!(set.iter().len(), xs.len() - 1);
     }
 
     #[test]
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
deleted file mode 100644
index 31e7a693135..00000000000
--- a/src/libstd/collections/hash/table.rs
+++ /dev/null
@@ -1,1131 +0,0 @@
-use crate::alloc::{Global, Alloc, Layout, LayoutErr, handle_alloc_error};
-use crate::collections::CollectionAllocErr;
-use crate::hash::{BuildHasher, Hash, Hasher};
-use crate::marker;
-use crate::mem::{self, size_of, needs_drop};
-use crate::ops::{Deref, DerefMut};
-use crate::ptr::{self, Unique, NonNull};
-use crate::hint;
-
-use self::BucketState::*;
-
-/// Integer type used for stored hash values.
-///
-/// No more than bit_width(usize) bits are needed to select a bucket.
-///
-/// The most significant bit is ours to use for tagging `SafeHash`.
-///
-/// (Even if we could have usize::MAX bytes allocated for buckets,
-/// each bucket stores at least a `HashUint`, so there can be no more than
-/// usize::MAX / size_of(usize) buckets.)
-type HashUint = usize;
-
-const EMPTY_BUCKET: HashUint = 0;
-const EMPTY: usize = 1;
-
-/// Special `Unique<HashUint>` that uses the lower bit of the pointer
-/// to expose a boolean tag.
-/// Note: when the pointer is initialized to EMPTY `.ptr()` will return
-/// null and the tag functions shouldn't be used.
-struct TaggedHashUintPtr(Unique<HashUint>);
-
-impl TaggedHashUintPtr {
-    #[inline]
-    unsafe fn new(ptr: *mut HashUint) -> Self {
-        debug_assert!(ptr as usize & 1 == 0 || ptr as usize == EMPTY as usize);
-        TaggedHashUintPtr(Unique::new_unchecked(ptr))
-    }
-
-    #[inline]
-    fn set_tag(&mut self, value: bool) {
-        let mut usize_ptr = self.0.as_ptr() as usize;
-        unsafe {
-            if value {
-                usize_ptr |= 1;
-            } else {
-                usize_ptr &= !1;
-            }
-            self.0 = Unique::new_unchecked(usize_ptr as *mut HashUint)
-        }
-    }
-
-    #[inline]
-    fn tag(&self) -> bool {
-        (self.0.as_ptr() as usize) & 1 == 1
-    }
-
-    #[inline]
-    fn ptr(&self) -> *mut HashUint {
-        (self.0.as_ptr() as usize & !1) as *mut HashUint
-    }
-}
-
-/// The raw hashtable, providing safe-ish access to the unzipped and highly
-/// optimized arrays of hashes, and key-value pairs.
-///
-/// This design is a lot faster than the naive
-/// `Vec<Option<(u64, K, V)>>`, because we don't pay for the overhead of an
-/// option on every element, and we get a generally more cache-aware design.
-///
-/// Essential invariants of this structure:
-///
-///   - if `t.hashes[i] == EMPTY_BUCKET`, then `Bucket::at_index(&t, i).raw`
-///     points to 'undefined' contents. Don't read from it. This invariant is
-///     enforced outside this module with the `EmptyBucket`, `FullBucket`,
-///     and `SafeHash` types.
-///
-///   - An `EmptyBucket` is only constructed at an index with
-///     a hash of EMPTY_BUCKET.
-///
-///   - A `FullBucket` is only constructed at an index with a
-///     non-EMPTY_BUCKET hash.
-///
-///   - A `SafeHash` is only constructed for non-`EMPTY_BUCKET` hash. We get
-///     around hashes of zero by changing them to 0x8000_0000_0000_0000,
-///     which will likely map to the same bucket, while not being confused
-///     with "empty".
-///
-///   - Both "arrays represented by pointers" are the same length:
-///     `capacity`. This is set at creation and never changes. The arrays
-///     are unzipped and are more cache aware (scanning through 8 hashes
-///     brings in at most 2 cache lines, since they're all right beside each
-///     other). This layout may waste space in padding such as in a map from
-///     u64 to u8, but is a more cache conscious layout as the key-value pairs
-///     are only very shortly probed and the desired value will be in the same
-///     or next cache line.
-///
-/// You can kind of think of this module/data structure as a safe wrapper
-/// around just the "table" part of the hashtable. It enforces some
-/// invariants at the type level and employs some performance trickery,
-/// but in general is just a tricked out `Vec<Option<(u64, K, V)>>`.
-///
-/// The hashtable also exposes a special boolean tag. The tag defaults to false
-/// when the RawTable is created and is accessible with the `tag` and `set_tag`
-/// functions.
-pub struct RawTable<K, V> {
-    capacity_mask: usize,
-    size: usize,
-    hashes: TaggedHashUintPtr,
-
-    // Because K/V do not appear directly in any of the types in the struct,
-    // inform rustc that in fact instances of K and V are reachable from here.
-    marker: marker::PhantomData<(K, V)>,
-}
-
-// An unsafe view of a RawTable bucket
-// Valid indexes are within [0..table_capacity)
-pub struct RawBucket<K, V> {
-    hash_start: *mut HashUint,
-    // We use *const to ensure covariance with respect to K and V
-    pair_start: *const (K, V),
-    idx: usize,
-    _marker: marker::PhantomData<(K, V)>,
-}
-
-impl<K, V> Copy for RawBucket<K, V> {}
-impl<K, V> Clone for RawBucket<K, V> {
-    fn clone(&self) -> RawBucket<K, V> {
-        *self
-    }
-}
-
-pub struct Bucket<K, V, M> {
-    raw: RawBucket<K, V>,
-    table: M,
-}
-
-impl<K, V, M: Copy> Copy for Bucket<K, V, M> {}
-impl<K, V, M: Copy> Clone for Bucket<K, V, M> {
-    fn clone(&self) -> Bucket<K, V, M> {
-        *self
-    }
-}
-
-pub struct EmptyBucket<K, V, M> {
-    raw: RawBucket<K, V>,
-    table: M,
-}
-
-pub struct FullBucket<K, V, M> {
-    raw: RawBucket<K, V>,
-    table: M,
-}
-
-pub type FullBucketMut<'table, K, V> = FullBucket<K, V, &'table mut RawTable<K, V>>;
-
-pub enum BucketState<K, V, M> {
-    Empty(EmptyBucket<K, V, M>),
-    Full(FullBucket<K, V, M>),
-}
-
-// A GapThenFull encapsulates the state of two consecutive buckets at once.
-// The first bucket, called the gap, is known to be empty.
-// The second bucket is full.
-pub struct GapThenFull<K, V, M> {
-    gap: EmptyBucket<K, V, ()>,
-    full: FullBucket<K, V, M>,
-}
-
-/// A hash that is not zero, since we use a hash of zero to represent empty
-/// buckets.
-#[derive(PartialEq, Copy, Clone)]
-pub struct SafeHash {
-    hash: HashUint,
-}
-
-impl SafeHash {
-    /// Peek at the hash value, which is guaranteed to be non-zero.
-    #[inline(always)]
-    pub fn inspect(&self) -> HashUint {
-        self.hash
-    }
-
-    #[inline(always)]
-    pub fn new(hash: u64) -> Self {
-        // We need to avoid 0 in order to prevent collisions with
-        // EMPTY_HASH. We can maintain our precious uniform distribution
-        // of initial indexes by unconditionally setting the MSB,
-        // effectively reducing the hashes by one bit.
-        //
-        // Truncate hash to fit in `HashUint`.
-        let hash_bits = size_of::<HashUint>() * 8;
-        SafeHash { hash: (1 << (hash_bits - 1)) | (hash as HashUint) }
-    }
-}
-
-/// We need to remove hashes of 0. That's reserved for empty buckets.
-/// This function wraps up `hash_keyed` to be the only way outside this
-/// module to generate a SafeHash.
-pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
-    where T: Hash,
-          S: BuildHasher
-{
-    let mut state = hash_state.build_hasher();
-    t.hash(&mut state);
-    SafeHash::new(state.finish())
-}
-
-// `replace` casts a `*HashUint` to a `*SafeHash`. Since we statically
-// ensure that a `FullBucket` points to an index with a non-zero hash,
-// and a `SafeHash` is just a `HashUint` with a different name, this is
-// safe.
-//
-// This test ensures that a `SafeHash` really IS the same size as a
-// `HashUint`. If you need to change the size of `SafeHash` (and
-// consequently made this test fail), `replace` needs to be
-// modified to no longer assume this.
-#[test]
-fn can_alias_safehash_as_hash() {
-    assert_eq!(size_of::<SafeHash>(), size_of::<HashUint>())
-}
-
-// RawBucket methods are unsafe as it's possible to
-// make a RawBucket point to invalid memory using safe code.
-impl<K, V> RawBucket<K, V> {
-    unsafe fn hash(&self) -> *mut HashUint {
-        self.hash_start.add(self.idx)
-    }
-    unsafe fn pair(&self) -> *mut (K, V) {
-        self.pair_start.add(self.idx) as *mut (K, V)
-    }
-    unsafe fn hash_pair(&self) -> (*mut HashUint, *mut (K, V)) {
-        (self.hash(), self.pair())
-    }
-}
-
-// Buckets hold references to the table.
-impl<K, V, M> FullBucket<K, V, M> {
-    /// Borrow a reference to the table.
-    pub fn table(&self) -> &M {
-        &self.table
-    }
-    /// Borrow a mutable reference to the table.
-    pub fn table_mut(&mut self) -> &mut M {
-        &mut self.table
-    }
-    /// Move out the reference to the table.
-    pub fn into_table(self) -> M {
-        self.table
-    }
-    /// Gets the raw index.
-    pub fn index(&self) -> usize {
-        self.raw.idx
-    }
-    /// Gets the raw bucket.
-    pub fn raw(&self) -> RawBucket<K, V> {
-        self.raw
-    }
-}
-
-impl<K, V, M> EmptyBucket<K, V, M> {
-    /// Borrow a reference to the table.
-    pub fn table(&self) -> &M {
-        &self.table
-    }
-    /// Borrow a mutable reference to the table.
-    pub fn table_mut(&mut self) -> &mut M {
-        &mut self.table
-    }
-}
-
-impl<K, V, M> Bucket<K, V, M> {
-    /// Gets the raw index.
-    pub fn index(&self) -> usize {
-        self.raw.idx
-    }
-    /// get the table.
-    pub fn into_table(self) -> M {
-        self.table
-    }
-}
-
-impl<K, V, M> Deref for FullBucket<K, V, M>
-    where M: Deref<Target = RawTable<K, V>>
-{
-    type Target = RawTable<K, V>;
-    fn deref(&self) -> &RawTable<K, V> {
-        &self.table
-    }
-}
-
-/// `Put` is implemented for types which provide access to a table and cannot be invalidated
-///  by filling a bucket. A similar implementation for `Take` is possible.
-pub trait Put<K, V> {
-    unsafe fn borrow_table_mut(&mut self) -> &mut RawTable<K, V>;
-}
-
-
-impl<K, V> Put<K, V> for &mut RawTable<K, V> {
-    unsafe fn borrow_table_mut(&mut self) -> &mut RawTable<K, V> {
-        *self
-    }
-}
-
-impl<K, V, M> Put<K, V> for Bucket<K, V, M>
-    where M: Put<K, V>
-{
-    unsafe fn borrow_table_mut(&mut self) -> &mut RawTable<K, V> {
-        self.table.borrow_table_mut()
-    }
-}
-
-impl<K, V, M> Put<K, V> for FullBucket<K, V, M>
-    where M: Put<K, V>
-{
-    unsafe fn borrow_table_mut(&mut self) -> &mut RawTable<K, V> {
-        self.table.borrow_table_mut()
-    }
-}
-
-impl<K, V, M: Deref<Target = RawTable<K, V>>> Bucket<K, V, M> {
-    #[inline]
-    pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> {
-        Bucket::at_index(table, hash.inspect() as usize)
-    }
-
-    pub fn new_from(r: RawBucket<K, V>, t: M)
-        -> Bucket<K, V, M>
-    {
-        Bucket {
-            raw: r,
-            table: t,
-        }
-    }
-
-    #[inline]
-    pub fn at_index(table: M, ib_index: usize) -> Bucket<K, V, M> {
-        // if capacity is 0, then the RawBucket will be populated with bogus pointers.
-        // This is an uncommon case though, so avoid it in release builds.
-        debug_assert!(table.capacity() > 0,
-                      "Table should have capacity at this point");
-        let ib_index = ib_index & table.capacity_mask;
-        Bucket {
-            raw: table.raw_bucket_at(ib_index),
-            table,
-        }
-    }
-
-    pub fn first(table: M) -> Bucket<K, V, M> {
-        Bucket {
-            raw: table.raw_bucket_at(0),
-            table,
-        }
-    }
-
-    // "So a few of the first shall be last: for many be called,
-    // but few chosen."
-    //
-    // We'll most likely encounter a few buckets at the beginning that
-    // have their initial buckets near the end of the table. They were
-    // placed at the beginning as the probe wrapped around the table
-    // during insertion. We must skip forward to a bucket that won't
-    // get reinserted too early and won't unfairly steal others spot.
-    // This eliminates the need for robin hood.
-    pub fn head_bucket(table: M) -> Bucket<K, V, M> {
-        let mut bucket = Bucket::first(table);
-
-        loop {
-            bucket = match bucket.peek() {
-                Full(full) => {
-                    if full.displacement() == 0 {
-                        // This bucket occupies its ideal spot.
-                        // It indicates the start of another "cluster".
-                        bucket = full.into_bucket();
-                        break;
-                    }
-                    // Leaving this bucket in the last cluster for later.
-                    full.into_bucket()
-                }
-                Empty(b) => {
-                    // Encountered a hole between clusters.
-                    b.into_bucket()
-                }
-            };
-            bucket.next();
-        }
-        bucket
-    }
-
-    /// Reads a bucket at a given index, returning an enum indicating whether
-    /// it's initialized or not. You need to match on this enum to get
-    /// the appropriate types to call most of the other functions in
-    /// this module.
-    pub fn peek(self) -> BucketState<K, V, M> {
-        match unsafe { *self.raw.hash() } {
-            EMPTY_BUCKET => {
-                Empty(EmptyBucket {
-                    raw: self.raw,
-                    table: self.table,
-                })
-            }
-            _ => {
-                Full(FullBucket {
-                    raw: self.raw,
-                    table: self.table,
-                })
-            }
-        }
-    }
-
-    /// Modifies the bucket in place to make it point to the next slot.
-    pub fn next(&mut self) {
-        self.raw.idx = self.raw.idx.wrapping_add(1) & self.table.capacity_mask;
-    }
-
-    /// Modifies the bucket in place to make it point to the previous slot.
-    pub fn prev(&mut self) {
-        self.raw.idx = self.raw.idx.wrapping_sub(1) & self.table.capacity_mask;
-    }
-}
-
-impl<K, V, M: Deref<Target = RawTable<K, V>>> EmptyBucket<K, V, M> {
-    #[inline]
-    pub fn next(self) -> Bucket<K, V, M> {
-        let mut bucket = self.into_bucket();
-        bucket.next();
-        bucket
-    }
-
-    #[inline]
-    pub fn into_bucket(self) -> Bucket<K, V, M> {
-        Bucket {
-            raw: self.raw,
-            table: self.table,
-        }
-    }
-
-    pub fn gap_peek(self) -> Result<GapThenFull<K, V, M>, Bucket<K, V, M>> {
-        let gap = EmptyBucket {
-            raw: self.raw,
-            table: (),
-        };
-
-        match self.next().peek() {
-            Full(bucket) => {
-                Ok(GapThenFull {
-                    gap,
-                    full: bucket,
-                })
-            }
-            Empty(e) => Err(e.into_bucket()),
-        }
-    }
-}
-
-impl<K, V, M> EmptyBucket<K, V, M>
-    where M: Put<K, V>
-{
-    /// Puts given key and value pair, along with the key's hash,
-    /// into this bucket in the hashtable. Note how `self` is 'moved' into
-    /// this function, because this slot will no longer be empty when
-    /// we return! A `FullBucket` is returned for later use, pointing to
-    /// the newly-filled slot in the hashtable.
-    ///
-    /// Use `make_hash` to construct a `SafeHash` to pass to this function.
-    pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket<K, V, M> {
-        unsafe {
-            *self.raw.hash() = hash.inspect();
-            ptr::write(self.raw.pair(), (key, value));
-
-            self.table.borrow_table_mut().size += 1;
-        }
-
-        FullBucket {
-            raw: self.raw,
-            table: self.table,
-        }
-    }
-}
-
-impl<K, V, M: Deref<Target = RawTable<K, V>>> FullBucket<K, V, M> {
-    #[inline]
-    pub fn next(self) -> Bucket<K, V, M> {
-        let mut bucket = self.into_bucket();
-        bucket.next();
-        bucket
-    }
-
-    #[inline]
-    pub fn into_bucket(self) -> Bucket<K, V, M> {
-        Bucket {
-            raw: self.raw,
-            table: self.table,
-        }
-    }
-
-    /// Duplicates the current position. This can be useful for operations
-    /// on two or more buckets.
-    pub fn stash(self) -> FullBucket<K, V, Self> {
-        FullBucket {
-            raw: self.raw,
-            table: self,
-        }
-    }
-
-    /// Gets the distance between this bucket and the 'ideal' location
-    /// as determined by the key's hash stored in it.
-    ///
-    /// In the cited blog posts above, this is called the "distance to
-    /// initial bucket", or DIB. Also known as "probe count".
-    pub fn displacement(&self) -> usize {
-        // Calculates the distance one has to travel when going from
-        // `hash mod capacity` onwards to `idx mod capacity`, wrapping around
-        // if the destination is not reached before the end of the table.
-        (self.raw.idx.wrapping_sub(self.hash().inspect() as usize)) & self.table.capacity_mask
-    }
-
-    #[inline]
-    pub fn hash(&self) -> SafeHash {
-        unsafe { SafeHash { hash: *self.raw.hash() } }
-    }
-
-    /// Gets references to the key and value at a given index.
-    pub fn read(&self) -> (&K, &V) {
-        unsafe {
-            let pair_ptr = self.raw.pair();
-            (&(*pair_ptr).0, &(*pair_ptr).1)
-        }
-    }
-}
-
-// We take a mutable reference to the table instead of accepting anything that
-// implements `DerefMut` to prevent fn `take` from being called on `stash`ed
-// buckets.
-impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
-    /// Removes this bucket's key and value from the hashtable.
-    ///
-    /// This works similarly to `put`, building an `EmptyBucket` out of the
-    /// taken bucket.
-    pub fn take(self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
-        self.table.size -= 1;
-
-        unsafe {
-            *self.raw.hash() = EMPTY_BUCKET;
-            let (k, v) = ptr::read(self.raw.pair());
-            (EmptyBucket {
-                 raw: self.raw,
-                 table: self.table,
-             },
-            k,
-            v)
-        }
-    }
-}
-
-// This use of `Put` is misleading and restrictive, but safe and sufficient for our use cases
-// where `M` is a full bucket or table reference type with mutable access to the table.
-impl<K, V, M> FullBucket<K, V, M>
-    where M: Put<K, V>
-{
-    pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) {
-        unsafe {
-            let old_hash = ptr::replace(self.raw.hash() as *mut SafeHash, h);
-            let (old_key, old_val) = ptr::replace(self.raw.pair(), (k, v));
-
-            (old_hash, old_key, old_val)
-        }
-    }
-}
-
-impl<K, V, M> FullBucket<K, V, M>
-    where M: Deref<Target = RawTable<K, V>> + DerefMut
-{
-    /// Gets mutable references to the key and value at a given index.
-    pub fn read_mut(&mut self) -> (&mut K, &mut V) {
-        unsafe {
-            let pair_ptr = self.raw.pair();
-            (&mut (*pair_ptr).0, &mut (*pair_ptr).1)
-        }
-    }
-}
-
-impl<'t, K, V, M> FullBucket<K, V, M>
-    where M: Deref<Target = RawTable<K, V>> + 't
-{
-    /// Exchange a bucket state for immutable references into the table.
-    /// Because the underlying reference to the table is also consumed,
-    /// no further changes to the structure of the table are possible;
-    /// in exchange for this, the returned references have a longer lifetime
-    /// than the references returned by `read()`.
-    pub fn into_refs(self) -> (&'t K, &'t V) {
-        unsafe {
-            let pair_ptr = self.raw.pair();
-            (&(*pair_ptr).0, &(*pair_ptr).1)
-        }
-    }
-}
-
-impl<'t, K, V, M> FullBucket<K, V, M>
-    where M: Deref<Target = RawTable<K, V>> + DerefMut + 't
-{
-    /// This works similarly to `into_refs`, exchanging a bucket state
-    /// for mutable references into the table.
-    pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
-        unsafe {
-            let pair_ptr = self.raw.pair();
-            (&mut (*pair_ptr).0, &mut (*pair_ptr).1)
-        }
-    }
-}
-
-impl<K, V, M> GapThenFull<K, V, M>
-    where M: Deref<Target = RawTable<K, V>>
-{
-    #[inline]
-    pub fn full(&self) -> &FullBucket<K, V, M> {
-        &self.full
-    }
-
-    pub fn into_table(self) -> M {
-        self.full.into_table()
-    }
-
-    pub fn shift(mut self) -> Result<GapThenFull<K, V, M>, Bucket<K, V, M>> {
-        unsafe {
-            let (gap_hash, gap_pair) = self.gap.raw.hash_pair();
-            let (full_hash, full_pair) = self.full.raw.hash_pair();
-            *gap_hash = mem::replace(&mut *full_hash, EMPTY_BUCKET);
-            ptr::copy_nonoverlapping(full_pair, gap_pair, 1);
-        }
-
-        let FullBucket { raw: prev_raw, .. } = self.full;
-
-        match self.full.next().peek() {
-            Full(bucket) => {
-                self.gap.raw = prev_raw;
-
-                self.full = bucket;
-
-                Ok(self)
-            }
-            Empty(b) => Err(b.into_bucket()),
-        }
-    }
-}
-
-// Returns a Layout which describes the allocation required for a hash table,
-// and the offset of the array of (key, value) pairs in the allocation.
-#[inline(always)]
-fn calculate_layout<K, V>(capacity: usize) -> Result<(Layout, usize), LayoutErr> {
-    let hashes = Layout::array::<HashUint>(capacity)?;
-    let pairs = Layout::array::<(K, V)>(capacity)?;
-    hashes.extend(pairs).map(|(layout, _)| {
-        // LLVM seems to have trouble properly const-propagating pairs.align(),
-        // possibly due to the use of NonZeroUsize. This little hack allows it
-        // to generate optimal code.
-        //
-        // See https://github.com/rust-lang/rust/issues/51346 for more details.
-        (
-            layout,
-            hashes.size() + hashes.padding_needed_for(mem::align_of::<(K, V)>()),
-        )
-    })
-}
-
-pub(crate) enum Fallibility {
-    Fallible,
-    Infallible,
-}
-
-use self::Fallibility::*;
-
-impl<K, V> RawTable<K, V> {
-    /// Does not initialize the buckets. The caller should ensure they,
-    /// at the very least, set every hash to EMPTY_BUCKET.
-    /// Returns an error if it cannot allocate or capacity overflows.
-    unsafe fn new_uninitialized_internal(
-        capacity: usize,
-        fallibility: Fallibility,
-    ) -> Result<RawTable<K, V>, CollectionAllocErr> {
-        if capacity == 0 {
-            return Ok(RawTable {
-                size: 0,
-                capacity_mask: capacity.wrapping_sub(1),
-                hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint),
-                marker: marker::PhantomData,
-            });
-        }
-
-        // Allocating hashmaps is a little tricky. We need to allocate two
-        // arrays, but since we know their sizes and alignments up front,
-        // we just allocate a single array, and then have the subarrays
-        // point into it.
-        let (layout, _) = calculate_layout::<K, V>(capacity)?;
-        let buffer = Global.alloc(layout).map_err(|e| match fallibility {
-            Infallible => handle_alloc_error(layout),
-            Fallible => e,
-        })?;
-
-        Ok(RawTable {
-            capacity_mask: capacity.wrapping_sub(1),
-            size: 0,
-            hashes: TaggedHashUintPtr::new(buffer.cast().as_ptr()),
-            marker: marker::PhantomData,
-        })
-    }
-
-    /// Does not initialize the buckets. The caller should ensure they,
-    /// at the very least, set every hash to EMPTY_BUCKET.
-    unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
-        match Self::new_uninitialized_internal(capacity, Infallible) {
-            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => unreachable!(),
-            Ok(table) => { table }
-        }
-    }
-
-    #[inline(always)]
-    fn raw_bucket_at(&self, index: usize) -> RawBucket<K, V> {
-        let (_, pairs_offset) = calculate_layout::<K, V>(self.capacity())
-            .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() });
-        let buffer = self.hashes.ptr() as *mut u8;
-        unsafe {
-            RawBucket {
-                hash_start: buffer as *mut HashUint,
-                pair_start: buffer.add(pairs_offset) as *const (K, V),
-                idx: index,
-                _marker: marker::PhantomData,
-            }
-        }
-    }
-
-    #[inline]
-    fn new_internal(
-        capacity: usize,
-        fallibility: Fallibility,
-    ) -> Result<RawTable<K, V>, CollectionAllocErr> {
-        unsafe {
-            let ret = RawTable::new_uninitialized_internal(capacity, fallibility)?;
-            if capacity > 0 {
-                ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
-            }
-            Ok(ret)
-        }
-    }
-
-    /// Tries to create a new raw table from a given capacity. If it cannot allocate,
-    /// it returns with AllocErr.
-    #[inline]
-    pub fn try_new(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> {
-        Self::new_internal(capacity, Fallible)
-    }
-
-    /// Creates a new raw table from a given capacity. All buckets are
-    /// initially empty.
-    #[inline]
-    pub fn new(capacity: usize) -> RawTable<K, V> {
-        match Self::new_internal(capacity, Infallible) {
-            Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => unreachable!(),
-            Ok(table) => { table }
-        }
-    }
-
-    /// The hashtable's capacity, similar to a vector's.
-    pub fn capacity(&self) -> usize {
-        self.capacity_mask.wrapping_add(1)
-    }
-
-    /// The number of elements ever `put` in the hashtable, minus the number
-    /// of elements ever `take`n.
-    pub fn size(&self) -> usize {
-        self.size
-    }
-
-    fn raw_buckets(&self) -> RawBuckets<K, V> {
-        RawBuckets {
-            raw: self.raw_bucket_at(0),
-            elems_left: self.size,
-            marker: marker::PhantomData,
-        }
-    }
-
-    pub fn iter(&self) -> Iter<K, V> {
-        Iter {
-            iter: self.raw_buckets(),
-        }
-    }
-
-    pub fn iter_mut(&mut self) -> IterMut<K, V> {
-        IterMut {
-            iter: self.raw_buckets(),
-            _marker: marker::PhantomData,
-        }
-    }
-
-    pub fn into_iter(self) -> IntoIter<K, V> {
-        let RawBuckets { raw, elems_left, .. } = self.raw_buckets();
-        // Replace the marker regardless of lifetime bounds on parameters.
-        IntoIter {
-            iter: RawBuckets {
-                raw,
-                elems_left,
-                marker: marker::PhantomData,
-            },
-            table: self,
-        }
-    }
-
-    pub fn drain(&mut self) -> Drain<K, V> {
-        let RawBuckets { raw, elems_left, .. } = self.raw_buckets();
-        // Replace the marker regardless of lifetime bounds on parameters.
-        Drain {
-            iter: RawBuckets {
-                raw,
-                elems_left,
-                marker: marker::PhantomData,
-            },
-            table: NonNull::from(self),
-            marker: marker::PhantomData,
-        }
-    }
-
-    /// Drops buckets in reverse order. It leaves the table in an inconsistent
-    /// state and should only be used for dropping the table's remaining
-    /// entries. It's used in the implementation of Drop.
-    unsafe fn rev_drop_buckets(&mut self) {
-        // initialize the raw bucket past the end of the table
-        let mut raw = self.raw_bucket_at(self.capacity());
-        let mut elems_left = self.size;
-
-        while elems_left != 0 {
-            raw.idx -= 1;
-
-            if *raw.hash() != EMPTY_BUCKET {
-                elems_left -= 1;
-                ptr::drop_in_place(raw.pair());
-            }
-        }
-    }
-
-    /// Sets the table tag.
-    pub fn set_tag(&mut self, value: bool) {
-        self.hashes.set_tag(value)
-    }
-
-    /// Gets the table tag.
-    pub fn tag(&self) -> bool {
-        self.hashes.tag()
-    }
-}
-
-/// A raw iterator. The basis for some other iterators in this module. Although
-/// this interface is safe, it's not used outside this module.
-struct RawBuckets<'a, K, V> {
-    raw: RawBucket<K, V>,
-    elems_left: usize,
-
-    // Strictly speaking, this should be &'a (K,V), but that would
-    // require that K:'a, and we often use RawBuckets<'static...> for
-    // move iterations, so that messes up a lot of other things. So
-    // just use `&'a (K,V)` as this is not a publicly exposed type
-    // anyway.
-    marker: marker::PhantomData<&'a ()>,
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for RawBuckets<'_, K, V> {
-    fn clone(&self) -> Self {
-        RawBuckets {
-            raw: self.raw,
-            elems_left: self.elems_left,
-            marker: marker::PhantomData,
-        }
-    }
-}
-
-
-impl<'a, K, V> Iterator for RawBuckets<'a, K, V> {
-    type Item = RawBucket<K, V>;
-
-    fn next(&mut self) -> Option<RawBucket<K, V>> {
-        if self.elems_left == 0 {
-            return None;
-        }
-
-        loop {
-            unsafe {
-                let item = self.raw;
-                self.raw.idx += 1;
-                if *item.hash() != EMPTY_BUCKET {
-                    self.elems_left -= 1;
-                    return Some(item);
-                }
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.elems_left, Some(self.elems_left))
-    }
-}
-
-impl<K, V> ExactSizeIterator for RawBuckets<'_, K, V> {
-    fn len(&self) -> usize {
-        self.elems_left
-    }
-}
-
-/// Iterator over shared references to entries in a table.
-pub struct Iter<'a, K: 'a, V: 'a> {
-    iter: RawBuckets<'a, K, V>,
-}
-
-unsafe impl<K: Sync, V: Sync> Sync for Iter<'_, K, V> {}
-unsafe impl<K: Sync, V: Sync> Send for Iter<'_, K, V> {}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Iter<'_, K, V> {
-    fn clone(&self) -> Self {
-        Iter {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-/// Iterator over mutable references to entries in a table.
-pub struct IterMut<'a, K: 'a, V: 'a> {
-    iter: RawBuckets<'a, K, V>,
-    // To ensure invariance with respect to V
-    _marker: marker::PhantomData<&'a mut V>,
-}
-
-unsafe impl<K: Sync, V: Sync> Sync for IterMut<'_, K, V> {}
-// Both K: Sync and K: Send are correct for IterMut's Send impl,
-// but Send is the more useful bound
-unsafe impl<K: Send, V: Send> Send for IterMut<'_, K, V> {}
-
-impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> {
-    pub fn iter(&self) -> Iter<K, V> {
-        Iter {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-/// Iterator over the entries in a table, consuming the table.
-pub struct IntoIter<K, V> {
-    table: RawTable<K, V>,
-    iter: RawBuckets<'static, K, V>,
-}
-
-unsafe impl<K: Sync, V: Sync> Sync for IntoIter<K, V> {}
-unsafe impl<K: Send, V: Send> Send for IntoIter<K, V> {}
-
-impl<K, V> IntoIter<K, V> {
-    pub fn iter(&self) -> Iter<K, V> {
-        Iter {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-/// Iterator over the entries in a table, clearing the table.
-pub struct Drain<'a, K: 'a, V: 'a> {
-    table: NonNull<RawTable<K, V>>,
-    iter: RawBuckets<'static, K, V>,
-    marker: marker::PhantomData<&'a RawTable<K, V>>,
-}
-
-unsafe impl<K: Sync, V: Sync> Sync for Drain<'_, K, V> {}
-unsafe impl<K: Send, V: Send> Send for Drain<'_, K, V> {}
-
-impl<'a, K, V> Drain<'a, K, V> {
-    pub fn iter(&self) -> Iter<K, V> {
-        Iter {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-impl<'a, K, V> Iterator for Iter<'a, K, V> {
-    type Item = (&'a K, &'a V);
-
-    fn next(&mut self) -> Option<(&'a K, &'a V)> {
-        self.iter.next().map(|raw| unsafe {
-            let pair_ptr = raw.pair();
-            (&(*pair_ptr).0, &(*pair_ptr).1)
-        })
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-
-impl<'a, K, V> Iterator for IterMut<'a, K, V> {
-    type Item = (&'a K, &'a mut V);
-
-    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
-        self.iter.next().map(|raw| unsafe {
-            let pair_ptr = raw.pair();
-            (&(*pair_ptr).0, &mut (*pair_ptr).1)
-        })
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-
-impl<K, V> Iterator for IntoIter<K, V> {
-    type Item = (SafeHash, K, V);
-
-    fn next(&mut self) -> Option<(SafeHash, K, V)> {
-        self.iter.next().map(|raw| {
-            self.table.size -= 1;
-            unsafe {
-                let (k, v) = ptr::read(raw.pair());
-                (SafeHash { hash: *raw.hash() }, k, v)
-            }
-        })
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<K, V> ExactSizeIterator for IntoIter<K, V> {
-    fn len(&self) -> usize {
-        self.iter().len()
-    }
-}
-
-impl<'a, K, V> Iterator for Drain<'a, K, V> {
-    type Item = (SafeHash, K, V);
-
-    #[inline]
-    fn next(&mut self) -> Option<(SafeHash, K, V)> {
-        self.iter.next().map(|raw| {
-            unsafe {
-                self.table.as_mut().size -= 1;
-                let (k, v) = ptr::read(raw.pair());
-                (SafeHash { hash: ptr::replace(&mut *raw.hash(), EMPTY_BUCKET) }, k, v)
-            }
-        })
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<K, V> ExactSizeIterator for Drain<'_, K, V> {
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-
-impl<K, V> Drop for Drain<'_, K, V> {
-    fn drop(&mut self) {
-        self.for_each(drop);
-    }
-}
-
-impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
-    fn clone(&self) -> RawTable<K, V> {
-        unsafe {
-            let cap = self.capacity();
-            let mut new_ht = RawTable::new_uninitialized(cap);
-
-            let mut new_buckets = new_ht.raw_bucket_at(0);
-            let mut buckets = self.raw_bucket_at(0);
-            while buckets.idx < cap {
-                *new_buckets.hash() = *buckets.hash();
-                if *new_buckets.hash() != EMPTY_BUCKET {
-                    let pair_ptr = buckets.pair();
-                    let kv = ((*pair_ptr).0.clone(), (*pair_ptr).1.clone());
-                    ptr::write(new_buckets.pair(), kv);
-                }
-                buckets.idx += 1;
-                new_buckets.idx += 1;
-            }
-
-            new_ht.size = self.size();
-            new_ht.set_tag(self.tag());
-
-            new_ht
-        }
-    }
-}
-
-unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
-    fn drop(&mut self) {
-        if self.capacity() == 0 {
-            return;
-        }
-
-        // This is done in reverse because we've likely partially taken
-        // some elements out with `.into_iter()` from the front.
-        // Check if the size is 0, so we don't do a useless scan when
-        // dropping empty tables such as on resize.
-        // Also avoid double drop of elements that have been already moved out.
-        unsafe {
-            if needs_drop::<(K, V)>() {
-                // avoid linear runtime for types that don't need drop
-                self.rev_drop_buckets();
-            }
-        }
-
-        let (layout, _) = calculate_layout::<K, V>(self.capacity())
-            .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() });
-        unsafe {
-            Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).cast(), layout);
-            // Remember how everything was allocated out of one buffer
-            // during initialization? We only need one call to free here.
-        }
-    }
-}
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 286ce2d389b..15c2532f8b4 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -150,10 +150,9 @@
 //! Any `with_capacity` constructor will instruct the collection to allocate
 //! enough space for the specified number of elements. Ideally this will be for
 //! exactly that many elements, but some implementation details may prevent
-//! this. [`Vec`] and [`VecDeque`] can be relied on to allocate exactly the
-//! requested amount, though. Use `with_capacity` when you know exactly how many
-//! elements will be inserted, or at least have a reasonable upper-bound on that
-//! number.
+//! this. See collection-specific documentation for details. In general, use
+//! `with_capacity` when you know exactly how many elements will be inserted, or
+//! at least have a reasonable upper-bound on that number.
 //!
 //! When anticipating a large influx of elements, the `reserve` family of
 //! methods can be used to hint to the collection how much room it should make
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 97c67f562a7..1f5de25b65c 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -156,7 +156,7 @@ impl Iterator for Vars {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Vars {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Vars { .. }")
     }
 }
@@ -170,7 +170,7 @@ impl Iterator for VarsOs {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for VarsOs {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("VarsOs { .. }")
     }
 }
@@ -253,7 +253,7 @@ pub enum VarError {
 
 #[stable(feature = "env", since = "1.0.0")]
 impl fmt::Display for VarError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             VarError::NotPresent => write!(f, "environment variable not found"),
             VarError::NotUnicode(ref s) => {
@@ -359,9 +359,12 @@ fn _remove_var(k: &OsStr) {
 /// An iterator that splits an environment variable into paths according to
 /// platform-specific conventions.
 ///
+/// The iterator element type is [`PathBuf`].
+///
 /// This structure is created by the [`std::env::split_paths`] function. See its
 /// documentation for more.
 ///
+/// [`PathBuf`]: ../../std/path/struct.PathBuf.html
 /// [`std::env::split_paths`]: fn.split_paths.html
 #[stable(feature = "env", since = "1.0.0")]
 pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
@@ -369,7 +372,8 @@ pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
 /// Parses input according to platform conventions for the `PATH`
 /// environment variable.
 ///
-/// Returns an iterator over the paths contained in `unparsed`.
+/// Returns an iterator over the paths contained in `unparsed`. The iterator
+/// element type is [`PathBuf`].
 ///
 /// # Examples
 ///
@@ -386,8 +390,10 @@ pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
+///
+/// [`PathBuf`]: ../../std/path/struct.PathBuf.html
 #[stable(feature = "env", since = "1.0.0")]
-pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths {
+pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
     SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
 }
 
@@ -400,7 +406,7 @@ impl<'a> Iterator for SplitPaths<'a> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for SplitPaths<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("SplitPaths { .. }")
     }
 }
@@ -459,7 +465,7 @@ pub struct JoinPathsError {
 /// # }
 /// ```
 ///
-/// Using `env::join_paths` with `env::spit_paths` to append an item to the `PATH` environment
+/// Using `env::join_paths` with [`env::split_paths`] to append an item to the `PATH` environment
 /// variable:
 ///
 /// ```
@@ -477,6 +483,8 @@ pub struct JoinPathsError {
 ///     Ok(())
 /// }
 /// ```
+///
+/// [`env::split_paths`]: fn.split_paths.html
 #[stable(feature = "env", since = "1.0.0")]
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
     where I: IntoIterator<Item=T>, T: AsRef<OsStr>
@@ -488,7 +496,7 @@ pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
 
 #[stable(feature = "env", since = "1.0.0")]
 impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.inner.fmt(f)
     }
 }
@@ -757,7 +765,7 @@ impl DoubleEndedIterator for Args {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Args {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Args")
             .field("inner", &self.inner.inner.inner_debug())
             .finish()
@@ -790,7 +798,7 @@ impl DoubleEndedIterator for ArgsOs {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ArgsOs {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("ArgsOs")
             .field("inner", &self.inner.inner_debug())
             .finish()
@@ -839,7 +847,6 @@ pub mod consts {
     /// - ios
     /// - freebsd
     /// - dragonfly
-    /// - bitrig
     /// - netbsd
     /// - openbsd
     /// - solaris
@@ -968,6 +975,11 @@ mod arch {
     pub const ARCH: &str = "wasm32";
 }
 
+#[cfg(target_arch = "hexagon")]
+mod arch {
+    pub const ARCH: &'static str = "hexagon";
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -975,7 +987,7 @@ mod tests {
     use crate::path::Path;
 
     #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
     fn test_self_exe_path() {
         let path = current_exe();
         assert!(path.is_ok());
@@ -989,6 +1001,7 @@ mod tests {
     fn test() {
         assert!((!Path::new("test-path").is_absolute()));
 
+        #[cfg(not(target_env = "sgx"))]
         current_dir().unwrap();
     }
 
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 3eb289501cb..117a430eec6 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -84,7 +84,7 @@ pub trait Error: Debug + Display {
     /// }
     ///
     /// impl fmt::Display for SuperError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "SuperError is here!")
     ///     }
     /// }
@@ -94,7 +94,7 @@ pub trait Error: Debug + Display {
     ///         "I'm the superhero of errors"
     ///     }
     ///
-    ///     fn cause(&self) -> Option<&Error> {
+    ///     fn cause(&self) -> Option<&dyn Error> {
     ///         Some(&self.side)
     ///     }
     /// }
@@ -103,7 +103,7 @@ pub trait Error: Debug + Display {
     /// struct SuperErrorSideKick;
     ///
     /// impl fmt::Display for SuperErrorSideKick {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "SuperErrorSideKick is here!")
     ///     }
     /// }
@@ -149,7 +149,7 @@ pub trait Error: Debug + Display {
     /// }
     ///
     /// impl fmt::Display for SuperError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "SuperError is here!")
     ///     }
     /// }
@@ -168,7 +168,7 @@ pub trait Error: Debug + Display {
     /// struct SuperErrorSideKick;
     ///
     /// impl fmt::Display for SuperErrorSideKick {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "SuperErrorSideKick is here!")
     ///     }
     /// }
@@ -198,16 +198,28 @@ pub trait Error: Debug + Display {
 
     /// Gets the `TypeId` of `self`
     #[doc(hidden)]
-    #[stable(feature = "error_type_id", since = "1.34.0")]
-    fn type_id(&self) -> TypeId where Self: 'static {
+    #[unstable(feature = "error_type_id",
+               reason = "this is memory unsafe to override in user code",
+               issue = "60784")]
+    fn type_id(&self, _: private::Internal) -> TypeId where Self: 'static {
         TypeId::of::<Self>()
     }
 }
 
+mod private {
+    // This is a hack to prevent `type_id` from being overridden by `Error`
+    // implementations, since that can enable unsound downcasting.
+    #[unstable(feature = "error_type_id", issue = "60784")]
+    #[derive(Debug)]
+    pub struct Internal;
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
     /// Converts a type of [`Error`] into a box of dyn [`Error`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -219,7 +231,7 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
     /// struct AnError;
     ///
     /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f , "An error")
     ///     }
     /// }
@@ -232,7 +244,7 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
     ///
     /// let an_error = AnError;
     /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<Error>::from(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> {
@@ -242,8 +254,10 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 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`].
+    /// Converts a type of [`Error`] + [`trait@Send`] + [`trait@Sync`] into a box of
+    /// dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    ///
+    /// [`Error`]: ../error/trait.Error.html
     ///
     /// # Examples
     ///
@@ -256,7 +270,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
     /// struct AnError;
     ///
     /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f , "An error")
     ///     }
     /// }
@@ -273,7 +287,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
     ///
     /// let an_error = AnError;
     /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<Error + Send + Sync>::from(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))
     /// ```
@@ -284,7 +298,9 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for Box<dyn Error + Send + Sync> {
-    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    /// Converts a [`String`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    ///
+    /// [`Error`]: ../error/trait.Error.html
     ///
     /// # Examples
     ///
@@ -293,12 +309,11 @@ impl From<String> for Box<dyn Error + Send + Sync> {
     /// use std::mem;
     ///
     /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_string_error);
+    /// 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))
     /// ```
     fn from(err: String) -> Box<dyn Error + Send + Sync> {
-        #[derive(Debug)]
         struct StringError(String);
 
         impl Error for StringError {
@@ -306,11 +321,18 @@ impl From<String> for Box<dyn Error + Send + Sync> {
         }
 
         impl Display for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            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))
     }
 }
@@ -319,6 +341,8 @@ impl From<String> for Box<dyn Error + Send + Sync> {
 impl From<String> for Box<dyn Error> {
     /// Converts a [`String`] into a box of dyn [`Error`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -326,7 +350,7 @@ impl From<String> for Box<dyn Error> {
     /// use std::mem;
     ///
     /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<Error>::from(a_string_error);
+    /// 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> {
@@ -338,7 +362,9 @@ impl From<String> for Box<dyn Error> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    /// Converts a [`str`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    ///
+    /// [`Error`]: ../error/trait.Error.html
     ///
     /// # Examples
     ///
@@ -347,7 +373,7 @@ impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
     /// use std::mem;
     ///
     /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<Error + Send + Sync>::from(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))
     /// ```
@@ -360,6 +386,8 @@ impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
 impl From<&str> for Box<dyn Error> {
     /// Converts a [`str`] into a box of dyn [`Error`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -367,7 +395,7 @@ impl From<&str> for Box<dyn Error> {
     /// use std::mem;
     ///
     /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<Error>::from(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> {
@@ -377,7 +405,10 @@ impl From<&str> for Box<dyn Error> {
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
 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`].
+    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
+    ///
+    /// [`Cow`]: ../borrow/enum.Cow.html
+    /// [`Error`]: ../error/trait.Error.html
     ///
     /// # Examples
     ///
@@ -387,7 +418,7 @@ impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
     /// use std::borrow::Cow;
     ///
     /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_cow_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))
     /// ```
@@ -400,6 +431,9 @@ impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
 impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
     /// Converts a [`Cow`] into a box of dyn [`Error`].
     ///
+    /// [`Cow`]: ../borrow/enum.Cow.html
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -408,7 +442,7 @@ impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
     /// use std::borrow::Cow;
     ///
     /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<Error>::from(a_cow_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> {
@@ -526,6 +560,10 @@ impl<T: Error> Error for Box<T> {
     fn cause(&self) -> Option<&dyn Error> {
         Error::cause(&**self)
     }
+
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        Error::source(&**self)
+    }
 }
 
 #[stable(feature = "fmt_error", since = "1.11.0")]
@@ -573,7 +611,7 @@ impl dyn Error + 'static {
         let t = TypeId::of::<T>();
 
         // Get TypeId of the type in the trait object
-        let boxed = self.type_id();
+        let boxed = self.type_id(private::Internal);
 
         // Compare both TypeIds on equality
         t == boxed
@@ -686,13 +724,13 @@ impl dyn Error {
     /// struct B(Option<Box<dyn Error + 'static>>);
     ///
     /// impl fmt::Display for A {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     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 {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "B")
     ///     }
     /// }
@@ -721,7 +759,7 @@ impl dyn Error {
     /// [`source`]: trait.Error.html#method.source
     #[unstable(feature = "error_iter", issue = "58520")]
     #[inline]
-    pub fn iter_chain(&self) -> ErrorIter {
+    pub fn iter_chain(&self) -> ErrorIter<'_> {
         ErrorIter {
             current: Some(self),
         }
@@ -747,19 +785,19 @@ impl dyn Error {
     /// struct C(Option<Box<dyn Error + 'static>>);
     ///
     /// impl fmt::Display for A {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     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 {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "B")
     ///     }
     /// }
     ///
     /// impl fmt::Display for C {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "C")
     ///     }
     /// }
@@ -795,7 +833,7 @@ impl dyn Error {
     /// [`source`]: trait.Error.html#method.source
     #[inline]
     #[unstable(feature = "error_iter", issue = "58520")]
-    pub fn iter_sources(&self) -> ErrorIter {
+    pub fn iter_sources(&self) -> ErrorIter<'_> {
         ErrorIter {
             current: self.source(),
         }
@@ -861,12 +899,12 @@ mod tests {
     struct B;
 
     impl fmt::Display for A {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        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 {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             write!(f, "B")
         }
     }
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index a2b12d00a78..f649170c403 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -32,11 +32,13 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// let f = 3.99_f32;
+    /// let f = 3.7_f32;
     /// let g = 3.0_f32;
+    /// let h = -3.7_f32;
     ///
     /// assert_eq!(f.floor(), 3.0);
     /// assert_eq!(g.floor(), 3.0);
+    /// assert_eq!(h.floor(), -4.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -104,11 +106,13 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// let f = 3.3_f32;
-    /// let g = -3.7_f32;
+    /// let f = 3.7_f32;
+    /// let g = 3.0_f32;
+    /// let h = -3.7_f32;
     ///
     /// assert_eq!(f.trunc(), 3.0);
-    /// assert_eq!(g.trunc(), -3.0);
+    /// assert_eq!(g.trunc(), 3.0);
+    /// assert_eq!(h.trunc(), -3.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -184,21 +188,20 @@ impl f32 {
         if self.is_nan() {
             NAN
         } else {
-            unsafe { intrinsics::copysignf32(1.0, self) }
+            1.0_f32.copysign(self)
         }
     }
 
     /// Returns a number composed of the magnitude of `self` and the sign of
-    /// `y`.
+    /// `sign`.
     ///
-    /// Equal to `self` if the sign of `self` and `y` are the same, otherwise
+    /// 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
-    /// `y` is returned.
+    /// `sign` is returned.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(copysign)]
     /// use std::f32;
     ///
     /// let f = 3.5_f32;
@@ -212,9 +215,9 @@ impl f32 {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature="copysign", issue="55169")]
-    pub fn copysign(self, y: f32) -> f32 {
-        unsafe { intrinsics::copysignf32(self, y) }
+    #[stable(feature = "copysign", since = "1.35.0")]
+    pub fn copysign(self, sign: f32) -> f32 {
+        unsafe { intrinsics::copysignf32(self, sign) }
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -253,7 +256,6 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f32 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
@@ -262,7 +264,7 @@ impl f32 {
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f32) -> f32 {
         let q = (self / rhs).trunc();
         if self % rhs < 0.0 {
@@ -285,7 +287,6 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f32 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.rem_euclid(b), 3.0);
@@ -296,7 +297,7 @@ impl f32 {
     /// assert!((-std::f32::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f32) -> f32 {
         let r = self % rhs;
         if r < 0.0 {
@@ -956,16 +957,27 @@ impl f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
-    /// Returns max if self is greater than max, and min if self is less than min.
-    /// Otherwise this returns self.  Panics if min > max, min equals NaN, or max equals NaN.
+
+    /// Restrict a value to a certain interval unless it is NaN.
+    ///
+    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+    /// less than `min`. Otherwise this returns `self`.
+    ///
+    /// Not that this function returns NaN if the initial value was NaN as
+    /// well.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(clamp)]
-    /// assert!((-3.0f32).clamp(-2.0f32, 1.0f32) == -2.0f32);
-    /// assert!((0.0f32).clamp(-2.0f32, 1.0f32) == 0.0f32);
-    /// assert!((2.0f32).clamp(-2.0f32, 1.0f32) == 1.0f32);
+    /// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0);
+    /// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
+    /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
+    /// assert!((std::f32::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[unstable(feature = "clamp", issue = "44095")]
     #[inline]
@@ -1577,4 +1589,22 @@ mod tests {
         assert_eq!(f32::from_bits(masked_nan1).to_bits(), masked_nan1);
         assert_eq!(f32::from_bits(masked_nan2).to_bits(), masked_nan2);
     }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_greater_than_max() {
+        1.0f32.clamp(3.0, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_is_nan() {
+        1.0f32.clamp(NAN, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_max_is_nan() {
+        1.0f32.clamp(3.0, NAN);
+    }
 }
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index be5cd92d416..f61630997dc 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -32,11 +32,13 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// let f = 3.99_f64;
+    /// let f = 3.7_f64;
     /// let g = 3.0_f64;
+    /// let h = -3.7_f64;
     ///
     /// assert_eq!(f.floor(), 3.0);
     /// assert_eq!(g.floor(), 3.0);
+    /// assert_eq!(h.floor(), -4.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -84,11 +86,13 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// let f = 3.3_f64;
-    /// let g = -3.7_f64;
+    /// let f = 3.7_f64;
+    /// let g = 3.0_f64;
+    /// let h = -3.7_f64;
     ///
     /// assert_eq!(f.trunc(), 3.0);
-    /// assert_eq!(g.trunc(), -3.0);
+    /// assert_eq!(g.trunc(), 3.0);
+    /// assert_eq!(h.trunc(), -3.0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -162,21 +166,20 @@ impl f64 {
         if self.is_nan() {
             NAN
         } else {
-            unsafe { intrinsics::copysignf64(1.0, self) }
+            1.0_f64.copysign(self)
         }
     }
 
     /// Returns a number composed of the magnitude of `self` and the sign of
-    /// `y`.
+    /// `sign`.
     ///
-    /// Equal to `self` if the sign of `self` and `y` are the same, otherwise
+    /// 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
-    /// `y` is returned.
+    /// `sign` is returned.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(copysign)]
     /// use std::f64;
     ///
     /// let f = 3.5_f64;
@@ -190,9 +193,9 @@ impl f64 {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature="copysign", issue="55169")]
-    pub fn copysign(self, y: f64) -> f64 {
-        unsafe { intrinsics::copysignf64(self, y) }
+    #[stable(feature = "copysign", since = "1.35.0")]
+    pub fn copysign(self, sign: f64) -> f64 {
+        unsafe { intrinsics::copysignf64(self, sign) }
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -229,7 +232,6 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f64 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
@@ -238,7 +240,7 @@ impl f64 {
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f64) -> f64 {
         let q = (self / rhs).trunc();
         if self % rhs < 0.0 {
@@ -261,7 +263,6 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(euclidean_division)]
     /// let a: f64 = 7.0;
     /// let b = 4.0;
     /// assert_eq!(a.rem_euclid(b), 3.0);
@@ -272,7 +273,7 @@ impl f64 {
     /// assert!((-std::f64::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
     #[inline]
-    #[unstable(feature = "euclidean_division", issue = "49048")]
+    #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f64) -> f64 {
         let r = self % rhs;
         if r < 0.0 {
@@ -878,16 +879,26 @@ impl f64 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
-    /// Returns max if self is greater than max, and min if self is less than min.
-    /// Otherwise this returns self.  Panics if min > max, min equals NaN, or max equals NaN.
+    /// Restrict a value to a certain interval unless it is NaN.
+    ///
+    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+    /// less than `min`. Otherwise this returns `self`.
+    ///
+    /// Not that this function returns NaN if the initial value was NaN as
+    /// well.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(clamp)]
-    /// assert!((-3.0f64).clamp(-2.0f64, 1.0f64) == -2.0f64);
-    /// assert!((0.0f64).clamp(-2.0f64, 1.0f64) == 0.0f64);
-    /// assert!((2.0f64).clamp(-2.0f64, 1.0f64) == 1.0f64);
+    /// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
+    /// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
+    /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
+    /// assert!((std::f64::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[unstable(feature = "clamp", issue = "44095")]
     #[inline]
@@ -1518,4 +1529,22 @@ mod tests {
         assert_eq!(f64::from_bits(masked_nan1).to_bits(), masked_nan1);
         assert_eq!(f64::from_bits(masked_nan2).to_bits(), masked_nan2);
     }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_greater_than_max() {
+        1.0f64.clamp(3.0, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_min_is_nan() {
+        1.0f64.clamp(NAN, 1.0);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clamp_max_is_nan() {
+        1.0f64.clamp(3.0, NAN);
+    }
 }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index ad3f45bfada..6e111f24236 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -43,7 +43,9 @@ use crate::sys;
 /// `CString` implements a [`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()`.
+/// string, like C's `strdup()`. Notice that [`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
 ///
@@ -61,7 +63,7 @@ use crate::sys;
 ///
 /// 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 raw pointer to pass to
+/// [`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.
 ///
@@ -597,11 +599,12 @@ impl CString {
     ///
     /// [`Drop`]: ../ops/trait.Drop.html
     fn into_inner(self) -> Box<[u8]> {
-        unsafe {
-            let result = ptr::read(&self.inner);
-            mem::forget(self);
-            result
-        }
+        // 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) }
     }
 }
 
@@ -628,7 +631,7 @@ impl ops::Deref for CString {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for CString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
 }
@@ -649,7 +652,7 @@ impl From<CString> for Vec<u8> {
 
 #[stable(feature = "cstr_debug", since = "1.3.0")]
 impl fmt::Debug for CStr {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    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)?;
@@ -847,7 +850,7 @@ impl Error for NulError {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for NulError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "nul byte found in provided data at position: {}", self.0)
     }
 }
@@ -878,7 +881,7 @@ impl Error for FromBytesWithNulError {
 
 #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
 impl fmt::Display for FromBytesWithNulError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    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)?;
@@ -917,7 +920,7 @@ impl Error for IntoStringError {
 
 #[stable(feature = "cstring_into", since = "1.7.0")]
 impl fmt::Display for IntoStringError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.description().fmt(f)
     }
 }
@@ -1043,13 +1046,16 @@ impl CStr {
     ///
     /// **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)]
-    /// use std::ffi::{CString};
+    /// use std::ffi::CString;
     ///
     /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
     /// unsafe {
@@ -1065,7 +1071,7 @@ impl CStr {
     ///
     /// ```no_run
     /// # #![allow(unused_must_use)]
-    /// use std::ffi::{CString};
+    /// use std::ffi::CString;
     ///
     /// let hello = CString::new("Hello").expect("CString::new failed");
     /// let ptr = hello.as_ptr();
@@ -1208,11 +1214,11 @@ impl CStr {
     ///                  .expect("CStr::from_bytes_with_nul failed");
     /// assert_eq!(
     ///     c_str.to_string_lossy(),
-    ///     Cow::Owned(String::from("Hello �World")) as Cow<str>
+    ///     Cow::Owned(String::from("Hello �World")) as Cow<'_, str>
     /// );
     /// ```
     #[stable(feature = "cstr_to_str", since = "1.4.0")]
-    pub fn to_string_lossy(&self) -> Cow<str> {
+    pub fn to_string_lossy(&self) -> Cow<'_, str> {
         String::from_utf8_lossy(self.to_bytes())
     }
 
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index 7a38f0ebd5a..69fcfa8b39c 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -170,7 +170,7 @@ pub use core::ffi::c_void;
            reason = "the `c_variadic` feature has not been properly tested on \
                      all supported platforms",
            issue = "44930")]
-pub use core::ffi::VaList;
+pub use core::ffi::{VaList, VaListImpl};
 
 mod c_str;
 mod os_str;
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 3a0590021c9..54e1c876f4c 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -32,7 +32,7 @@ use crate::sys_common::{AsInner, IntoInner, FromInner};
 /// in each pair are owned strings; the latter are borrowed
 /// references.
 ///
-/// Note, `OsString` and `OsStr` internally do not necessarily hold strings in
+/// Note, `OsString` and [`OsStr`] internally do not necessarily hold strings in
 /// the form native to the platform; While on Unix, strings are stored as a
 /// sequence of 8-bit values, on Windows, where strings are 16-bit value based
 /// as just discussed, strings are also actually stored as a sequence of 8-bit
@@ -351,6 +351,8 @@ impl From<String> for OsString {
     /// Converts a [`String`] into a [`OsString`].
     ///
     /// The conversion copies the data, and includes an allocation on the heap.
+    ///
+    /// [`OsString`]: ../../std/ffi/struct.OsString.html
     fn from(s: String) -> OsString {
         OsString { inner: Buf::from_string(s) }
     }
@@ -394,7 +396,7 @@ impl Default for OsString {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for OsString {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&**self, formatter)
     }
 }
@@ -563,7 +565,7 @@ impl OsStr {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn to_string_lossy(&self) -> Cow<str> {
+    pub fn to_string_lossy(&self) -> Cow<'_, str> {
         self.inner.to_string_lossy()
     }
 
@@ -665,10 +667,11 @@ impl From<&OsStr> for Box<OsStr> {
 
 #[stable(feature = "os_string_from_box", since = "1.18.0")]
 impl From<Box<OsStr>> for OsString {
-    /// Converts a `Box<OsStr>` into a `OsString` without copying or allocating.
+    /// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or
+    /// allocating.
     ///
     /// [`Box`]: ../boxed/struct.Box.html
-    /// [`OsString`]: ../ffi/struct.OsString.html
+    /// [`OsStr`]: ../ffi/struct.OsStr.html
     fn from(boxed: Box<OsStr>) -> OsString {
         boxed.into_os_string()
     }
@@ -891,13 +894,13 @@ impl Hash for OsStr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for OsStr {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.inner, formatter)
     }
 }
 
 impl OsStr {
-    pub(crate) fn display(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    pub(crate) fn display(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(&self.inner, formatter)
     }
 }
@@ -960,6 +963,7 @@ impl IntoInner<Buf> for OsString {
 }
 
 impl AsInner<Slice> for OsStr {
+    #[inline]
     fn as_inner(&self) -> &Slice {
         &self.inner
     }
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 25f2dd73504..5f76875bd66 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 //! Filesystem manipulation operations.
 //!
 //! This module contains basic methods to manipulate the contents of the local
@@ -9,7 +11,7 @@
 
 use crate::fmt;
 use crate::ffi::OsString;
-use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write};
+use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write, IoSlice, IoSliceMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInnerMut, FromInner, AsInner, IntoInner};
@@ -21,7 +23,9 @@ use crate::time::SystemTime;
 /// it was opened with. Files also implement [`Seek`] to alter the logical cursor
 /// that the file contains internally.
 ///
-/// Files are automatically closed when they go out of scope.
+/// Files are automatically closed when they go out of scope.  Errors detected
+/// on closing are ignored by the implementation of `Drop`.  Use the method
+/// [`sync_all`] if these errors must be manually handled.
 ///
 /// # Examples
 ///
@@ -84,6 +88,7 @@ use crate::time::SystemTime;
 /// [`Read`]: ../io/trait.Read.html
 /// [`Write`]: ../io/trait.Write.html
 /// [`BufReader<R>`]: ../io/struct.BufReader.html
+/// [`sync_all`]: struct.File.html#method.sync_all
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct File {
     inner: fs_imp::File,
@@ -211,7 +216,7 @@ pub struct DirBuilder {
     recursive: bool,
 }
 
-/// How large a buffer to pre-allocate before reading the entire file.
+/// Indicates how large a buffer to pre-allocate before reading the entire file.
 fn initial_buffer_size(file: &File) -> usize {
     // Allocate one extra byte so the buffer doesn't need to grow before the
     // final `read` call at the end of the file.  Don't worry about `usize`
@@ -391,9 +396,13 @@ impl File {
 
     /// Attempts to sync all OS-internal metadata to disk.
     ///
-    /// This function will attempt to ensure that all in-core data reaches the
+    /// This function will attempt to ensure that all in-memory data reaches the
     /// filesystem before returning.
     ///
+    /// This can be used to handle errors that would otherwise only be caught
+    /// when the `File` is closed.  Dropping a file will ignore errors in
+    /// synchronizing this in-memory data.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -459,6 +468,8 @@ impl File {
     /// # Errors
     ///
     /// This function will return an error if the file is not opened for writing.
+    /// Also, std::io::ErrorKind::InvalidInput will be returned if the desired
+    /// length would cause an overflow due to the implementation specifics.
     ///
     /// # Examples
     ///
@@ -597,7 +608,7 @@ impl IntoInner<fs_imp::File> for File {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for File {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.inner.fmt(f)
     }
 }
@@ -608,6 +619,10 @@ impl Read for File {
         self.inner.read(buf)
     }
 
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -618,6 +633,11 @@ impl Write for File {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -632,6 +652,10 @@ impl Read for &File {
         self.inner.read(buf)
     }
 
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -642,6 +666,11 @@ impl Write for &File {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -876,11 +905,14 @@ impl OpenOptions {
     }
 
     fn _open(&self, path: &Path) -> io::Result<File> {
-        let inner = fs_imp::File::open(path, &self.0)?;
-        Ok(File { inner })
+        fs_imp::File::open(path, &self.0).map(|inner| File { inner })
     }
 }
 
+impl AsInner<fs_imp::OpenOptions> for OpenOptions {
+    fn as_inner(&self) -> &fs_imp::OpenOptions { &self.0 }
+}
+
 impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
     fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
 }
@@ -1087,7 +1119,7 @@ impl Metadata {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Metadata {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Metadata")
             .field("file_type", &self.file_type())
             .field("is_dir", &self.is_dir())
@@ -1104,6 +1136,10 @@ impl AsInner<fs_imp::FileAttr> for Metadata {
     fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 }
 }
 
+impl FromInner<fs_imp::FileAttr> for Metadata {
+    fn from_inner(attr: fs_imp::FileAttr) -> Metadata { Metadata(attr) }
+}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
@@ -1394,7 +1430,7 @@ impl DirEntry {
 
 #[stable(feature = "dir_entry_debug", since = "1.13.0")]
 impl fmt::Debug for DirEntry {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("DirEntry")
             .field(&self.path())
             .finish()
@@ -1581,7 +1617,8 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// `O_CLOEXEC` is set for returned file descriptors.
 /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
 /// NTFS streams are copied but only the size of the main stream is returned by
-/// this function.
+/// this function. On MacOS, this function corresponds to `fclonefileat` and
+/// `fcopyfile`.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: ../io/index.html#platform-specific-behavior
@@ -1777,6 +1814,8 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 ///   function.)
 /// * `path` already exists.
 ///
+/// [`create_dir_all`]: fn.create_dir_all.html
+///
 /// # Examples
 ///
 /// ```no_run
@@ -1939,7 +1978,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// use std::path::Path;
 ///
 /// // one possible implementation of walking a directory only visiting files
-/// fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
+/// fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> {
 ///     if dir.is_dir() {
 ///         for entry in fs::read_dir(dir)? {
 ///             let entry = entry?;
@@ -2094,7 +2133,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::prelude::*;
 
@@ -2837,6 +2876,26 @@ mod tests {
     }
 
     #[test]
+    fn copy_file_follows_dst_symlink() {
+        let tmp = tmpdir();
+        if !got_symlink_permission(&tmp) { return };
+
+        let in_path = tmp.join("in.txt");
+        let out_path = tmp.join("out.txt");
+        let out_path_symlink = tmp.join("out_symlink.txt");
+
+        check!(fs::write(&in_path, "foo"));
+        check!(fs::write(&out_path, "bar"));
+        check!(symlink_file(&out_path, &out_path_symlink));
+
+        check!(fs::copy(&in_path, &out_path_symlink));
+
+        assert!(check!(out_path_symlink.symlink_metadata()).file_type().is_symlink());
+        assert_eq!(check!(fs::read(&out_path_symlink)), b"foo".to_vec());
+        assert_eq!(check!(fs::read(&out_path)), b"foo".to_vec());
+    }
+
+    #[test]
     fn symlinks_work() {
         let tmpdir = tmpdir();
         if !got_symlink_permission(&tmpdir) { return };
@@ -3259,11 +3318,11 @@ mod tests {
         fs::create_dir_all(&d).unwrap();
         File::create(&f).unwrap();
         if cfg!(not(windows)) {
-            symlink_dir("../d/e", &c).unwrap();
+            symlink_file("../d/e", &c).unwrap();
             symlink_file("../f", &e).unwrap();
         }
         if cfg!(windows) {
-            symlink_dir(r"..\d\e", &c).unwrap();
+            symlink_file(r"..\d\e", &c).unwrap();
             symlink_file(r"..\f", &e).unwrap();
         }
 
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index aa784746122..0406549ff07 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -5,22 +5,25 @@ use core::marker::Unpin;
 use core::pin::Pin;
 use core::option::Option;
 use core::ptr::NonNull;
-use core::task::{Waker, Poll};
+use core::task::{Context, Poll};
 use core::ops::{Drop, Generator, GeneratorState};
 
 #[doc(inline)]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub use core::future::*;
 
 /// Wrap a generator in a future.
 ///
 /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
 /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
+#[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
     GenFuture(x)
 }
 
 /// A wrapper around generators used to implement `Future` for `async`/`await` code.
+#[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
 struct GenFuture<T: Generator<Yield = ()>>(T);
@@ -29,13 +32,14 @@ struct GenFuture<T: Generator<Yield = ()>>(T);
 // self-referential borrows in the underlying generator.
 impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
 
+#[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
     type Output = T::Return;
-    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         // Safe because we're !Unpin + !Drop mapping to a ?Unpin value
         let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
-        set_task_waker(waker, || match gen.resume() {
+        set_task_context(cx, || match gen.resume() {
             GeneratorState::Yielded(()) => Poll::Pending,
             GeneratorState::Complete(x) => Poll::Ready(x),
         })
@@ -43,61 +47,75 @@ impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
 }
 
 thread_local! {
-    static TLS_WAKER: Cell<Option<NonNull<Waker>>> = Cell::new(None);
+    static TLS_CX: Cell<Option<NonNull<Context<'static>>>> = Cell::new(None);
 }
 
-struct SetOnDrop(Option<NonNull<Waker>>);
+struct SetOnDrop(Option<NonNull<Context<'static>>>);
 
 impl Drop for SetOnDrop {
     fn drop(&mut self) {
-        TLS_WAKER.with(|tls_waker| {
-            tls_waker.set(self.0.take());
+        TLS_CX.with(|tls_cx| {
+            tls_cx.set(self.0.take());
         });
     }
 }
 
+#[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Sets the thread-local task context used by async/await futures.
-pub fn set_task_waker<F, R>(waker: &Waker, f: F) -> R
+pub fn set_task_context<F, R>(cx: &mut Context<'_>, f: F) -> R
 where
     F: FnOnce() -> R
 {
-    let old_waker = TLS_WAKER.with(|tls_waker| {
-        tls_waker.replace(Some(NonNull::from(waker)))
+    // transmute the context's lifetime to 'static so we can store it.
+    let cx = unsafe {
+        core::mem::transmute::<&mut Context<'_>, &mut Context<'static>>(cx)
+    };
+    let old_cx = TLS_CX.with(|tls_cx| {
+        tls_cx.replace(Some(NonNull::from(cx)))
     });
-    let _reset_waker = SetOnDrop(old_waker);
+    let _reset = SetOnDrop(old_cx);
     f()
 }
 
+#[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
-/// Retrieves the thread-local task waker used by async/await futures.
+/// Retrieves the thread-local task context used by async/await futures.
 ///
-/// This function acquires exclusive access to the task waker.
+/// This function acquires exclusive access to the task context.
 ///
-/// Panics if no waker has been set or if the waker has already been
-/// retrieved by a surrounding call to get_task_waker.
-pub fn get_task_waker<F, R>(f: F) -> R
+/// Panics if no context has been set or if the context has already been
+/// retrieved by a surrounding call to get_task_context.
+pub fn get_task_context<F, R>(f: F) -> R
 where
-    F: FnOnce(&Waker) -> R
+    F: FnOnce(&mut Context<'_>) -> R
 {
-    let waker_ptr = TLS_WAKER.with(|tls_waker| {
+    let cx_ptr = TLS_CX.with(|tls_cx| {
         // Clear the entry so that nested `get_task_waker` calls
         // will fail or set their own value.
-        tls_waker.replace(None)
+        tls_cx.replace(None)
     });
-    let _reset_waker = SetOnDrop(waker_ptr);
+    let _reset = SetOnDrop(cx_ptr);
 
-    let waker_ptr = waker_ptr.expect(
-        "TLS Waker not set. This is a rustc bug. \
+    let mut cx_ptr = cx_ptr.expect(
+        "TLS Context not set. This is a rustc bug. \
         Please file an issue on https://github.com/rust-lang/rust.");
-    unsafe { f(waker_ptr.as_ref()) }
+
+    // Safety: we've ensured exclusive access to the context by
+    // removing the pointer from TLS, only to be replaced once
+    // we're done with it.
+    //
+    // The pointer that was inserted came from an `&mut Context<'_>`,
+    // so it is safe to treat as mutable.
+    unsafe { f(cx_ptr.as_mut()) }
 }
 
+#[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Polls a future in the current thread-local task waker.
-pub fn poll_with_tls_waker<F>(f: Pin<&mut F>) -> Poll<F::Output>
+pub fn poll_with_tls_context<F>(f: Pin<&mut F>) -> Poll<F::Output>
 where
     F: Future
 {
-    get_task_waker(|waker| F::poll(f, waker))
+    get_task_context(|cx| F::poll(f, cx))
 }
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index a14c10d0b61..aaf628e6c26 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -5,7 +5,8 @@ use crate::io::prelude::*;
 use crate::cmp;
 use crate::error;
 use crate::fmt;
-use crate::io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom, IoVec, IoVecMut};
+use crate::io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom, IoSlice,
+        IoSliceMut};
 use crate::memchr;
 
 /// The `BufReader` struct adds buffering to any reader.
@@ -21,6 +22,10 @@ use crate::memchr;
 /// times. It also provides no advantage when reading from a source that is
 /// already in memory, like a `Vec<u8>`.
 ///
+/// When the `BufReader` is dropped, the contents of its buffer will be
+/// discarded. Creating multiple instances of a `BufReader` on the same
+/// stream can cause data loss.
+///
 /// [`Read`]: ../../std/io/trait.Read.html
 /// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read
 /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
@@ -88,10 +93,10 @@ impl<R: Read> BufReader<R> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
+    pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
         unsafe {
-            let mut buffer = Vec::with_capacity(cap);
-            buffer.set_len(cap);
+            let mut buffer = Vec::with_capacity(capacity);
+            buffer.set_len(capacity);
             inner.initializer().initialize(&mut buffer);
             BufReader {
                 inner,
@@ -153,7 +158,6 @@ impl<R> BufReader<R> {
     /// # Examples
     ///
     /// ```no_run
-    /// # #![feature(bufreader_buffer)]
     /// use std::io::{BufReader, BufRead};
     /// use std::fs::File;
     ///
@@ -168,7 +172,7 @@ impl<R> BufReader<R> {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "bufreader_buffer", issue = "45323")]
+    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
     pub fn buffer(&self) -> &[u8] {
         &self.buf[self.pos..self.cap]
     }
@@ -193,6 +197,13 @@ impl<R> BufReader<R> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_inner(self) -> R { self.inner }
+
+    /// Invalidates all data in the internal buffer.
+    #[inline]
+    fn discard_buffer(&mut self) {
+        self.pos = 0;
+        self.cap = 0;
+    }
 }
 
 impl<R: Seek> BufReader<R> {
@@ -227,6 +238,7 @@ impl<R: Read> Read for BufReader<R> {
         // (larger than our internal buffer), bypass our internal buffer
         // entirely.
         if self.pos == self.cap && buf.len() >= self.buf.len() {
+            self.discard_buffer();
             return self.inner.read(buf);
         }
         let nread = {
@@ -237,9 +249,10 @@ impl<R: Read> Read for BufReader<R> {
         Ok(nread)
     }
 
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
         if self.pos == self.cap && total_len >= self.buf.len() {
+            self.discard_buffer();
             return self.inner.read_vectored(bufs);
         }
         let nread = {
@@ -278,7 +291,7 @@ impl<R: Read> BufRead for BufReader<R> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.debug_struct("BufReader")
             .field("reader", &self.inner)
             .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
@@ -325,14 +338,14 @@ impl<R: Seek> Seek for BufReader<R> {
             } else {
                 // seek backwards by our remainder, and then by the offset
                 self.inner.seek(SeekFrom::Current(-remainder))?;
-                self.pos = self.cap; // empty the buffer
+                self.discard_buffer();
                 result = self.inner.seek(SeekFrom::Current(n))?;
             }
         } else {
             // Seeking with Start/End doesn't care about our buffer length.
             result = self.inner.seek(pos)?;
         }
-        self.pos = self.cap; // empty the buffer
+        self.discard_buffer();
         Ok(result)
     }
 }
@@ -341,7 +354,7 @@ impl<R: Seek> Seek for BufReader<R> {
 ///
 /// It can be excessively inefficient to work directly with something that
 /// implements [`Write`]. For example, every call to
-/// [`write`][`Tcpstream::write`] on [`TcpStream`] results in a system call. A
+/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
 /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying
 /// writer in large, infrequent batches.
 ///
@@ -392,7 +405,7 @@ impl<R: Seek> Seek for BufReader<R> {
 /// the `stream` is dropped.
 ///
 /// [`Write`]: ../../std/io/trait.Write.html
-/// [`Tcpstream::write`]: ../../std/net/struct.TcpStream.html#method.write
+/// [`TcpStream::write`]: ../../std/net/struct.TcpStream.html#method.write
 /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
 /// [`flush`]: #method.flush
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -464,10 +477,10 @@ impl<W: Write> BufWriter<W> {
     /// let mut buffer = BufWriter::with_capacity(100, stream);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(cap: usize, inner: W) -> BufWriter<W> {
+    pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
         BufWriter {
             inner: Some(inner),
-            buf: Vec::with_capacity(cap),
+            buf: Vec::with_capacity(capacity),
             panicked: false,
         }
     }
@@ -538,7 +551,6 @@ impl<W: Write> BufWriter<W> {
     /// # Examples
     ///
     /// ```no_run
-    /// # #![feature(bufreader_buffer)]
     /// use std::io::BufWriter;
     /// use std::net::TcpStream;
     ///
@@ -547,7 +559,7 @@ impl<W: Write> BufWriter<W> {
     /// // See how many bytes are currently buffered
     /// let bytes_buffered = buf_writer.buffer().len();
     /// ```
-    #[unstable(feature = "bufreader_buffer", issue = "45323")]
+    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
     pub fn buffer(&self) -> &[u8] {
         &self.buf
     }
@@ -588,7 +600,7 @@ impl<W: Write> Write for BufWriter<W> {
         }
         if buf.len() >= self.buf.capacity() {
             self.panicked = true;
-            let r = self.inner.as_mut().unwrap().write(buf);
+            let r = self.get_mut().write(buf);
             self.panicked = false;
             r
         } else {
@@ -596,14 +608,14 @@ impl<W: Write> Write for BufWriter<W> {
         }
     }
 
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
         if self.buf.len() + total_len > self.buf.capacity() {
             self.flush_buf()?;
         }
         if total_len >= self.buf.capacity() {
             self.panicked = true;
-            let r = self.inner.as_mut().unwrap().write_vectored(bufs);
+            let r = self.get_mut().write_vectored(bufs);
             self.panicked = false;
             r
         } else {
@@ -618,7 +630,7 @@ impl<W: Write> Write for BufWriter<W> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.debug_struct("BufWriter")
             .field("writer", &self.inner.as_ref().unwrap())
             .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
@@ -726,7 +738,7 @@ impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W> fmt::Display for IntoInnerError<W> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.error().fmt(f)
     }
 }
@@ -740,7 +752,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
 /// completed, rather than the entire buffer at once. Enter `LineWriter`. It
 /// does exactly that.
 ///
-/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the
+/// Like [`BufWriter`][bufwriter], a `LineWriter`’s buffer will also be flushed when the
 /// `LineWriter` goes out of scope or when its internal buffer is full.
 ///
 /// [bufwriter]: struct.BufWriter.html
@@ -838,9 +850,9 @@ impl<W: Write> LineWriter<W> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
+    pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
         LineWriter {
-            inner: BufWriter::with_capacity(cap, inner),
+            inner: BufWriter::with_capacity(capacity, inner),
             need_flush: false,
         }
     }
@@ -968,7 +980,7 @@ impl<W: Write> Write for LineWriter<W> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.debug_struct("LineWriter")
             .field("writer", &self.inner.inner)
             .field("buffer",
@@ -1069,6 +1081,40 @@ mod tests {
     }
 
     #[test]
+    fn test_buffered_reader_invalidated_after_read() {
+        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+        let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
+
+        assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
+        reader.consume(3);
+
+        let mut buffer = [0, 0, 0, 0, 0];
+        assert_eq!(reader.read(&mut buffer).ok(), Some(5));
+        assert_eq!(buffer, [0, 1, 2, 3, 4]);
+
+        assert!(reader.seek_relative(-2).is_ok());
+        let mut buffer = [0, 0];
+        assert_eq!(reader.read(&mut buffer).ok(), Some(2));
+        assert_eq!(buffer, [3, 4]);
+    }
+
+    #[test]
+    fn test_buffered_reader_invalidated_after_seek() {
+        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+        let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
+
+        assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
+        reader.consume(3);
+
+        assert!(reader.seek(SeekFrom::Current(5)).is_ok());
+
+        assert!(reader.seek_relative(-2).is_ok());
+        let mut buffer = [0, 0];
+        assert_eq!(reader.read(&mut buffer).ok(), Some(2));
+        assert_eq!(buffer, [3, 4]);
+    }
+
+    #[test]
     fn test_buffered_reader_seek_underflow() {
         // gimmick reader that yields its position modulo 256 for each byte
         struct PositionReader {
@@ -1115,6 +1161,41 @@ mod tests {
     }
 
     #[test]
+    fn test_buffered_reader_seek_underflow_discard_buffer_between_seeks() {
+        // gimmick reader that returns Err after first seek
+        struct ErrAfterFirstSeekReader {
+            first_seek: bool,
+        }
+        impl Read for ErrAfterFirstSeekReader {
+            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+                for x in &mut *buf {
+                    *x = 0;
+                }
+                Ok(buf.len())
+            }
+        }
+        impl Seek for ErrAfterFirstSeekReader {
+            fn seek(&mut self, _: SeekFrom) -> io::Result<u64> {
+                if self.first_seek {
+                    self.first_seek = false;
+                    Ok(0)
+                } else {
+                    Err(io::Error::new(io::ErrorKind::Other, "oh no!"))
+                }
+            }
+        }
+
+        let mut reader = BufReader::with_capacity(5, ErrAfterFirstSeekReader { first_seek: true });
+        assert_eq!(reader.fill_buf().ok(), Some(&[0, 0, 0, 0, 0][..]));
+
+        // The following seek will require two underlying seeks.  The first will
+        // succeed but the second will fail.  This should still invalidate the
+        // buffer.
+        assert!(reader.seek(SeekFrom::Current(i64::min_value())).is_err());
+        assert_eq!(reader.buffer().len(), 0);
+    }
+
+    #[test]
     fn test_buffered_writer() {
         let inner = Vec::new();
         let mut writer = BufWriter::with_capacity(2, inner);
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 873da0898c7..a94176e7100 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -1,7 +1,7 @@
 use crate::io::prelude::*;
 
 use crate::cmp;
-use crate::io::{self, Initializer, SeekFrom, Error, ErrorKind, IoVec, IoVecMut};
+use crate::io::{self, Initializer, SeekFrom, Error, ErrorKind, IoSlice, IoSliceMut};
 
 use core::convert::TryInto;
 
@@ -72,7 +72,7 @@ use core::convert::TryInto;
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Default)]
 pub struct Cursor<T> {
     inner: T,
     pos: u64,
@@ -212,6 +212,14 @@ impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> {
                            "invalid seek to a negative or overflowing position"))
         }
     }
+
+    fn stream_len(&mut self) -> io::Result<u64> {
+        Ok(self.inner.as_ref().len() as u64)
+    }
+
+    fn stream_position(&mut self) -> io::Result<u64> {
+        Ok(self.pos)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -222,7 +230,7 @@ impl<T> Read for Cursor<T> where T: AsRef<[u8]> {
         Ok(n)
     }
 
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let mut nread = 0;
         for buf in bufs {
             let n = self.read(buf)?;
@@ -257,6 +265,7 @@ impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> {
 }
 
 // Non-resizing write implementation
+#[inline]
 fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
     let pos = cmp::min(*pos_mut, slice.len() as u64);
     let amt = (&mut slice[(pos as usize)..]).write(buf)?;
@@ -264,10 +273,11 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<us
     Ok(amt)
 }
 
+#[inline]
 fn slice_write_vectored(
     pos_mut: &mut u64,
     slice: &mut [u8],
-    bufs: &[IoVec<'_>],
+    bufs: &[IoSlice<'_>],
 ) -> io::Result<usize>
 {
     let mut nwritten = 0;
@@ -311,7 +321,7 @@ fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usi
 fn vec_write_vectored(
     pos_mut: &mut u64,
     vec: &mut Vec<u8>,
-    bufs: &[IoVec<'_>],
+    bufs: &[IoSlice<'_>],
 ) -> io::Result<usize>
 {
     let mut nwritten = 0;
@@ -329,10 +339,11 @@ impl Write for Cursor<&mut [u8]> {
     }
 
     #[inline]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         slice_write_vectored(&mut self.pos, self.inner, bufs)
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
@@ -342,10 +353,11 @@ impl Write for Cursor<&mut Vec<u8>> {
         vec_write(&mut self.pos, self.inner, buf)
     }
 
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         vec_write_vectored(&mut self.pos, self.inner, bufs)
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
@@ -355,10 +367,11 @@ impl Write for Cursor<Vec<u8>> {
         vec_write(&mut self.pos, &mut self.inner, buf)
     }
 
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         vec_write_vectored(&mut self.pos, &mut self.inner, bufs)
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
@@ -370,17 +383,18 @@ impl Write for Cursor<Box<[u8]>> {
     }
 
     #[inline]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         slice_write_vectored(&mut self.pos, &mut self.inner, bufs)
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
 #[cfg(test)]
 mod tests {
     use crate::io::prelude::*;
-    use crate::io::{Cursor, SeekFrom, IoVec, IoVecMut};
+    use crate::io::{Cursor, SeekFrom, IoSlice, IoSliceMut};
 
     #[test]
     fn test_vec_writer() {
@@ -389,7 +403,7 @@ mod tests {
         assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
         assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
         assert_eq!(writer.write_vectored(
-            &[IoVec::new(&[]), IoVec::new(&[8, 9]), IoVec::new(&[10])],
+            &[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],
         ).unwrap(), 3);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
         assert_eq!(writer, b);
@@ -402,7 +416,7 @@ mod tests {
         assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
         assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
         assert_eq!(writer.write_vectored(
-            &[IoVec::new(&[]), IoVec::new(&[8, 9]), IoVec::new(&[10])],
+            &[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],
         ).unwrap(), 3);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
         assert_eq!(&writer.get_ref()[..], b);
@@ -416,7 +430,7 @@ mod tests {
         assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
         assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
         assert_eq!(writer.write_vectored(
-            &[IoVec::new(&[]), IoVec::new(&[8, 9]), IoVec::new(&[10])],
+            &[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],
         ).unwrap(), 3);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
         assert_eq!(&writer.get_ref()[..], b);
@@ -444,18 +458,21 @@ mod tests {
     fn test_box_slice_writer_vectored() {
         let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
         assert_eq!(writer.position(), 0);
-        assert_eq!(writer.write_vectored(&[IoVec::new(&[0])]).unwrap(), 1);
+        assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
         assert_eq!(writer.position(), 1);
         assert_eq!(
-            writer.write_vectored(&[IoVec::new(&[1, 2, 3]), IoVec::new(&[4, 5, 6, 7])]).unwrap(),
+            writer.write_vectored(&[
+                IoSlice::new(&[1, 2, 3]),
+                IoSlice::new(&[4, 5, 6, 7]),
+            ]).unwrap(),
             7,
         );
         assert_eq!(writer.position(), 8);
         assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
         assert_eq!(writer.position(), 8);
 
-        assert_eq!(writer.write_vectored(&[IoVec::new(&[8, 9])]).unwrap(), 1);
-        assert_eq!(writer.write_vectored(&[IoVec::new(&[10])]).unwrap(), 0);
+        assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
+        assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
         assert_eq!(&**writer.get_ref(), b);
     }
@@ -487,11 +504,11 @@ mod tests {
         {
             let mut writer = Cursor::new(&mut buf[..]);
             assert_eq!(writer.position(), 0);
-            assert_eq!(writer.write_vectored(&[IoVec::new(&[0])]).unwrap(), 1);
+            assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
             assert_eq!(writer.position(), 1);
             assert_eq!(
                 writer.write_vectored(
-                    &[IoVec::new(&[1, 2, 3]), IoVec::new(&[4, 5, 6, 7])],
+                    &[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5, 6, 7])],
                 ).unwrap(),
                 7,
             );
@@ -499,8 +516,8 @@ mod tests {
             assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
             assert_eq!(writer.position(), 8);
 
-            assert_eq!(writer.write_vectored(&[IoVec::new(&[8, 9])]).unwrap(), 1);
-            assert_eq!(writer.write_vectored(&[IoVec::new(&[10])]).unwrap(), 0);
+            assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
+            assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
         }
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
         assert_eq!(buf, b);
@@ -570,11 +587,14 @@ mod tests {
     fn test_mem_reader_vectored() {
         let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
         let mut buf = [];
-        assert_eq!(reader.read_vectored(&mut [IoVecMut::new(&mut buf)]).unwrap(), 0);
+        assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
         assert_eq!(reader.position(), 0);
         let mut buf = [0];
         assert_eq!(
-            reader.read_vectored(&mut [IoVecMut::new(&mut []), IoVecMut::new(&mut buf)]).unwrap(),
+            reader.read_vectored(&mut [
+                IoSliceMut::new(&mut []),
+                IoSliceMut::new(&mut buf),
+            ]).unwrap(),
             1,
         );
         assert_eq!(reader.position(), 1);
@@ -583,9 +603,10 @@ mod tests {
         let mut buf1 = [0; 4];
         let mut buf2 = [0; 4];
         assert_eq!(
-            reader.read_vectored(
-                &mut [IoVecMut::new(&mut buf1), IoVecMut::new(&mut buf2)],
-            ).unwrap(),
+            reader.read_vectored(&mut [
+                IoSliceMut::new(&mut buf1),
+                IoSliceMut::new(&mut buf2),
+            ]).unwrap(),
             7,
         );
         let b1: &[_] = &[1, 2, 3, 4];
@@ -621,11 +642,14 @@ mod tests {
     fn test_boxed_slice_reader_vectored() {
         let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
         let mut buf = [];
-        assert_eq!(reader.read_vectored(&mut [IoVecMut::new(&mut buf)]).unwrap(), 0);
+        assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
         assert_eq!(reader.position(), 0);
         let mut buf = [0];
         assert_eq!(
-            reader.read_vectored(&mut [IoVecMut::new(&mut []), IoVecMut::new(&mut buf)]).unwrap(),
+            reader.read_vectored(&mut [
+                IoSliceMut::new(&mut []),
+                IoSliceMut::new(&mut buf),
+            ]).unwrap(),
             1,
         );
         assert_eq!(reader.position(), 1);
@@ -635,7 +659,7 @@ mod tests {
         let mut buf2 = [0; 4];
         assert_eq!(
             reader.read_vectored(
-                &mut [IoVecMut::new(&mut buf1), IoVecMut::new(&mut buf2)],
+                &mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],
             ).unwrap(),
             7,
         );
@@ -681,10 +705,13 @@ mod tests {
         let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
         let reader = &mut &in_buf[..];
         let mut buf = [];
-        assert_eq!(reader.read_vectored(&mut [IoVecMut::new(&mut buf)]).unwrap(), 0);
+        assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
         let mut buf = [0];
         assert_eq!(
-            reader.read_vectored(&mut [IoVecMut::new(&mut []), IoVecMut::new(&mut buf)]).unwrap(),
+            reader.read_vectored(&mut [
+                IoSliceMut::new(&mut []),
+                IoSliceMut::new(&mut buf),
+            ]).unwrap(),
             1,
         );
         assert_eq!(reader.len(), 7);
@@ -694,7 +721,7 @@ mod tests {
         let mut buf2 = [0; 4];
         assert_eq!(
             reader.read_vectored(
-                &mut [IoVecMut::new(&mut buf1), IoVecMut::new(&mut buf2)],
+                &mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],
             ).unwrap(),
             7,
         );
diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs
index 614b79124cc..c29a68e6f02 100644
--- a/src/libstd/io/error.rs
+++ b/src/libstd/io/error.rs
@@ -59,7 +59,7 @@ pub struct Error {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.repr, f)
     }
 }
@@ -413,7 +413,7 @@ impl Error {
     /// }
     ///
     /// impl Display for MyError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         write!(f, "MyError: {}", &self.v)
     ///     }
     /// }
@@ -512,7 +512,7 @@ impl Error {
 }
 
 impl fmt::Debug for Repr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             Repr::Os(code) =>
                 fmt.debug_struct("Os")
@@ -527,7 +527,7 @@ impl fmt::Debug for Repr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Error {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.repr {
             Repr::Os(code) => {
                 let detail = sys::os::error_string(code);
@@ -612,7 +612,7 @@ mod test {
         struct TestError;
 
         impl fmt::Display for TestError {
-            fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+            fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
                 Ok(())
             }
         }
diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs
index b286e4016da..c959f2d389b 100644
--- a/src/libstd/io/impls.rs
+++ b/src/libstd/io/impls.rs
@@ -1,6 +1,6 @@
 use crate::cmp;
-use crate::io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind, IoVecMut,
-         IoVec};
+use crate::io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind,
+        IoSliceMut, IoSlice};
 use crate::fmt;
 use crate::mem;
 
@@ -15,7 +15,7 @@ impl<R: Read + ?Sized> Read for &mut R {
     }
 
     #[inline]
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         (**self).read_vectored(bufs)
     }
 
@@ -45,7 +45,7 @@ impl<W: Write + ?Sized> Write for &mut W {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
 
     #[inline]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         (**self).write_vectored(bufs)
     }
 
@@ -58,7 +58,7 @@ impl<W: Write + ?Sized> Write for &mut W {
     }
 
     #[inline]
-    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
+    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
         (**self).write_fmt(fmt)
     }
 }
@@ -94,7 +94,7 @@ impl<R: Read + ?Sized> Read for Box<R> {
     }
 
     #[inline]
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         (**self).read_vectored(bufs)
     }
 
@@ -124,7 +124,7 @@ impl<W: Write + ?Sized> Write for Box<W> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
 
     #[inline]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         (**self).write_vectored(bufs)
     }
 
@@ -137,7 +137,7 @@ impl<W: Write + ?Sized> Write for Box<W> {
     }
 
     #[inline]
-    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
+    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
         (**self).write_fmt(fmt)
     }
 }
@@ -207,7 +207,7 @@ impl Read for &[u8] {
     }
 
     #[inline]
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let mut nread = 0;
         for buf in bufs {
             nread += self.read(buf)?;
@@ -280,7 +280,7 @@ impl Write for &mut [u8] {
     }
 
     #[inline]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let mut nwritten = 0;
         for buf in bufs {
             nwritten += self.write(buf)?;
@@ -316,7 +316,7 @@ impl Write for Vec<u8> {
     }
 
     #[inline]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let len = bufs.iter().map(|b| b.len()).sum();
         self.reserve(len);
         for buf in bufs {
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index e3e2754a7aa..f2b6ce6feb2 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -24,9 +24,9 @@
 //!     let mut buffer = [0; 10];
 //!
 //!     // read up to 10 bytes
-//!     f.read(&mut buffer)?;
+//!     let n = f.read(&mut buffer)?;
 //!
-//!     println!("The bytes: {:?}", buffer);
+//!     println!("The bytes: {:?}", &buffer[..n]);
 //!     Ok(())
 //! }
 //! ```
@@ -56,9 +56,9 @@
 //!     f.seek(SeekFrom::End(-10))?;
 //!
 //!     // read up to 10 bytes
-//!     f.read(&mut buffer)?;
+//!     let n = f.read(&mut buffer)?;
 //!
-//!     println!("The bytes: {:?}", buffer);
+//!     println!("The bytes: {:?}", &buffer[..n]);
 //!     Ok(())
 //! }
 //! ```
@@ -390,6 +390,28 @@ fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
     ret
 }
 
+pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
+where
+    F: FnOnce(&mut [u8]) -> Result<usize>
+{
+    let buf = bufs
+        .iter_mut()
+        .find(|b| !b.is_empty())
+        .map_or(&mut [][..], |b| &mut **b);
+    read(buf)
+}
+
+pub(crate) fn default_write_vectored<F>(write: F, bufs: &[IoSlice<'_>]) -> Result<usize>
+where
+    F: FnOnce(&[u8]) -> Result<usize>
+{
+    let buf = bufs
+        .iter()
+        .find(|b| !b.is_empty())
+        .map_or(&[][..], |b| &**b);
+    write(buf)
+}
+
 /// The `Read` trait allows for reading bytes from a source.
 ///
 /// Implementors of the `Read` trait are called 'readers'.
@@ -484,9 +506,18 @@ pub trait Read {
     ///
     /// No guarantees are provided about the contents of `buf` when this
     /// function is called, implementations cannot rely on any property of the
-    /// contents of `buf` being true. It is recommended that implementations
+    /// contents of `buf` being true. It is recommended that *implementations*
     /// only write data to `buf` instead of reading its contents.
     ///
+    /// Correspondingly, however, *callers* of this method may not assume any guarantees
+    /// about how the implementation uses `buf`. The trait is safe to implement,
+    /// so it is possible that the code that's supposed to write to the buffer might also read
+    /// from it. It is your responsibility to make sure that `buf` is initialized
+    /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
+    /// obtains via [`MaybeUninit<T>`]) is not safe, and can lead to undefined behavior.
+    ///
+    /// [`MaybeUninit<T>`]: ../mem/union.MaybeUninit.html
+    ///
     /// # Errors
     ///
     /// If this function encounters any form of I/O or other error, an error
@@ -515,7 +546,9 @@ pub trait Read {
     ///     let mut buffer = [0; 10];
     ///
     ///     // read up to 10 bytes
-    ///     f.read(&mut buffer[..])?;
+    ///     let n = f.read(&mut buffer[..])?;
+    ///
+    ///     println!("The bytes: {:?}", &buffer[..n]);
     ///     Ok(())
     /// }
     /// ```
@@ -528,14 +561,11 @@ pub trait Read {
     /// written to possibly being only partially filled. This method must behave
     /// as a single call to `read` with the buffers concatenated would.
     ///
-    /// The default implementation simply passes the first nonempty buffer to
-    /// `read`.
-    #[unstable(feature = "iovec", issue = "58452")]
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> Result<usize> {
-        match bufs.iter_mut().find(|b| !b.is_empty()) {
-            Some(buf) => self.read(buf),
-            None => Ok(0),
-        }
+    /// The default implementation calls `read` with either the first nonempty
+    /// buffer provided, or an empty one if none exists.
+    #[stable(feature = "iovec", since = "1.36.0")]
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
+        default_read_vectored(|b| self.read(b), bufs)
     }
 
     /// Determines if this `Read`er can work with buffers of uninitialized
@@ -890,32 +920,88 @@ pub trait Read {
 /// It is semantically a wrapper around an `&mut [u8]`, but is guaranteed to be
 /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
 /// Windows.
-#[unstable(feature = "iovec", issue = "58452")]
+#[stable(feature = "iovec", since = "1.36.0")]
 #[repr(transparent)]
-pub struct IoVecMut<'a>(sys::io::IoVecMut<'a>);
+pub struct IoSliceMut<'a>(sys::io::IoSliceMut<'a>);
 
-#[unstable(feature = "iovec", issue = "58452")]
-impl<'a> fmt::Debug for IoVecMut<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> fmt::Debug for IoSliceMut<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(self.0.as_slice(), fmt)
     }
 }
 
-impl<'a> IoVecMut<'a> {
-    /// Creates a new `IoVecMut` wrapping a byte slice.
+impl<'a> IoSliceMut<'a> {
+    /// Creates a new `IoSliceMut` wrapping a byte slice.
     ///
     /// # Panics
     ///
     /// Panics on Windows if the slice is larger than 4GB.
-    #[unstable(feature = "iovec", issue = "58452")]
+    #[stable(feature = "iovec", since = "1.36.0")]
     #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoVecMut<'a> {
-        IoVecMut(sys::io::IoVecMut::new(buf))
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut(sys::io::IoSliceMut::new(buf))
+    }
+
+    /// Advance the internal cursor of the slice.
+    ///
+    /// # Notes
+    ///
+    /// Elements in the slice may be modified if the cursor is not advanced to
+    /// the end of the slice. For example if we have a slice of buffers with 2
+    /// `IoSliceMut`s, both of length 8, and we advance the cursor by 10 bytes
+    /// the first `IoSliceMut` will be untouched however the second will be
+    /// modified to remove the first 2 bytes (10 - 8).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(io_slice_advance)]
+    ///
+    /// use std::io::IoSliceMut;
+    /// use std::mem;
+    /// use std::ops::Deref;
+    ///
+    /// let mut buf1 = [1; 8];
+    /// let mut buf2 = [2; 16];
+    /// let mut buf3 = [3; 8];
+    /// let mut bufs = &mut [
+    ///     IoSliceMut::new(&mut buf1),
+    ///     IoSliceMut::new(&mut buf2),
+    ///     IoSliceMut::new(&mut buf3),
+    /// ][..];
+    ///
+    /// // Mark 10 bytes as read.
+    /// bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 10);
+    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
+    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+    /// ```
+    #[unstable(feature = "io_slice_advance", issue = "62726")]
+    #[inline]
+    pub fn advance<'b>(bufs: &'b mut [IoSliceMut<'a>], n: usize) -> &'b mut [IoSliceMut<'a>] {
+        // Number of buffers to remove.
+        let mut remove = 0;
+        // Total length of all the to be removed buffers.
+        let mut accumulated_len = 0;
+        for buf in bufs.iter() {
+            if accumulated_len + buf.len() > n {
+                break;
+            } else {
+                accumulated_len += buf.len();
+                remove += 1;
+            }
+        }
+
+        let bufs = &mut bufs[remove..];
+        if !bufs.is_empty() {
+            bufs[0].0.advance(n - accumulated_len)
+        }
+        bufs
     }
 }
 
-#[unstable(feature = "iovec", issue = "58452")]
-impl<'a> Deref for IoVecMut<'a> {
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> Deref for IoSliceMut<'a> {
     type Target = [u8];
 
     #[inline]
@@ -924,8 +1010,8 @@ impl<'a> Deref for IoVecMut<'a> {
     }
 }
 
-#[unstable(feature = "iovec", issue = "58452")]
-impl<'a> DerefMut for IoVecMut<'a> {
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> DerefMut for IoSliceMut<'a> {
     #[inline]
     fn deref_mut(&mut self) -> &mut [u8] {
         self.0.as_mut_slice()
@@ -937,32 +1023,87 @@ impl<'a> DerefMut for IoVecMut<'a> {
 /// It is semantically a wrapper around an `&[u8]`, but is guaranteed to be
 /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
 /// Windows.
-#[unstable(feature = "iovec", issue = "58452")]
+#[stable(feature = "iovec", since = "1.36.0")]
 #[repr(transparent)]
-pub struct IoVec<'a>(sys::io::IoVec<'a>);
+pub struct IoSlice<'a>(sys::io::IoSlice<'a>);
 
-#[unstable(feature = "iovec", issue = "58452")]
-impl<'a> fmt::Debug for IoVec<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> fmt::Debug for IoSlice<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(self.0.as_slice(), fmt)
     }
 }
 
-impl<'a> IoVec<'a> {
-    /// Creates a new `IoVec` wrapping a byte slice.
+impl<'a> IoSlice<'a> {
+    /// Creates a new `IoSlice` wrapping a byte slice.
     ///
     /// # Panics
     ///
     /// Panics on Windows if the slice is larger than 4GB.
-    #[unstable(feature = "iovec", issue = "58452")]
+    #[stable(feature = "iovec", since = "1.36.0")]
     #[inline]
-    pub fn new(buf: &'a [u8]) -> IoVec<'a> {
-        IoVec(sys::io::IoVec::new(buf))
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice(sys::io::IoSlice::new(buf))
+    }
+
+    /// Advance the internal cursor of the slice.
+    ///
+    /// # Notes
+    ///
+    /// Elements in the slice may be modified if the cursor is not advanced to
+    /// the end of the slice. For example if we have a slice of buffers with 2
+    /// `IoSlice`s, both of length 8, and we advance the cursor by 10 bytes the
+    /// first `IoSlice` will be untouched however the second will be modified to
+    /// remove the first 2 bytes (10 - 8).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(io_slice_advance)]
+    ///
+    /// use std::io::IoSlice;
+    /// use std::mem;
+    /// use std::ops::Deref;
+    ///
+    /// let mut buf1 = [1; 8];
+    /// let mut buf2 = [2; 16];
+    /// let mut buf3 = [3; 8];
+    /// let mut bufs = &mut [
+    ///     IoSlice::new(&mut buf1),
+    ///     IoSlice::new(&mut buf2),
+    ///     IoSlice::new(&mut buf3),
+    /// ][..];
+    ///
+    /// // Mark 10 bytes as written.
+    /// bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 10);
+    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
+    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+    #[unstable(feature = "io_slice_advance", issue = "62726")]
+    #[inline]
+    pub fn advance<'b>(bufs: &'b mut [IoSlice<'a>], n: usize) -> &'b mut [IoSlice<'a>] {
+        // Number of buffers to remove.
+        let mut remove = 0;
+        // Total length of all the to be removed buffers.
+        let mut accumulated_len = 0;
+        for buf in bufs.iter() {
+            if accumulated_len + buf.len() > n {
+                break;
+            } else {
+                accumulated_len += buf.len();
+                remove += 1;
+            }
+        }
+
+        let bufs = &mut bufs[remove..];
+        if !bufs.is_empty() {
+            bufs[0].0.advance(n - accumulated_len)
+        }
+        bufs
     }
 }
 
-#[unstable(feature = "iovec", issue = "58452")]
-impl<'a> Deref for IoVec<'a> {
+#[stable(feature = "iovec", since = "1.36.0")]
+impl<'a> Deref for IoSlice<'a> {
     type Target = [u8];
 
     #[inline]
@@ -1043,12 +1184,23 @@ impl Initializer {
 /// use std::fs::File;
 ///
 /// fn main() -> std::io::Result<()> {
+///     let data = b"some bytes";
+///
+///     let mut pos = 0;
 ///     let mut buffer = File::create("foo.txt")?;
 ///
-///     buffer.write(b"some bytes")?;
+///     while pos < data.len() {
+///         let bytes_written = buffer.write(&data[pos..])?;
+///         pos += bytes_written;
+///     }
 ///     Ok(())
 /// }
 /// ```
+///
+/// The trait also provides convenience methods like [`write_all`], which calls
+/// `write` in a loop until its entire input has been written.
+///
+/// [`write_all`]: #method.write_all
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(spotlight)]
 pub trait Write {
@@ -1064,7 +1216,7 @@ pub trait Write {
     /// an [`Err`] variant.
     ///
     /// If the return value is [`Ok(n)`] then it must be guaranteed that
-    /// `0 <= n <= buf.len()`. A return value of `0` typically means that the
+    /// `n <= buf.len()`. A return value of `0` typically means that the
     /// underlying object is no longer able to accept bytes and will likely not
     /// be able to in the future as well, or that the buffer provided is empty.
     ///
@@ -1103,18 +1255,15 @@ pub trait Write {
 
     /// Like `write`, except that it writes from a slice of buffers.
     ///
-    /// Data is copied to from each buffer in order, with the final buffer
+    /// Data is copied from each buffer in order, with the final buffer
     /// read from possibly being only partially consumed. This method must
     /// behave as a call to `write` with the buffers concatenated would.
     ///
-    /// The default implementation simply passes the first nonempty buffer to
-    /// `write`.
-    #[unstable(feature = "iovec", issue = "58452")]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> Result<usize> {
-        match bufs.iter().find(|b| !b.is_empty()) {
-            Some(buf) => self.write(buf),
-            None => Ok(0),
-        }
+    /// The default implementation calls `write` with either the first nonempty
+    /// buffer provided, or an empty one if none exists.
+    #[stable(feature = "iovec", since = "1.36.0")]
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
+        default_write_vectored(|b| self.write(b), bufs)
     }
 
     /// Flush this output stream, ensuring that all intermediately buffered
@@ -1135,7 +1284,7 @@ pub trait Write {
     /// fn main() -> std::io::Result<()> {
     ///     let mut buffer = BufWriter::new(File::create("foo.txt")?);
     ///
-    ///     buffer.write(b"some bytes")?;
+    ///     buffer.write_all(b"some bytes")?;
     ///     buffer.flush()?;
     ///     Ok(())
     /// }
@@ -1226,7 +1375,7 @@ pub trait Write {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {
+    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
         // Create a shim which translates a Write to a fmt::Write and saves
         // off I/O errors. instead of discarding them
         struct Adaptor<'a, T: ?Sized + 'a> {
@@ -1329,6 +1478,85 @@ pub trait Seek {
     /// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
     #[stable(feature = "rust1", since = "1.0.0")]
     fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
+
+    /// Returns the length of this stream (in bytes).
+    ///
+    /// This method is implemented using up to three seek operations. If this
+    /// method returns successfully, the seek position is unchanged (i.e. the
+    /// position before calling this method is the same as afterwards).
+    /// However, if this method returns an error, the seek position is
+    /// unspecified.
+    ///
+    /// If you need to obtain the length of *many* streams and you don't care
+    /// about the seek position afterwards, you can reduce the number of seek
+    /// operations by simply calling `seek(SeekFrom::End(0))` and using its
+    /// return value (it is also the stream length).
+    ///
+    /// Note that length of a stream can change over time (for example, when
+    /// data is appended to a file). So calling this method multiple times does
+    /// not necessarily return the same length each time.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(seek_convenience)]
+    /// use std::{
+    ///     io::{self, Seek},
+    ///     fs::File,
+    /// };
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = File::open("foo.txt")?;
+    ///
+    ///     let len = f.stream_len()?;
+    ///     println!("The file is currently {} bytes long", len);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "seek_convenience", issue = "59359")]
+    fn stream_len(&mut self) -> Result<u64> {
+        let old_pos = self.stream_position()?;
+        let len = self.seek(SeekFrom::End(0))?;
+
+        // Avoid seeking a third time when we were already at the end of the
+        // stream. The branch is usually way cheaper than a seek operation.
+        if old_pos != len {
+            self.seek(SeekFrom::Start(old_pos))?;
+        }
+
+        Ok(len)
+    }
+
+    /// Returns the current seek position from the start of the stream.
+    ///
+    /// This is equivalent to `self.seek(SeekFrom::Current(0))`.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(seek_convenience)]
+    /// use std::{
+    ///     io::{self, BufRead, BufReader, Seek},
+    ///     fs::File,
+    /// };
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut f = BufReader::new(File::open("foo.txt")?);
+    ///
+    ///     let before = f.stream_position()?;
+    ///     f.read_line(&mut String::new())?;
+    ///     let after = f.stream_position()?;
+    ///
+    ///     println!("The first line was {} bytes long", after - before);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "seek_convenience", issue = "59359")]
+    fn stream_position(&mut self) -> Result<u64> {
+        self.seek(SeekFrom::Current(0))
+    }
 }
 
 /// Enumeration of possible methods to seek within an I/O object.
@@ -1471,18 +1699,13 @@ pub trait BufRead: Read {
     /// let stdin = io::stdin();
     /// let mut stdin = stdin.lock();
     ///
-    /// // we can't have two `&mut` references to `stdin`, so use a block
-    /// // to end the borrow early.
-    /// let length = {
-    ///     let buffer = stdin.fill_buf().unwrap();
+    /// let buffer = stdin.fill_buf().unwrap();
     ///
-    ///     // work with buffer
-    ///     println!("{:?}", buffer);
-    ///
-    ///     buffer.len()
-    /// };
+    /// // work with buffer
+    /// println!("{:?}", buffer);
     ///
     /// // ensure the bytes we worked with aren't returned again later
+    /// let length = buffer.len();
     /// stdin.consume(length);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1798,7 +2021,7 @@ impl<T, U> Chain<T, U> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Chain")
             .field("t", &self.first)
             .field("u", &self.second)
@@ -1811,14 +2034,14 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
         if !self.done_first {
             match self.first.read(buf)? {
-                0 if buf.len() != 0 => self.done_first = true,
+                0 if !buf.is_empty() => self.done_first = true,
                 n => return Ok(n),
             }
         }
         self.second.read(buf)
     }
 
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {
         if !self.done_first {
             match self.first.read_vectored(bufs)? {
                 0 if bufs.iter().any(|b| !b.is_empty()) => self.done_first = true,
@@ -1843,7 +2066,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
     fn fill_buf(&mut self) -> Result<&[u8]> {
         if !self.done_first {
             match self.first.fill_buf()? {
-                buf if buf.len() == 0 => { self.done_first = true; }
+                buf if buf.is_empty() => { self.done_first = true; }
                 buf => return Ok(buf),
             }
         }
@@ -2156,9 +2379,10 @@ impl<B: BufRead> Iterator for Lines<B> {
 #[cfg(test)]
 mod tests {
     use crate::io::prelude::*;
-    use crate::io;
-    use super::Cursor;
-    use super::repeat;
+    use super::{Cursor, SeekFrom, repeat};
+    use crate::io::{self, IoSlice, IoSliceMut};
+    use crate::mem;
+    use crate::ops::Deref;
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
@@ -2380,4 +2604,135 @@ mod tests {
             super::read_to_end(&mut lr, &mut vec)
         });
     }
+
+    #[test]
+    fn seek_len() -> io::Result<()> {
+        let mut c = Cursor::new(vec![0; 15]);
+        assert_eq!(c.stream_len()?, 15);
+
+        c.seek(SeekFrom::End(0))?;
+        let old_pos = c.stream_position()?;
+        assert_eq!(c.stream_len()?, 15);
+        assert_eq!(c.stream_position()?, old_pos);
+
+        c.seek(SeekFrom::Start(7))?;
+        c.seek(SeekFrom::Current(2))?;
+        let old_pos = c.stream_position()?;
+        assert_eq!(c.stream_len()?, 15);
+        assert_eq!(c.stream_position()?, old_pos);
+
+        Ok(())
+    }
+
+    #[test]
+    fn seek_position() -> io::Result<()> {
+        // All `asserts` are duplicated here to make sure the method does not
+        // change anything about the seek state.
+        let mut c = Cursor::new(vec![0; 15]);
+        assert_eq!(c.stream_position()?, 0);
+        assert_eq!(c.stream_position()?, 0);
+
+        c.seek(SeekFrom::End(0))?;
+        assert_eq!(c.stream_position()?, 15);
+        assert_eq!(c.stream_position()?, 15);
+
+
+        c.seek(SeekFrom::Start(7))?;
+        c.seek(SeekFrom::Current(2))?;
+        assert_eq!(c.stream_position()?, 9);
+        assert_eq!(c.stream_position()?, 9);
+
+        c.seek(SeekFrom::End(-3))?;
+        c.seek(SeekFrom::Current(1))?;
+        c.seek(SeekFrom::Current(-5))?;
+        assert_eq!(c.stream_position()?, 8);
+        assert_eq!(c.stream_position()?, 8);
+
+        Ok(())
+    }
+
+    #[test]
+    fn io_slice_mut_advance() {
+        let mut buf1 = [1; 8];
+        let mut buf2 = [2; 16];
+        let mut buf3 = [3; 8];
+        let mut bufs = &mut [
+            IoSliceMut::new(&mut buf1),
+            IoSliceMut::new(&mut buf2),
+            IoSliceMut::new(&mut buf3),
+        ][..];
+
+        // Only in a single buffer..
+        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 1);
+        assert_eq!(bufs[0].deref(), [1; 7].as_ref());
+        assert_eq!(bufs[1].deref(), [2; 16].as_ref());
+        assert_eq!(bufs[2].deref(), [3; 8].as_ref());
+
+        // Removing a buffer, leaving others as is.
+        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 7);
+        assert_eq!(bufs[0].deref(), [2; 16].as_ref());
+        assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+
+        // Removing a buffer and removing from the next buffer.
+        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 18);
+        assert_eq!(bufs[0].deref(), [3; 6].as_ref());
+    }
+
+    #[test]
+    fn io_slice_mut_advance_empty_slice() {
+        let mut empty_bufs = &mut [][..];
+        // Shouldn't panic.
+        IoSliceMut::advance(&mut empty_bufs, 1);
+    }
+
+    #[test]
+    fn io_slice_mut_advance_beyond_total_length() {
+        let mut buf1 = [1; 8];
+        let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
+
+        // Going beyond the total length should be ok.
+        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 9);
+        assert!(bufs.is_empty());
+    }
+
+    #[test]
+    fn io_slice_advance() {
+        let mut buf1 = [1; 8];
+        let mut buf2 = [2; 16];
+        let mut buf3 = [3; 8];
+        let mut bufs =
+            &mut [IoSlice::new(&mut buf1), IoSlice::new(&mut buf2), IoSlice::new(&mut buf3)][..];
+
+        // Only in a single buffer..
+        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 1);
+        assert_eq!(bufs[0].deref(), [1; 7].as_ref());
+        assert_eq!(bufs[1].deref(), [2; 16].as_ref());
+        assert_eq!(bufs[2].deref(), [3; 8].as_ref());
+
+        // Removing a buffer, leaving others as is.
+        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 7);
+        assert_eq!(bufs[0].deref(), [2; 16].as_ref());
+        assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+
+        // Removing a buffer and removing from the next buffer.
+        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 18);
+        assert_eq!(bufs[0].deref(), [3; 6].as_ref());
+    }
+
+    #[test]
+    fn io_slice_advance_empty_slice() {
+        let mut empty_bufs = &mut [][..];
+        // Shouldn't panic.
+        IoSlice::advance(&mut empty_bufs, 1);
+    }
+
+    #[test]
+    fn io_slice_advance_beyond_total_length() {
+        let mut buf1 = [1; 8];
+        let mut bufs = &mut [IoSlice::new(&mut buf1)][..];
+
+        // Going beyond the total length should be ok.
+        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 9);
+        assert!(bufs.is_empty());
+    }
 }
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index d53a294fa6a..990c0eb8955 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -5,7 +5,7 @@ use crate::io::prelude::*;
 use crate::cell::RefCell;
 use crate::fmt;
 use crate::io::lazy::Lazy;
-use crate::io::{self, Initializer, BufReader, LineWriter};
+use crate::io::{self, Initializer, BufReader, LineWriter, IoSlice, IoSliceMut};
 use crate::sync::{Arc, Mutex, MutexGuard};
 use crate::sys::stdio;
 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
@@ -75,6 +75,10 @@ fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }
 impl Read for StdinRaw {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
 
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -82,10 +86,20 @@ impl Read for StdinRaw {
 }
 impl Write for StdoutRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
 }
 impl Write for StderrRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
 }
 
@@ -102,6 +116,14 @@ impl<W: io::Write> io::Write for Maybe<W> {
         }
     }
 
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let total = bufs.iter().map(|b| b.len()).sum();
+        match self {
+            Maybe::Real(w) => handle_ebadf(w.write_vectored(bufs), total),
+            Maybe::Fake => Ok(total),
+        }
+    }
+
     fn flush(&mut self) -> io::Result<()> {
         match *self {
             Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
@@ -117,6 +139,13 @@ impl<R: io::Read> io::Read for Maybe<R> {
             Maybe::Fake => Ok(0)
         }
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self {
+            Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0),
+            Maybe::Fake => Ok(0)
+        }
+    }
 }
 
 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
@@ -255,7 +284,7 @@ impl Stdin {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn lock(&self) -> StdinLock {
+    pub fn lock(&self) -> StdinLock<'_> {
         StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
     }
 
@@ -295,7 +324,7 @@ impl Stdin {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdin {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Stdin { .. }")
     }
 }
@@ -305,6 +334,9 @@ impl Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.lock().read(buf)
     }
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.lock().read_vectored(bufs)
+    }
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -325,6 +357,11 @@ impl Read for StdinLock<'_> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -339,7 +376,7 @@ impl BufRead for StdinLock<'_> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for StdinLock<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("StdinLock { .. }")
     }
 }
@@ -405,7 +442,7 @@ pub struct StdoutLock<'a> {
 /// use std::io::{self, Write};
 ///
 /// fn main() -> io::Result<()> {
-///     io::stdout().write(b"hello world")?;
+///     io::stdout().write_all(b"hello world")?;
 ///
 ///     Ok(())
 /// }
@@ -420,7 +457,7 @@ pub struct StdoutLock<'a> {
 ///     let stdout = io::stdout();
 ///     let mut handle = stdout.lock();
 ///
-///     handle.write(b"hello world")?;
+///     handle.write_all(b"hello world")?;
 ///
 ///     Ok(())
 /// }
@@ -460,20 +497,20 @@ impl Stdout {
     ///     let stdout = io::stdout();
     ///     let mut handle = stdout.lock();
     ///
-    ///     handle.write(b"hello world")?;
+    ///     handle.write_all(b"hello world")?;
     ///
     ///     Ok(())
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn lock(&self) -> StdoutLock {
+    pub fn lock(&self) -> StdoutLock<'_> {
         StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
     }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdout {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Stdout { .. }")
     }
 }
@@ -483,13 +520,16 @@ impl Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.lock().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.lock().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.lock().flush()
     }
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
         self.lock().write_all(buf)
     }
-    fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> {
+    fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
         self.lock().write_fmt(args)
     }
 }
@@ -498,6 +538,9 @@ impl Write for StdoutLock<'_> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.borrow_mut().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.inner.borrow_mut().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.inner.borrow_mut().flush()
     }
@@ -505,7 +548,7 @@ impl Write for StdoutLock<'_> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for StdoutLock<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("StdoutLock { .. }")
     }
 }
@@ -558,7 +601,7 @@ pub struct StderrLock<'a> {
 /// use std::io::{self, Write};
 ///
 /// fn main() -> io::Result<()> {
-///     io::stderr().write(b"hello world")?;
+///     io::stderr().write_all(b"hello world")?;
 ///
 ///     Ok(())
 /// }
@@ -573,7 +616,7 @@ pub struct StderrLock<'a> {
 ///     let stderr = io::stderr();
 ///     let mut handle = stderr.lock();
 ///
-///     handle.write(b"hello world")?;
+///     handle.write_all(b"hello world")?;
 ///
 ///     Ok(())
 /// }
@@ -613,20 +656,20 @@ impl Stderr {
     ///     let stderr = io::stderr();
     ///     let mut handle = stderr.lock();
     ///
-    ///     handle.write(b"hello world")?;
+    ///     handle.write_all(b"hello world")?;
     ///
     ///     Ok(())
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn lock(&self) -> StderrLock {
+    pub fn lock(&self) -> StderrLock<'_> {
         StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
     }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stderr {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Stderr { .. }")
     }
 }
@@ -636,13 +679,16 @@ impl Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.lock().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.lock().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.lock().flush()
     }
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
         self.lock().write_all(buf)
     }
-    fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> {
+    fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
         self.lock().write_fmt(args)
     }
 }
@@ -651,6 +697,9 @@ impl Write for StderrLock<'_> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.borrow_mut().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.inner.borrow_mut().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.inner.borrow_mut().flush()
     }
@@ -658,7 +707,7 @@ impl Write for StderrLock<'_> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for StderrLock<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("StderrLock { .. }")
     }
 }
@@ -720,7 +769,7 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
 ///
 /// However, if the actual I/O causes an error, this function does panic.
 fn print_to<T>(
-    args: fmt::Arguments,
+    args: fmt::Arguments<'_>,
     local_s: &'static LocalKey<RefCell<Option<Box<dyn Write+Send>>>>,
     global_s: fn() -> T,
     label: &str,
@@ -749,7 +798,7 @@ where
            issue = "0")]
 #[doc(hidden)]
 #[cfg(not(test))]
-pub fn _print(args: fmt::Arguments) {
+pub fn _print(args: fmt::Arguments<'_>) {
     print_to(args, &LOCAL_STDOUT, stdout, "stdout");
 }
 
@@ -758,7 +807,7 @@ pub fn _print(args: fmt::Arguments) {
            issue = "0")]
 #[doc(hidden)]
 #[cfg(not(test))]
-pub fn _eprint(args: fmt::Arguments) {
+pub fn _eprint(args: fmt::Arguments<'_>) {
     print_to(args, &LOCAL_STDERR, stderr, "stderr");
 }
 
@@ -777,7 +826,7 @@ mod tests {
     }
     #[test]
     fn stdoutlock_unwind_safe() {
-        assert_unwind_safe::<StdoutLock>();
+        assert_unwind_safe::<StdoutLock<'_>>();
         assert_unwind_safe::<StdoutLock<'static>>();
     }
     #[test]
@@ -786,7 +835,7 @@ mod tests {
     }
     #[test]
     fn stderrlock_unwind_safe() {
-        assert_unwind_safe::<StderrLock>();
+        assert_unwind_safe::<StderrLock<'_>>();
         assert_unwind_safe::<StderrLock<'static>>();
     }
 
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index 6aaf8f1889a..33cc87eb795 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -1,8 +1,8 @@
 #![allow(missing_copy_implementations)]
 
 use crate::fmt;
-use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoVec, IoVecMut};
-use crate::mem;
+use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoSlice, IoSliceMut};
+use crate::mem::MaybeUninit;
 
 /// Copies the entire contents of a reader into a writer.
 ///
@@ -43,21 +43,23 @@ use crate::mem;
 pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
     where R: Read, W: Write
 {
-    let mut buf = unsafe {
-        let mut buf: [u8; super::DEFAULT_BUF_SIZE] = mem::uninitialized();
-        reader.initializer().initialize(&mut buf);
-        buf
-    };
+    let mut buf = MaybeUninit::<[u8; super::DEFAULT_BUF_SIZE]>::uninit();
+    // FIXME(#53491): This is calling `get_mut` and `get_ref` on an uninitialized
+    // `MaybeUninit`. Revisit this once we decided whether that is valid or not.
+    // This is still technically undefined behavior due to creating a reference
+    // to uninitialized data, but within libstd we can rely on more guarantees
+    // than if this code were in an external lib.
+    unsafe { reader.initializer().initialize(buf.get_mut()); }
 
     let mut written = 0;
     loop {
-        let len = match reader.read(&mut buf) {
+        let len = match reader.read(unsafe { buf.get_mut() }) {
             Ok(0) => return Ok(written),
             Ok(len) => len,
             Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
             Err(e) => return Err(e),
         };
-        writer.write_all(&buf[..len])?;
+        writer.write_all(unsafe { &buf.get_ref()[..len] })?;
         written += len as u64;
     }
 }
@@ -111,7 +113,7 @@ impl BufRead for Empty {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Empty {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Empty { .. }")
     }
 }
@@ -153,7 +155,7 @@ impl Read for Repeat {
     }
 
     #[inline]
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let mut nwritten = 0;
         for buf in bufs {
             nwritten += self.read(buf)?;
@@ -169,7 +171,7 @@ impl Read for Repeat {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Repeat {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Repeat { .. }")
     }
 }
@@ -206,7 +208,7 @@ impl Write for Sink {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
 
     #[inline]
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let total_len = bufs.iter().map(|b| b.len()).sum();
         Ok(total_len)
     }
@@ -217,7 +219,7 @@ impl Write for Sink {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Sink {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Sink { .. }")
     }
 }
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index bef6bc92661..f5018485ef7 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -1,6 +1,6 @@
 #[doc(keyword = "as")]
 //
-/// The keyword for casting a value to a type.
+/// Cast between types, or rename an import.
 ///
 /// `as` is most commonly used to turn primitive types into other primitive types, but it has other
 /// uses that include turning pointers into addresses, addresses into pointers, and pointers into
@@ -25,14 +25,22 @@
 ///
 /// For more information on what `as` is capable of, see the [Reference]
 ///
-/// [Reference]:
-/// https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
+/// [Reference]: ../reference/expressions/operator-expr.html#type-cast-expressions
 /// [`crate`]: keyword.crate.html
 mod as_keyword { }
 
+#[doc(keyword = "break")]
+//
+/// Exit early from a loop.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod break_keyword { }
+
 #[doc(keyword = "const")]
 //
-/// The keyword for defining constants.
+/// Compile-time constants and deterministic functions.
 ///
 /// Sometimes a certain value is used many times throughout a program, and it can become
 /// inconvenient to copy it over and over. What's more, it's not always possible or desirable to
@@ -80,13 +88,22 @@ mod as_keyword { }
 ///
 /// [pointer]: primitive.pointer.html
 /// [Rust Book]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
-/// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html
+/// ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
+/// [Reference]: ../reference/items/constant-items.html
 mod const_keyword { }
 
+#[doc(keyword = "continue")]
+//
+/// Skip to the next iteration of a loop.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod continue_keyword { }
+
 #[doc(keyword = "crate")]
 //
-/// The `crate` keyword.
+/// A Rust binary or library.
 ///
 /// The primary use of the `crate` keyword is as a part of `extern crate` declarations, which are
 /// used to specify a dependency on a crate external to the one it's declared in. Crates are the
@@ -102,7 +119,7 @@ mod const_keyword { }
 /// The `as` keyword can be used to change what the crate is referred to as in your project. If a
 /// crate name includes a dash, it is implicitly imported with the dashes replaced by underscores.
 ///
-/// `crate` is also used as in conjunction with `pub` to signify that the item it's attached to
+/// `crate` can also be used as in conjunction with `pub` to signify that the item it's attached to
 /// is public only to other members of the same crate it's in.
 ///
 /// ```rust
@@ -114,17 +131,31 @@ mod const_keyword { }
 /// }
 /// ```
 ///
-/// [Reference]: https://doc.rust-lang.org/reference/items/extern-crates.html
+/// `crate` is also used to represent the absolute path of a module, where `crate` refers to the
+/// root of the current crate. For instance, `crate::foo::bar` refers to the name `bar` inside the
+/// module `foo`, from anywhere else in the same crate.
+///
+/// [Reference]: ../reference/items/extern-crates.html
 mod crate_keyword { }
 
+#[doc(keyword = "else")]
+//
+/// What to do when an [`if`] condition does not hold.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [`if`]: keyword.if.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod else_keyword { }
+
 #[doc(keyword = "enum")]
 //
-/// For defining enumerations.
+/// A type that can be any one of several variants.
 ///
 /// Enums in Rust are similar to those of other compiled languages like C, but have important
 /// differences that make them considerably more powerful. What Rust calls enums are more commonly
-/// known as [Algebraic Data Types] if you're coming from a functional programming background. The
-/// important detail is that each enum variant can have data to go along with it.
+/// known as [Algebraic Data Types][ADT] if you're coming from a functional programming background.
+/// The important detail is that each enum variant can have data to go along with it.
 ///
 /// ```rust
 /// # struct Coord;
@@ -167,15 +198,15 @@ mod crate_keyword { }
 ///
 /// For more information, take a look at the [Rust Book] or the [Reference]
 ///
-/// [Algebraic Data Types]: https://en.wikipedia.org/wiki/Algebraic_data_type
+/// [ADT]: https://en.wikipedia.org/wiki/Algebraic_data_type
 /// [`Option`]: option/enum.Option.html
-/// [Rust Book]: https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html
-/// [Reference]: https://doc.rust-lang.org/reference/items/enumerations.html
+/// [Rust Book]: ../book/ch06-01-defining-an-enum.html
+/// [Reference]: ../reference/items/enumerations.html
 mod enum_keyword { }
 
 #[doc(keyword = "extern")]
 //
-/// For external connections in Rust code.
+/// Link to or import external code.
 ///
 /// The `extern` keyword is used in two places in Rust. One is in conjunction with the [`crate`]
 /// keyword to make your Rust code aware of other Rust crates in your project, i.e., `extern crate
@@ -211,13 +242,23 @@ mod enum_keyword { }
 /// For more information on FFI, check the [Rust book] or the [Reference].
 ///
 /// [Rust book]:
-/// https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
-/// [Reference]: https://doc.rust-lang.org/reference/items/external-blocks.html
+/// ../book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
+/// [Reference]: ../reference/items/external-blocks.html
 mod extern_keyword { }
 
+#[doc(keyword = "false")]
+//
+/// A value of type [`bool`] representing logical **false**.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [`bool`]: primitive.bool.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod false_keyword { }
+
 #[doc(keyword = "fn")]
 //
-/// The keyword for defining functions.
+/// A function or function pointer.
 ///
 /// Functions are the primary way code is executed within Rust. Function blocks, usually just
 /// called functions, can be defined in a variety of different places and be assigned many
@@ -278,19 +319,25 @@ mod extern_keyword { }
 ///
 /// [`impl`]: keyword.impl.html
 /// [`extern`]: keyword.extern.html
-/// [Rust book]: https://doc.rust-lang.org/book/ch03-03-how-functions-work.html
-/// [Reference]: https://doc.rust-lang.org/reference/items/functions.html
+/// [Rust book]: ../book/ch03-03-how-functions-work.html
+/// [Reference]: ../reference/items/functions.html
 mod fn_keyword { }
 
 #[doc(keyword = "for")]
 //
-/// The `for` keyword.
+/// Iteration with [`in`], trait implementation with [`impl`], or [higher-ranked trait bounds]
+/// (`for<'a>`).
+///
+/// The `for` keyword is used in many syntactic locations:
+///
+/// * `for` is used in for-in-loops (see below).
+/// * `for` is used when implementing traits as in `impl Trait for Type` (see [`impl`] for more info
+///   on that).
+/// * `for` is also used for [higher-ranked trait bounds] as in `for<'a> &'a T: PartialEq<i32>`.
 ///
-/// `for` is primarily used in for-in-loops, but it has a few other pieces of syntactic uses such as
-/// `impl Trait for Type` (see [`impl`] for more info on that). for-in-loops, or to be more
-/// precise, iterator loops, are a simple syntactic sugar over an exceedingly common practice
-/// within Rust, which is to loop over an iterator until that iterator returns `None` (or `break`
-/// is called).
+/// for-in-loops, or to be more precise, iterator loops, are a simple syntactic sugar over a common
+/// practice within Rust, which is to loop over an iterator until that iterator returns `None` (or
+/// `break` is called).
 ///
 /// ```rust
 /// for i in 0..5 {
@@ -346,16 +393,18 @@ mod fn_keyword { }
 ///
 /// For more information on for-loops, see the [Rust book] or the [Reference].
 ///
+/// [`in`]: keyword.in.html
 /// [`impl`]: keyword.impl.html
+/// [higher-ranked trait bounds]: ../reference/trait-bounds.html#higher-ranked-trait-bounds
 /// [`IntoIterator`]: iter/trait.IntoIterator.html
 /// [Rust book]:
-/// https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for
-/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops
+/// ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
+/// [Reference]: ../reference/expressions/loop-expr.html#iterator-loops
 mod for_keyword { }
 
 #[doc(keyword = "if")]
 //
-/// If statements and expressions.
+/// Evaluate a block if a condition holds.
 ///
 /// `if` is a familiar construct to most programmers, and is the main way you'll often do logic in
 /// your code. However, unlike in most languages, `if` blocks can also act as expressions.
@@ -423,14 +472,13 @@ mod for_keyword { }
 ///
 /// For more information on `if` expressions, see the [Rust book] or the [Reference].
 ///
-/// [Rust book]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions
-/// [Reference]: https://doc.rust-lang.org/reference/expressions/if-expr.html
+/// [Rust book]: ../book/ch03-05-control-flow.html#if-expressions
+/// [Reference]: ../reference/expressions/if-expr.html
 mod if_keyword { }
 
 #[doc(keyword = "impl")]
 //
-/// The implementation-defining keyword.
+/// Implement some functionality for a type.
 ///
 /// The `impl` keyword is primarily used to define implementations on types. Inherent
 /// implementations are standalone, while trait implementations are used to implement traits for
@@ -486,15 +534,24 @@ mod if_keyword { }
 ///
 /// For more information on `impl Trait` syntax, see the [Rust book][book2].
 ///
-/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch05-03-method-syntax.html
-/// [Reference]: https://doc.rust-lang.org/reference/items/implementations.html
-/// [book2]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch10-02-traits.html#returning-traits
+/// [book1]: ../book/ch05-03-method-syntax.html
+/// [Reference]: ../reference/items/implementations.html
+/// [book2]: ../book/ch10-02-traits.html#returning-types-that-implement-traits
 mod impl_keyword { }
 
+#[doc(keyword = "in")]
+//
+/// Iterate over a series of values with [`for`].
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [`for`]: keyword.for.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod in_keyword { }
+
 #[doc(keyword = "let")]
 //
-/// The variable binding keyword.
+/// Bind a value to a variable.
 ///
 /// The primary use for the `let` keyword is in `let` statements, which are used to introduce a new
 /// set of variables into the current scope, as given by a pattern.
@@ -547,18 +604,73 @@ mod impl_keyword { }
 /// enumerations. `while let` also exists, which runs a loop with a pattern matched value until
 /// that pattern can't be matched.
 ///
-/// For more information on the `let` keyword, see the [Rust book] or the [Reference]
+/// For more information on the `let` keyword, see the [Rust book][book2] or the [Reference]
 ///
-/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch06-02-match.html
+/// [book1]: ../book/ch06-02-match.html
 /// [`if`]: keyword.if.html
-/// [book2]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch18-01-all-the-places-for-patterns.html#let-statements
-/// [Reference]: https://doc.rust-lang.org/reference/statements.html#let-statements
+/// [book2]: ../book/ch18-01-all-the-places-for-patterns.html#let-statements
+/// [Reference]: ../reference/statements.html#let-statements
 mod let_keyword { }
 
+#[doc(keyword = "while")]
+//
+/// Loop while a condition is upheld.
+///
+/// A `while` expression is used for predicate loops. The `while` expression runs the conditional
+/// expression before running the loop body, then runs the loop body if the conditional
+/// expression evaluates to `true`, or exits the loop otherwise.
+///
+/// ```rust
+/// let mut counter = 0;
+///
+/// while counter < 10 {
+///     println!("{}", counter);
+///     counter += 1;
+/// }
+/// ```
+///
+/// Like the [`for`] expression, we can use `break` and `continue`. A `while` expression
+/// cannot break with a value and always evaluates to `()` unlike [`loop`].
+///
+/// ```rust
+/// let mut i = 1;
+///
+/// while i < 100 {
+///     i *= 2;
+///     if i == 64 {
+///         break; // Exit when `i` is 64.
+///     }
+/// }
+/// ```
+///
+/// As `if` expressions have their pattern matching variant in `if let`, so too do `while`
+/// expressions with `while let`. The `while let` expression matches the pattern against the
+/// expression, then runs the loop body if pattern matching succeeds, or exits the loop otherwise.
+/// We can use `break` and `continue` in `while let` expressions just like in `while`.
+///
+/// ```rust
+/// let mut counter = Some(0);
+///
+/// while let Some(i) = counter {
+///     if i == 10 {
+///         counter = None;
+///     } else {
+///         println!("{}", i);
+///         counter = Some (i + 1);
+///     }
+/// }
+/// ```
+///
+/// For more information on `while` and loops in general, see the [reference].
+///
+/// [`for`]: keyword.for.html
+/// [`loop`]: keyword.loop.html
+/// [reference]: ../reference/expressions/loop-expr.html#predicate-loops
+mod while_keyword { }
+
 #[doc(keyword = "loop")]
 //
-/// The loop-defining keyword.
+/// Loop indefinitely.
 ///
 /// `loop` is used to define the simplest kind of loop supported in Rust. It runs the code inside
 /// it until the code uses `break` or the program exits.
@@ -598,12 +710,107 @@ mod let_keyword { }
 ///
 /// For more information on `loop` and loops in general, see the [Reference].
 ///
-/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html
+/// [Reference]: ../reference/expressions/loop-expr.html
 mod loop_keyword { }
 
+#[doc(keyword = "match")]
+//
+/// Control flow based on pattern matching.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod match_keyword { }
+
+#[doc(keyword = "mod")]
+//
+/// Organize code into [modules].
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [modules]: ../reference/items/modules.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod mod_keyword { }
+
+#[doc(keyword = "move")]
+//
+/// Capture a [closure]'s environment by value.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [closure]: ../book/second-edition/ch13-01-closures.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod move_keyword { }
+
+#[doc(keyword = "mut")]
+//
+/// A mutable binding, reference, or pointer.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod mut_keyword { }
+
+#[doc(keyword = "pub")]
+//
+/// Make an item visible to others.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod pub_keyword { }
+
+#[doc(keyword = "ref")]
+//
+/// Bind by reference during pattern matching.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod ref_keyword { }
+
+#[doc(keyword = "return")]
+//
+/// Return a value from a function.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod return_keyword { }
+
+#[doc(keyword = "self")]
+//
+/// The receiver of a method, or the current module.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod self_keyword { }
+
+#[doc(keyword = "Self")]
+//
+/// The implementing type within a [`trait`] or [`impl`] block, or the current type within a type
+/// definition.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [`impl`]: keyword.impl.html
+/// [`trait`]: keyword.trait.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod self_upper_keyword { }
+
+#[doc(keyword = "static")]
+//
+/// A place that is valid for the duration of a program.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod static_keyword { }
+
 #[doc(keyword = "struct")]
 //
-/// The keyword used to define structs.
+/// A type that is composed of other types.
 ///
 /// Structs in Rust come in three flavors: Structs with named fields, tuple structs, and unit
 /// structs.
@@ -705,6 +912,116 @@ mod loop_keyword { }
 /// [Reference][reference].
 ///
 /// [`PhantomData`]: marker/struct.PhantomData.html
-/// [book]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
-/// [reference]: https://doc.rust-lang.org/reference/items/structs.html
+/// [book]: ../book/ch05-01-defining-structs.html
+/// [reference]: ../reference/items/structs.html
 mod struct_keyword { }
+
+#[doc(keyword = "super")]
+//
+/// The parent of the current [module].
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [module]: ../reference/items/modules.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod super_keyword { }
+
+#[doc(keyword = "trait")]
+//
+/// A common interface for a class of types.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod trait_keyword { }
+
+#[doc(keyword = "true")]
+//
+/// A value of type [`bool`] representing logical **true**.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [`bool`]: primitive.bool.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod true_keyword { }
+
+#[doc(keyword = "type")]
+//
+/// Define an alias for an existing type.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod type_keyword { }
+
+#[doc(keyword = "unsafe")]
+//
+/// Code or interfaces whose [memory safety] cannot be verified by the type system.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [memory safety]: ../book/ch19-01-unsafe-rust.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod unsafe_keyword { }
+
+#[doc(keyword = "use")]
+//
+/// Import or rename items from other crates or modules.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod use_keyword { }
+
+#[doc(keyword = "where")]
+//
+/// Add constraints that must be upheld to use an item.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod where_keyword { }
+
+// 2018 Edition keywords
+
+#[unstable(feature = "async_await", issue = "50547")]
+#[doc(keyword = "async")]
+//
+/// Return a [`Future`] instead of blocking the current thread.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [`Future`]: ./future/trait.Future.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod async_keyword { }
+
+#[unstable(feature = "async_await", issue = "50547")]
+#[doc(keyword = "await")]
+//
+/// Suspend execution until the result of a [`Future`] is ready.
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [`Future`]: ./future/trait.Future.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod await_keyword { }
+
+#[doc(keyword = "dyn")]
+//
+/// Name the type of a [trait object].
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [trait object]: ../book/ch17-02-trait-objects.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod dyn_keyword { }
+
+#[doc(keyword = "union")]
+//
+/// The [Rust equivalent of a C-style union][union].
+///
+/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+///
+/// [union]: ../reference/items/unions.html
+/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+mod union_keyword { }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index b830c90cc43..cfee49a7b55 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -205,13 +205,12 @@
 // Don't link to std. We are std.
 #![no_std]
 
-#![deny(missing_docs)]
-#![deny(intra_doc_link_resolution_failure)]
-#![deny(missing_debug_implementations)]
-
-#![deny(rust_2018_idioms)]
+#![warn(deprecated_in_future)]
+#![warn(missing_docs)]
+#![warn(missing_debug_implementations)]
+#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
 #![allow(explicit_outlives_requirements)]
-#![allow(elided_lifetimes_in_paths)]
+#![allow(unused_lifetimes)]
 
 // Tell the compiler to link to either panic_abort or panic_unwind
 #![needs_panic_runtime]
@@ -219,18 +218,19 @@
 // std may use features in a platform-specific way
 #![allow(unused_features)]
 
-#![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))]
+#![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))]
 #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
-            feature(global_asm, range_contains, slice_index_methods,
-                    decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
+            feature(slice_index_methods, decl_macro, coerce_unsized,
+                    sgx_platform, ptr_wrapping_offset_from))]
+#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"),
+            feature(fixed_size_array, maybe_uninit_extra))]
 
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
 // NB: the following list is sorted to minimize merge conflicts.
-#![feature(align_offset)]
+#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))]
 #![feature(alloc_error_handler)]
 #![feature(alloc_layout_extra)]
-#![feature(alloc)]
 #![feature(allocator_api)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
@@ -251,6 +251,7 @@
 #![feature(const_cstr_unchecked)]
 #![feature(const_raw_ptr_deref)]
 #![feature(core_intrinsics)]
+#![feature(custom_test_frameworks)]
 #![feature(doc_alias)]
 #![feature(doc_cfg)]
 #![feature(doc_keyword)]
@@ -261,20 +262,23 @@
 #![feature(exact_size_is_empty)]
 #![feature(exhaustive_patterns)]
 #![feature(external_doc)]
-#![feature(fixed_size_array)]
 #![feature(fn_traits)]
-#![feature(fnbox)]
-#![feature(futures_api)]
+#![feature(format_args_nl)]
 #![feature(generator_trait)]
+#![feature(global_asm)]
 #![feature(hash_raw_entry)]
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
+#![feature(int_error_matching)]
 #![feature(integer_atomics)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
-#![feature(maybe_uninit)]
+#![feature(log_syntax)]
+#![feature(maybe_uninit_ref)]
+#![feature(maybe_uninit_slice)]
+#![feature(mem_take)]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
 #![feature(nll)]
@@ -300,8 +304,11 @@
 #![feature(stdsimd)]
 #![feature(stmt_expr_attributes)]
 #![feature(str_internals)]
+#![feature(test)]
 #![feature(thread_local)]
+#![feature(todo_macro)]
 #![feature(toowned_clone_into)]
+#![feature(trace_macros)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
@@ -323,7 +330,7 @@ use prelude::v1::*;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use core::{unreachable, unimplemented, write, writeln, r#try};
+pub use core::{unreachable, unimplemented, write, writeln, r#try, todo};
 
 #[allow(unused_imports)] // macros from `alloc` are not used on all platforms
 #[macro_use]
@@ -337,6 +344,12 @@ extern crate libc;
 #[allow(unused_extern_crates)]
 extern crate unwind;
 
+// Only needed for now for the `std_detect` module until that crate changes to
+// use `cfg_if::cfg_if!`
+#[macro_use]
+#[cfg(not(test))]
+extern crate cfg_if;
+
 // During testing, this crate is not actually the "real" std library, but rather
 // it links to the real std library, which was compiled from this same source
 // code. So any lang items std defines are conditionally excluded (or else they
@@ -436,6 +449,8 @@ pub use core::char;
 pub use core::u128;
 #[stable(feature = "core_hint", since = "1.27.0")]
 pub use core::hint;
+#[stable(feature = "core_array", since = "1.36.0")]
+pub use core::array;
 
 pub mod f32;
 pub mod f64;
@@ -458,18 +473,15 @@ pub mod process;
 pub mod sync;
 pub mod time;
 
-#[unstable(feature = "futures_api",
-           reason = "futures in libcore are unstable",
-           issue = "50547")]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub mod task {
     //! Types and Traits for working with asynchronous tasks.
     #[doc(inline)]
+    #[stable(feature = "futures_api", since = "1.36.0")]
     pub use core::task::*;
 }
 
-#[unstable(feature = "futures_api",
-           reason = "futures in libcore are unstable",
-           issue = "50547")]
+#[stable(feature = "futures_api", since = "1.36.0")]
 pub mod future;
 
 // Platform-abstraction modules
@@ -488,12 +500,12 @@ mod memchr;
 pub mod rt;
 
 // Pull in the `std_detect` crate directly into libstd. The contents of
-// `std_detect` are in a different repository: rust-lang-nursery/stdsimd.
+// `std_detect` are in a different repository: rust-lang/stdarch.
 //
 // `std_detect` depends on libstd, but the contents of this module are
 // set up in such a way that directly pulling it here works such that the
 // crate uses the this crate as its libstd.
-#[path = "../stdsimd/crates/std_detect/src/mod.rs"]
+#[path = "../stdarch/crates/std_detect/src/mod.rs"]
 #[allow(missing_debug_implementations, missing_docs, dead_code)]
 #[unstable(feature = "stdsimd", issue = "48556")]
 #[cfg(not(test))]
@@ -504,6 +516,36 @@ mod std_detect;
 #[cfg(not(test))]
 pub use std_detect::detect;
 
+// Document built-in macros in the crate root for consistency with libcore and existing tradition.
+// FIXME: Attribute and derive macros are not reexported because rustdoc renders them
+// as reexports rather than as macros, and that's not what we want.
+#[cfg(rustdoc)]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+pub use crate::prelude::v1::{
+    __rust_unstable_column,
+    asm,
+    assert,
+    cfg,
+    column,
+    compile_error,
+    concat,
+    concat_idents,
+    env,
+    file,
+    format_args,
+    format_args_nl,
+    global_asm,
+    include,
+    include_bytes,
+    include_str,
+    line,
+    log_syntax,
+    module_path,
+    option_env,
+    stringify,
+    trace_macros,
+};
+
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 9d0eb2e6b1c..839b4c5656a 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -4,7 +4,7 @@
 //! library. Each macro is available for use when linking against the standard
 //! library.
 
-/// The entry point for panic of Rust threads.
+/// Panics the current thread.
 ///
 /// This allows a program to terminate immediately and provide feedback
 /// to the caller of the program. `panic!` should be used when a program reaches
@@ -56,13 +56,13 @@
 #[allow_internal_unstable(__rust_unstable_column, libstd_sys_internals)]
 macro_rules! panic {
     () => ({
-        panic!("explicit panic")
+        $crate::panic!("explicit panic")
     });
     ($msg:expr) => ({
         $crate::rt::begin_panic($msg, &(file!(), line!(), __rust_unstable_column!()))
     });
     ($msg:expr,) => ({
-        panic!($msg)
+        $crate::panic!($msg)
     });
     ($fmt:expr, $($arg:tt)+) => ({
         $crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+),
@@ -70,7 +70,7 @@ macro_rules! panic {
     });
 }
 
-/// Macro for printing to the standard output.
+/// Prints to the standard output.
 ///
 /// Equivalent to the [`println!`] macro except that a newline is not printed at
 /// the end of the message.
@@ -116,7 +116,7 @@ macro_rules! print {
     ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
 }
 
-/// Macro for printing to the standard output, with a newline.
+/// Prints to the standard output, with a newline.
 ///
 /// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
 /// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
@@ -145,13 +145,13 @@ macro_rules! print {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(print_internals, format_args_nl)]
 macro_rules! println {
-    () => (print!("\n"));
+    () => ($crate::print!("\n"));
     ($($arg:tt)*) => ({
         $crate::io::_print(format_args_nl!($($arg)*));
     })
 }
 
-/// Macro for printing to the standard error.
+/// Prints to the standard error.
 ///
 /// Equivalent to the [`print!`] macro, except that output goes to
 /// [`io::stderr`] instead of `io::stdout`. See [`print!`] for
@@ -179,7 +179,7 @@ macro_rules! eprint {
     ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
 }
 
-/// Macro for printing to the standard error, with a newline.
+/// Prints to the standard error, with a newline.
 ///
 /// Equivalent to the [`println!`] macro, except that output goes to
 /// [`io::stderr`] instead of `io::stdout`. See [`println!`] for
@@ -204,14 +204,16 @@ macro_rules! eprint {
 #[stable(feature = "eprint", since = "1.19.0")]
 #[allow_internal_unstable(print_internals, format_args_nl)]
 macro_rules! eprintln {
-    () => (eprint!("\n"));
+    () => ($crate::eprint!("\n"));
     ($($arg:tt)*) => ({
         $crate::io::_eprint(format_args_nl!($($arg)*));
     })
 }
 
-/// A macro for quick and dirty debugging with which you can inspect
-/// the value of a given expression. An example:
+/// Prints and returns the value of a given expression for quick and dirty
+/// debugging.
+///
+/// An example:
 ///
 /// ```rust
 /// let a = 2;
@@ -231,10 +233,14 @@ macro_rules! eprintln {
 /// to give up ownership, you can instead borrow with `dbg!(&expr)`
 /// for some expression `expr`.
 ///
+/// The `dbg!` macro works exactly the same in release builds.
+/// This is useful when debugging issues that only occur in release
+/// builds or when debugging in release mode is significantly faster.
+///
 /// Note that the macro is intended as a debugging tool and therefore you
 /// should avoid having uses of it in version control for longer periods.
 /// Use cases involving debug output that should be added to version control
-/// may be better served by macros such as `debug!` from the `log` crate.
+/// are better served by macros such as [`debug!`] from the [`log`] crate.
 ///
 /// # Stability
 ///
@@ -305,99 +311,50 @@ macro_rules! eprintln {
 /// let _ = dbg!(a); // <-- `a` is moved again; error!
 /// ```
 ///
+/// You can also use `dbg!()` without a value to just print the
+/// file and line whenever it's reached.
+///
+/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
+/// a tuple (and return it, too):
+///
+/// ```
+/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
+/// ```
+///
+/// However, a single argument with a trailing comma will still not be treated
+/// as a tuple, following the convention of ignoring trailing commas in macro
+/// invocations. You can use a 1-tuple directly if you need one:
+///
+/// ```
+/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
+/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
+/// ```
+///
 /// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
+/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
+/// [`log`]: https://crates.io/crates/log
 #[macro_export]
 #[stable(feature = "dbg_macro", since = "1.32.0")]
 macro_rules! dbg {
+    () => {
+        $crate::eprintln!("[{}:{}]", file!(), line!());
+    };
     ($val:expr) => {
         // Use of `match` here is intentional because it affects the lifetimes
         // of temporaries - https://stackoverflow.com/a/48732525/1063961
         match $val {
             tmp => {
-                eprintln!("[{}:{}] {} = {:#?}",
+                $crate::eprintln!("[{}:{}] {} = {:#?}",
                     file!(), line!(), stringify!($val), &tmp);
                 tmp
             }
         }
-    }
-}
-
-/// A macro to await on an async call.
-#[macro_export]
-#[unstable(feature = "await_macro", issue = "50547")]
-#[allow_internal_unstable(gen_future, generators)]
-#[allow_internal_unsafe]
-macro_rules! r#await {
-    ($e:expr) => { {
-        let mut pinned = $e;
-        loop {
-            if let $crate::task::Poll::Ready(x) =
-                $crate::future::poll_with_tls_waker(unsafe {
-                    $crate::pin::Pin::new_unchecked(&mut pinned)
-                })
-            {
-                break x;
-            }
-            // FIXME(cramertj) prior to stabilizing await, we have to ensure that this
-            // can't be used to create a generator on stable via `|| await!()`.
-            yield
-        }
-    } }
-}
-
-/// A macro to select an event from a number of receivers.
-///
-/// This macro is used to wait for the first event to occur on a number of
-/// receivers. It places no restrictions on the types of receivers given to
-/// this macro, this can be viewed as a heterogeneous select.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(mpsc_select)]
-///
-/// use std::thread;
-/// use std::sync::mpsc;
-///
-/// // two placeholder functions for now
-/// fn long_running_thread() {}
-/// fn calculate_the_answer() -> u32 { 42 }
-///
-/// let (tx1, rx1) = mpsc::channel();
-/// let (tx2, rx2) = mpsc::channel();
-///
-/// thread::spawn(move|| { long_running_thread(); tx1.send(()).unwrap(); });
-/// thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
-///
-/// select! {
-///     _ = rx1.recv() => println!("the long running thread finished first"),
-///     answer = rx2.recv() => {
-///         println!("the answer was: {}", answer.unwrap());
-///     }
-/// }
-/// # drop(rx1.recv());
-/// # drop(rx2.recv());
-/// ```
-///
-/// For more information about select, see the `std::sync::mpsc::Select` structure.
-#[macro_export]
-#[unstable(feature = "mpsc_select", issue = "27800")]
-#[rustc_deprecated(since = "1.32.0",
-                   reason = "channel selection will be removed in a future release")]
-macro_rules! select {
-    (
-        $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
-    ) => ({
-        use $crate::sync::mpsc::Select;
-        let sel = Select::new();
-        $( let mut $rx = sel.handle(&$rx); )+
-        unsafe {
-            $( $rx.add(); )+
-        }
-        let ret = sel.wait();
-        $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
-        { unreachable!() }
-    })
+    };
+    // Trailing comma with single argument is ignored
+    ($val:expr,) => { $crate::dbg!($val) };
+    ($($val:expr),+ $(,)?) => {
+        ($($crate::dbg!($val)),+,)
+    };
 }
 
 #[cfg(test)]
@@ -408,568 +365,3 @@ macro_rules! assert_approx_eq {
                 "{} is not approximately equal to {}", *a, *b);
     })
 }
-
-/// Built-in macros to the compiler itself.
-///
-/// These macros do not have any corresponding definition with a `macro_rules!`
-/// macro, but are documented here. Their implementations can be found hardcoded
-/// into libsyntax itself.
-#[cfg(rustdoc)]
-mod builtin {
-
-    /// Unconditionally causes compilation to fail with the given error message when encountered.
-    ///
-    /// This macro should be used when a crate uses a conditional compilation strategy to provide
-    /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
-    /// which emits an error at *runtime*, rather than during compilation.
-    ///
-    /// # Examples
-    ///
-    /// Two such examples are macros and `#[cfg]` environments.
-    ///
-    /// Emit better compiler error if a macro is passed invalid values. Without the final branch,
-    /// the compiler would still emit an error, but the error's message would not mention the two
-    /// valid values.
-    ///
-    /// ```compile_fail
-    /// macro_rules! give_me_foo_or_bar {
-    ///     (foo) => {};
-    ///     (bar) => {};
-    ///     ($x:ident) => {
-    ///         compile_error!("This macro only accepts `foo` or `bar`");
-    ///     }
-    /// }
-    ///
-    /// give_me_foo_or_bar!(neither);
-    /// // ^ will fail at compile time with message "This macro only accepts `foo` or `bar`"
-    /// ```
-    ///
-    /// Emit compiler error if one of a number of features isn't available.
-    ///
-    /// ```compile_fail
-    /// #[cfg(not(any(feature = "foo", feature = "bar")))]
-    /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.")
-    /// ```
-    ///
-    /// [`panic!`]: ../std/macro.panic.html
-    #[stable(feature = "compile_error_macro", since = "1.20.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! compile_error {
-        ($msg:expr) => ({ /* compiler built-in */ });
-        ($msg:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// The core macro for formatted string creation & output.
-    ///
-    /// This macro functions by taking a formatting string literal containing
-    /// `{}` for each additional argument passed. `format_args!` prepares the
-    /// additional parameters to ensure the output can be interpreted as a string
-    /// and canonicalizes the arguments into a single type. Any value that implements
-    /// the [`Display`] trait can be passed to `format_args!`, as can any
-    /// [`Debug`] implementation be passed to a `{:?}` within the formatting string.
-    ///
-    /// This macro produces a value of type [`fmt::Arguments`]. This value can be
-    /// passed to the macros within [`std::fmt`] for performing useful redirection.
-    /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are
-    /// proxied through this one. `format_args!`, unlike its derived macros, avoids
-    /// heap allocations.
-    ///
-    /// You can use the [`fmt::Arguments`] value that `format_args!` returns
-    /// in `Debug` and `Display` contexts as seen below. The example also shows
-    /// that `Debug` and `Display` format to the same thing: the interpolated
-    /// format string in `format_args!`.
-    ///
-    /// ```rust
-    /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
-    /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
-    /// assert_eq!("1 foo 2", display);
-    /// assert_eq!(display, debug);
-    /// ```
-    ///
-    /// For more information, see the documentation in [`std::fmt`].
-    ///
-    /// [`Display`]: ../std/fmt/trait.Display.html
-    /// [`Debug`]: ../std/fmt/trait.Debug.html
-    /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html
-    /// [`std::fmt`]: ../std/fmt/index.html
-    /// [`format!`]: ../std/macro.format.html
-    /// [`write!`]: ../std/macro.write.html
-    /// [`println!`]: ../std/macro.println.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::fmt;
-    ///
-    /// let s = fmt::format(format_args!("hello {}", "world"));
-    /// assert_eq!(s, format!("hello {}", "world"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! format_args {
-        ($fmt:expr) => ({ /* compiler built-in */ });
-        ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
-    }
-
-    /// Inspect an environment variable at compile time.
-    ///
-    /// This macro will expand to the value of the named environment variable at
-    /// compile time, yielding an expression of type `&'static str`.
-    ///
-    /// If the environment variable is not defined, then a compilation error
-    /// will be emitted. To not emit a compile error, use the [`option_env!`]
-    /// macro instead.
-    ///
-    /// [`option_env!`]: ../std/macro.option_env.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let path: &'static str = env!("PATH");
-    /// println!("the $PATH variable at the time of compiling was: {}", path);
-    /// ```
-    ///
-    /// You can customize the error message by passing a string as the second
-    /// parameter:
-    ///
-    /// ```compile_fail
-    /// let doc: &'static str = env!("documentation", "what's that?!");
-    /// ```
-    ///
-    /// If the `documentation` environment variable is not defined, you'll get
-    /// the following error:
-    ///
-    /// ```text
-    /// error: what's that?!
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! env {
-        ($name:expr) => ({ /* compiler built-in */ });
-        ($name:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Optionally inspect an environment variable at compile time.
-    ///
-    /// If the named environment variable is present at compile time, this will
-    /// expand into an expression of type `Option<&'static str>` whose value is
-    /// `Some` of the value of the environment variable. If the environment
-    /// variable is not present, then this will expand to `None`. See
-    /// [`Option<T>`][option] for more information on this type.
-    ///
-    /// A compile time error is never emitted when using this macro regardless
-    /// of whether the environment variable is present or not.
-    ///
-    /// [option]: ../std/option/enum.Option.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let key: Option<&'static str> = option_env!("SECRET_KEY");
-    /// println!("the secret key might be: {:?}", key);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! option_env {
-        ($name:expr) => ({ /* compiler built-in */ });
-        ($name:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Concatenate identifiers into one identifier.
-    ///
-    /// This macro takes any number of comma-separated identifiers, and
-    /// concatenates them all into one, yielding an expression which is a new
-    /// identifier. Note that hygiene makes it such that this macro cannot
-    /// capture local variables. Also, as a general rule, macros are only
-    /// allowed in item, statement or expression position. That means while
-    /// you may use this macro for referring to existing variables, functions or
-    /// modules etc, you cannot define a new one with it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(concat_idents)]
-    ///
-    /// # fn main() {
-    /// fn foobar() -> u32 { 23 }
-    ///
-    /// let f = concat_idents!(foo, bar);
-    /// println!("{}", f());
-    ///
-    /// // fn concat_idents!(new, fun, name) { } // not usable in this way!
-    /// # }
-    /// ```
-    #[unstable(feature = "concat_idents_macro", issue = "29599")]
-    #[rustc_doc_only_macro]
-    macro_rules! concat_idents {
-        ($($e:ident),+) => ({ /* compiler built-in */ });
-        ($($e:ident,)+) => ({ /* compiler built-in */ });
-    }
-
-    /// Concatenates literals into a static string slice.
-    ///
-    /// This macro takes any number of comma-separated literals, yielding an
-    /// expression of type `&'static str` which represents all of the literals
-    /// concatenated left-to-right.
-    ///
-    /// Integer and floating point literals are stringified in order to be
-    /// concatenated.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let s = concat!("test", 10, 'b', true);
-    /// assert_eq!(s, "test10btrue");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! concat {
-        ($($e:expr),*) => ({ /* compiler built-in */ });
-        ($($e:expr,)*) => ({ /* compiler built-in */ });
-    }
-
-    /// A macro which expands to the line number on which it was invoked.
-    ///
-    /// With [`column!`] and [`file!`], these macros provide debugging information for
-    /// developers about the location within the source.
-    ///
-    /// The expanded expression has type `u32` and is 1-based, so the first line
-    /// in each file evaluates to 1, the second to 2, etc. This is consistent
-    /// with error messages by common compilers or popular editors.
-    /// The returned line is *not necessarily* the line of the `line!` invocation itself,
-    /// but rather the first macro invocation leading up to the invocation
-    /// of the `line!` macro.
-    ///
-    /// [`column!`]: macro.column.html
-    /// [`file!`]: macro.file.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let current_line = line!();
-    /// println!("defined on line: {}", current_line);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! line { () => ({ /* compiler built-in */ }) }
-
-    /// A macro which expands to the column number on which it was invoked.
-    ///
-    /// With [`line!`] and [`file!`], these macros provide debugging information for
-    /// developers about the location within the source.
-    ///
-    /// The expanded expression has type `u32` and is 1-based, so the first column
-    /// in each line evaluates to 1, the second to 2, etc. This is consistent
-    /// with error messages by common compilers or popular editors.
-    /// The returned column is *not necessarily* the line of the `column!` invocation itself,
-    /// but rather the first macro invocation leading up to the invocation
-    /// of the `column!` macro.
-    ///
-    /// [`line!`]: macro.line.html
-    /// [`file!`]: macro.file.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let current_col = column!();
-    /// println!("defined on column: {}", current_col);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! column { () => ({ /* compiler built-in */ }) }
-
-    /// A macro which expands to the file name from which it was invoked.
-    ///
-    /// With [`line!`] and [`column!`], these macros provide debugging information for
-    /// developers about the location within the source.
-    ///
-    ///
-    /// The expanded expression has type `&'static str`, and the returned file
-    /// is not the invocation of the `file!` macro itself, but rather the
-    /// first macro invocation leading up to the invocation of the `file!`
-    /// macro.
-    ///
-    /// [`line!`]: macro.line.html
-    /// [`column!`]: macro.column.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let this_file = file!();
-    /// println!("defined in file: {}", this_file);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! file { () => ({ /* compiler built-in */ }) }
-
-    /// A macro which stringifies its arguments.
-    ///
-    /// This macro will yield an expression of type `&'static str` which is the
-    /// stringification of all the tokens passed to the macro. No restrictions
-    /// are placed on the syntax of the macro invocation itself.
-    ///
-    /// Note that the expanded results of the input tokens may change in the
-    /// future. You should be careful if you rely on the output.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let one_plus_one = stringify!(1 + 1);
-    /// assert_eq!(one_plus_one, "1 + 1");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }
-
-    /// Includes a utf8-encoded file as a string.
-    ///
-    /// The file is located relative to the current file. (similarly to how
-    /// modules are found)
-    ///
-    /// This macro will yield an expression of type `&'static str` which is the
-    /// contents of the file.
-    ///
-    /// # Examples
-    ///
-    /// Assume there are two files in the same directory with the following
-    /// contents:
-    ///
-    /// File 'spanish.in':
-    ///
-    /// ```text
-    /// adiós
-    /// ```
-    ///
-    /// File 'main.rs':
-    ///
-    /// ```ignore (cannot-doctest-external-file-dependency)
-    /// fn main() {
-    ///     let my_str = include_str!("spanish.in");
-    ///     assert_eq!(my_str, "adiós\n");
-    ///     print!("{}", my_str);
-    /// }
-    /// ```
-    ///
-    /// Compiling 'main.rs' and running the resulting binary will print "adiós".
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! include_str {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Includes a file as a reference to a byte array.
-    ///
-    /// The file is located relative to the current file. (similarly to how
-    /// modules are found)
-    ///
-    /// This macro will yield an expression of type `&'static [u8; N]` which is
-    /// the contents of the file.
-    ///
-    /// # Examples
-    ///
-    /// Assume there are two files in the same directory with the following
-    /// contents:
-    ///
-    /// File 'spanish.in':
-    ///
-    /// ```text
-    /// adiós
-    /// ```
-    ///
-    /// File 'main.rs':
-    ///
-    /// ```ignore (cannot-doctest-external-file-dependency)
-    /// fn main() {
-    ///     let bytes = include_bytes!("spanish.in");
-    ///     assert_eq!(bytes, b"adi\xc3\xb3s\n");
-    ///     print!("{}", String::from_utf8_lossy(bytes));
-    /// }
-    /// ```
-    ///
-    /// Compiling 'main.rs' and running the resulting binary will print "adiós".
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! include_bytes {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Expands to a string that represents the current module path.
-    ///
-    /// The current module path can be thought of as the hierarchy of modules
-    /// leading back up to the crate root. The first component of the path
-    /// returned is the name of the crate currently being compiled.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// mod test {
-    ///     pub fn foo() {
-    ///         assert!(module_path!().ends_with("test"));
-    ///     }
-    /// }
-    ///
-    /// test::foo();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! module_path { () => ({ /* compiler built-in */ }) }
-
-    /// Boolean evaluation of configuration flags, at compile-time.
-    ///
-    /// In addition to the `#[cfg]` attribute, this macro is provided to allow
-    /// boolean expression evaluation of configuration flags. This frequently
-    /// leads to less duplicated code.
-    ///
-    /// The syntax given to this macro is the same syntax as the `cfg`
-    /// attribute.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let my_directory = if cfg!(windows) {
-    ///     "windows-specific-directory"
-    /// } else {
-    ///     "unix-directory"
-    /// };
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
-
-    /// Parse a file as an expression or an item according to the context.
-    ///
-    /// The file is located relative to the current file (similarly to how
-    /// modules are found).
-    ///
-    /// Using this macro is often a bad idea, because if the file is
-    /// parsed as an expression, it is going to be placed in the
-    /// surrounding code unhygienically. This could result in variables
-    /// or functions being different from what the file expected if
-    /// there are variables or functions that have the same name in
-    /// the current file.
-    ///
-    /// # Examples
-    ///
-    /// Assume there are two files in the same directory with the following
-    /// contents:
-    ///
-    /// File 'monkeys.in':
-    ///
-    /// ```ignore (only-for-syntax-highlight)
-    /// ['🙈', '🙊', '🙉']
-    ///     .iter()
-    ///     .cycle()
-    ///     .take(6)
-    ///     .collect::<String>()
-    /// ```
-    ///
-    /// File 'main.rs':
-    ///
-    /// ```ignore (cannot-doctest-external-file-dependency)
-    /// fn main() {
-    ///     let my_string = include!("monkeys.in");
-    ///     assert_eq!("🙈🙊🙉🙈🙊🙉", my_string);
-    ///     println!("{}", my_string);
-    /// }
-    /// ```
-    ///
-    /// Compiling 'main.rs' and running the resulting binary will print
-    /// "🙈🙊🙉🙈🙊🙉".
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! include {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Ensure that a boolean expression is `true` at runtime.
-    ///
-    /// This will invoke the [`panic!`] macro if the provided expression cannot be
-    /// evaluated to `true` at runtime.
-    ///
-    /// # Uses
-    ///
-    /// Assertions are always checked in both debug and release builds, and cannot
-    /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
-    /// release builds by default.
-    ///
-    /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
-    /// violated could lead to unsafety.
-    ///
-    /// Other use-cases of `assert!` include testing and enforcing run-time
-    /// invariants in safe code (whose violation cannot result in unsafety).
-    ///
-    /// # Custom Messages
-    ///
-    /// This macro has a second form, where a custom panic message can
-    /// be provided with or without arguments for formatting. See [`std::fmt`]
-    /// for syntax for this form.
-    ///
-    /// [`panic!`]: macro.panic.html
-    /// [`debug_assert!`]: macro.debug_assert.html
-    /// [`std::fmt`]: ../std/fmt/index.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// // the panic message for these assertions is the stringified value of the
-    /// // expression given.
-    /// assert!(true);
-    ///
-    /// fn some_computation() -> bool { true } // a very simple function
-    ///
-    /// assert!(some_computation());
-    ///
-    /// // assert with a custom message
-    /// let x = true;
-    /// assert!(x, "x wasn't true!");
-    ///
-    /// let a = 3; let b = 27;
-    /// assert!(a + b == 30, "a = {}, b = {}", a, b);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! assert {
-        ($cond:expr) => ({ /* compiler built-in */ });
-        ($cond:expr,) => ({ /* compiler built-in */ });
-        ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
-    }
-}
-
-/// A macro for defining `#[cfg]` if-else statements.
-///
-/// This is similar to the `if/elif` C preprocessor macro by allowing definition
-/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
-/// first.
-///
-/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
-/// without having to rewrite each clause multiple times.
-macro_rules! cfg_if {
-    ($(
-        if #[cfg($($meta:meta),*)] { $($it:item)* }
-    ) else * else {
-        $($it2:item)*
-    }) => {
-        __cfg_if_items! {
-            () ;
-            $( ( ($($meta),*) ($($it)*) ), )*
-            ( () ($($it2)*) ),
-        }
-    }
-}
-
-macro_rules! __cfg_if_items {
-    (($($not:meta,)*) ; ) => {};
-    (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
-        __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* }
-        __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
-    }
-}
-
-macro_rules! __cfg_if_apply {
-    ($m:meta, $($it:item)*) => {
-        $(#[$m] $it)*
-    }
-}
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index f5a87cc3ea6..ca86a175058 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -546,6 +546,9 @@ impl FromInner<c::sockaddr_in6> for SocketAddrV6 {
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV4> for SocketAddr {
     /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
+    ///
+    /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+    /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
     fn from(sock4: SocketAddrV4) -> SocketAddr {
         SocketAddr::V4(sock4)
     }
@@ -554,6 +557,9 @@ impl From<SocketAddrV4> for SocketAddr {
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV6> for SocketAddr {
     /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
+    ///
+    /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+    /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
     fn from(sock6: SocketAddrV6) -> SocketAddr {
         SocketAddr::V6(sock6)
     }
@@ -567,6 +573,13 @@ impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
     /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].
     ///
     /// `u16` is treated as port of the newly created [`SocketAddr`].
+    ///
+    /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+    /// [`IpAddr::V4`]: ../../std/net/enum.IpAddr.html#variant.V4
+    /// [`IpAddr::V6`]: ../../std/net/enum.IpAddr.html#variant.V6
+    /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+    /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
+    /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
     fn from(pieces: (I, u16)) -> SocketAddr {
         SocketAddr::new(pieces.0.into(), pieces.1)
     }
@@ -587,7 +600,7 @@ impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddr {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             SocketAddr::V4(ref a) => a.fmt(f),
             SocketAddr::V6(ref a) => a.fmt(f),
@@ -597,28 +610,28 @@ impl fmt::Display for SocketAddr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddrV4 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}:{}", self.ip(), self.port())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for SocketAddrV4 {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self, fmt)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddrV6 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "[{}]:{}", self.ip(), self.port())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for SocketAddrV6 {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self, fmt)
     }
 }
@@ -941,7 +954,10 @@ mod tests {
         assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53)));
 
         let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+        #[cfg(not(target_env = "sgx"))]
         assert!(tsa(("localhost", 23924)).unwrap().contains(&a));
+        #[cfg(target_env = "sgx")]
+        let _ = a;
     }
 
     #[test]
@@ -953,7 +969,10 @@ mod tests {
         assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53"));
 
         let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+        #[cfg(not(target_env = "sgx"))]
         assert!(tsa("localhost:23924").unwrap().contains(&a));
+        #[cfg(target_env = "sgx")]
+        let _ = a;
     }
 
     #[test]
@@ -968,9 +987,9 @@ mod tests {
         // s has been moved into the tsa call
     }
 
-    // FIXME: figure out why this fails on openbsd and bitrig and fix it
+    // FIXME: figure out why this fails on openbsd and fix it
     #[test]
-    #[cfg(not(any(windows, target_os = "openbsd", target_os = "bitrig")))]
+    #[cfg(not(any(windows, target_os = "openbsd")))]
     fn to_socket_addr_str_bad() {
         assert!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err());
     }
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index fa256ce5086..6b504056e5f 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -502,12 +502,19 @@ impl Ipv4Addr {
     ///
     /// The following return false:
     ///
-    /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16)
-    /// - the loopback address (127.0.0.0/8)
-    /// - the link-local address (169.254.0.0/16)
-    /// - the broadcast address (255.255.255.255/32)
-    /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
-    /// - the unspecified address (0.0.0.0)
+    /// - private addresses (see [`is_private()`](#method.is_private))
+    /// - the loopback address (see [`is_loopback()`](#method.is_loopback))
+    /// - the link-local address (see [`is_link_local()`](#method.is_link_local))
+    /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast))
+    /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation))
+    /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole
+    ///   0.0.0.0/8 block
+    /// - addresses reserved for future protocols (see
+    /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except
+    /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
+    /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved)
+    /// - addresses reserved for networking devices benchmarking (see
+    /// [`is_benchmarking`](#method.is_benchmarking))
     ///
     /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
     /// [`true`]: ../../std/primitive.bool.html
@@ -520,16 +527,181 @@ impl Ipv4Addr {
     /// use std::net::Ipv4Addr;
     ///
     /// fn main() {
+    ///     // private addresses are not global
     ///     assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
     ///     assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
     ///     assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
+    ///
+    ///     // the 0.0.0.0/8 block is not global
+    ///     assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
+    ///     // in particular, the unspecified address is not global
     ///     assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
+    ///
+    ///     // the loopback address is not global
+    ///     assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
+    ///
+    ///     // link local addresses are not global
+    ///     assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
+    ///
+    ///     // the broadcast address is not global
+    ///     assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
+    ///
+    ///     // the broadcast address is not global
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
+    ///     assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
+    ///     assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
+    ///
+    ///     // shared addresses are not global
+    ///     assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
+    ///
+    ///     // addresses reserved for protocol assignment are not global
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
+    ///
+    ///     // addresses reserved for future use are not global
+    ///     assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
+    ///
+    ///     // addresses reserved for network devices benchmarking are not global
+    ///     assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+    ///
+    ///     // All the other addresses are global
+    ///     assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
     ///     assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
     /// }
     /// ```
     pub fn is_global(&self) -> bool {
-        !self.is_private() && !self.is_loopback() && !self.is_link_local() &&
-        !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
+        // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
+        // globally routable addresses in the 192.0.0.0/24 range.
+        if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
+            return true;
+        }
+        !self.is_private()
+            && !self.is_loopback()
+            && !self.is_link_local()
+            && !self.is_broadcast()
+            && !self.is_documentation()
+            && !self.is_shared()
+            && !self.is_ietf_protocol_assignment()
+            && !self.is_reserved()
+            && !self.is_benchmarking()
+            // Make sure the address is not in 0.0.0.0/8
+            && self.octets()[0] != 0
+    }
+
+    /// Returns [`true`] if this address is part of the Shared Address Space defined in
+    /// [IETF RFC 6598] (`100.64.0.0/10`).
+    ///
+    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
+    ///     assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
+    ///     assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
+    /// }
+    /// ```
+    pub fn is_shared(&self) -> bool {
+        self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+    }
+
+    /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to
+    /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890].
+    ///
+    /// Note that parts of this block are in use:
+    ///
+    /// - `192.0.0.8/32` is the "IPv4 dummy address" (see [IETF RFC 7600])
+    /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723])
+    /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155])
+    ///
+    /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890
+    /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600
+    /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723
+    /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
+    ///     assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
+    /// }
+    /// ```
+    pub fn is_ietf_protocol_assignment(&self) -> bool {
+        self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
+    }
+
+    /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
+    /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
+    /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
+    ///
+    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+    /// [errate 423]: https://www.rfc-editor.org/errata/eid423
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
+    ///     assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
+    ///     assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
+    ///     assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
+    /// }
+    /// ```
+    pub fn is_benchmarking(&self) -> bool {
+        self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+    }
+
+    /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
+    /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
+    /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since
+    /// it is obviously not reserved for future use.
+    ///
+    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Warning
+    ///
+    /// As IANA assigns new addresses, this method will be
+    /// updated. This may result in non-reserved addresses being
+    /// treated as reserved in code that relies on an outdated version
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
+    ///     assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
+    ///
+    ///     assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
+    ///     // The broadcast address is not considered as reserved for future use by this
+    ///     // implementation
+    ///     assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
+    /// }
+    /// ```
+    pub fn is_reserved(&self) -> bool {
+        self.octets()[0] & 240 == 240 && !self.is_broadcast()
     }
 
     /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
@@ -658,7 +830,7 @@ impl Ipv4Addr {
 
 #[stable(feature = "ip_addr", since = "1.7.0")]
 impl fmt::Display for IpAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             IpAddr::V4(ip) => ip.fmt(fmt),
             IpAddr::V6(ip) => ip.fmt(fmt),
@@ -682,7 +854,7 @@ impl From<Ipv6Addr> for IpAddr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Ipv4Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         let octets = self.octets();
         write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
     }
@@ -690,7 +862,7 @@ impl fmt::Display for Ipv4Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Ipv4Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self, fmt)
     }
 }
@@ -1003,7 +1175,7 @@ impl Ipv6Addr {
         }
     }
 
-    /// Returns [`true`] if this is a unique local address (fc00::/7).
+    /// Returns [`true`] if this is a unique local address (`fc00::/7`).
     ///
     /// This property is defined in [IETF RFC 4193].
     ///
@@ -1027,12 +1199,83 @@ impl Ipv6Addr {
         (self.segments()[0] & 0xfe00) == 0xfc00
     }
 
-    /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
+    /// Returns [`true`] if the address is a unicast link-local address (`fe80::/64`).
     ///
-    /// This property is defined in [IETF RFC 4291].
+    /// A common mis-conception is to think that "unicast link-local addresses start with
+    /// `fe80::`", but the [IETF RFC 4291] actually defines a stricter format for these addresses:
+    ///
+    /// ```no_rust
+    /// |   10     |
+    /// |  bits    |         54 bits         |          64 bits           |
+    /// +----------+-------------------------+----------------------------+
+    /// |1111111010|           0             |       interface ID         |
+    /// +----------+-------------------------+----------------------------+
+    /// ```
+    ///
+    /// This method validates the format defined in the RFC and won't recognize the following
+    /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example.
+    /// If you need a less strict validation use [`is_unicast_link_local()`] instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// fn main() {
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local_strict());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
+    ///     assert!(ip.is_unicast_link_local_strict());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
+    ///     assert!(!ip.is_unicast_link_local_strict());
+    ///     assert!(ip.is_unicast_link_local());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(!ip.is_unicast_link_local_strict());
+    ///     assert!(ip.is_unicast_link_local());
+    /// }
+    /// ```
+    ///
+    /// # See also
+    ///
+    /// - [IETF RFC 4291 section 2.5.6]
+    /// - [RFC 4291 errata 4406]
+    /// - [`is_unicast_link_local()`]
     ///
     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
     /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
+    /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local
+    ///
+    pub fn is_unicast_link_local_strict(&self) -> bool {
+        (self.segments()[0] & 0xffff) == 0xfe80
+            && (self.segments()[1] & 0xffff) == 0
+            && (self.segments()[2] & 0xffff) == 0
+            && (self.segments()[3] & 0xffff) == 0
+    }
+
+    /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`).
+    ///
+    /// This method returns [`true`] for addresses in the range reserved by [RFC 4291 section 2.4],
+    /// i.e. addresses with the following format:
+    ///
+    /// ```no_rust
+    /// |   10     |
+    /// |  bits    |         54 bits         |          64 bits           |
+    /// +----------+-------------------------+----------------------------+
+    /// |1111111010|    arbitratry value     |       interface ID         |
+    /// +----------+-------------------------+----------------------------+
+    /// ```
+    ///
+    /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be
+    /// unicast link-local addresses, whereas [`is_unicast_link_local_strict()`] does not. If you
+    /// need a strict validation fully compliant with the RFC, use
+    /// [`is_unicast_link_local_strict()`].
     ///
     /// # Examples
     ///
@@ -1042,19 +1285,49 @@ impl Ipv6Addr {
     /// use std::net::Ipv6Addr;
     ///
     /// fn main() {
-    ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(),
-    ///                false);
-    ///     assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
+    ///     assert!(ip.is_unicast_link_local());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local());
+    ///     assert!(!ip.is_unicast_link_local_strict());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local());
+    ///     assert!(!ip.is_unicast_link_local_strict());
     /// }
     /// ```
+    ///
+    /// # See also
+    ///
+    /// - [IETF RFC 4291 section 2.4]
+    /// - [RFC 4291 errata 4406]
+    ///
+    /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
+    /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
+    /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict
+    ///
     pub fn is_unicast_link_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
 
-    /// Returns [`true`] if this is a deprecated unicast site-local address
-    /// (fec0::/10).
+    /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The
+    /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as:
+    ///
+    /// ```no_rust
+    /// |   10     |
+    /// |  bits    |         54 bits         |         64 bits            |
+    /// +----------+-------------------------+----------------------------+
+    /// |1111111011|        subnet ID        |       interface ID         |
+    /// +----------+-------------------------+----------------------------+
+    /// ```
     ///
     /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
     ///
     /// # Examples
     ///
@@ -1069,6 +1342,14 @@ impl Ipv6Addr {
     ///     assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
     /// }
     /// ```
+    ///
+    /// # Warning
+    ///
+    /// As per [RFC 3879], the whole `FEC0::/10` prefix is
+    /// deprecated. New software must not support site-local
+    /// addresses.
+    ///
+    /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
     pub fn is_unicast_site_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfec0
     }
@@ -1104,12 +1385,20 @@ impl Ipv6Addr {
     ///
     /// - the loopback address
     /// - the link-local addresses
-    /// - the (deprecated) site-local addresses
     /// - unique local addresses
     /// - the unspecified address
     /// - the address range reserved for documentation
     ///
+    /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
+    ///
+    /// ```no_rust
+    /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
+    /// be supported in new implementations (i.e., new implementations must treat this prefix as
+    /// Global Unicast).
+    /// ```
+    ///
     /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
     ///
     /// # Examples
     ///
@@ -1126,9 +1415,11 @@ impl Ipv6Addr {
     /// ```
     pub fn is_unicast_global(&self) -> bool {
         !self.is_multicast()
-            && !self.is_loopback() && !self.is_unicast_link_local()
-            && !self.is_unicast_site_local() && !self.is_unique_local()
-            && !self.is_unspecified() && !self.is_documentation()
+            && !self.is_loopback()
+            && !self.is_unicast_link_local()
+            && !self.is_unique_local()
+            && !self.is_unspecified()
+            && !self.is_documentation()
     }
 
     /// Returns the address's multicast scope if the address is multicast.
@@ -1229,7 +1520,7 @@ impl Ipv6Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Ipv6Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.segments() {
             // We need special cases for :: and ::1, otherwise they're formatted
             // as ::0.0.0.[01]
@@ -1276,7 +1567,7 @@ impl fmt::Display for Ipv6Addr {
                 let (zeros_at, zeros_len) = find_zero_slice(&self.segments());
 
                 if zeros_len > 1 {
-                    fn fmt_subslice(segments: &[u16], fmt: &mut fmt::Formatter) -> fmt::Result {
+                    fn fmt_subslice(segments: &[u16], fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
                         if !segments.is_empty() {
                             write!(fmt, "{:x}", segments[0])?;
                             for &seg in &segments[1..] {
@@ -1301,7 +1592,7 @@ impl fmt::Display for Ipv6Addr {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Ipv6Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self, fmt)
     }
 }
@@ -1510,8 +1801,8 @@ impl From<[u16; 8]> for IpAddr {
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use crate::net::*;
-    use crate::net::Ipv6MulticastScope::*;
     use crate::net::test::{tsa, sa6, sa4};
+    use crate::str::FromStr;
 
     #[test]
     fn test_from_str_ipv4() {
@@ -1675,164 +1966,491 @@ mod tests {
 
     #[test]
     fn ip_properties() {
-        fn check4(octets: &[u8; 4], unspec: bool, loopback: bool,
-                  global: bool, multicast: bool, documentation: bool) {
-            let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]));
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_multicast(), multicast);
-            assert_eq!(ip.is_documentation(), documentation);
+        macro_rules! ip {
+            ($s:expr) => {
+                IpAddr::from_str($s).unwrap()
+            }
         }
 
-        fn check6(str_addr: &str, unspec: bool, loopback: bool,
-                  global: bool, u_doc: bool, mcast: bool) {
-            let ip = IpAddr::V6(str_addr.parse().unwrap());
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_documentation(), u_doc);
-            assert_eq!(ip.is_multicast(), mcast);
+        macro_rules! check {
+            ($s:expr) => {
+                check!($s, 0);
+            };
+
+            ($s:expr, $mask:expr) => {{
+                let unspec: u8 = 1 << 0;
+                let loopback: u8 = 1 << 1;
+                let global: u8 = 1 << 2;
+                let multicast: u8 = 1 << 3;
+                let doc: u8 = 1 << 4;
+
+                if ($mask & unspec) == unspec {
+                    assert!(ip!($s).is_unspecified());
+                } else {
+                    assert!(!ip!($s).is_unspecified());
+                }
+
+                if ($mask & loopback) == loopback {
+                    assert!(ip!($s).is_loopback());
+                } else {
+                    assert!(!ip!($s).is_loopback());
+                }
+
+                if ($mask & global) == global {
+                    assert!(ip!($s).is_global());
+                } else {
+                    assert!(!ip!($s).is_global());
+                }
+
+                if ($mask & multicast) == multicast {
+                    assert!(ip!($s).is_multicast());
+                } else {
+                    assert!(!ip!($s).is_multicast());
+                }
+
+                if ($mask & doc) == doc {
+                    assert!(ip!($s).is_documentation());
+                } else {
+                    assert!(!ip!($s).is_documentation());
+                }
+            }}
         }
 
-        //     address                unspec loopbk global multicast doc
-        check4(&[0, 0, 0, 0],         true,  false, false,  false,   false);
-        check4(&[0, 0, 0, 1],         false, false, true,   false,   false);
-        check4(&[0, 1, 0, 0],         false, false, true,   false,   false);
-        check4(&[10, 9, 8, 7],        false, false, false,  false,   false);
-        check4(&[127, 1, 2, 3],       false, true,  false,  false,   false);
-        check4(&[172, 31, 254, 253],  false, false, false,  false,   false);
-        check4(&[169, 254, 253, 242], false, false, false,  false,   false);
-        check4(&[192, 0, 2, 183],     false, false, false,  false,   true);
-        check4(&[192, 1, 2, 183],     false, false, true,   false,   false);
-        check4(&[192, 168, 254, 253], false, false, false,  false,   false);
-        check4(&[198, 51, 100, 0],    false, false, false,  false,   true);
-        check4(&[203, 0, 113, 0],     false, false, false,  false,   true);
-        check4(&[203, 2, 113, 0],     false, false, true,   false,   false);
-        check4(&[224, 0, 0, 0],       false, false, true,   true,    false);
-        check4(&[239, 255, 255, 255], false, false, true,   true,    false);
-        check4(&[255, 255, 255, 255], false, false, false,  false,   false);
-
-        //     address                            unspec loopbk global doc    mcast
-        check6("::",                              true,  false, false, false, false);
-        check6("::1",                             false, true,  false, false, false);
-        check6("::0.0.0.2",                       false, false, true,  false, false);
-        check6("1::",                             false, false, true,  false, false);
-        check6("fc00::",                          false, false, false, false, false);
-        check6("fdff:ffff::",                     false, false, false, false, false);
-        check6("fe80:ffff::",                     false, false, false, false, false);
-        check6("febf:ffff::",                     false, false, false, false, false);
-        check6("fec0::",                          false, false, false, false, false);
-        check6("ff01::",                          false, false, false, false, true);
-        check6("ff02::",                          false, false, false, false, true);
-        check6("ff03::",                          false, false, false, false, true);
-        check6("ff04::",                          false, false, false, false, true);
-        check6("ff05::",                          false, false, false, false, true);
-        check6("ff08::",                          false, false, false, false, true);
-        check6("ff0e::",                          false, false, true,  false, true);
-        check6("2001:db8:85a3::8a2e:370:7334",    false, false, false, true,  false);
-        check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true,  false, false);
+        let unspec: u8 = 1 << 0;
+        let loopback: u8 = 1 << 1;
+        let global: u8 = 1 << 2;
+        let multicast: u8 = 1 << 3;
+        let doc: u8 = 1 << 4;
+
+        check!("0.0.0.0", unspec);
+        check!("0.0.0.1");
+        check!("0.1.0.0");
+        check!("10.9.8.7");
+        check!("127.1.2.3", loopback);
+        check!("172.31.254.253");
+        check!("169.254.253.242");
+        check!("192.0.2.183", doc);
+        check!("192.1.2.183", global);
+        check!("192.168.254.253");
+        check!("198.51.100.0", doc);
+        check!("203.0.113.0", doc);
+        check!("203.2.113.0", global);
+        check!("224.0.0.0", global|multicast);
+        check!("239.255.255.255", global|multicast);
+        check!("255.255.255.255");
+        // make sure benchmarking addresses are not global
+        check!("198.18.0.0");
+        check!("198.18.54.2");
+        check!("198.19.255.255");
+        // make sure addresses reserved for protocol assignment are not global
+        check!("192.0.0.0");
+        check!("192.0.0.255");
+        check!("192.0.0.100");
+        // make sure reserved addresses are not global
+        check!("240.0.0.0");
+        check!("251.54.1.76");
+        check!("254.255.255.255");
+        // make sure shared addresses are not global
+        check!("100.64.0.0");
+        check!("100.127.255.255");
+        check!("100.100.100.0");
+
+        check!("::", unspec);
+        check!("::1", loopback);
+        check!("::0.0.0.2", global);
+        check!("1::", global);
+        check!("fc00::");
+        check!("fdff:ffff::");
+        check!("fe80:ffff::");
+        check!("febf:ffff::");
+        check!("fec0::", global);
+        check!("ff01::", multicast);
+        check!("ff02::", multicast);
+        check!("ff03::", multicast);
+        check!("ff04::", multicast);
+        check!("ff05::", multicast);
+        check!("ff08::", multicast);
+        check!("ff0e::", global|multicast);
+        check!("2001:db8:85a3::8a2e:370:7334", doc);
+        check!("102:304:506:708:90a:b0c:d0e:f10", global);
     }
 
     #[test]
     fn ipv4_properties() {
-        fn check(octets: &[u8; 4], unspec: bool, loopback: bool,
-                 private: bool, link_local: bool, global: bool,
-                 multicast: bool, broadcast: bool, documentation: bool) {
-            let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]);
-            assert_eq!(octets, &ip.octets());
-
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_private(), private);
-            assert_eq!(ip.is_link_local(), link_local);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_multicast(), multicast);
-            assert_eq!(ip.is_broadcast(), broadcast);
-            assert_eq!(ip.is_documentation(), documentation);
+        macro_rules! ip {
+            ($s:expr) => {
+                Ipv4Addr::from_str($s).unwrap()
+            }
         }
 
-        //    address                unspec loopbk privt  linloc global multicast brdcast doc
-        check(&[0, 0, 0, 0],         true,  false, false, false, false,  false,    false,  false);
-        check(&[0, 0, 0, 1],         false, false, false, false, true,   false,    false,  false);
-        check(&[0, 1, 0, 0],         false, false, false, false, true,   false,    false,  false);
-        check(&[10, 9, 8, 7],        false, false, true,  false, false,  false,    false,  false);
-        check(&[127, 1, 2, 3],       false, true,  false, false, false,  false,    false,  false);
-        check(&[172, 31, 254, 253],  false, false, true,  false, false,  false,    false,  false);
-        check(&[169, 254, 253, 242], false, false, false, true,  false,  false,    false,  false);
-        check(&[192, 0, 2, 183],     false, false, false, false, false,  false,    false,  true);
-        check(&[192, 1, 2, 183],     false, false, false, false, true,   false,    false,  false);
-        check(&[192, 168, 254, 253], false, false, true,  false, false,  false,    false,  false);
-        check(&[198, 51, 100, 0],    false, false, false, false, false,  false,    false,  true);
-        check(&[203, 0, 113, 0],     false, false, false, false, false,  false,    false,  true);
-        check(&[203, 2, 113, 0],     false, false, false, false, true,   false,    false,  false);
-        check(&[224, 0, 0, 0],       false, false, false, false, true,   true,     false,  false);
-        check(&[239, 255, 255, 255], false, false, false, false, true,   true,     false,  false);
-        check(&[255, 255, 255, 255], false, false, false, false, false,  false,    true,   false);
+        macro_rules! check {
+            ($s:expr) => {
+                check!($s, 0);
+            };
+
+            ($s:expr, $mask:expr) => {{
+                let unspec: u16 = 1 << 0;
+                let loopback: u16 = 1 << 1;
+                let private: u16 = 1 << 2;
+                let link_local: u16 = 1 << 3;
+                let global: u16 = 1 << 4;
+                let multicast: u16 = 1 << 5;
+                let broadcast: u16 = 1 << 6;
+                let documentation: u16 = 1 << 7;
+                let benchmarking: u16 = 1 << 8;
+                let ietf_protocol_assignment: u16 = 1 << 9;
+                let reserved: u16 = 1 << 10;
+                let shared: u16 = 1 << 11;
+
+                if ($mask & unspec) == unspec {
+                    assert!(ip!($s).is_unspecified());
+                } else {
+                    assert!(!ip!($s).is_unspecified());
+                }
+
+                if ($mask & loopback) == loopback {
+                    assert!(ip!($s).is_loopback());
+                } else {
+                    assert!(!ip!($s).is_loopback());
+                }
+
+                if ($mask & private) == private {
+                    assert!(ip!($s).is_private());
+                } else {
+                    assert!(!ip!($s).is_private());
+                }
+
+                if ($mask & link_local) == link_local {
+                    assert!(ip!($s).is_link_local());
+                } else {
+                    assert!(!ip!($s).is_link_local());
+                }
+
+                if ($mask & global) == global {
+                    assert!(ip!($s).is_global());
+                } else {
+                    assert!(!ip!($s).is_global());
+                }
+
+                if ($mask & multicast) == multicast {
+                    assert!(ip!($s).is_multicast());
+                } else {
+                    assert!(!ip!($s).is_multicast());
+                }
+
+                if ($mask & broadcast) == broadcast {
+                    assert!(ip!($s).is_broadcast());
+                } else {
+                    assert!(!ip!($s).is_broadcast());
+                }
+
+                if ($mask & documentation) == documentation {
+                    assert!(ip!($s).is_documentation());
+                } else {
+                    assert!(!ip!($s).is_documentation());
+                }
+
+                if ($mask & benchmarking) == benchmarking {
+                    assert!(ip!($s).is_benchmarking());
+                } else {
+                    assert!(!ip!($s).is_benchmarking());
+                }
+
+                if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
+                    assert!(ip!($s).is_ietf_protocol_assignment());
+                } else {
+                    assert!(!ip!($s).is_ietf_protocol_assignment());
+                }
+
+                if ($mask & reserved) == reserved {
+                    assert!(ip!($s).is_reserved());
+                } else {
+                    assert!(!ip!($s).is_reserved());
+                }
+
+                if ($mask & shared) == shared {
+                    assert!(ip!($s).is_shared());
+                } else {
+                    assert!(!ip!($s).is_shared());
+                }
+            }}
+        }
+
+        let unspec: u16 = 1 << 0;
+        let loopback: u16 = 1 << 1;
+        let private: u16 = 1 << 2;
+        let link_local: u16 = 1 << 3;
+        let global: u16 = 1 << 4;
+        let multicast: u16 = 1 << 5;
+        let broadcast: u16 = 1 << 6;
+        let documentation: u16 = 1 << 7;
+        let benchmarking: u16 = 1 << 8;
+        let ietf_protocol_assignment: u16 = 1 << 9;
+        let reserved: u16 = 1 << 10;
+        let shared: u16 = 1 << 11;
+
+        check!("0.0.0.0", unspec);
+        check!("0.0.0.1");
+        check!("0.1.0.0");
+        check!("10.9.8.7", private);
+        check!("127.1.2.3", loopback);
+        check!("172.31.254.253", private);
+        check!("169.254.253.242", link_local);
+        check!("192.0.2.183", documentation);
+        check!("192.1.2.183", global);
+        check!("192.168.254.253", private);
+        check!("198.51.100.0", documentation);
+        check!("203.0.113.0", documentation);
+        check!("203.2.113.0", global);
+        check!("224.0.0.0", global|multicast);
+        check!("239.255.255.255", global|multicast);
+        check!("255.255.255.255", broadcast);
+        check!("198.18.0.0", benchmarking);
+        check!("198.18.54.2", benchmarking);
+        check!("198.19.255.255", benchmarking);
+        check!("192.0.0.0", ietf_protocol_assignment);
+        check!("192.0.0.255", ietf_protocol_assignment);
+        check!("192.0.0.100", ietf_protocol_assignment);
+        check!("240.0.0.0", reserved);
+        check!("251.54.1.76", reserved);
+        check!("254.255.255.255", reserved);
+        check!("100.64.0.0", shared);
+        check!("100.127.255.255", shared);
+        check!("100.100.100.0", shared);
     }
 
     #[test]
     fn ipv6_properties() {
-        fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool,
-                 unique_local: bool, global: bool,
-                 u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool,
-                 m_scope: Option<Ipv6MulticastScope>) {
-            let ip: Ipv6Addr = str_addr.parse().unwrap();
-            assert_eq!(str_addr, ip.to_string());
-            assert_eq!(&ip.octets(), octets);
-            assert_eq!(Ipv6Addr::from(*octets), ip);
-
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_unique_local(), unique_local);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_unicast_link_local(), u_link_local);
-            assert_eq!(ip.is_unicast_site_local(), u_site_local);
-            assert_eq!(ip.is_unicast_global(), u_global);
-            assert_eq!(ip.is_documentation(), u_doc);
-            assert_eq!(ip.multicast_scope(), m_scope);
-            assert_eq!(ip.is_multicast(), m_scope.is_some());
+        macro_rules! ip {
+            ($s:expr) => {
+                Ipv6Addr::from_str($s).unwrap()
+            }
+        }
+
+        macro_rules! check {
+            ($s:expr, &[$($octet:expr),*], $mask:expr) => {
+                assert_eq!($s, ip!($s).to_string());
+                let octets = &[$($octet),*];
+                assert_eq!(&ip!($s).octets(), octets);
+                assert_eq!(Ipv6Addr::from(*octets), ip!($s));
+
+                let unspecified: u16 = 1 << 0;
+                let loopback: u16 = 1 << 1;
+                let unique_local: u16 = 1 << 2;
+                let global: u16 = 1 << 3;
+                let unicast_link_local: u16 = 1 << 4;
+                let unicast_link_local_strict: u16 = 1 << 5;
+                let unicast_site_local: u16 = 1 << 6;
+                let unicast_global: u16 = 1 << 7;
+                let documentation: u16 = 1 << 8;
+                let multicast_interface_local: u16 = 1 << 9;
+                let multicast_link_local: u16 = 1 << 10;
+                let multicast_realm_local: u16 = 1 << 11;
+                let multicast_admin_local: u16 = 1 << 12;
+                let multicast_site_local: u16 = 1 << 13;
+                let multicast_organization_local: u16 = 1 << 14;
+                let multicast_global: u16 = 1 << 15;
+                let multicast: u16 = multicast_interface_local
+                    | multicast_admin_local
+                    | multicast_global
+                    | multicast_link_local
+                    | multicast_realm_local
+                    | multicast_site_local
+                    | multicast_organization_local;
+
+                if ($mask & unspecified) == unspecified {
+                    assert!(ip!($s).is_unspecified());
+                } else {
+                    assert!(!ip!($s).is_unspecified());
+                }
+                if ($mask & loopback) == loopback {
+                    assert!(ip!($s).is_loopback());
+                } else {
+                    assert!(!ip!($s).is_loopback());
+                }
+                if ($mask & unique_local) == unique_local {
+                    assert!(ip!($s).is_unique_local());
+                } else {
+                    assert!(!ip!($s).is_unique_local());
+                }
+                if ($mask & global) == global {
+                    assert!(ip!($s).is_global());
+                } else {
+                    assert!(!ip!($s).is_global());
+                }
+                if ($mask & unicast_link_local) == unicast_link_local {
+                    assert!(ip!($s).is_unicast_link_local());
+                } else {
+                    assert!(!ip!($s).is_unicast_link_local());
+                }
+                if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
+                    assert!(ip!($s).is_unicast_link_local_strict());
+                } else {
+                    assert!(!ip!($s).is_unicast_link_local_strict());
+                }
+                if ($mask & unicast_site_local) == unicast_site_local {
+                    assert!(ip!($s).is_unicast_site_local());
+                } else {
+                    assert!(!ip!($s).is_unicast_site_local());
+                }
+                if ($mask & unicast_global) == unicast_global {
+                    assert!(ip!($s).is_unicast_global());
+                } else {
+                    assert!(!ip!($s).is_unicast_global());
+                }
+                if ($mask & documentation) == documentation {
+                    assert!(ip!($s).is_documentation());
+                } else {
+                    assert!(!ip!($s).is_documentation());
+                }
+                if ($mask & multicast) != 0 {
+                    assert!(ip!($s).multicast_scope().is_some());
+                    assert!(ip!($s).is_multicast());
+                } else {
+                    assert!(ip!($s).multicast_scope().is_none());
+                    assert!(!ip!($s).is_multicast());
+                }
+                if ($mask & multicast_interface_local) == multicast_interface_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::InterfaceLocal);
+                }
+                if ($mask & multicast_link_local) == multicast_link_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::LinkLocal);
+                }
+                if ($mask & multicast_realm_local) == multicast_realm_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::RealmLocal);
+                }
+                if ($mask & multicast_admin_local) == multicast_admin_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::AdminLocal);
+                }
+                if ($mask & multicast_site_local) == multicast_site_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::SiteLocal);
+                }
+                if ($mask & multicast_organization_local) == multicast_organization_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::OrganizationLocal);
+                }
+                if ($mask & multicast_global) == multicast_global {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::Global);
+                }
+            }
         }
 
-        //    unspec loopbk uniqlo global unill  unisl  uniglo doc    mscope
-        check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              true,  false, false, false, false, false, false, false, None);
-        check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
-              false, true,  false, false, false, false, false, false, None);
-        check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
-              false, false, false, true,  false, false, true,  false, None);
-        check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, true,  false, false, true,  false, None);
-        check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, true,  false, false, false, false, false, None);
-        check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, true,  false, false, false, false, false, None);
-        check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, true,  false, false, false, None);
-        check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, true,  false, false, false, None);
-        check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, true,  false, false, None);
-        check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(InterfaceLocal));
-        check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(LinkLocal));
-        check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(RealmLocal));
-        check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(AdminLocal));
-        check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(SiteLocal));
-        check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(OrganizationLocal));
-        check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, true,  false, false, false, false, Some(Global));
-        check("2001:db8:85a3::8a2e:370:7334",
-              &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
-              false, false, false, false, false, false, false, true, None);
-        check("102:304:506:708:90a:b0c:d0e:f10",
-              &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
-              false, false, false, true,  false, false, true,  false, None);
+        let unspecified: u16 = 1 << 0;
+        let loopback: u16 = 1 << 1;
+        let unique_local: u16 = 1 << 2;
+        let global: u16 = 1 << 3;
+        let unicast_link_local: u16 = 1 << 4;
+        let unicast_link_local_strict: u16 = 1 << 5;
+        let unicast_site_local: u16 = 1 << 6;
+        let unicast_global: u16 = 1 << 7;
+        let documentation: u16 = 1 << 8;
+        let multicast_interface_local: u16 = 1 << 9;
+        let multicast_link_local: u16 = 1 << 10;
+        let multicast_realm_local: u16 = 1 << 11;
+        let multicast_admin_local: u16 = 1 << 12;
+        let multicast_site_local: u16 = 1 << 13;
+        let multicast_organization_local: u16 = 1 << 14;
+        let multicast_global: u16 = 1 << 15;
+
+        check!("::",
+               &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unspecified);
+
+        check!("::1",
+               &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+               loopback);
+
+        check!("::0.0.0.2",
+               &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
+               global | unicast_global);
+
+        check!("1::",
+               &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               global | unicast_global);
+
+        check!("fc00::",
+               &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unique_local);
+
+        check!("fdff:ffff::",
+               &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unique_local);
+
+        check!("fe80:ffff::",
+               &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("fe80::",
+               &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local|unicast_link_local_strict);
+
+        check!("febf:ffff::",
+               &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("febf::",
+               &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+               &[0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+               unicast_link_local);
+
+        check!("fe80::ffff:ffff:ffff:ffff",
+               &[0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+               unicast_link_local|unicast_link_local_strict);
+
+        check!("fe80:0:0:1::",
+               &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("fec0::",
+               &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_site_local|unicast_global|global);
+
+        check!("ff01::",
+               &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_interface_local);
+
+        check!("ff02::",
+               &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_link_local);
+
+        check!("ff03::",
+               &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_realm_local);
+
+        check!("ff04::",
+               &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_admin_local);
+
+        check!("ff05::",
+               &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_site_local);
+
+        check!("ff08::",
+               &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_organization_local);
+
+        check!("ff0e::",
+               &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_global | global);
+
+        check!("2001:db8:85a3::8a2e:370:7334",
+               &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
+               documentation);
+
+        check!("102:304:506:708:90a:b0c:d0e:f10",
+               &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+               global| unicast_global);
     }
 
     #[test]
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 7951cd6bcf2..5a76139530a 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -28,7 +28,7 @@ impl<'a> Parser<'a> {
 
     // Commit only if parser returns Some
     fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
-        F: FnOnce(&mut Parser) -> Option<T>,
+        F: FnOnce(&mut Parser<'_>) -> Option<T>,
     {
         let pos = self.pos;
         let r = cb(self);
@@ -40,7 +40,7 @@ impl<'a> Parser<'a> {
 
     // Commit only if parser read till EOF
     fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
-        F: FnOnce(&mut Parser) -> Option<T>,
+        F: FnOnce(&mut Parser<'_>) -> Option<T>,
     {
         self.read_atomically(move |p| {
             cb(p).filter(|_| p.is_eof())
@@ -48,10 +48,10 @@ impl<'a> Parser<'a> {
     }
 
     // Return result of first successful parser
-    fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>])
+    fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser<'_>) -> Option<T> + 'static>])
                -> Option<T> {
         for pf in parsers {
-            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
+            if let Some(r) = self.read_atomically(|p: &mut Parser<'_>| pf(p)) {
                 return Some(r);
             }
         }
@@ -64,9 +64,9 @@ impl<'a> Parser<'a> {
                                        pb: PB,
                                        pc: PC)
                                        -> Option<(A, B, C)> where
-        PA: FnOnce(&mut Parser) -> Option<A>,
-        PB: FnOnce(&mut Parser) -> Option<B>,
-        PC: FnOnce(&mut Parser) -> Option<C>,
+        PA: FnOnce(&mut Parser<'_>) -> Option<A>,
+        PB: FnOnce(&mut Parser<'_>) -> Option<B>,
+        PC: FnOnce(&mut Parser<'_>) -> Option<C>,
     {
         self.read_atomically(move |p| {
             let a = pa(p);
@@ -177,7 +177,7 @@ impl<'a> Parser<'a> {
             Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
         }
 
-        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
+        fn read_groups(p: &mut Parser<'_>, groups: &mut [u16; 8], limit: usize)
                        -> (usize, bool) {
             let mut i = 0;
             while i < limit {
@@ -244,15 +244,15 @@ impl<'a> Parser<'a> {
     }
 
     fn read_ip_addr(&mut self) -> Option<IpAddr> {
-        let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr().map(IpAddr::V4);
-        let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr().map(IpAddr::V6);
+        let ipv4_addr = |p: &mut Parser<'_>| p.read_ipv4_addr().map(IpAddr::V4);
+        let ipv6_addr = |p: &mut Parser<'_>| p.read_ipv6_addr().map(IpAddr::V6);
         self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
     }
 
     fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
-        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
-        let colon = |p: &mut Parser| p.read_given_char(':');
-        let port = |p: &mut Parser| {
+        let ip_addr = |p: &mut Parser<'_>| p.read_ipv4_addr();
+        let colon = |p: &mut Parser<'_>| p.read_given_char(':');
+        let port = |p: &mut Parser<'_>| {
             p.read_number(10, 5, 0x10000).map(|n| n as u16)
         };
 
@@ -263,14 +263,14 @@ impl<'a> Parser<'a> {
     }
 
     fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
-        let ip_addr = |p: &mut Parser| {
-            let open_br = |p: &mut Parser| p.read_given_char('[');
-            let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
-            let clos_br = |p: &mut Parser| p.read_given_char(']');
+        let ip_addr = |p: &mut Parser<'_>| {
+            let open_br = |p: &mut Parser<'_>| p.read_given_char('[');
+            let ip_addr = |p: &mut Parser<'_>| p.read_ipv6_addr();
+            let clos_br = |p: &mut Parser<'_>| p.read_given_char(']');
             p.read_seq_3(open_br, ip_addr, clos_br).map(|t| t.1)
         };
-        let colon = |p: &mut Parser| p.read_given_char(':');
-        let port = |p: &mut Parser| {
+        let colon = |p: &mut Parser<'_>| p.read_given_char(':');
+        let port = |p: &mut Parser<'_>| {
             p.read_number(10, 5, 0x10000).map(|n| n as u16)
         };
 
@@ -281,8 +281,8 @@ impl<'a> Parser<'a> {
     }
 
     fn read_socket_addr(&mut self) -> Option<SocketAddr> {
-        let v4 = |p: &mut Parser| p.read_socket_addr_v4().map(SocketAddr::V4);
-        let v6 = |p: &mut Parser| p.read_socket_addr_v6().map(SocketAddr::V6);
+        let v4 = |p: &mut Parser<'_>| p.read_socket_addr_v4().map(SocketAddr::V4);
+        let v6 = |p: &mut Parser<'_>| p.read_socket_addr_v6().map(SocketAddr::V6);
         self.read_or(&mut [Box::new(v4), Box::new(v6)])
     }
 }
@@ -391,7 +391,7 @@ pub struct AddrParseError(());
 
 #[stable(feature = "addr_parse_error_error", since = "1.4.0")]
 impl fmt::Display for AddrParseError {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.write_str(self.description())
     }
 }
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index ce0c5c0bb0d..cdffa390223 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -1,7 +1,7 @@
 use crate::io::prelude::*;
 
 use crate::fmt;
-use crate::io::{self, Initializer, IoVec, IoVecMut};
+use crate::io::{self, Initializer, IoSlice, IoSliceMut};
 use crate::net::{ToSocketAddrs, SocketAddr, Shutdown};
 use crate::sys_common::net as net_imp;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -569,7 +569,7 @@ impl TcpStream {
 impl Read for TcpStream {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
 
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         self.0.read_vectored(bufs)
     }
 
@@ -582,7 +582,7 @@ impl Read for TcpStream {
 impl Write for TcpStream {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
 
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         self.0.write_vectored(bufs)
     }
 
@@ -592,7 +592,7 @@ impl Write for TcpStream {
 impl Read for &TcpStream {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
 
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         self.0.read_vectored(bufs)
     }
 
@@ -605,7 +605,7 @@ impl Read for &TcpStream {
 impl Write for &TcpStream {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
 
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         self.0.write_vectored(bufs)
     }
 
@@ -626,7 +626,7 @@ impl IntoInner<net_imp::TcpStream> for TcpStream {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for TcpStream {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(f)
     }
 }
@@ -771,7 +771,7 @@ impl TcpListener {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn incoming(&self) -> Incoming {
+    pub fn incoming(&self) -> Incoming<'_> {
         Incoming { listener: self }
     }
 
@@ -922,19 +922,19 @@ impl IntoInner<net_imp::TcpListener> for TcpListener {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for TcpListener {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
-    use crate::io::{ErrorKind, IoVec, IoVecMut};
+    use crate::fmt;
+    use crate::io::{ErrorKind, IoSlice, IoSliceMut};
     use crate::io::prelude::*;
     use crate::net::*;
     use crate::net::test::{next_test_ip4, next_test_ip6};
     use crate::sync::mpsc::channel;
-    use crate::sys_common::AsInner;
     use crate::time::{Instant, Duration};
     use crate::thread;
 
@@ -1129,7 +1129,7 @@ mod tests {
                 connect(i + 1, addr);
                 t!(stream.write(&[i as u8]));
             });
-            t.join().ok().unwrap();
+            t.join().ok().expect("thread panicked");
         }
     }
 
@@ -1162,7 +1162,7 @@ mod tests {
                 connect(i + 1, addr);
                 t!(stream.write(&[99]));
             });
-            t.join().ok().unwrap();
+            t.join().ok().expect("thread panicked");
         }
     }
 
@@ -1216,7 +1216,7 @@ mod tests {
             let mut b = [0];
             let mut c = [0; 3];
             let len = t!(s2.read_vectored(
-                &mut [IoVecMut::new(&mut a), IoVecMut::new(&mut b), IoVecMut::new(&mut c)],
+                &mut [IoSliceMut::new(&mut a), IoSliceMut::new(&mut b), IoSliceMut::new(&mut c)],
             ));
             assert!(len > 0);
             assert_eq!(b, [10]);
@@ -1235,7 +1235,7 @@ mod tests {
             let a = [];
             let b = [10];
             let c = [11, 12];
-            t!(s1.write_vectored(&[IoVec::new(&a), IoVec::new(&b), IoVec::new(&c)]));
+            t!(s1.write_vectored(&[IoSlice::new(&a), IoSlice::new(&b), IoSlice::new(&c)]));
 
             let mut buf = [0; 4];
             let len = t!(s2.read(&mut buf));
@@ -1377,6 +1377,8 @@ mod tests {
     }
 
     #[test]
+    // FIXME: https://github.com/fortanix/rust-sgx/issues/110
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn shutdown_smoke() {
         each_ip(&mut |addr| {
             let a = t!(TcpListener::bind(&addr));
@@ -1397,6 +1399,8 @@ mod tests {
     }
 
     #[test]
+    // FIXME: https://github.com/fortanix/rust-sgx/issues/110
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn close_readwrite_smoke() {
         each_ip(&mut |addr| {
             let a = t!(TcpListener::bind(&addr));
@@ -1550,30 +1554,51 @@ mod tests {
 
     #[test]
     fn debug() {
-        let name = if cfg!(windows) {"socket"} else {"fd"};
+        #[cfg(not(target_env = "sgx"))]
+        fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+            addr
+        }
+        #[cfg(target_env = "sgx")]
+        fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+            addr.to_string()
+        }
+
+        #[cfg(unix)]
+        use crate::os::unix::io::AsRawFd;
+        #[cfg(target_env = "sgx")]
+        use crate::os::fortanix_sgx::io::AsRawFd;
+        #[cfg(not(windows))]
+        fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
+            addr.as_raw_fd()
+        }
+        #[cfg(windows)]
+        fn render_inner(addr: &dyn crate::os::windows::io::AsRawSocket) -> impl fmt::Debug {
+            addr.as_raw_socket()
+        }
+
+        let inner_name = if cfg!(windows) {"socket"} else {"fd"};
         let socket_addr = next_test_ip4();
 
         let listener = t!(TcpListener::bind(&socket_addr));
-        let listener_inner = listener.0.socket().as_inner();
         let compare = format!("TcpListener {{ addr: {:?}, {}: {:?} }}",
-                              socket_addr, name, listener_inner);
+                              render_socket_addr(&socket_addr),
+                              inner_name,
+                              render_inner(&listener));
         assert_eq!(format!("{:?}", listener), compare);
 
-        let stream = t!(TcpStream::connect(&("localhost",
-                                                 socket_addr.port())));
-        let stream_inner = stream.0.socket().as_inner();
-        let compare = format!("TcpStream {{ addr: {:?}, \
-                              peer: {:?}, {}: {:?} }}",
-                              stream.local_addr().unwrap(),
-                              stream.peer_addr().unwrap(),
-                              name,
-                              stream_inner);
+        let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
+        let compare = format!("TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
+                              render_socket_addr(&stream.local_addr().unwrap()),
+                              render_socket_addr(&stream.peer_addr().unwrap()),
+                              inner_name,
+                              render_inner(&stream));
         assert_eq!(format!("{:?}", stream), compare);
     }
 
-    // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
+    // FIXME: re-enabled openbsd tests once their socket timeout code
     //        no longer has rounding errors.
-    #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
+    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     #[test]
     fn timeouts() {
         let addr = next_test_ip4();
@@ -1601,6 +1626,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_read_timeout() {
         let addr = next_test_ip4();
         let listener = t!(TcpListener::bind(&addr));
@@ -1618,6 +1644,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_read_with_timeout() {
         let addr = next_test_ip4();
         let listener = t!(TcpListener::bind(&addr));
@@ -1661,6 +1688,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn nodelay() {
         let addr = next_test_ip4();
         let _listener = t!(TcpListener::bind(&addr));
@@ -1675,6 +1703,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn ttl() {
         let ttl = 100;
 
@@ -1691,6 +1720,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn set_nonblocking() {
         let addr = next_test_ip4();
         let listener = t!(TcpListener::bind(&addr));
@@ -1712,6 +1742,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn peek() {
         each_ip(&mut |addr| {
             let (txdone, rxdone) = channel();
@@ -1743,6 +1774,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn connect_timeout_valid() {
         let listener = TcpListener::bind("127.0.0.1:0").unwrap();
         let addr = listener.local_addr().unwrap();
diff --git a/src/libstd/net/test.rs b/src/libstd/net/test.rs
index 89fefd9d1d5..e2991cbdd88 100644
--- a/src/libstd/net/test.rs
+++ b/src/libstd/net/test.rs
@@ -36,12 +36,16 @@ pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
 // all want to use ports. This function figures out which workspace
 // it is running in and assigns a port range based on it.
 fn base_port() -> u16 {
-    let cwd = env::current_dir().unwrap();
+    let cwd = if cfg!(target_env = "sgx") {
+        String::from("sgx")
+    } else {
+        env::current_dir().unwrap().into_os_string().into_string().unwrap()
+    };
     let dirs = ["32-opt", "32-nopt",
                 "musl-64-opt", "cross-opt",
                 "64-opt", "64-nopt", "64-opt-vg", "64-debug-opt",
-                "all-opt", "snap3", "dist"];
+                "all-opt", "snap3", "dist", "sgx"];
     dirs.iter().enumerate().find(|&(_, dir)| {
-        cwd.to_str().unwrap().contains(dir)
+        cwd.contains(dir)
     }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600
 }
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index edc9d665444..c430e103951 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -180,6 +180,37 @@ impl UdpSocket {
         }
     }
 
+    /// Returns the socket address of the remote peer this socket was connected to.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(udp_peer_addr)]
+    /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// socket.connect("192.168.0.1:41203").expect("couldn't connect to address");
+    /// assert_eq!(socket.peer_addr().unwrap(),
+    ///            SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203)));
+    /// ```
+    ///
+    /// If the socket isn't connected, it will return a [`NotConnected`] error.
+    ///
+    /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected
+    ///
+    /// ```no_run
+    /// #![feature(udp_peer_addr)]
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// assert_eq!(socket.peer_addr().unwrap_err().kind(),
+    ///            ::std::io::ErrorKind::NotConnected);
+    /// ```
+    #[unstable(feature = "udp_peer_addr", issue = "59127")]
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        self.0.peer_addr()
+    }
+
     /// Returns the socket address that this socket was created from.
     ///
     /// # Examples
@@ -391,7 +422,7 @@ impl UdpSocket {
     /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
     ///
     /// If enabled, multicast packets will be looped back to the local socket.
-    /// Note that this may not have any affect on IPv6 sockets.
+    /// Note that this may not have any effect on IPv6 sockets.
     ///
     /// # Examples
     ///
@@ -433,7 +464,7 @@ impl UdpSocket {
     /// this socket. The default value is 1 which means that multicast packets
     /// don't leave the local network unless explicitly requested.
     ///
-    /// Note that this may not have any affect on IPv6 sockets.
+    /// Note that this may not have any effect on IPv6 sockets.
     ///
     /// # Examples
     ///
@@ -801,12 +832,12 @@ impl IntoInner<net_imp::UdpSocket> for UdpSocket {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for UdpSocket {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::ErrorKind;
     use crate::net::*;
@@ -865,7 +896,7 @@ mod tests {
     }
 
     #[test]
-    fn socket_name_ip4() {
+    fn socket_name() {
         each_ip(&mut |addr, _| {
             let server = t!(UdpSocket::bind(&addr));
             assert_eq!(addr, t!(server.local_addr()));
@@ -873,6 +904,16 @@ mod tests {
     }
 
     #[test]
+    fn socket_peer() {
+        each_ip(&mut |addr1, addr2| {
+            let server = t!(UdpSocket::bind(&addr1));
+            assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected);
+            t!(server.connect(&addr2));
+            assert_eq!(addr2, t!(server.peer_addr()));
+        })
+    }
+
+    #[test]
     fn udp_clone_smoke() {
         each_ip(&mut |addr1, addr2| {
             let sock1 = t!(UdpSocket::bind(&addr1));
@@ -983,9 +1024,9 @@ mod tests {
         assert_eq!(format!("{:?}", udpsock), compare);
     }
 
-    // FIXME: re-enabled bitrig/openbsd/netbsd tests once their socket timeout code
+    // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
     //        no longer has rounding errors.
-    #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
+    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)]
     #[test]
     fn timeouts() {
         let addr = next_test_ip4();
diff --git a/src/libstd/num.rs b/src/libstd/num.rs
index 828d5720eec..2a2ca0b5237 100644
--- a/src/libstd/num.rs
+++ b/src/libstd/num.rs
@@ -13,6 +13,14 @@ pub use core::num::Wrapping;
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
+#[stable(feature = "signed_nonzero", since = "1.34.0")]
+pub use core::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize};
+
+#[unstable(feature = "int_error_matching",
+           reason = "it can be useful to match errors when making error messages \
+                     for integer parsing",
+           issue = "22639")]
+pub use core::num::IntErrorKind;
 
 #[cfg(test)] use crate::fmt;
 #[cfg(test)] use crate::ops::{Add, Sub, Mul, Div, Rem};
diff --git a/src/libstd/os/android/fs.rs b/src/libstd/os/android/fs.rs
index 9b24f86204b..90fdee567ae 100644
--- a/src/libstd/os/android/fs.rs
+++ b/src/libstd/os/android/fs.rs
@@ -116,4 +116,3 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_blocks as u64
     }
 }
-
diff --git a/src/libstd/os/android/raw.rs b/src/libstd/os/android/raw.rs
index acf5ca1e429..946a77cbfd3 100644
--- a/src/libstd/os/android/raw.rs
+++ b/src/libstd/os/android/raw.rs
@@ -217,4 +217,3 @@ mod arch {
         __unused: [c_long; 3],
     }
 }
-
diff --git a/src/libstd/os/dragonfly/fs.rs b/src/libstd/os/dragonfly/fs.rs
index ba38660224f..ba3d8d7867d 100644
--- a/src/libstd/os/dragonfly/fs.rs
+++ b/src/libstd/os/dragonfly/fs.rs
@@ -131,4 +131,3 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_lspare as u32
     }
 }
-
diff --git a/src/libstd/os/fortanix_sgx/mod.rs b/src/libstd/os/fortanix_sgx/mod.rs
index bca22e717d7..4e30b1edd15 100644
--- a/src/libstd/os/fortanix_sgx/mod.rs
+++ b/src/libstd/os/fortanix_sgx/mod.rs
@@ -43,3 +43,8 @@ pub mod mem {
 }
 
 pub use crate::sys::ext::{io, arch, ffi};
+
+/// Functions for querying thread-related information.
+pub mod thread {
+    pub use crate::sys::abi::thread::current;
+}
diff --git a/src/libstd/os/freebsd/fs.rs b/src/libstd/os/freebsd/fs.rs
index 4cc3a4b91fb..cfe8d575c67 100644
--- a/src/libstd/os/freebsd/fs.rs
+++ b/src/libstd/os/freebsd/fs.rs
@@ -141,4 +141,3 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_lspare as u32
     }
 }
-
diff --git a/src/libstd/os/ios/fs.rs b/src/libstd/os/ios/fs.rs
index 7b625f5e3fe..9bdfa8e690b 100644
--- a/src/libstd/os/ios/fs.rs
+++ b/src/libstd/os/ios/fs.rs
@@ -141,4 +141,3 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_lspare as u32
     }
 }
-
diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs
index ec5e9837076..78321ac3185 100644
--- a/src/libstd/os/linux/fs.rs
+++ b/src/libstd/os/linux/fs.rs
@@ -34,9 +34,10 @@ pub trait MetadataExt {
     /// }
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
-    #[rustc_deprecated(since = "1.8.0",
-                       reason = "deprecated in favor of the accessor \
-                                 methods of this trait")]
+    #[rustc_deprecated(
+        since = "1.8.0",
+        reason = "other methods of this trait are now prefered"
+    )]
     #[allow(deprecated)]
     fn as_raw_stat(&self) -> &raw::stat;
 
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index 77eeacb4b47..21e1cf8a22b 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -147,6 +147,62 @@ mod arch {
     }
 }
 
+#[cfg(target_arch = "hexagon")]
+mod arch {
+    use crate::os::raw::{c_long, c_int, c_longlong, culonglong};
+
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = c_longlong;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = c_long;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = c_ulonglong;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = c_uint;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = c_longlong;
+    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = c_long;
+
+    #[repr(C)]
+    #[derive(Clone)]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub struct stat {
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_dev: ::dev_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ino: ::c_ulonglong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mode: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_nlink: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_uid: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_gid: ::c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_rdev: ::c_ulonglong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad1: ::c_ulong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_size: ::c_longlong,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blksize: ::blksize_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad2: ::c_int,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_blocks: ::blkcnt_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: ::time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime_nsec: ::c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime: ::time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_mtime_nsec: ::c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime: ::time_t,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_ctime_nsec: ::c_long,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad3: [::c_int;2],
+    }
+}
+
 #[cfg(any(target_arch = "mips64",
           target_arch = "s390x",
           target_arch = "sparc64"))]
diff --git a/src/libstd/os/macos/fs.rs b/src/libstd/os/macos/fs.rs
index 1bd66ad4c76..bf951ee18c9 100644
--- a/src/libstd/os/macos/fs.rs
+++ b/src/libstd/os/macos/fs.rs
@@ -147,4 +147,3 @@ impl MetadataExt for Metadata {
         [qspare[0] as u64, qspare[1] as u64]
     }
 }
-
diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs
index 5cce3df71d6..fcd81f0a1b2 100644
--- a/src/libstd/os/mod.rs
+++ b/src/libstd/os/mod.rs
@@ -3,7 +3,7 @@
 #![stable(feature = "os", since = "1.0.0")]
 #![allow(missing_docs, nonstandard_style, missing_debug_implementations)]
 
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(rustdoc)] {
 
         // When documenting libstd we want to show unix/windows/linux modules as
@@ -24,7 +24,7 @@ cfg_if! {
         // If we're not documenting libstd then we just expose the main modules
         // as we otherwise would.
 
-        #[cfg(any(target_os = "redox", unix))]
+        #[cfg(any(target_os = "redox", unix, target_os = "vxworks"))]
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use crate::sys::ext as unix;
 
@@ -39,7 +39,6 @@ cfg_if! {
 }
 
 #[cfg(target_os = "android")]    pub mod android;
-#[cfg(target_os = "bitrig")]     pub mod bitrig;
 #[cfg(target_os = "dragonfly")]  pub mod dragonfly;
 #[cfg(target_os = "freebsd")]    pub mod freebsd;
 #[cfg(target_os = "haiku")]      pub mod haiku;
@@ -51,6 +50,9 @@ cfg_if! {
 #[cfg(target_os = "emscripten")] pub mod emscripten;
 #[cfg(target_os = "fuchsia")]    pub mod fuchsia;
 #[cfg(target_os = "hermit")]     pub mod hermit;
+#[cfg(target_os = "redox")]      pub mod redox;
+#[cfg(target_os = "wasi")]       pub mod wasi;
+#[cfg(target_os = "vxworks")]    pub mod vxworks;
 #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] pub mod fortanix_sgx;
 
 pub mod raw;
diff --git a/src/libstd/os/netbsd/fs.rs b/src/libstd/os/netbsd/fs.rs
index 6dffb70b5dc..dedfc6390ce 100644
--- a/src/libstd/os/netbsd/fs.rs
+++ b/src/libstd/os/netbsd/fs.rs
@@ -136,4 +136,3 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_flags as u32
     }
 }
-
diff --git a/src/libstd/os/openbsd/fs.rs b/src/libstd/os/openbsd/fs.rs
index 73f9757f3b7..1c019159be0 100644
--- a/src/libstd/os/openbsd/fs.rs
+++ b/src/libstd/os/openbsd/fs.rs
@@ -136,4 +136,3 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_flags as u32
     }
 }
-
diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs
index e9043b4b40d..0761c50f4b2 100644
--- a/src/libstd/os/raw/mod.rs
+++ b/src/libstd/os/raw/mod.rs
@@ -8,9 +8,11 @@
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
-#[doc(include = "os/raw/char.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
 #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                        target_arch = "arm",
+                                       target_arch = "hexagon",
                                        target_arch = "powerpc",
                                        target_arch = "powerpc64",
                                        target_arch = "s390x")),
@@ -25,11 +27,17 @@
                                         target_arch = "arm",
                                         target_arch = "powerpc")),
           all(target_os = "openbsd", target_arch = "aarch64"),
+          all(target_os = "vxworks", any(target_arch = "aarch64",
+                                         target_arch = "arm",
+                                         target_arch = "powerpc64",
+                                         target_arch = "powerpc")),
           all(target_os = "fuchsia", target_arch = "aarch64")))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
-#[doc(include = "os/raw/char.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
 #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                            target_arch = "arm",
+                                           target_arch = "hexagon",
                                            target_arch = "powerpc",
                                            target_arch = "powerpc64",
                                            target_arch = "s390x")),
@@ -44,39 +52,57 @@
                                             target_arch = "arm",
                                             target_arch = "powerpc")),
               all(target_os = "openbsd", target_arch = "aarch64"),
+              all(target_os = "vxworks", any(target_arch = "aarch64",
+                                             target_arch = "arm",
+                                             target_arch = "powerpc64",
+                                             target_arch = "powerpc")),
               all(target_os = "fuchsia", target_arch = "aarch64"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
-#[doc(include = "os/raw/schar.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "schar.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
-#[doc(include = "os/raw/uchar.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
-#[doc(include = "os/raw/short.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "short.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
-#[doc(include = "os/raw/ushort.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
-#[doc(include = "os/raw/int.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "int.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
-#[doc(include = "os/raw/uint.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "uint.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
-#[doc(include = "os/raw/long.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
-#[doc(include = "os/raw/ulong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
 #[cfg(any(target_pointer_width = "32", windows))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
-#[doc(include = "os/raw/long.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
-#[doc(include = "os/raw/ulong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
 #[cfg(all(target_pointer_width = "64", not(windows)))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
-#[doc(include = "os/raw/longlong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
-#[doc(include = "os/raw/ulonglong.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
-#[doc(include = "os/raw/float.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "float.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
-#[doc(include = "os/raw/double.md")]
+#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))]
+#[cfg_attr(not(bootstrap), doc(include = "double.md"))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;
 
 #[stable(feature = "raw_os", since = "1.1.0")]
diff --git a/src/libstd/os/redox/fs.rs b/src/libstd/os/redox/fs.rs
new file mode 100644
index 00000000000..80a12907619
--- /dev/null
+++ b/src/libstd/os/redox/fs.rs
@@ -0,0 +1,383 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+#[allow(deprecated)]
+use crate::os::redox::raw;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    /// Gain a reference to the underlying `stat` structure which contains
+    /// the raw information returned by the OS.
+    ///
+    /// The contents of the returned [`stat`] are **not** consistent across
+    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
+    /// cross-Unix abstractions contained within the raw stat.
+    ///
+    /// [`stat`]: ../../../../std/os/redox/raw/struct.stat.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let stat = meta.as_raw_stat();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    #[rustc_deprecated(since = "1.8.0",
+                       reason = "deprecated in favor of the accessor \
+                                 methods of this trait")]
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat;
+
+    /// Returns the device ID on which this file resides.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_dev());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    /// Returns the inode number.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_ino());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    /// Returns the file type and mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_mode());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    /// Returns the number of hard links to file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_nlink());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    /// Returns the user ID of the file owner.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_uid());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    /// Returns the group ID of the file owner.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_gid());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    /// Returns the device ID that this file represents. Only relevant for special file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_rdev());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
+    ///
+    /// The size of a symbolic link is the length of the pathname it contains,
+    /// without a terminating null byte.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_size());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    /// Returns the last access time of the file, in seconds since Unix Epoch.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_atime());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    /// Returns the last access time of the file, in nanoseconds since [`st_atime`].
+    ///
+    /// [`st_atime`]: #tymethod.st_atime
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_atime_nsec());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    /// Returns the last modification time of the file, in seconds since Unix Epoch.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_mtime());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`].
+    ///
+    /// [`st_mtime`]: #tymethod.st_mtime
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_mtime_nsec());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    /// Returns the last status change time of the file, in seconds since Unix Epoch.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_ctime());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`].
+    ///
+    /// [`st_ctime`]: #tymethod.st_ctime
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_ctime_nsec());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    /// Returns the "preferred" blocksize for efficient filesystem I/O.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_blksize());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    /// Returns the number of blocks allocated to the file, 512-byte units.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::io;
+    /// use std::os::redox::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     println!("{}", meta.st_blocks());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat {
+        unsafe {
+            &*(self.as_inner().as_inner() as *const libc::stat
+                                          as *const raw::stat)
+        }
+    }
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atime as i64
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atime_nsec as i64
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime as i64
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime_nsec as i64
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime as i64
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime_nsec as i64
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+}
diff --git a/src/libstd/os/bitrig/mod.rs b/src/libstd/os/redox/mod.rs
index 0bc105bb2b4..c60da5926da 100644
--- a/src/libstd/os/bitrig/mod.rs
+++ b/src/libstd/os/redox/mod.rs
@@ -1,4 +1,4 @@
-//! Bitrig-specific definitions
+//! Redox-specific definitions
 
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
diff --git a/src/libstd/os/bitrig/raw.rs b/src/libstd/os/redox/raw.rs
index c966d5a8e5b..23d8ff7694b 100644
--- a/src/libstd/os/bitrig/raw.rs
+++ b/src/libstd/os/redox/raw.rs
@@ -1,4 +1,4 @@
-//! Bitrig-specific raw type definitions
+//! Redox-specific raw type definitions
 
 #![stable(feature = "raw_ext", since = "1.1.0")]
 #![rustc_deprecated(since = "1.8.0",
@@ -7,65 +7,61 @@
                               crates.io should be used instead for the correct \
                               definitions")]
 #![allow(deprecated)]
+#![allow(missing_debug_implementations)]
 
-use crate::os::raw::c_long;
-use crate::os::unix::raw::{uid_t, gid_t};
+use crate::os::raw::{c_char, c_int, c_long, c_ulong, c_void};
 
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = c_long;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type gid_t = c_int;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = c_int;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type uid_t = c_int;
 
 #[stable(feature = "pthread_t", since = "1.8.0")]
-pub type pthread_t = usize;
+pub type pthread_t = *mut c_void;
+
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = c_ulong;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = c_ulong;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = c_ulong;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = c_ulong;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = c_long;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = c_long;
 
 #[repr(C)]
 #[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mode: u32,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_dev: i32,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ino: u64,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_nlink: u32,
+    pub st_dev: dev_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_uid: u32,
+    pub st_ino: ino_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_gid: u32,
+    pub st_nlink: nlink_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_rdev: i32,
+    pub st_mode: mode_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_atime: i64,
+    pub st_uid: uid_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_atime_nsec: i64,
+    pub st_gid: gid_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mtime: u64,
+    pub st_rdev: dev_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mtime_nsec: i64,
+    pub st_size: off_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ctime: i64,
+    pub st_blksize: blksize_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ctime_nsec: i64,
+    pub st_blocks: blkcnt_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_size: i64,
+    pub st_atime: time_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_blocks: i64,
+    pub st_atime_nsec: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_blksize: u32,
+    pub st_mtime: time_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_flags: u32,
+    pub st_mtime_nsec: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_gen: u32,
+    pub st_ctime: time_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_birthtime: i64,
+    pub st_ctime_nsec: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_birthtime_nsec: i64,
+    pub _pad: [c_char; 24],
 }
diff --git a/src/libstd/os/bitrig/fs.rs b/src/libstd/os/vxworks/fs.rs
index 849d4aa67f2..57ab4fb943e 100644
--- a/src/libstd/os/bitrig/fs.rs
+++ b/src/libstd/os/vxworks/fs.rs
@@ -3,27 +3,10 @@
 use crate::fs::Metadata;
 use crate::sys_common::AsInner;
 
-#[allow(deprecated)]
-use crate::os::bitrig::raw;
-
-/// OS-specific extensions to [`fs::Metadata`].
 ///
 /// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
-    /// Gain a reference to the underlying `stat` structure which contains
-    /// the raw information returned by the OS.
-    ///
-    /// The contents of the returned `stat` are **not** consistent across
-    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
-    /// cross-Unix abstractions contained within the raw stat.
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    #[rustc_deprecated(since = "1.8.0",
-                       reason = "deprecated in favor of the accessor \
-                                 methods of this trait")]
-    #[allow(deprecated)]
-    fn as_raw_stat(&self) -> &raw::stat;
-
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_dev(&self) -> u64;
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
@@ -43,38 +26,19 @@ pub trait MetadataExt {
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_atime(&self) -> i64;
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_atime_nsec(&self) -> i64;
-    #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_mtime(&self) -> i64;
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_mtime_nsec(&self) -> i64;
-    #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_ctime(&self) -> i64;
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_ctime_nsec(&self) -> i64;
-    #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_birthtime(&self) -> i64;
-    #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_birthtime_nsec(&self) -> i64;
-    #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_blksize(&self) -> u64;
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_blocks(&self) -> u64;
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_flags(&self) -> u32;
-    #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_gen(&self) -> u32;
+    fn st_attrib(&self) -> u8;
 }
 
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 impl MetadataExt for Metadata {
-    #[allow(deprecated)]
-    fn as_raw_stat(&self) -> &raw::stat {
-        unsafe {
-            &*(self.as_inner().as_inner() as *const libc::stat
-                                          as *const raw::stat)
-        }
-    }
     fn st_dev(&self) -> u64 {
         self.as_inner().as_inner().st_dev as u64
     }
@@ -102,38 +66,19 @@ impl MetadataExt for Metadata {
     fn st_atime(&self) -> i64 {
         self.as_inner().as_inner().st_atime as i64
     }
-    fn st_atime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_atime_nsec as i64
-    }
     fn st_mtime(&self) -> i64 {
         self.as_inner().as_inner().st_mtime as i64
     }
-    fn st_mtime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_mtime_nsec as i64
-    }
     fn st_ctime(&self) -> i64 {
         self.as_inner().as_inner().st_ctime as i64
     }
-    fn st_ctime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_ctime_nsec as i64
-    }
-    fn st_birthtime(&self) -> i64 {
-        self.as_inner().as_inner().st_birthtime as i64
-    }
-    fn st_birthtime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_birthtime_nsec as i64
-    }
     fn st_blksize(&self) -> u64 {
         self.as_inner().as_inner().st_blksize as u64
     }
     fn st_blocks(&self) -> u64 {
         self.as_inner().as_inner().st_blocks as u64
     }
-    fn st_gen(&self) -> u32 {
-        self.as_inner().as_inner().st_gen as u32
-    }
-    fn st_flags(&self) -> u32 {
-        self.as_inner().as_inner().st_flags as u32
+    fn st_attrib(&self) -> u8 {
+        self.as_inner().as_inner().st_attrib as u8
     }
 }
-
diff --git a/src/libstd/os/vxworks/mod.rs b/src/libstd/os/vxworks/mod.rs
new file mode 100644
index 00000000000..2255a103d35
--- /dev/null
+++ b/src/libstd/os/vxworks/mod.rs
@@ -0,0 +1,6 @@
+//! VxWorks-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod raw;
+pub mod fs;
diff --git a/src/libstd/os/vxworks/raw.rs b/src/libstd/os/vxworks/raw.rs
new file mode 100644
index 00000000000..ae0560a5a92
--- /dev/null
+++ b/src/libstd/os/vxworks/raw.rs
@@ -0,0 +1,7 @@
+//! VxWorks-specific raw type definitions
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::os::raw::{c_ulong};
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = c_ulong;
diff --git a/src/libstd/os/wasi.rs b/src/libstd/os/wasi.rs
new file mode 100644
index 00000000000..d25b8d39ed6
--- /dev/null
+++ b/src/libstd/os/wasi.rs
@@ -0,0 +1,6 @@
+//! WASI-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::sys::ext::*;
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 6a16414c141..1d4fd98dd75 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -4,6 +4,7 @@
 
 use crate::any::Any;
 use crate::cell::UnsafeCell;
+use crate::collections;
 use crate::fmt;
 use crate::future::Future;
 use crate::pin::Pin;
@@ -12,7 +13,7 @@ use crate::panicking;
 use crate::ptr::{Unique, NonNull};
 use crate::rc::Rc;
 use crate::sync::{Arc, Mutex, RwLock, atomic};
-use crate::task::{Waker, Poll};
+use crate::task::{Context, Poll};
 use crate::thread::Result;
 
 #[stable(feature = "panic_hooks", since = "1.10.0")]
@@ -285,6 +286,11 @@ impl RefUnwindSafe for atomic::AtomicBool {}
 #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
 impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {}
 
+// https://github.com/rust-lang/rust/issues/62301
+#[stable(feature = "hashbrown", since = "1.36.0")]
+impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S>
+    where K: UnwindSafe, V: UnwindSafe, S: UnwindSafe {}
+
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T> Deref for AssertUnwindSafe<T> {
     type Target = T;
@@ -312,20 +318,20 @@ impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("AssertUnwindSafe")
             .field(&self.0)
             .finish()
     }
 }
 
-#[unstable(feature = "futures_api", issue = "50547")]
+#[stable(feature = "futures_api", since = "1.36.0")]
 impl<F: Future> Future for AssertUnwindSafe<F> {
     type Output = F::Output;
 
-    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) };
-        F::poll(pinned_field, waker)
+        F::poll(pinned_field, cx)
     }
 }
 
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index eae885602d3..952fd9ebfdf 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -51,7 +51,7 @@ extern {
 #[derive(Copy, Clone)]
 enum Hook {
     Default,
-    Custom(*mut (dyn Fn(&PanicInfo) + 'static + Sync + Send)),
+    Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
 }
 
 static HOOK_LOCK: RWLock = RWLock::new();
@@ -91,7 +91,7 @@ static mut HOOK: Hook = Hook::Default;
 /// panic!("Normal panic");
 /// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub fn set_hook(hook: Box<dyn Fn(&PanicInfo) + 'static + Sync + Send>) {
+pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
     if thread::panicking() {
         panic!("cannot modify the panic hook from a panicking thread");
     }
@@ -103,7 +103,9 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo) + 'static + Sync + Send>) {
         HOOK_LOCK.write_unlock();
 
         if let Hook::Custom(ptr) = old_hook {
-            Box::from_raw(ptr);
+            #[allow(unused_must_use)] {
+                Box::from_raw(ptr);
+            }
         }
     }
 }
@@ -136,7 +138,7 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo) + 'static + Sync + Send>) {
 /// panic!("Normal panic");
 /// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub fn take_hook() -> Box<dyn Fn(&PanicInfo) + 'static + Sync + Send> {
+pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
     if thread::panicking() {
         panic!("cannot modify the panic hook from a panicking thread");
     }
@@ -154,7 +156,7 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo) + 'static + Sync + Send> {
     }
 }
 
-fn default_hook(info: &PanicInfo) {
+fn default_hook(info: &PanicInfo<'_>) {
     #[cfg(feature = "backtrace")]
     use crate::sys_common::backtrace;
 
@@ -171,7 +173,8 @@ fn default_hook(info: &PanicInfo) {
         }
     };
 
-    let location = info.location().unwrap();  // The current implementation always returns Some
+    // The current implementation always returns `Some`.
+    let location = info.location().unwrap();
 
     let msg = match info.payload().downcast_ref::<&'static str>() {
         Some(s) => *s,
@@ -196,7 +199,7 @@ fn default_hook(info: &PanicInfo) {
             if let Some(format) = log_backtrace {
                 let _ = backtrace::print(err, format);
             } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
-                let _ = writeln!(err, "note: Run with `RUST_BACKTRACE=1` \
+                let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \
                                        environment variable to display a backtrace.");
             }
         }
@@ -304,7 +307,7 @@ pub fn panicking() -> bool {
 #[cfg(not(test))]
 #[panic_handler]
 #[unwind(allowed)]
-pub fn rust_begin_panic(info: &PanicInfo) -> ! {
+pub fn rust_begin_panic(info: &PanicInfo<'_>) -> ! {
     continue_panic_fmt(&info)
 }
 
@@ -322,7 +325,7 @@ pub fn rust_begin_panic(info: &PanicInfo) -> ! {
 // otherwise avoid inlining because of it is cold path.
 #[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
 #[cfg_attr(    feature="panic_immediate_abort" ,inline)]
-pub fn begin_panic_fmt(msg: &fmt::Arguments,
+pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>,
                        file_line_col: &(&'static str, u32, u32)) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         unsafe { intrinsics::abort() }
@@ -336,7 +339,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
     continue_panic_fmt(&info)
 }
 
-fn continue_panic_fmt(info: &PanicInfo) -> ! {
+fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
     struct PanicPayload<'a> {
         inner: &'a fmt::Arguments<'a>,
         string: Option<String>,
@@ -361,7 +364,7 @@ fn continue_panic_fmt(info: &PanicInfo) -> ! {
 
     unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
         fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
-            let contents = mem::replace(self.fill(), String::new());
+            let contents = mem::take(self.fill());
             Box::into_raw(Box::new(contents))
         }
 
@@ -441,7 +444,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
 /// panics, panic hooks, and finally dispatching to the panic runtime to either
 /// abort or unwind.
 fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
-                        message: Option<&fmt::Arguments>,
+                        message: Option<&fmt::Arguments<'_>>,
                         file_line_col: &(&str, u32, u32)) -> ! {
     let (file, line, col) = *file_line_col;
 
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index ea3fcd8ce28..87c071b512a 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 //! Cross-platform path manipulation.
 //!
 //! This module provides two types, [`PathBuf`] and [`Path`][`Path`] (akin to [`String`]
@@ -315,7 +317,7 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
 
 // Detect scheme on Redox
 fn has_redox_scheme(s: &[u8]) -> bool {
-    cfg!(target_os = "redox") && s.split(|b| *b == b'/').next().unwrap_or(b"").contains(&b':')
+    cfg!(target_os = "redox") && s.contains(&b':')
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -323,7 +325,7 @@ fn has_redox_scheme(s: &[u8]) -> bool {
 ////////////////////////////////////////////////////////////////////////////////
 
 /// Says whether the first byte after the prefix is a separator.
-fn has_physical_root(s: &[u8], prefix: Option<Prefix>) -> bool {
+fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
     let path = if let Some(p) = prefix {
         &s[p.len()..]
     } else {
@@ -630,11 +632,11 @@ pub struct Iter<'a> {
 
 #[stable(feature = "path_components_debug", since = "1.13.0")]
 impl fmt::Debug for Components<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         struct DebugHelper<'a>(&'a Path);
 
         impl fmt::Debug for DebugHelper<'_> {
-            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 f.debug_list()
                     .entries(self.0.components())
                     .finish()
@@ -828,11 +830,11 @@ impl AsRef<OsStr> for Components<'_> {
 
 #[stable(feature = "path_iter_debug", since = "1.13.0")]
 impl fmt::Debug for Iter<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         struct DebugHelper<'a>(&'a Path);
 
         impl fmt::Debug for DebugHelper<'_> {
-            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 f.debug_list()
                     .entries(self.0.iter())
                     .finish()
@@ -1551,15 +1553,13 @@ impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
     fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
-        for p in iter {
-            self.push(p.as_ref())
-        }
+        iter.into_iter().for_each(move |p| self.push(p.as_ref()));
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for PathBuf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&**self, formatter)
     }
 }
@@ -1819,6 +1819,8 @@ impl Path {
     /// Yields a [`&str`] slice if the `Path` is valid unicode.
     ///
     /// This conversion may entail doing a check for UTF-8 validity.
+    /// Note that validation is performed because non-UTF-8 strings are
+    /// perfectly valid for some OS.
     ///
     /// [`&str`]: ../primitive.str.html
     ///
@@ -1857,7 +1859,7 @@ impl Path {
     /// Had `path` contained invalid unicode, the `to_string_lossy` call might
     /// have returned `"fo�.txt"`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn to_string_lossy(&self) -> Cow<str> {
+    pub fn to_string_lossy(&self) -> Cow<'_, str> {
         self.inner.to_string_lossy()
     }
 
@@ -1926,7 +1928,7 @@ impl Path {
         !self.is_absolute()
     }
 
-    fn prefix(&self) -> Option<Prefix> {
+    fn prefix(&self) -> Option<Prefix<'_>> {
         self.components().prefix
     }
 
@@ -2007,7 +2009,7 @@ impl Path {
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     /// [`parent`]: struct.Path.html#method.parent
     #[stable(feature = "path_ancestors", since = "1.28.0")]
-    pub fn ancestors(&self) -> Ancestors {
+    pub fn ancestors(&self) -> Ancestors<'_> {
         Ancestors {
             next: Some(&self),
         }
@@ -2305,7 +2307,7 @@ impl Path {
     /// [`Component`]: enum.Component.html
     /// [`CurDir`]: enum.Component.html#variant.CurDir
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn components(&self) -> Components {
+    pub fn components(&self) -> Components<'_> {
         let prefix = parse_prefix(self.as_os_str());
         Components {
             path: self.as_u8_slice(),
@@ -2339,7 +2341,7 @@ impl Path {
     /// assert_eq!(it.next(), None)
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter {
+    pub fn iter(&self) -> Iter<'_> {
         Iter { inner: self.components() }
     }
 
@@ -2358,7 +2360,7 @@ impl Path {
     /// println!("{}", path.display());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn display(&self) -> Display {
+    pub fn display(&self) -> Display<'_> {
         Display { path: self }
     }
 
@@ -2578,7 +2580,7 @@ impl AsRef<OsStr> for Path {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Path {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.inner, formatter)
     }
 }
@@ -2610,14 +2612,14 @@ pub struct Display<'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Display<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.path, f)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Display<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.path.inner.display(f)
     }
 }
@@ -2805,7 +2807,7 @@ impl_cmp_os_str!(Cow<'a, Path>, OsString);
 
 #[stable(since = "1.7.0", feature = "strip_prefix")]
 impl fmt::Display for StripPrefixError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.description().fmt(f)
     }
 }
@@ -2915,7 +2917,7 @@ mod tests {
 
         {
             let path: &Path = &pathbuf;
-            let borrowed_cow_path: Cow<Path> = path.into();
+            let borrowed_cow_path: Cow<'_, Path> = path.into();
 
             assert_eq!(static_cow_path, borrowed_cow_path);
         }
@@ -3801,7 +3803,7 @@ mod tests {
             });
         );
 
-        if cfg!(unix) {
+        if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
             tp!("", "foo", "foo");
             tp!("foo", "bar", "foo/bar");
             tp!("foo/", "bar", "foo/bar");
@@ -3960,7 +3962,7 @@ mod tests {
         tfn!("foo", "bar", "bar");
         tfn!("foo", "", "");
         tfn!("", "foo", "foo");
-        if cfg!(unix) {
+        if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
             tfn!(".", "foo", "./foo");
             tfn!("foo/", "bar", "bar");
             tfn!("foo/.", "bar", "bar");
@@ -4013,8 +4015,8 @@ mod tests {
         let mut owned: PathBuf = PathBuf::new();
         owned.push("foo");
         owned.push("bar");
-        let borrowed_cow: Cow<Path> = borrowed.into();
-        let owned_cow: Cow<Path> = owned.clone().into();
+        let borrowed_cow: Cow<'_, Path> = borrowed.into();
+        let owned_cow: Cow<'_, Path> = owned.clone().into();
 
         macro_rules! t {
             ($($current:expr),+) => {
diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs
index 551e982a3c6..3085c3d8296 100644
--- a/src/libstd/prelude/mod.rs
+++ b/src/libstd/prelude/mod.rs
@@ -71,9 +71,6 @@
 //! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
 //!   that may succeed or fail. Like [`Option`], its variants are exported as
 //!   well.
-//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
-//!   reasons, but shouldn't have to exist. It provides a few useful methods on
-//!   slices.
 //! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
 //! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
 //!   vector.
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index ce1e8e3319c..1c61f21f7df 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -7,9 +7,13 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 // Re-exported core operators
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
-pub use crate::marker::{Copy, Send, Sized, Sync, Unpin};
+pub use crate::marker::Copy;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)]
+pub use crate::marker::{Send, Sized, Sync, Unpin};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
@@ -20,15 +24,18 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
 pub use crate::mem::drop;
 
 // Re-exported types and traits
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::clone::Clone;
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::convert::{AsRef, AsMut, Into, From};
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::default::Default;
@@ -45,6 +52,58 @@ pub use crate::option::Option::{self, Some, None};
 #[doc(no_inline)]
 pub use crate::result::Result::{self, Ok, Err};
 
+// Re-exported built-in macros
+#[cfg(not(bootstrap))]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[doc(no_inline)]
+pub use core::prelude::v1::{
+    __rust_unstable_column,
+    asm,
+    assert,
+    cfg,
+    column,
+    compile_error,
+    concat,
+    concat_idents,
+    env,
+    file,
+    format_args,
+    format_args_nl,
+    global_asm,
+    include,
+    include_bytes,
+    include_str,
+    line,
+    log_syntax,
+    module_path,
+    option_env,
+    stringify,
+    trace_macros,
+};
+
+// FIXME: Attribute and derive macros are not documented because for them rustdoc generates
+// dead links which fail link checker testing.
+#[cfg(not(bootstrap))]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[allow(deprecated)]
+#[doc(hidden)]
+pub use core::prelude::v1::{
+    Clone,
+    Copy,
+    Debug,
+    Default,
+    Eq,
+    Hash,
+    Ord,
+    PartialEq,
+    PartialOrd,
+    RustcDecodable,
+    RustcEncodable,
+    bench,
+    global_allocator,
+    test,
+    test_case,
+};
 
 // The file so far is equivalent to src/libcore/prelude/v1.rs,
 // and below to src/liballoc/prelude.rs.
@@ -60,9 +119,6 @@ pub use crate::boxed::Box;
 pub use crate::borrow::ToOwned;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
-pub use crate::slice::SliceConcatExt;
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)]
 pub use crate::string::{String, ToString};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 6bb7f28efeb..d9a3da66a67 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -120,7 +120,7 @@ mod prim_bool { }
 /// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since
 /// converting a string into a string will never result in an error, the appropriate type is `!`.
 /// (Currently the type actually used is an enum with no variants, though this is only because `!`
-/// was added to Rust at a later date and it may change in the future). With an [`Err`] type of
+/// was added to Rust at a later date and it may change in the future.) With an [`Err`] type of
 /// `!`, if we have to call [`String::from_str`] for some reason the result will be a
 /// [`Result<String, !>`] which we can unpack like this:
 ///
@@ -204,10 +204,10 @@ mod prim_bool { }
 /// #![feature(never_type)]
 /// # use std::fmt;
 /// # trait Debug {
-/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
+/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
 /// # }
 /// impl Debug for ! {
-///     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+///     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///         *self
 ///     }
 /// }
@@ -279,7 +279,7 @@ mod prim_never { }
 ///
 /// As always, remember that a human intuition for 'character' may not map to
 /// Unicode's definitions. For example, despite looking similar, the 'é'
-/// character is one Unicode code point while 'é' is two Unicode code points:
+/// character is one Unicode code point while 'é' is two Unicode code points:
 ///
 /// ```
 /// let mut chars = "é".chars();
@@ -362,8 +362,13 @@ mod prim_unit { }
 ///
 /// *[See also the `std::ptr` module](ptr/index.html).*
 ///
-/// Working with raw pointers in Rust is uncommon,
-/// typically limited to a few patterns.
+/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns.
+/// Raw pointers can be unaligned or [`null`]. However, when a raw pointer is
+/// dereferenced (using the `*` operator), it must be non-null and aligned.
+///
+/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so
+/// [`write`] must be used if the type has drop glue and memory is not already
+/// initialized - otherwise `drop` would be called on the uninitialized memory.
 ///
 /// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
 /// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
@@ -442,6 +447,7 @@ mod prim_unit { }
 /// [`offset`]: ../std/primitive.pointer.html#method.offset
 /// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
 /// [`drop`]: ../std/mem/fn.drop.html
+/// [`write`]: ../std/ptr/fn.write.html
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer { }
 
@@ -482,8 +488,8 @@ mod prim_pointer { }
 /// an array. Indeed, this provides most of the API for working with arrays.
 /// Slices have a dynamic size and do not coerce to arrays.
 ///
-/// There is no way to move elements out of an array. See [`mem::replace`][replace]
-/// for an alternative.
+/// You can move elements out of an array with a slice pattern. If you want
+/// one element, see [`mem::replace`][replace].
 ///
 /// # Examples
 ///
@@ -525,6 +531,16 @@ mod prim_pointer { }
 /// for x in &array { }
 /// ```
 ///
+/// You can use a slice pattern to move elements out of an array:
+///
+/// ```
+/// fn move_away(_: String) { /* Do interesting things. */ }
+///
+/// let [john, roa] = ["John".to_string(), "Roa".to_string()];
+/// move_away(john);
+/// move_away(roa);
+/// ```
+///
 /// [slice]: primitive.slice.html
 /// [copy]: marker/trait.Copy.html
 /// [clone]: clone/trait.Clone.html
@@ -683,6 +699,10 @@ mod prim_str { }
 /// assert_eq!(tuple.2, 'c');
 /// ```
 ///
+/// The sequential nature of the tuple applies to its implementations of various
+/// traits.  For example, in `PartialOrd` and `Ord`, the elements are compared
+/// sequentially until the first non-equal set is found.
+///
 /// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
 ///
 /// # Trait implementations
@@ -877,9 +897,13 @@ mod prim_usize { }
 /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
 /// operators on a value, or by using a `ref` or `ref mut` pattern.
 ///
-/// For those familiar with pointers, a reference is just a pointer that is assumed to not be null.
-/// In fact, `Option<&T>` has the same memory representation as a nullable pointer, and can be
-/// passed across FFI boundaries as such.
+/// For those familiar with pointers, a reference is just a pointer that is assumed to be
+/// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
+/// `&bool` can only point to an allocation containing the integer values `1` (`true`) or `0`
+/// (`false`), but creating a `&bool` that points to an allocation containing
+/// the value `3` causes undefined behaviour.
+/// In fact, `Option<&T>` has the same memory representation as a
+/// nullable but aligned pointer, and can be passed across FFI boundaries as such.
 ///
 /// In most cases, references can be used much like the original value. Field access, method
 /// calling, and indexing work the same (save for mutability rules, of course). In addition, the
@@ -1022,6 +1046,11 @@ mod prim_ref { }
 /// [`FnMut`]: ops/trait.FnMut.html
 /// [`FnOnce`]: ops/trait.FnOnce.html
 ///
+/// Function pointers are pointers that point to *code*, not data. They can be called
+/// just like functions. Like references, function pointers are, among other things, assumed to
+/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
+/// pointers, make your type `Option<fn()>` with your required signature.
+///
 /// Plain function pointers are obtained by casting either plain functions, or closures that don't
 /// capture an environment:
 ///
@@ -1077,10 +1106,6 @@ mod prim_ref { }
 ///
 /// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
 ///
-/// Like references in rust, function pointers are assumed to not be null, so if you want to pass a
-/// function pointer over FFI and be able to accommodate null pointers, make your type
-/// `Option<fn()>` with your required signature.
-///
 /// Function pointers implement the following traits:
 ///
 /// * [`Clone`]
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 56840009344..000f80f99e7 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -8,7 +8,7 @@
 //!
 //! The [`Command`] struct is used to configure and spawn processes:
 //!
-//! ```
+//! ```no_run
 //! use std::process::Command;
 //!
 //! let output = Command::new("echo")
@@ -111,7 +111,7 @@ use crate::io::prelude::*;
 use crate::ffi::OsStr;
 use crate::fmt;
 use crate::fs;
-use crate::io::{self, Initializer};
+use crate::io::{self, Initializer, IoSlice, IoSliceMut};
 use crate::path::Path;
 use crate::str;
 use crate::sys::pipe::{read2, AnonPipe};
@@ -134,6 +134,18 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 /// the parent process wait until the child has actually exited before
 /// continuing.
 ///
+/// # Warning
+///
+/// On some system, calling [`wait`] or similar is necessary for the OS to
+/// release resources. A process that terminated but has not been waited on is
+/// still around as a "zombie". Leaving too many zombies around may exhaust
+/// global resources (for example process IDs).
+///
+/// The standard library does *not* automatically wait on child processes (not
+/// even if the `Child` is dropped), it is up to the application developer to do
+/// so. As a consequence, dropping `Child` handles without waiting on them first
+/// is not recommended in long-running applications.
+///
 /// # Examples
 ///
 /// ```should_panic
@@ -194,7 +206,7 @@ impl IntoInner<imp::Process> for Child {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Child {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Child")
             .field("stdin", &self.stdin)
             .field("stdout", &self.stdout)
@@ -225,6 +237,10 @@ impl Write for ChildStdin {
         self.inner.write(buf)
     }
 
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -246,7 +262,7 @@ impl FromInner<AnonPipe> for ChildStdin {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStdin {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("ChildStdin { .. }")
     }
 }
@@ -271,6 +287,11 @@ impl Read for ChildStdout {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -293,7 +314,7 @@ impl FromInner<AnonPipe> for ChildStdout {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStdout {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("ChildStdout { .. }")
     }
 }
@@ -318,6 +339,11 @@ impl Read for ChildStderr {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -340,7 +366,7 @@ impl FromInner<AnonPipe> for ChildStderr {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStderr {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("ChildStderr { .. }")
     }
 }
@@ -803,7 +829,7 @@ impl fmt::Debug for Command {
     /// Format the program and arguments of a Command for display. Any
     /// non-utf8 data is lossily converted using the utf8 replacement
     /// character.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.inner.fmt(f)
     }
 }
@@ -844,7 +870,7 @@ pub struct Output {
 // strings, otherwise it prints the byte sequence instead
 #[stable(feature = "process_output_debug", since = "1.7.0")]
 impl fmt::Debug for Output {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
         let stdout_utf8 = str::from_utf8(&self.stdout);
         let stdout_debug: &dyn fmt::Debug = match stdout_utf8 {
@@ -1002,7 +1028,7 @@ impl FromInner<imp::Stdio> for Stdio {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdio {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Stdio { .. }")
     }
 }
@@ -1127,10 +1153,13 @@ impl From<fs::File> for Stdio {
 ///
 /// This `struct` is used to represent the exit status of a child process.
 /// Child processes are created via the [`Command`] struct and their exit
-/// status is exposed through the [`status`] method.
+/// status is exposed through the [`status`] method, or the [`wait`] method
+/// of a [`Child`] process.
 ///
 /// [`Command`]: struct.Command.html
+/// [`Child`]: struct.Child.html
 /// [`status`]: struct.Command.html#method.status
+/// [`wait`]: struct.Child.html#method.wait
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ExitStatus(imp::ExitStatus);
@@ -1199,7 +1228,7 @@ impl FromInner<imp::ExitStatus> for ExitStatus {
 
 #[stable(feature = "process", since = "1.0.0")]
 impl fmt::Display for ExitStatus {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(f)
     }
 }
@@ -1621,7 +1650,7 @@ impl Termination for ExitCode {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::prelude::*;
 
@@ -1736,33 +1765,6 @@ mod tests {
         assert_eq!(out, "foobar\n");
     }
 
-
-    #[test]
-    #[cfg_attr(target_os = "android", ignore)]
-    #[cfg(unix)]
-    fn uid_works() {
-        use crate::os::unix::prelude::*;
-
-        let mut p = Command::new("/bin/sh")
-                            .arg("-c").arg("true")
-                            .uid(unsafe { libc::getuid() })
-                            .gid(unsafe { libc::getgid() })
-                            .spawn().unwrap();
-        assert!(p.wait().unwrap().success());
-    }
-
-    #[test]
-    #[cfg_attr(target_os = "android", ignore)]
-    #[cfg(unix)]
-    fn uid_to_root_fails() {
-        use crate::os::unix::prelude::*;
-
-        // if we're already root, this isn't a valid test. Most of the bots run
-        // as non-root though (android is an exception).
-        if unsafe { libc::getuid() == 0 } { return }
-        assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
-    }
-
     #[test]
     #[cfg_attr(target_os = "android", ignore)]
     fn test_process_status() {
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index a4205daba8b..23ba63a6109 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -59,7 +59,7 @@ pub struct BarrierWaitResult(bool);
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Barrier {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Barrier { .. }")
     }
 }
@@ -151,7 +151,7 @@ impl Barrier {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for BarrierWaitResult {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("BarrierWaitResult")
             .field("is_leader", &self.is_leader())
             .finish()
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 5ebb61754e1..aeff57716e8 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -36,7 +36,7 @@ impl WaitTimeoutResult {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///
     ///     // Let's wait 20 milliseconds before notifying the condvar.
     ///     thread::sleep(Duration::from_millis(20));
@@ -48,7 +48,7 @@ impl WaitTimeoutResult {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
     /// loop {
     ///     // Let's put a timeout on the condvar's wait.
@@ -94,7 +94,7 @@ impl WaitTimeoutResult {
 ///
 /// // Inside of our lock, spawn a new thread, and then wait for it to start.
 /// thread::spawn(move|| {
-///     let &(ref lock, ref cvar) = &*pair2;
+///     let (lock, cvar) = &*pair2;
 ///     let mut started = lock.lock().unwrap();
 ///     *started = true;
 ///     // We notify the condvar that the value has changed.
@@ -102,7 +102,7 @@ impl WaitTimeoutResult {
 /// });
 ///
 /// // Wait for the thread to start up.
-/// let &(ref lock, ref cvar) = &*pair;
+/// let (lock, cvar) = &*pair;
 /// let mut started = lock.lock().unwrap();
 /// while !*started {
 ///     started = cvar.wait(started).unwrap();
@@ -180,7 +180,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -188,9 +188,9 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
     ///     started = cvar.wait(started).unwrap();
     /// }
@@ -245,7 +245,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -253,8 +253,8 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// let (lock, cvar) = &*pair;
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
     /// ```
     #[unstable(feature = "wait_until", issue = "47960")]
@@ -301,7 +301,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -309,9 +309,9 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// loop {
     ///     let result = cvar.wait_timeout_ms(started, 10).unwrap();
     ///     // 10 milliseconds have passed, or maybe the value changed!
@@ -374,7 +374,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -382,9 +382,9 @@ impl Condvar {
     /// });
     ///
     /// // wait for the thread to start up
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // as long as the value inside the `Mutex` is false, we wait
+    /// // as long as the value inside the `Mutex<bool>` is `false`, we wait
     /// loop {
     ///     let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
     ///     // 10 milliseconds have passed, or maybe the value changed!
@@ -449,7 +449,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -457,7 +457,7 @@ impl Condvar {
     /// });
     ///
     /// // wait for the thread to start up
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let result = cvar.wait_timeout_until(
     ///     lock.lock().unwrap(),
     ///     Duration::from_millis(100),
@@ -508,7 +508,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -516,9 +516,9 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
     ///     started = cvar.wait(started).unwrap();
     /// }
@@ -548,7 +548,7 @@ impl Condvar {
     /// let pair2 = pair.clone();
     ///
     /// thread::spawn(move|| {
-    ///     let &(ref lock, ref cvar) = &*pair2;
+    ///     let (lock, cvar) = &*pair2;
     ///     let mut started = lock.lock().unwrap();
     ///     *started = true;
     ///     // We notify the condvar that the value has changed.
@@ -556,9 +556,9 @@ impl Condvar {
     /// });
     ///
     /// // Wait for the thread to start up.
-    /// let &(ref lock, ref cvar) = &*pair;
+    /// let (lock, cvar) = &*pair;
     /// let mut started = lock.lock().unwrap();
-    /// // As long as the value inside the `Mutex` is false, we wait.
+    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
     /// while !*started {
     ///     started = cvar.wait(started).unwrap();
     /// }
@@ -589,7 +589,7 @@ impl Condvar {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Condvar {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Condvar { .. }")
     }
 }
@@ -705,6 +705,7 @@ mod tests {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
@@ -724,6 +725,7 @@ mod tests {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_until_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
@@ -748,6 +750,7 @@ mod tests {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_until_wake() {
         let pair = Arc::new((Mutex::new(false), Condvar::new()));
         let pair_copy = pair.clone();
@@ -771,6 +774,7 @@ mod tests {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_wake() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs
index 809ee882698..e29faf18d83 100644
--- a/src/libstd/sync/mod.rs
+++ b/src/libstd/sync/mod.rs
@@ -163,6 +163,8 @@ pub use self::condvar::{Condvar, WaitTimeoutResult};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::mutex::{Mutex, MutexGuard};
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(bootstrap, allow(deprecated_in_future))]
+#[allow(deprecated)]
 pub use self::once::{Once, OnceState, ONCE_INIT};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use crate::sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 90c5c50c23b..69ecd201063 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 //! Multi-producer, single-consumer FIFO queue communication primitives.
 //!
 //! This module provides message-based communication over channels, concretely
@@ -114,7 +116,6 @@
 //! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
-#![allow(deprecated)] // for mpsc_select
 
 // A description of how Rust's channel implementation works
 //
@@ -261,6 +262,8 @@
 // believe that there is anything fundamental that needs to change about these
 // channels, however, in order to support a more efficient select().
 //
+// FIXME: Select is now removed, so these factors are ready to be cleaned up!
+//
 // # Conclusion
 //
 // And now that you've seen all the races that I found and attempted to fix,
@@ -273,18 +276,8 @@ use crate::mem;
 use crate::cell::UnsafeCell;
 use crate::time::{Duration, Instant};
 
-#[unstable(feature = "mpsc_select", issue = "27800")]
-pub use self::select::{Select, Handle};
-use self::select::StartResult;
-use self::select::StartResult::*;
-use self::blocking::SignalToken;
-
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod select_tests;
-
 mod blocking;
 mod oneshot;
-mod select;
 mod shared;
 mod stream;
 mod sync;
@@ -914,7 +907,7 @@ impl<T> Drop for Sender<T> {
 
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
 impl<T> fmt::Debug for Sender<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Sender").finish()
     }
 }
@@ -1005,7 +998,7 @@ impl<T> SyncSender<T> {
     /// thread::spawn(move || {
     ///     // This will return an error and send
     ///     // no message if the buffer is full
-    ///     sync_sender2.try_send(3).is_err();
+    ///     let _ = sync_sender2.try_send(3);
     /// });
     ///
     /// let mut msg;
@@ -1044,7 +1037,7 @@ impl<T> Drop for SyncSender<T> {
 
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
 impl<T> fmt::Debug for SyncSender<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("SyncSender").finish()
     }
 }
@@ -1463,7 +1456,7 @@ impl<T> Receiver<T> {
     /// assert_eq!(iter.next(), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter<T> {
+    pub fn iter(&self) -> Iter<'_, T> {
         Iter { rx: self }
     }
 
@@ -1506,84 +1499,12 @@ impl<T> Receiver<T> {
     /// assert_eq!(iter.next(), None);
     /// ```
     #[stable(feature = "receiver_try_iter", since = "1.15.0")]
-    pub fn try_iter(&self) -> TryIter<T> {
+    pub fn try_iter(&self) -> TryIter<'_, T> {
         TryIter { rx: self }
     }
 
 }
 
-impl<T> select::Packet for Receiver<T> {
-    fn can_recv(&self) -> bool {
-        loop {
-            let new_port = match *unsafe { self.inner() } {
-                Flavor::Oneshot(ref p) => {
-                    match p.can_recv() {
-                        Ok(ret) => return ret,
-                        Err(upgrade) => upgrade,
-                    }
-                }
-                Flavor::Stream(ref p) => {
-                    match p.can_recv() {
-                        Ok(ret) => return ret,
-                        Err(upgrade) => upgrade,
-                    }
-                }
-                Flavor::Shared(ref p) => return p.can_recv(),
-                Flavor::Sync(ref p) => return p.can_recv(),
-            };
-            unsafe {
-                mem::swap(self.inner_mut(),
-                          new_port.inner_mut());
-            }
-        }
-    }
-
-    fn start_selection(&self, mut token: SignalToken) -> StartResult {
-        loop {
-            let (t, new_port) = match *unsafe { self.inner() } {
-                Flavor::Oneshot(ref p) => {
-                    match p.start_selection(token) {
-                        oneshot::SelSuccess => return Installed,
-                        oneshot::SelCanceled => return Abort,
-                        oneshot::SelUpgraded(t, rx) => (t, rx),
-                    }
-                }
-                Flavor::Stream(ref p) => {
-                    match p.start_selection(token) {
-                        stream::SelSuccess => return Installed,
-                        stream::SelCanceled => return Abort,
-                        stream::SelUpgraded(t, rx) => (t, rx),
-                    }
-                }
-                Flavor::Shared(ref p) => return p.start_selection(token),
-                Flavor::Sync(ref p) => return p.start_selection(token),
-            };
-            token = t;
-            unsafe {
-                mem::swap(self.inner_mut(), new_port.inner_mut());
-            }
-        }
-    }
-
-    fn abort_selection(&self) -> bool {
-        let mut was_upgrade = false;
-        loop {
-            let result = match *unsafe { self.inner() } {
-                Flavor::Oneshot(ref p) => p.abort_selection(),
-                Flavor::Stream(ref p) => p.abort_selection(was_upgrade),
-                Flavor::Shared(ref p) => return p.abort_selection(was_upgrade),
-                Flavor::Sync(ref p) => return p.abort_selection(),
-            };
-            let new_port = match result { Ok(b) => return b, Err(p) => p };
-            was_upgrade = true;
-            unsafe {
-                mem::swap(self.inner_mut(),
-                          new_port.inner_mut());
-            }
-        }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = T;
@@ -1636,21 +1557,21 @@ impl<T> Drop for Receiver<T> {
 
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
 impl<T> fmt::Debug for Receiver<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Receiver").finish()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for SendError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "SendError(..)".fmt(f)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for SendError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "sending on a closed channel".fmt(f)
     }
 }
@@ -1668,7 +1589,7 @@ impl<T: Send> error::Error for SendError<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for TrySendError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             TrySendError::Full(..) => "Full(..)".fmt(f),
             TrySendError::Disconnected(..) => "Disconnected(..)".fmt(f),
@@ -1678,7 +1599,7 @@ impl<T> fmt::Debug for TrySendError<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for TrySendError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             TrySendError::Full(..) => {
                 "sending on a full channel".fmt(f)
@@ -1720,7 +1641,7 @@ impl<T> From<SendError<T>> for TrySendError<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for RecvError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "receiving on a closed channel".fmt(f)
     }
 }
@@ -1739,7 +1660,7 @@ impl error::Error for RecvError {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for TryRecvError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             TryRecvError::Empty => {
                 "receiving on an empty channel".fmt(f)
@@ -1781,7 +1702,7 @@ impl From<RecvError> for TryRecvError {
 
 #[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
 impl fmt::Display for RecvTimeoutError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             RecvTimeoutError::Timeout => {
                 "timed out waiting on channel".fmt(f)
@@ -1951,7 +1872,7 @@ mod tests {
         for _ in 0..10000 {
             assert_eq!(rx.recv().unwrap(), 1);
         }
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1977,7 +1898,7 @@ mod tests {
             });
         }
         drop(tx);
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1996,8 +1917,8 @@ mod tests {
                 tx2.send(1).unwrap();
             }
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        t1.join().ok().expect("thread panicked");
+        t2.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2011,7 +1932,7 @@ mod tests {
         for _ in 0..40 {
             tx.send(1).unwrap();
         }
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2026,8 +1947,8 @@ mod tests {
             tx1.send(1).unwrap();
             assert_eq!(rx2.recv().unwrap(), 2);
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        t1.join().ok().expect("thread panicked");
+        t2.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2225,6 +2146,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn oneshot_single_thread_recv_timeout() {
         let (tx, rx) = channel();
         tx.send(()).unwrap();
@@ -2235,6 +2157,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_two_threads() {
         let (tx, rx) = channel();
         let stress = stress_factor() + 100;
@@ -2265,6 +2188,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn recv_timeout_upgrade() {
         let (tx, rx) = channel::<()>();
         let timeout = Duration::from_millis(1);
@@ -2276,6 +2200,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_shared() {
         let (tx, rx) = channel();
         let stress = stress_factor() + 100;
@@ -2306,6 +2231,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn very_long_recv_timeout_wont_panic() {
         let (tx, rx) = channel::<()>();
         let join_handle = thread::spawn(move || {
@@ -2325,6 +2251,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn shared_recv_timeout() {
         let (tx, rx) = channel();
         let total = 5;
@@ -2550,6 +2477,7 @@ mod sync_tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn recv_timeout() {
         let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout));
@@ -2639,6 +2567,7 @@ mod sync_tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_two_threads() {
         let (tx, rx) = sync_channel::<i32>(0);
 
@@ -2662,6 +2591,7 @@ mod sync_tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_shared() {
         const AMT: u32 = 1000;
         const NTHREADS: u32 = 8;
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index 5c516d5de0f..e7a5cc46b31 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -24,7 +24,6 @@
 
 pub use self::Failure::*;
 pub use self::UpgradeResult::*;
-pub use self::SelectionResult::*;
 use self::MyUpgrade::*;
 
 use crate::sync::mpsc::Receiver;
@@ -66,12 +65,6 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
-    SelCanceled,
-    SelUpgraded(SignalToken, Receiver<T>),
-    SelSuccess,
-}
-
 enum MyUpgrade<T> {
     NothingSent,
     SendUsed,
@@ -264,71 +257,6 @@ impl<T> Packet<T> {
     // select implementation
     ////////////////////////////////////////////////////////////////////////////
 
-    // If Ok, the value is whether this port has data, if Err, then the upgraded
-    // port needs to be checked instead of this one.
-    pub fn can_recv(&self) -> Result<bool, Receiver<T>> {
-        unsafe {
-            match self.state.load(Ordering::SeqCst) {
-                EMPTY => Ok(false), // Welp, we tried
-                DATA => Ok(true),   // we have some un-acquired data
-                DISCONNECTED if (*self.data.get()).is_some() => Ok(true), // we have data
-                DISCONNECTED => {
-                    match ptr::replace(self.upgrade.get(), SendUsed) {
-                        // The other end sent us an upgrade, so we need to
-                        // propagate upwards whether the upgrade can receive
-                        // data
-                        GoUp(upgrade) => Err(upgrade),
-
-                        // If the other end disconnected without sending an
-                        // upgrade, then we have data to receive (the channel is
-                        // disconnected).
-                        up => { ptr::write(self.upgrade.get(), up); Ok(true) }
-                    }
-                }
-                _ => unreachable!(), // we're the "one blocker"
-            }
-        }
-    }
-
-    // Attempts to start selection on this port. This can either succeed, fail
-    // because there is data, or fail because there is an upgrade pending.
-    pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> {
-        unsafe {
-            let ptr = token.cast_to_usize();
-            match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) {
-                EMPTY => SelSuccess,
-                DATA => {
-                    drop(SignalToken::cast_from_usize(ptr));
-                    SelCanceled
-                }
-                DISCONNECTED if (*self.data.get()).is_some() => {
-                    drop(SignalToken::cast_from_usize(ptr));
-                    SelCanceled
-                }
-                DISCONNECTED => {
-                    match ptr::replace(self.upgrade.get(), SendUsed) {
-                        // The other end sent us an upgrade, so we need to
-                        // propagate upwards whether the upgrade can receive
-                        // data
-                        GoUp(upgrade) => {
-                            SelUpgraded(SignalToken::cast_from_usize(ptr), upgrade)
-                        }
-
-                        // If the other end disconnected without sending an
-                        // upgrade, then we have data to receive (the channel is
-                        // disconnected).
-                        up => {
-                            ptr::write(self.upgrade.get(), up);
-                            drop(SignalToken::cast_from_usize(ptr));
-                            SelCanceled
-                        }
-                    }
-                }
-                _ => unreachable!(), // we're the "one blocker"
-            }
-        }
-    }
-
     // Remove a previous selecting thread from this port. This ensures that the
     // blocked thread will no longer be visible to any other threads.
     //
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
deleted file mode 100644
index 19c94908645..00000000000
--- a/src/libstd/sync/mpsc/select.rs
+++ /dev/null
@@ -1,352 +0,0 @@
-//! Selection over an array of receivers
-//!
-//! This module contains the implementation machinery necessary for selecting
-//! over a number of receivers. One large goal of this module is to provide an
-//! efficient interface to selecting over any receiver of any type.
-//!
-//! This is achieved through an architecture of a "receiver set" in which
-//! receivers are added to a set and then the entire set is waited on at once.
-//! The set can be waited on multiple times to prevent re-adding each receiver
-//! to the set.
-//!
-//! Usage of this module is currently encouraged to go through the use of the
-//! `select!` macro. This macro allows naturally binding of variables to the
-//! received values of receivers in a much more natural syntax then usage of the
-//! `Select` structure directly.
-//!
-//! # Examples
-//!
-//! ```rust
-//! #![feature(mpsc_select)]
-//!
-//! use std::sync::mpsc::channel;
-//!
-//! let (tx1, rx1) = channel();
-//! let (tx2, rx2) = channel();
-//!
-//! tx1.send(1).unwrap();
-//! tx2.send(2).unwrap();
-//!
-//! select! {
-//!     val = rx1.recv() => {
-//!         assert_eq!(val.unwrap(), 1);
-//!     },
-//!     val = rx2.recv() => {
-//!         assert_eq!(val.unwrap(), 2);
-//!     }
-//! }
-//! ```
-
-#![allow(dead_code)]
-#![unstable(feature = "mpsc_select",
-            reason = "This implementation, while likely sufficient, is unsafe and \
-                      likely to be error prone. At some point in the future this \
-                      module will be removed.",
-            issue = "27800")]
-#![rustc_deprecated(since = "1.32.0",
-                    reason = "channel selection will be removed in a future release")]
-
-use core::cell::{Cell, UnsafeCell};
-use core::marker;
-use core::ptr;
-use core::usize;
-
-use crate::fmt;
-use crate::sync::mpsc::{Receiver, RecvError};
-use crate::sync::mpsc::blocking::{self, SignalToken};
-
-/// The "receiver set" of the select interface. This structure is used to manage
-/// a set of receivers which are being selected over.
-pub struct Select {
-    inner: UnsafeCell<SelectInner>,
-    next_id: Cell<usize>,
-}
-
-struct SelectInner {
-    head: *mut Handle<'static, ()>,
-    tail: *mut Handle<'static, ()>,
-}
-
-impl !marker::Send for Select {}
-
-/// A handle to a receiver which is currently a member of a `Select` set of
-/// receivers. This handle is used to keep the receiver in the set as well as
-/// interact with the underlying receiver.
-pub struct Handle<'rx, T:Send+'rx> {
-    /// The ID of this handle, used to compare against the return value of
-    /// `Select::wait()`.
-    id: usize,
-    selector: *mut SelectInner,
-    next: *mut Handle<'static, ()>,
-    prev: *mut Handle<'static, ()>,
-    added: bool,
-    packet: &'rx (dyn Packet+'rx),
-
-    // due to our fun transmutes, we be sure to place this at the end. (nothing
-    // previous relies on T)
-    rx: &'rx Receiver<T>,
-}
-
-struct Packets { cur: *mut Handle<'static, ()> }
-
-#[doc(hidden)]
-#[derive(PartialEq, Eq)]
-pub enum StartResult {
-    Installed,
-    Abort,
-}
-
-#[doc(hidden)]
-pub trait Packet {
-    fn can_recv(&self) -> bool;
-    fn start_selection(&self, token: SignalToken) -> StartResult;
-    fn abort_selection(&self) -> bool;
-}
-
-impl Select {
-    /// Creates a new selection structure. This set is initially empty.
-    ///
-    /// Usage of this struct directly can sometimes be burdensome, and usage is much easier through
-    /// the `select!` macro.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(mpsc_select)]
-    ///
-    /// use std::sync::mpsc::Select;
-    ///
-    /// let select = Select::new();
-    /// ```
-    pub fn new() -> Select {
-        Select {
-            inner: UnsafeCell::new(SelectInner {
-                head: ptr::null_mut(),
-                tail: ptr::null_mut(),
-            }),
-            next_id: Cell::new(1),
-        }
-    }
-
-    /// Creates a new handle into this receiver set for a new receiver. Note
-    /// that this does *not* add the receiver to the receiver set, for that you
-    /// must call the `add` method on the handle itself.
-    pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
-        let id = self.next_id.get();
-        self.next_id.set(id + 1);
-        Handle {
-            id,
-            selector: self.inner.get(),
-            next: ptr::null_mut(),
-            prev: ptr::null_mut(),
-            added: false,
-            rx,
-            packet: rx,
-        }
-    }
-
-    /// Waits for an event on this receiver set. The returned value is *not* an
-    /// index, but rather an ID. This ID can be queried against any active
-    /// `Handle` structures (each one has an `id` method). The handle with
-    /// the matching `id` will have some sort of event available on it. The
-    /// event could either be that data is available or the corresponding
-    /// channel has been closed.
-    pub fn wait(&self) -> usize {
-        self.wait2(true)
-    }
-
-    /// Helper method for skipping the preflight checks during testing
-    pub(super) fn wait2(&self, do_preflight_checks: bool) -> usize {
-        // Note that this is currently an inefficient implementation. We in
-        // theory have knowledge about all receivers in the set ahead of time,
-        // so this method shouldn't really have to iterate over all of them yet
-        // again. The idea with this "receiver set" interface is to get the
-        // interface right this time around, and later this implementation can
-        // be optimized.
-        //
-        // This implementation can be summarized by:
-        //
-        //      fn select(receivers) {
-        //          if any receiver ready { return ready index }
-        //          deschedule {
-        //              block on all receivers
-        //          }
-        //          unblock on all receivers
-        //          return ready index
-        //      }
-        //
-        // Most notably, the iterations over all of the receivers shouldn't be
-        // necessary.
-        unsafe {
-            // Stage 1: preflight checks. Look for any packets ready to receive
-            if do_preflight_checks {
-                for handle in self.iter() {
-                    if (*handle).packet.can_recv() {
-                        return (*handle).id();
-                    }
-                }
-            }
-
-            // Stage 2: begin the blocking process
-            //
-            // Create a number of signal tokens, and install each one
-            // sequentially until one fails. If one fails, then abort the
-            // selection on the already-installed tokens.
-            let (wait_token, signal_token) = blocking::tokens();
-            for (i, handle) in self.iter().enumerate() {
-                match (*handle).packet.start_selection(signal_token.clone()) {
-                    StartResult::Installed => {}
-                    StartResult::Abort => {
-                        // Go back and abort the already-begun selections
-                        for handle in self.iter().take(i) {
-                            (*handle).packet.abort_selection();
-                        }
-                        return (*handle).id;
-                    }
-                }
-            }
-
-            // Stage 3: no messages available, actually block
-            wait_token.wait();
-
-            // Stage 4: there *must* be message available; find it.
-            //
-            // Abort the selection process on each receiver. If the abort
-            // process returns `true`, then that means that the receiver is
-            // ready to receive some data. Note that this also means that the
-            // receiver may have yet to have fully read the `to_wake` field and
-            // woken us up (although the wakeup is guaranteed to fail).
-            //
-            // This situation happens in the window of where a sender invokes
-            // increment(), sees -1, and then decides to wake up the thread. After
-            // all this is done, the sending thread will set `selecting` to
-            // `false`. Until this is done, we cannot return. If we were to
-            // return, then a sender could wake up a receiver which has gone
-            // back to sleep after this call to `select`.
-            //
-            // Note that it is a "fairly small window" in which an increment()
-            // views that it should wake a thread up until the `selecting` bit
-            // is set to false. For now, the implementation currently just spins
-            // in a yield loop. This is very distasteful, but this
-            // implementation is already nowhere near what it should ideally be.
-            // A rewrite should focus on avoiding a yield loop, and for now this
-            // implementation is tying us over to a more efficient "don't
-            // iterate over everything every time" implementation.
-            let mut ready_id = usize::MAX;
-            for handle in self.iter() {
-                if (*handle).packet.abort_selection() {
-                    ready_id = (*handle).id;
-                }
-            }
-
-            // We must have found a ready receiver
-            assert!(ready_id != usize::MAX);
-            return ready_id;
-        }
-    }
-
-    fn iter(&self) -> Packets { Packets { cur: unsafe { &*self.inner.get() }.head } }
-}
-
-impl<'rx, T: Send> Handle<'rx, T> {
-    /// Retrieves the ID of this handle.
-    #[inline]
-    pub fn id(&self) -> usize { self.id }
-
-    /// Blocks to receive a value on the underlying receiver, returning `Some` on
-    /// success or `None` if the channel disconnects. This function has the same
-    /// semantics as `Receiver.recv`
-    pub fn recv(&mut self) -> Result<T, RecvError> { self.rx.recv() }
-
-    /// Adds this handle to the receiver set that the handle was created from. This
-    /// method can be called multiple times, but it has no effect if `add` was
-    /// called previously.
-    ///
-    /// This method is unsafe because it requires that the `Handle` is not moved
-    /// while it is added to the `Select` set.
-    pub unsafe fn add(&mut self) {
-        if self.added { return }
-        let selector = &mut *self.selector;
-        let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>;
-
-        if selector.head.is_null() {
-            selector.head = me;
-            selector.tail = me;
-        } else {
-            (*me).prev = selector.tail;
-            assert!((*me).next.is_null());
-            (*selector.tail).next = me;
-            selector.tail = me;
-        }
-        self.added = true;
-    }
-
-    /// Removes this handle from the `Select` set. This method is unsafe because
-    /// it has no guarantee that the `Handle` was not moved since `add` was
-    /// called.
-    pub unsafe fn remove(&mut self) {
-        if !self.added { return }
-
-        let selector = &mut *self.selector;
-        let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>;
-
-        if self.prev.is_null() {
-            assert_eq!(selector.head, me);
-            selector.head = self.next;
-        } else {
-            (*self.prev).next = self.next;
-        }
-        if self.next.is_null() {
-            assert_eq!(selector.tail, me);
-            selector.tail = self.prev;
-        } else {
-            (*self.next).prev = self.prev;
-        }
-
-        self.next = ptr::null_mut();
-        self.prev = ptr::null_mut();
-
-        self.added = false;
-    }
-}
-
-impl Drop for Select {
-    fn drop(&mut self) {
-        unsafe {
-            assert!((&*self.inner.get()).head.is_null());
-            assert!((&*self.inner.get()).tail.is_null());
-        }
-    }
-}
-
-impl<T: Send> Drop for Handle<'_, T> {
-    fn drop(&mut self) {
-        unsafe { self.remove() }
-    }
-}
-
-impl Iterator for Packets {
-    type Item = *mut Handle<'static, ()>;
-
-    fn next(&mut self) -> Option<*mut Handle<'static, ()>> {
-        if self.cur.is_null() {
-            None
-        } else {
-            let ret = Some(self.cur);
-            unsafe { self.cur = (*self.cur).next; }
-            ret
-        }
-    }
-}
-
-impl fmt::Debug for Select {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Select").finish()
-    }
-}
-
-impl<T: Send> fmt::Debug for Handle<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Handle").finish()
-    }
-}
diff --git a/src/libstd/sync/mpsc/select_tests.rs b/src/libstd/sync/mpsc/select_tests.rs
deleted file mode 100644
index 18d93462c78..00000000000
--- a/src/libstd/sync/mpsc/select_tests.rs
+++ /dev/null
@@ -1,413 +0,0 @@
-#![allow(unused_imports)]
-
-/// This file exists to hack around https://github.com/rust-lang/rust/issues/47238
-
-use crate::thread;
-use crate::sync::mpsc::*;
-
-// Don't use the libstd version so we can pull in the right Select structure
-// (std::comm points at the wrong one)
-macro_rules! select {
-    (
-        $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
-    ) => ({
-        let sel = Select::new();
-        $( let mut $rx = sel.handle(&$rx); )+
-        unsafe {
-            $( $rx.add(); )+
-        }
-        let ret = sel.wait();
-        $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
-        { unreachable!() }
-    })
-}
-
-#[test]
-fn smoke() {
-    let (tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    tx1.send(1).unwrap();
-    select! {
-        foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); },
-        _bar = rx2.recv() => { panic!() }
-    }
-    tx2.send(2).unwrap();
-    select! {
-        _foo = rx1.recv() => { panic!() },
-        bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) }
-    }
-    drop(tx1);
-    select! {
-        foo = rx1.recv() => { assert!(foo.is_err()); },
-        _bar = rx2.recv() => { panic!() }
-    }
-    drop(tx2);
-    select! {
-        bar = rx2.recv() => { assert!(bar.is_err()); }
-    }
-}
-
-#[test]
-fn smoke2() {
-    let (_tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (_tx3, rx3) = channel::<i32>();
-    let (_tx4, rx4) = channel::<i32>();
-    let (tx5, rx5) = channel::<i32>();
-    tx5.send(4).unwrap();
-    select! {
-        _foo = rx1.recv() => { panic!("1") },
-        _foo = rx2.recv() => { panic!("2") },
-        _foo = rx3.recv() => { panic!("3") },
-        _foo = rx4.recv() => { panic!("4") },
-        foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); }
-    }
-}
-
-#[test]
-fn closed() {
-    let (_tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    drop(tx2);
-
-    select! {
-        _a1 = rx1.recv() => { panic!() },
-        a2 = rx2.recv() => { assert!(a2.is_err()); }
-    }
-}
-
-#[test]
-fn unblocks() {
-    let (tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<i32>();
-
-    let _t = thread::spawn(move|| {
-        for _ in 0..20 { thread::yield_now(); }
-        tx1.send(1).unwrap();
-        rx3.recv().unwrap();
-        for _ in 0..20 { thread::yield_now(); }
-    });
-
-    select! {
-        a = rx1.recv() => { assert_eq!(a.unwrap(), 1); },
-        _b = rx2.recv() => { panic!() }
-    }
-    tx3.send(1).unwrap();
-    select! {
-        a = rx1.recv() => { assert!(a.is_err()) },
-        _b = rx2.recv() => { panic!() }
-    }
-}
-
-#[test]
-fn both_ready() {
-    let (tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        for _ in 0..20 { thread::yield_now(); }
-        tx1.send(1).unwrap();
-        tx2.send(2).unwrap();
-        rx3.recv().unwrap();
-    });
-
-    select! {
-        a = rx1.recv() => { assert_eq!(a.unwrap(), 1); },
-        a = rx2.recv() => { assert_eq!(a.unwrap(), 2); }
-    }
-    select! {
-        a = rx1.recv() => { assert_eq!(a.unwrap(), 1); },
-        a = rx2.recv() => { assert_eq!(a.unwrap(), 2); }
-    }
-    assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
-    assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty));
-    tx3.send(()).unwrap();
-}
-
-#[test]
-fn stress() {
-    const AMT: i32 = 10000;
-    let (tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        for i in 0..AMT {
-            if i % 2 == 0 {
-                tx1.send(i).unwrap();
-            } else {
-                tx2.send(i).unwrap();
-            }
-            rx3.recv().unwrap();
-        }
-    });
-
-    for i in 0..AMT {
-        select! {
-            i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); },
-            i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); }
-        }
-        tx3.send(()).unwrap();
-    }
-}
-
-#[allow(unused_must_use)]
-#[test]
-fn cloning() {
-    let (tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        rx3.recv().unwrap();
-        tx1.clone();
-        assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty));
-        tx1.send(2).unwrap();
-        rx3.recv().unwrap();
-    });
-
-    tx3.send(()).unwrap();
-    select! {
-        _i1 = rx1.recv() => {},
-        _i2 = rx2.recv() => panic!()
-    }
-    tx3.send(()).unwrap();
-}
-
-#[allow(unused_must_use)]
-#[test]
-fn cloning2() {
-    let (tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        rx3.recv().unwrap();
-        tx1.clone();
-        assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty));
-        tx1.send(2).unwrap();
-        rx3.recv().unwrap();
-    });
-
-    tx3.send(()).unwrap();
-    select! {
-        _i1 = rx1.recv() => {},
-        _i2 = rx2.recv() => panic!()
-    }
-    tx3.send(()).unwrap();
-}
-
-#[test]
-fn cloning3() {
-    let (tx1, rx1) = channel::<()>();
-    let (tx2, rx2) = channel::<()>();
-    let (tx3, rx3) = channel::<()>();
-    let _t = thread::spawn(move|| {
-        let s = Select::new();
-        let mut h1 = s.handle(&rx1);
-        let mut h2 = s.handle(&rx2);
-        unsafe { h2.add(); }
-        unsafe { h1.add(); }
-        assert_eq!(s.wait(), h2.id());
-        tx3.send(()).unwrap();
-    });
-
-    for _ in 0..1000 { thread::yield_now(); }
-    drop(tx1.clone());
-    tx2.send(()).unwrap();
-    rx3.recv().unwrap();
-}
-
-#[test]
-fn preflight1() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    select! {
-        _n = rx.recv() => {}
-    }
-}
-
-#[test]
-fn preflight2() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    tx.send(()).unwrap();
-    select! {
-        _n = rx.recv() => {}
-    }
-}
-
-#[test]
-fn preflight3() {
-    let (tx, rx) = channel();
-    drop(tx.clone());
-    tx.send(()).unwrap();
-    select! {
-        _n = rx.recv() => {}
-    }
-}
-
-#[test]
-fn preflight4() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight5() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    tx.send(()).unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight6() {
-    let (tx, rx) = channel();
-    drop(tx.clone());
-    tx.send(()).unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight7() {
-    let (tx, rx) = channel::<()>();
-    drop(tx);
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight8() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    drop(tx);
-    rx.recv().unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight9() {
-    let (tx, rx) = channel();
-    drop(tx.clone());
-    tx.send(()).unwrap();
-    drop(tx);
-    rx.recv().unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn oneshot_data_waiting() {
-    let (tx1, rx1) = channel();
-    let (tx2, rx2) = channel();
-    let _t = thread::spawn(move|| {
-        select! {
-            _n = rx1.recv() => {}
-        }
-        tx2.send(()).unwrap();
-    });
-
-    for _ in 0..100 { thread::yield_now() }
-    tx1.send(()).unwrap();
-    rx2.recv().unwrap();
-}
-
-#[test]
-fn stream_data_waiting() {
-    let (tx1, rx1) = channel();
-    let (tx2, rx2) = channel();
-    tx1.send(()).unwrap();
-    tx1.send(()).unwrap();
-    rx1.recv().unwrap();
-    rx1.recv().unwrap();
-    let _t = thread::spawn(move|| {
-        select! {
-            _n = rx1.recv() => {}
-        }
-        tx2.send(()).unwrap();
-    });
-
-    for _ in 0..100 { thread::yield_now() }
-    tx1.send(()).unwrap();
-    rx2.recv().unwrap();
-}
-
-#[test]
-fn shared_data_waiting() {
-    let (tx1, rx1) = channel();
-    let (tx2, rx2) = channel();
-    drop(tx1.clone());
-    tx1.send(()).unwrap();
-    rx1.recv().unwrap();
-    let _t = thread::spawn(move|| {
-        select! {
-            _n = rx1.recv() => {}
-        }
-        tx2.send(()).unwrap();
-    });
-
-    for _ in 0..100 { thread::yield_now() }
-    tx1.send(()).unwrap();
-    rx2.recv().unwrap();
-}
-
-#[test]
-fn sync1() {
-    let (tx, rx) = sync_channel::<i32>(1);
-    tx.send(1).unwrap();
-    select! {
-        n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
-    }
-}
-
-#[test]
-fn sync2() {
-    let (tx, rx) = sync_channel::<i32>(0);
-    let _t = thread::spawn(move|| {
-        for _ in 0..100 { thread::yield_now() }
-        tx.send(1).unwrap();
-    });
-    select! {
-        n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
-    }
-}
-
-#[test]
-fn sync3() {
-    let (tx1, rx1) = sync_channel::<i32>(0);
-    let (tx2, rx2): (Sender<i32>, Receiver<i32>) = channel();
-    let _t = thread::spawn(move|| { tx1.send(1).unwrap(); });
-    let _t = thread::spawn(move|| { tx2.send(2).unwrap(); });
-    select! {
-        n = rx1.recv() => {
-            let n = n.unwrap();
-            assert_eq!(n, 1);
-            assert_eq!(rx2.recv().unwrap(), 2);
-        },
-        n = rx2.recv() => {
-            let n = n.unwrap();
-            assert_eq!(n, 2);
-            assert_eq!(rx1.recv().unwrap(), 1);
-        }
-    }
-}
diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs
index 6a5d861f0e9..dbcdcdac932 100644
--- a/src/libstd/sync/mpsc/shared.rs
+++ b/src/libstd/sync/mpsc/shared.rs
@@ -9,6 +9,7 @@
 /// channels are quite similar, and this is no coincidence!
 
 pub use self::Failure::*;
+use self::StartResult::*;
 
 use core::cmp;
 use core::intrinsics::abort;
@@ -19,8 +20,6 @@ use crate::ptr;
 use crate::sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
 use crate::sync::mpsc::blocking::{self, SignalToken};
 use crate::sync::mpsc::mpsc_queue as mpsc;
-use crate::sync::mpsc::select::StartResult::*;
-use crate::sync::mpsc::select::StartResult;
 use crate::sync::{Mutex, MutexGuard};
 use crate::thread;
 use crate::time::Instant;
@@ -57,6 +56,12 @@ pub enum Failure {
     Disconnected,
 }
 
+#[derive(PartialEq, Eq)]
+enum StartResult {
+    Installed,
+    Abort,
+}
+
 impl<T> Packet<T> {
     // Creation of a packet *must* be followed by a call to postinit_lock
     // and later by inherit_blocker
@@ -78,7 +83,7 @@ impl<T> Packet<T> {
     // In other case mutex data will be duplicated while cloning
     // and that could cause problems on platforms where it is
     // represented by opaque data structure
-    pub fn postinit_lock(&self) -> MutexGuard<()> {
+    pub fn postinit_lock(&self) -> MutexGuard<'_, ()> {
         self.select_lock.lock().unwrap()
     }
 
@@ -89,7 +94,7 @@ impl<T> Packet<T> {
     // This can only be called at channel-creation time
     pub fn inherit_blocker(&self,
                            token: Option<SignalToken>,
-                           guard: MutexGuard<()>) {
+                           guard: MutexGuard<'_, ()>) {
         token.map(|token| {
             assert_eq!(self.cnt.load(Ordering::SeqCst), 0);
             assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
@@ -394,16 +399,6 @@ impl<T> Packet<T> {
     // select implementation
     ////////////////////////////////////////////////////////////////////////////
 
-    // Helper function for select, tests whether this port can receive without
-    // blocking (obviously not an atomic decision).
-    //
-    // This is different than the stream version because there's no need to peek
-    // at the queue, we can just look at the local count.
-    pub fn can_recv(&self) -> bool {
-        let cnt = self.cnt.load(Ordering::SeqCst);
-        cnt == DISCONNECTED || cnt - unsafe { *self.steals.get() } > 0
-    }
-
     // increment the count on the channel (used for selection)
     fn bump(&self, amt: isize) -> isize {
         match self.cnt.fetch_add(amt, Ordering::SeqCst) {
@@ -415,22 +410,6 @@ impl<T> Packet<T> {
         }
     }
 
-    // Inserts the signal token for selection on this port, returning true if
-    // blocking should proceed.
-    //
-    // The code here is the same as in stream.rs, except that it doesn't need to
-    // peek at the channel to see if an upgrade is pending.
-    pub fn start_selection(&self, token: SignalToken) -> StartResult {
-        match self.decrement(token) {
-            Installed => Installed,
-            Abort => {
-                let prev = self.bump(1);
-                assert!(prev == DISCONNECTED || prev >= 0);
-                Abort
-            }
-        }
-    }
-
     // Cancels a previous thread waiting on this port, returning whether there's
     // data on the port.
     //
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index 7ae6f68b514..40877282761 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -9,7 +9,6 @@
 
 pub use self::Failure::*;
 pub use self::UpgradeResult::*;
-pub use self::SelectionResult::*;
 use self::Message::*;
 
 use core::cmp;
@@ -60,12 +59,6 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
-    SelSuccess,
-    SelCanceled,
-    SelUpgraded(SignalToken, Receiver<T>),
-}
-
 // Any message could contain an "upgrade request" to a new shared port, so the
 // internal queue it's a queue of T, but rather Message<T>
 enum Message<T> {
@@ -338,27 +331,6 @@ impl<T> Packet<T> {
     // select implementation
     ////////////////////////////////////////////////////////////////////////////
 
-    // Tests to see whether this port can receive without blocking. If Ok is
-    // returned, then that's the answer. If Err is returned, then the returned
-    // port needs to be queried instead (an upgrade happened)
-    pub fn can_recv(&self) -> Result<bool, Receiver<T>> {
-        // We peek at the queue to see if there's anything on it, and we use
-        // this return value to determine if we should pop from the queue and
-        // upgrade this channel immediately. If it looks like we've got an
-        // upgrade pending, then go through the whole recv rigamarole to update
-        // the internal state.
-        match self.queue.peek() {
-            Some(&mut GoUp(..)) => {
-                match self.recv(None) {
-                    Err(Upgraded(port)) => Err(port),
-                    _ => unreachable!(),
-                }
-            }
-            Some(..) => Ok(true),
-            None => Ok(false)
-        }
-    }
-
     // increment the count on the channel (used for selection)
     fn bump(&self, amt: isize) -> isize {
         match self.queue.producer_addition().cnt.fetch_add(amt, Ordering::SeqCst) {
@@ -370,31 +342,6 @@ impl<T> Packet<T> {
         }
     }
 
-    // Attempts to start selecting on this port. Like a oneshot, this can fail
-    // immediately because of an upgrade.
-    pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> {
-        match self.decrement(token) {
-            Ok(()) => SelSuccess,
-            Err(token) => {
-                let ret = match self.queue.peek() {
-                    Some(&mut GoUp(..)) => {
-                        match self.queue.pop() {
-                            Some(GoUp(port)) => SelUpgraded(token, port),
-                            _ => unreachable!(),
-                        }
-                    }
-                    Some(..) => SelCanceled,
-                    None => SelCanceled,
-                };
-                // Undo our decrement above, and we should be guaranteed that the
-                // previous value is positive because we're not going to sleep
-                let prev = self.bump(1);
-                assert!(prev == DISCONNECTED || prev >= 0);
-                ret
-            }
-        }
-    }
-
     // Removes a previous thread from being blocked in this port
     pub fn abort_selection(&self,
                            was_upgrade: bool) -> Result<bool, Receiver<T>> {
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 485234a9495..58a4b716afb 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -33,7 +33,6 @@ use core::ptr;
 
 use crate::sync::atomic::{Ordering, AtomicUsize};
 use crate::sync::mpsc::blocking::{self, WaitToken, SignalToken};
-use crate::sync::mpsc::select::StartResult::{self, Installed, Abort};
 use crate::sync::{Mutex, MutexGuard};
 use crate::time::Instant;
 
@@ -141,7 +140,7 @@ fn wait_timeout_receiver<'a, 'b, T>(lock: &'a Mutex<State<T>>,
     new_guard
 }
 
-fn abort_selection<'a, T>(guard: &mut MutexGuard<'a , State<T>>) -> bool {
+fn abort_selection<T>(guard: &mut MutexGuard<'_, State<T>>) -> bool {
     match mem::replace(&mut guard.blocker, NoneBlocked) {
         NoneBlocked => true,
         BlockedSender(token) => {
@@ -153,7 +152,7 @@ fn abort_selection<'a, T>(guard: &mut MutexGuard<'a , State<T>>) -> bool {
 }
 
 /// Wakes up a thread, dropping the lock at the correct time
-fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
+fn wakeup<T>(token: SignalToken, guard: MutexGuard<'_, State<T>>) {
     // We need to be careful to wake up the waiting thread *outside* of the mutex
     // in case it incurs a context switch.
     drop(guard);
@@ -161,20 +160,20 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
 }
 
 impl<T> Packet<T> {
-    pub fn new(cap: usize) -> Packet<T> {
+    pub fn new(capacity: usize) -> Packet<T> {
         Packet {
             channels: AtomicUsize::new(1),
             lock: Mutex::new(State {
                 disconnected: false,
                 blocker: NoneBlocked,
-                cap,
+                cap: capacity,
                 canceled: None,
                 queue: Queue {
                     head: ptr::null_mut(),
                     tail: ptr::null_mut(),
                 },
                 buf: Buffer {
-                    buf: (0..cap + if cap == 0 {1} else {0}).map(|_| None).collect(),
+                    buf: (0..capacity + if capacity == 0 {1} else {0}).map(|_| None).collect(),
                     start: 0,
                     size: 0,
                 },
@@ -184,12 +183,12 @@ impl<T> Packet<T> {
 
     // wait until a send slot is available, returning locked access to
     // the channel state.
-    fn acquire_send_slot(&self) -> MutexGuard<State<T>> {
+    fn acquire_send_slot(&self) -> MutexGuard<'_, State<T>> {
         let mut node = Node { token: None, next: ptr::null_mut() };
         loop {
             let mut guard = self.lock.lock().unwrap();
             // are we ready to go?
-            if guard.disconnected || guard.buf.size() < guard.buf.cap() {
+            if guard.disconnected || guard.buf.size() < guard.buf.capacity() {
                 return guard;
             }
             // no room; actually block
@@ -231,7 +230,7 @@ impl<T> Packet<T> {
         let mut guard = self.lock.lock().unwrap();
         if guard.disconnected {
             Err(super::TrySendError::Disconnected(t))
-        } else if guard.buf.size() == guard.buf.cap() {
+        } else if guard.buf.size() == guard.buf.capacity() {
             Err(super::TrySendError::Full(t))
         } else if guard.cap == 0 {
             // With capacity 0, even though we have buffer space we can't
@@ -249,7 +248,7 @@ impl<T> Packet<T> {
             // If the buffer has some space and the capacity isn't 0, then we
             // just enqueue the data for later retrieval, ensuring to wake up
             // any blocked receiver if there is one.
-            assert!(guard.buf.size() < guard.buf.cap());
+            assert!(guard.buf.size() < guard.buf.capacity());
             guard.buf.enqueue(t);
             match mem::replace(&mut guard.blocker, NoneBlocked) {
                 BlockedReceiver(token) => wakeup(token, guard),
@@ -316,7 +315,7 @@ impl<T> Packet<T> {
     // * `waited` - flag if the receiver blocked to receive some data, or if it
     //              just picked up some data on the way out
     // * `guard` - the lock guard that is held over this channel's lock
-    fn wakeup_senders(&self, waited: bool, mut guard: MutexGuard<State<T>>) {
+    fn wakeup_senders(&self, waited: bool, mut guard: MutexGuard<'_, State<T>>) {
         let pending_sender1: Option<SignalToken> = guard.queue.dequeue();
 
         // If this is a no-buffer channel (cap == 0), then if we didn't wait we
@@ -384,7 +383,7 @@ impl<T> Packet<T> {
         // needs to be careful to destroy the data *outside* of the lock to
         // prevent deadlock.
         let _data = if guard.cap != 0 {
-            mem::replace(&mut guard.buf.buf, Vec::new())
+            mem::take(&mut guard.buf.buf)
         } else {
             Vec::new()
         };
@@ -406,42 +405,6 @@ impl<T> Packet<T> {
         while let Some(token) = queue.dequeue() { token.signal(); }
         waiter.map(|t| t.signal());
     }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // select implementation
-    ////////////////////////////////////////////////////////////////////////////
-
-    // If Ok, the value is whether this port has data, if Err, then the upgraded
-    // port needs to be checked instead of this one.
-    pub fn can_recv(&self) -> bool {
-        let guard = self.lock.lock().unwrap();
-        guard.disconnected || guard.buf.size() > 0
-    }
-
-    // Attempts to start selection on this port. This can either succeed or fail
-    // because there is data waiting.
-    pub fn start_selection(&self, token: SignalToken) -> StartResult {
-        let mut guard = self.lock.lock().unwrap();
-        if guard.disconnected || guard.buf.size() > 0 {
-            Abort
-        } else {
-            match mem::replace(&mut guard.blocker, BlockedReceiver(token)) {
-                NoneBlocked => {}
-                BlockedSender(..) => unreachable!(),
-                BlockedReceiver(..) => unreachable!(),
-            }
-            Installed
-        }
-    }
-
-    // Remove a previous selecting thread from this port. This ensures that the
-    // blocked thread will no longer be visible to any other threads.
-    //
-    // The return value indicates whether there's data on this port.
-    pub fn abort_selection(&self) -> bool {
-        let mut guard = self.lock.lock().unwrap();
-        abort_selection(&mut guard)
-    }
 }
 
 impl<T> Drop for Packet<T> {
@@ -475,7 +438,7 @@ impl<T> Buffer<T> {
     }
 
     fn size(&self) -> usize { self.size }
-    fn cap(&self) -> usize { self.buf.len() }
+    fn capacity(&self) -> usize { self.buf.len() }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 6b812e65b72..87c2318a937 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -215,7 +215,7 @@ impl<T: ?Sized> Mutex<T> {
     /// assert_eq!(*mutex.lock().unwrap(), 10);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn lock(&self) -> LockResult<MutexGuard<T>> {
+    pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
         unsafe {
             self.inner.raw_lock();
             MutexGuard::new(self)
@@ -258,7 +258,7 @@ impl<T: ?Sized> Mutex<T> {
     /// assert_eq!(*mutex.lock().unwrap(), 10);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
+    pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> {
         unsafe {
             if self.inner.try_lock() {
                 Ok(MutexGuard::new(self)?)
@@ -376,6 +376,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex<T> {
 impl<T> From<T> for Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     /// This is equivalent to [`Mutex::new`].
+    ///
+    /// [`Mutex::new`]: ../../std/sync/struct.Mutex.html#method.new
     fn from(t: T) -> Self {
         Mutex::new(t)
     }
@@ -391,7 +393,7 @@ impl<T: ?Sized + Default> Default for Mutex<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.try_lock() {
             Ok(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
             Err(TryLockError::Poisoned(err)) => {
@@ -400,7 +402,9 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
             Err(TryLockError::WouldBlock) => {
                 struct LockedPlaceholder;
                 impl fmt::Debug for LockedPlaceholder {
-                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") }
+                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                        f.write_str("<locked>")
+                    }
                 }
 
                 f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish()
@@ -449,14 +453,14 @@ impl<T: ?Sized> Drop for MutexGuard<'_, T> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
 }
 
 #[stable(feature = "std_guard_impls", since = "1.20.0")]
 impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         (**self).fmt(f)
     }
 }
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index a036c266662..e529b8c4227 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -115,6 +115,11 @@ pub struct OnceState {
 /// static START: Once = ONCE_INIT;
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(
+    since = "1.38.0",
+    reason = "the `new` function is now preferred",
+    suggestion = "Once::new()",
+)]
 pub const ONCE_INIT: Once = Once::new();
 
 // Four states that a Once can be in, encoded into the lower bits of `state` in
@@ -431,7 +436,7 @@ impl Once {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Once {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("Once { .. }")
     }
 }
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 0be83c76d62..b1b56f321fc 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -180,7 +180,7 @@ impl<T: ?Sized> RwLock<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
+    pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
         unsafe {
             self.inner.read();
             RwLockReadGuard::new(self)
@@ -219,7 +219,7 @@ impl<T: ?Sized> RwLock<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
+    pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> {
         unsafe {
             if self.inner.try_read() {
                 Ok(RwLockReadGuard::new(self)?)
@@ -262,7 +262,7 @@ impl<T: ?Sized> RwLock<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
+    pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> {
         unsafe {
             self.inner.write();
             RwLockWriteGuard::new(self)
@@ -301,7 +301,7 @@ impl<T: ?Sized> RwLock<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
+    pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
         unsafe {
             if self.inner.try_write() {
                 Ok(RwLockWriteGuard::new(self)?)
@@ -421,7 +421,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.try_read() {
             Ok(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(),
             Err(TryLockError::Poisoned(err)) => {
@@ -430,7 +430,9 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
             Err(TryLockError::WouldBlock) => {
                 struct LockedPlaceholder;
                 impl fmt::Debug for LockedPlaceholder {
-                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") }
+                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                        f.write_str("<locked>")
+                    }
                 }
 
                 f.debug_struct("RwLock").field("data", &LockedPlaceholder).finish()
@@ -451,6 +453,8 @@ impl<T: Default> Default for RwLock<T> {
 impl<T> From<T> for RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
     /// This is equivalent to [`RwLock::new`].
+    ///
+    /// [`RwLock::new`]: ../../std/sync/struct.RwLock.html#method.new
     fn from(t: T) -> Self {
         RwLock::new(t)
     }
@@ -481,7 +485,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RwLockReadGuard")
             .field("lock", &self.__lock)
             .finish()
@@ -490,14 +494,14 @@ impl<T: fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
 
 #[stable(feature = "std_guard_impls", since = "1.20.0")]
 impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         (**self).fmt(f)
     }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RwLockWriteGuard")
             .field("lock", &self.__lock)
             .finish()
@@ -506,7 +510,7 @@ impl<T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
 
 #[stable(feature = "std_guard_impls", since = "1.20.0")]
 impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         (**self).fmt(f)
     }
 }
diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs
index 2307e2167c5..9addba8b611 100644
--- a/src/libstd/sys/cloudabi/abi/cloudabi.rs
+++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs
@@ -1884,7 +1884,7 @@ pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) ->
 /// **time**:
 /// The time value of the clock.
 #[inline]
-pub unsafe fn clock_time_get(clock_id_: clockid, precision_: timestamp, time_: &mut timestamp) -> errno {
+pub unsafe fn clock_time_get(clock_id_: clockid, precision_: timestamp, time_: *mut timestamp) -> errno {
   cloudabi_sys_clock_time_get(clock_id_, precision_, time_)
 }
 
@@ -2643,7 +2643,7 @@ pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno {
 /// **nevents**:
 /// The number of events stored.
 #[inline]
-pub unsafe fn poll(in_: *const subscription, out_: *mut event, nsubscriptions_: usize, nevents_: &mut usize) -> errno {
+pub unsafe fn poll(in_: *const subscription, out_: *mut event, nsubscriptions_: usize, nevents_: *mut usize) -> errno {
   cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_)
 }
 
diff --git a/src/libstd/sys/cloudabi/backtrace.rs b/src/libstd/sys/cloudabi/backtrace.rs
deleted file mode 100644
index a15d2238e55..00000000000
--- a/src/libstd/sys/cloudabi/backtrace.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-use crate::error::Error;
-use crate::ffi::CStr;
-use crate::fmt;
-use crate::intrinsics;
-use crate::io;
-use crate::sys_common::backtrace::Frame;
-
-use unwind as uw;
-
-pub struct BacktraceContext;
-
-struct Context<'a> {
-    idx: usize,
-    frames: &'a mut [Frame],
-}
-
-#[derive(Debug)]
-struct UnwindError(uw::_Unwind_Reason_Code);
-
-impl Error for UnwindError {
-    fn description(&self) -> &'static str {
-        "unexpected return value while unwinding"
-    }
-}
-
-impl fmt::Display for UnwindError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}: {:?}", self.description(), self.0)
-    }
-}
-
-#[inline(never)] // if we know this is a function call, we can skip it when
-                 // tracing
-pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
-    let mut cx = Context { idx: 0, frames };
-    let result_unwind =
-        unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) };
-    // See libunwind:src/unwind/Backtrace.c for the return values.
-    // No, there is no doc.
-    match result_unwind {
-        // These return codes seem to be benign and need to be ignored for backtraces
-        // to show up properly on all tested platforms.
-        uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
-            Ok((cx.idx, BacktraceContext))
-        }
-        _ => Err(io::Error::new(
-            io::ErrorKind::Other,
-            UnwindError(result_unwind),
-        )),
-    }
-}
-
-extern "C" fn trace_fn(
-    ctx: *mut uw::_Unwind_Context,
-    arg: *mut libc::c_void,
-) -> uw::_Unwind_Reason_Code {
-    let cx = unsafe { &mut *(arg as *mut Context) };
-    if cx.idx >= cx.frames.len() {
-        return uw::_URC_NORMAL_STOP;
-    }
-
-    let mut ip_before_insn = 0;
-    let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
-    if !ip.is_null() && ip_before_insn == 0 {
-        // this is a non-signaling frame, so `ip` refers to the address
-        // after the calling instruction. account for that.
-        ip = (ip as usize - 1) as *mut _;
-    }
-
-    let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
-    cx.frames[cx.idx] = Frame {
-        symbol_addr: symaddr as *mut u8,
-        exact_position: ip as *mut u8,
-        inline_context: 0,
-    };
-    cx.idx += 1;
-
-    uw::_URC_NO_REASON
-}
-
-pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
-where
-    F: FnMut(&[u8], u32) -> io::Result<()>,
-{
-    // No way to obtain this information on CloudABI.
-    Ok(false)
-}
-
-pub fn resolve_symname<F>(frame: Frame, callback: F, _: &BacktraceContext) -> io::Result<()>
-where
-    F: FnOnce(Option<&str>) -> io::Result<()>,
-{
-    unsafe {
-        let mut info: Dl_info = intrinsics::init();
-        let symname =
-            if dladdr(frame.exact_position as *mut _, &mut info) == 0 || info.dli_sname.is_null() {
-                None
-            } else {
-                CStr::from_ptr(info.dli_sname).to_str().ok()
-            };
-        callback(symname)
-    }
-}
-
-#[repr(C)]
-struct Dl_info {
-    dli_fname: *const libc::c_char,
-    dli_fbase: *mut libc::c_void,
-    dli_sname: *const libc::c_char,
-    dli_saddr: *mut libc::c_void,
-}
-
-extern "C" {
-    fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
-}
diff --git a/src/libstd/sys/cloudabi/condvar.rs b/src/libstd/sys/cloudabi/condvar.rs
index 7aa0b0b6f49..ec1fca7805a 100644
--- a/src/libstd/sys/cloudabi/condvar.rs
+++ b/src/libstd/sys/cloudabi/condvar.rs
@@ -79,16 +79,21 @@ impl Condvar {
             },
             ..mem::zeroed()
         };
-        let mut event: abi::event = mem::uninitialized();
-        let mut nevents: usize = mem::uninitialized();
-        let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+        let mut event: mem::MaybeUninit<abi::event> = mem::MaybeUninit::uninit();
+        let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
+        let ret = abi::poll(
+            &subscription,
+            event.as_mut_ptr(),
+            1,
+            nevents.as_mut_ptr()
+        );
         assert_eq!(
             ret,
             abi::errno::SUCCESS,
             "Failed to wait on condition variable"
         );
         assert_eq!(
-            event.error,
+            event.assume_init().error,
             abi::errno::SUCCESS,
             "Failed to wait on condition variable"
         );
@@ -131,21 +136,27 @@ impl Condvar {
                 ..mem::zeroed()
             },
         ];
-        let mut events: [abi::event; 2] = mem::uninitialized();
-        let mut nevents: usize = mem::uninitialized();
-        let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
+        let mut events: [mem::MaybeUninit<abi::event>; 2] = [mem::MaybeUninit::uninit(); 2];
+        let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
+        let ret = abi::poll(
+            subscriptions.as_ptr(),
+            mem::MaybeUninit::first_ptr_mut(&mut events),
+            2,
+            nevents.as_mut_ptr()
+        );
         assert_eq!(
             ret,
             abi::errno::SUCCESS,
             "Failed to wait on condition variable"
         );
+        let nevents = nevents.assume_init();
         for i in 0..nevents {
             assert_eq!(
-                events[i].error,
+                events[i].assume_init().error,
                 abi::errno::SUCCESS,
                 "Failed to wait on condition variable"
             );
-            if events[i].type_ == abi::eventtype::CONDVAR {
+            if events[i].assume_init().type_ == abi::eventtype::CONDVAR {
                 return true;
             }
         }
diff --git a/src/libstd/sys/cloudabi/io.rs b/src/libstd/sys/cloudabi/io.rs
index 8b02d3fd19d..976e122463d 100644
--- a/src/libstd/sys/cloudabi/io.rs
+++ b/src/libstd/sys/cloudabi/io.rs
@@ -1,9 +1,16 @@
-pub struct IoVec<'a>(&'a [u8]);
+use crate::mem;
+
+pub struct IoSlice<'a>(&'a [u8]);
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice(buf)
+    }
 
-impl<'a> IoVec<'a> {
     #[inline]
-    pub fn new(buf: &'a [u8]) -> IoVec<'a> {
-        IoVec(buf)
+    pub fn advance(&mut self, n: usize) {
+        self.0 = &self.0[n..]
     }
 
     #[inline]
@@ -12,12 +19,19 @@ impl<'a> IoVec<'a> {
     }
 }
 
-pub struct IoVecMut<'a>(&'a mut [u8]);
+pub struct IoSliceMut<'a>(&'a mut [u8]);
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut(buf)
+    }
 
-impl<'a> IoVecMut<'a> {
     #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoVecMut<'a> {
-        IoVecMut(buf)
+    pub fn advance(&mut self, n: usize) {
+        let slice = mem::replace(&mut self.0, &mut []);
+        let (_, remaining) = slice.split_at_mut(n);
+        self.0 = remaining;
     }
 
     #[inline]
diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs
index 47c90fddd86..6e147612eb4 100644
--- a/src/libstd/sys/cloudabi/mod.rs
+++ b/src/libstd/sys/cloudabi/mod.rs
@@ -1,11 +1,11 @@
+#![allow(deprecated_in_future)] // mem::uninitialized; becomes `deprecated` when nightly is 1.39
+
 use crate::io::ErrorKind;
 use crate::mem;
 
 #[path = "../unix/alloc.rs"]
 pub mod alloc;
 pub mod args;
-#[cfg(feature = "backtrace")]
-pub mod backtrace;
 #[path = "../unix/cmath.rs"]
 pub mod cmath;
 pub mod condvar;
@@ -14,8 +14,6 @@ pub mod io;
 pub mod memchr;
 pub mod mutex;
 pub mod os;
-#[path = "../unix/os_str.rs"]
-pub mod os_str;
 pub mod rwlock;
 pub mod stack_overflow;
 pub mod stdio;
@@ -24,6 +22,8 @@ pub mod thread;
 pub mod thread_local;
 pub mod time;
 
+pub use crate::sys_common::os_str_bytes as os_str;
+
 mod abi;
 
 mod shims;
@@ -61,8 +61,11 @@ pub use libc::strlen;
 
 pub fn hashmap_random_keys() -> (u64, u64) {
     unsafe {
-        let mut v = mem::uninitialized();
-        libc::arc4random_buf(&mut v as *mut _ as *mut libc::c_void, mem::size_of_val(&v));
-        v
+        let mut v: mem::MaybeUninit<(u64, u64)> = mem::MaybeUninit::uninit();
+        libc::arc4random_buf(
+            v.as_mut_ptr() as *mut libc::c_void,
+            mem::size_of_val(&v)
+        );
+        v.assume_init()
     }
 }
diff --git a/src/libstd/sys/cloudabi/mutex.rs b/src/libstd/sys/cloudabi/mutex.rs
index 5e191e31d5f..d3ff0077b20 100644
--- a/src/libstd/sys/cloudabi/mutex.rs
+++ b/src/libstd/sys/cloudabi/mutex.rs
@@ -1,5 +1,6 @@
 use crate::cell::UnsafeCell;
 use crate::mem;
+use crate::mem::MaybeUninit;
 use crate::sync::atomic::{AtomicU32, Ordering};
 use crate::sys::cloudabi::abi;
 use crate::sys::rwlock::{self, RWLock};
@@ -47,24 +48,27 @@ impl Mutex {
 }
 
 pub struct ReentrantMutex {
-    lock: UnsafeCell<AtomicU32>,
-    recursion: UnsafeCell<u32>,
+    lock: UnsafeCell<MaybeUninit<AtomicU32>>,
+    recursion: UnsafeCell<MaybeUninit<u32>>,
 }
 
 impl ReentrantMutex {
     pub unsafe fn uninitialized() -> ReentrantMutex {
-        mem::uninitialized()
+        ReentrantMutex {
+            lock: UnsafeCell::new(MaybeUninit::uninit()),
+            recursion: UnsafeCell::new(MaybeUninit::uninit())
+        }
     }
 
     pub unsafe fn init(&mut self) {
-        self.lock = UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
-        self.recursion = UnsafeCell::new(0);
+        self.lock = UnsafeCell::new(MaybeUninit::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)));
+        self.recursion = UnsafeCell::new(MaybeUninit::new(0));
     }
 
     pub unsafe fn try_lock(&self) -> bool {
         // Attempt to acquire the lock.
-        let lock = self.lock.get();
-        let recursion = self.recursion.get();
+        let lock = (*self.lock.get()).as_mut_ptr();
+        let recursion = (*self.recursion.get()).as_mut_ptr();
         if let Err(old) = (*lock).compare_exchange(
             abi::LOCK_UNLOCKED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
@@ -109,8 +113,8 @@ impl ReentrantMutex {
     }
 
     pub unsafe fn unlock(&self) {
-        let lock = self.lock.get();
-        let recursion = self.recursion.get();
+        let lock = (*self.lock.get()).as_mut_ptr();
+        let recursion = (*self.recursion.get()).as_mut_ptr();
         assert_eq!(
             (*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
@@ -136,8 +140,8 @@ impl ReentrantMutex {
     }
 
     pub unsafe fn destroy(&self) {
-        let lock = self.lock.get();
-        let recursion = self.recursion.get();
+        let lock = (*self.lock.get()).as_mut_ptr();
+        let recursion = (*self.recursion.get()).as_mut_ptr();
         assert_eq!(
             (*lock).load(Ordering::Relaxed),
             abi::LOCK_UNLOCKED.0,
diff --git a/src/libstd/sys/cloudabi/shims/fs.rs b/src/libstd/sys/cloudabi/shims/fs.rs
index 56667bef007..05f91541011 100644
--- a/src/libstd/sys/cloudabi/shims/fs.rs
+++ b/src/libstd/sys/cloudabi/shims/fs.rs
@@ -1,7 +1,7 @@
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::io::{self, SeekFrom};
+use crate::io::{self, SeekFrom, IoSlice, IoSliceMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::{unsupported, Void};
@@ -81,7 +81,7 @@ impl PartialEq for FilePermissions {
 impl Eq for FilePermissions {}
 
 impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -123,13 +123,13 @@ impl Hash for FileType {
 }
 
 impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
 
 impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -198,10 +198,18 @@ impl File {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
@@ -234,7 +242,7 @@ impl DirBuilder {
 }
 
 impl fmt::Debug for File {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs
index 6d2a4962ab4..8d609cdfad5 100644
--- a/src/libstd/sys/cloudabi/shims/net.rs
+++ b/src/libstd/sys/cloudabi/shims/net.rs
@@ -1,5 +1,5 @@
 use crate::fmt;
-use crate::io::{self, IoVec, IoVecMut};
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
 use crate::time::Duration;
 use crate::sys::{unsupported, Void};
@@ -43,7 +43,7 @@ impl TcpStream {
         match self.0 {}
     }
 
-    pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         match self.0 {}
     }
 
@@ -51,7 +51,7 @@ impl TcpStream {
         match self.0 {}
     }
 
-    pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
+    pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
         match self.0 {}
     }
 
@@ -97,7 +97,7 @@ impl TcpStream {
 }
 
 impl fmt::Debug for TcpStream {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -147,7 +147,7 @@ impl TcpListener {
 }
 
 impl fmt::Debug for TcpListener {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -159,6 +159,10 @@ impl UdpSocket {
         unsupported()
     }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
@@ -277,7 +281,7 @@ impl UdpSocket {
 }
 
 impl fmt::Debug for UdpSocket {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/cloudabi/shims/os.rs b/src/libstd/sys/cloudabi/shims/os.rs
index 0c4690e12b0..944b9525b3b 100644
--- a/src/libstd/sys/cloudabi/shims/os.rs
+++ b/src/libstd/sys/cloudabi/shims/os.rs
@@ -34,7 +34,7 @@ pub fn unsetenv(_: &OsStr) -> io::Result<()> {
 
 pub struct SplitPaths<'a>(&'a Void);
 
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
     panic!("unsupported")
 }
 
@@ -57,7 +57,7 @@ where
 }
 
 impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "not supported on CloudABI yet".fmt(f)
     }
 }
diff --git a/src/libstd/sys/cloudabi/shims/pipe.rs b/src/libstd/sys/cloudabi/shims/pipe.rs
index f3debb95047..fb14dc59101 100644
--- a/src/libstd/sys/cloudabi/shims/pipe.rs
+++ b/src/libstd/sys/cloudabi/shims/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::sys::Void;
 
 pub struct AnonPipe(Void);
@@ -8,10 +8,18 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs
index 710c42c1149..e719b362cbf 100644
--- a/src/libstd/sys/cloudabi/shims/process.rs
+++ b/src/libstd/sys/cloudabi/shims/process.rs
@@ -71,7 +71,7 @@ impl From<File> for Stdio {
 }
 
 impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         Ok(())
     }
 }
@@ -105,13 +105,13 @@ impl PartialEq for ExitStatus {
 impl Eq for ExitStatus {}
 
 impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
 
 impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
index f853346e0e6..7da16c4d247 100644
--- a/src/libstd/sys/cloudabi/thread.rs
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::cmp;
 use crate::ffi::CStr;
 use crate::io;
@@ -22,7 +21,7 @@ unsafe impl Sync for Thread {}
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnBox()>) -> io::Result<Thread> {
+    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         let p = box p;
         let mut native: libc::pthread_t = mem::zeroed();
         let mut attr: libc::pthread_attr_t = mem::zeroed();
diff --git a/src/libstd/sys/cloudabi/time.rs b/src/libstd/sys/cloudabi/time.rs
index d7502c61eff..5e502dcb2ba 100644
--- a/src/libstd/sys/cloudabi/time.rs
+++ b/src/libstd/sys/cloudabi/time.rs
@@ -18,10 +18,10 @@ pub fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
 impl Instant {
     pub fn now() -> Instant {
         unsafe {
-            let mut t = mem::uninitialized();
-            let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, &mut t);
+            let mut t: mem::MaybeUninit<abi::timestamp> = mem::MaybeUninit::uninit();
+            let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, t.as_mut_ptr());
             assert_eq!(ret, abi::errno::SUCCESS);
-            Instant { t }
+            Instant { t: t.assume_init() }
         }
     }
 
@@ -33,11 +33,9 @@ impl Instant {
         Instant { t: 0 }
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        let diff = self.t
-            .checked_sub(other.t)
-            .expect("second instant is later than self");
-        Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        let diff = self.t.checked_sub(other.t)?;
+        Some(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
@@ -61,10 +59,10 @@ pub struct SystemTime {
 impl SystemTime {
     pub fn now() -> SystemTime {
         unsafe {
-            let mut t = mem::uninitialized();
-            let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, &mut t);
+            let mut t: mem::MaybeUninit<abi::timestamp> = mem::MaybeUninit::uninit();
+            let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, t.as_mut_ptr());
             assert_eq!(ret, abi::errno::SUCCESS);
-            SystemTime { t }
+            SystemTime { t: t.assume_init() }
         }
     }
 
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index 5ba9304c09b..5a5859a6ad8 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -22,8 +22,11 @@
 
 #![allow(missing_debug_implementations)]
 
-cfg_if! {
-    if #[cfg(unix)] {
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "vxworks")] {
+        mod vxworks;
+        pub use self::vxworks::*;
+    } else if #[cfg(unix)] {
         mod unix;
         pub use self::unix::*;
     } else if #[cfg(windows)] {
@@ -32,9 +35,9 @@ cfg_if! {
     } else if #[cfg(target_os = "cloudabi")] {
         mod cloudabi;
         pub use self::cloudabi::*;
-    } else if #[cfg(target_os = "redox")] {
-        mod redox;
-        pub use self::redox::*;
+    } else if #[cfg(target_os = "wasi")] {
+        mod wasi;
+        pub use self::wasi::*;
     } else if #[cfg(target_arch = "wasm32")] {
         mod wasm;
         pub use self::wasm::*;
@@ -51,8 +54,8 @@ cfg_if! {
 // Windows when we're compiling for Linux.
 
 #[cfg(rustdoc)]
-cfg_if! {
-    if #[cfg(any(unix, target_os = "redox"))] {
+cfg_if::cfg_if! {
+    if #[cfg(unix)] {
         // On unix we'll document what's already available
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use self::ext as unix_ext;
@@ -74,7 +77,7 @@ cfg_if! {
 }
 
 #[cfg(rustdoc)]
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(windows)] {
         // On windows we'll just be documenting what's already available
         #[allow(missing_docs)]
diff --git a/src/libstd/sys/redox/backtrace/mod.rs b/src/libstd/sys/redox/backtrace/mod.rs
deleted file mode 100644
index 8ea2783580a..00000000000
--- a/src/libstd/sys/redox/backtrace/mod.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-/// See sys/unix/backtrace/mod.rs for an explanation of the method used here.
-
-pub use self::tracing::unwind_backtrace;
-pub use self::printing::{foreach_symbol_fileline, resolve_symname};
-
-// tracing impls:
-mod tracing;
-// symbol resolvers:
-mod printing;
-
-pub mod gnu {
-    use crate::io;
-    use crate::fs;
-    use crate::vec::Vec;
-    use crate::ffi::OsStr;
-    use crate::os::unix::ffi::OsStrExt;
-    use crate::io::Read;
-    use libc::c_char;
-
-    pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
-        let mut exefile = fs::File::open("sys:exe")?;
-        let mut exename = Vec::new();
-        exefile.read_to_end(&mut exename)?;
-        if exename.last() == Some(&b'\n') {
-            exename.pop();
-        }
-        let file = fs::File::open(OsStr::from_bytes(&exename))?;
-        Ok((exename.into_iter().map(|c| c as c_char).collect(), file))
-    }
-}
-
-pub struct BacktraceContext;
diff --git a/src/libstd/sys/redox/backtrace/printing.rs b/src/libstd/sys/redox/backtrace/printing.rs
deleted file mode 100644
index 489eed4562d..00000000000
--- a/src/libstd/sys/redox/backtrace/printing.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub use crate::sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs
deleted file mode 100644
index e7a68eadbde..00000000000
--- a/src/libstd/sys/redox/backtrace/tracing.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-use crate::error::Error;
-use crate::fmt;
-use crate::io;
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys_common::backtrace::Frame;
-
-use unwind as uw;
-
-struct Context<'a> {
-    idx: usize,
-    frames: &'a mut [Frame],
-}
-
-#[derive(Debug)]
-struct UnwindError(uw::_Unwind_Reason_Code);
-
-impl Error for UnwindError {
-    fn description(&self) -> &'static str {
-        "unexpected return value while unwinding"
-    }
-}
-
-impl fmt::Display for UnwindError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}: {:?}", self.description(), self.0)
-    }
-}
-
-#[inline(never)] // if we know this is a function call, we can skip it when
-                 // tracing
-pub fn unwind_backtrace(frames: &mut [Frame])
-    -> io::Result<(usize, BacktraceContext)>
-{
-    let mut cx = Context {
-        idx: 0,
-        frames: frames,
-    };
-    let result_unwind = unsafe {
-        uw::_Unwind_Backtrace(trace_fn,
-                              &mut cx as *mut Context
-                              as *mut libc::c_void)
-    };
-    // See libunwind:src/unwind/Backtrace.c for the return values.
-    // No, there is no doc.
-    match result_unwind {
-        // These return codes seem to be benign and need to be ignored for backtraces
-        // to show up properly on all tested platforms.
-        uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
-            Ok((cx.idx, BacktraceContext))
-        }
-        _ => {
-            Err(io::Error::new(io::ErrorKind::Other,
-                               UnwindError(result_unwind)))
-        }
-    }
-}
-
-extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
-                   arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
-    let cx = unsafe { &mut *(arg as *mut Context) };
-    if cx.idx >= cx.frames.len() {
-        return uw::_URC_NORMAL_STOP;
-    }
-
-    let mut ip_before_insn = 0;
-    let mut ip = unsafe {
-        uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
-    };
-    if !ip.is_null() && ip_before_insn == 0 {
-        // this is a non-signaling frame, so `ip` refers to the address
-        // after the calling instruction. account for that.
-        ip = (ip as usize - 1) as *mut _;
-    }
-
-    // dladdr() on osx gets whiny when we use FindEnclosingFunction, and
-    // it appears to work fine without it, so we only use
-    // FindEnclosingFunction on non-osx platforms. In doing so, we get a
-    // slightly more accurate stack trace in the process.
-    //
-    // This is often because panic involves the last instruction of a
-    // function being "call std::rt::begin_unwind", with no ret
-    // instructions after it. This means that the return instruction
-    // pointer points *outside* of the calling function, and by
-    // unwinding it we go back to the original function.
-    let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
-        ip
-    } else {
-        unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
-    };
-
-    cx.frames[cx.idx] = Frame {
-        symbol_addr: symaddr as *mut u8,
-        exact_position: ip as *mut u8,
-        inline_context: 0,
-    };
-    cx.idx += 1;
-
-    uw::_URC_NO_REASON
-}
diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs
deleted file mode 100644
index a6365cac23e..00000000000
--- a/src/libstd/sys/redox/condvar.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-use crate::cell::UnsafeCell;
-use crate::intrinsics::{atomic_cxchg, atomic_load, atomic_xadd, atomic_xchg};
-use crate::ptr;
-use crate::time::Duration;
-
-use crate::sys::mutex::{mutex_unlock, Mutex};
-use crate::sys::syscall::{futex, TimeSpec, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
-
-pub struct Condvar {
-    lock: UnsafeCell<*mut i32>,
-    seq: UnsafeCell<i32>
-}
-
-impl Condvar {
-    pub const fn new() -> Condvar {
-        Condvar {
-            lock: UnsafeCell::new(ptr::null_mut()),
-            seq: UnsafeCell::new(0)
-        }
-    }
-
-    #[inline]
-    pub unsafe fn init(&self) {
-        *self.lock.get() = ptr::null_mut();
-        *self.seq.get() = 0;
-    }
-
-    #[inline]
-    pub fn notify_one(&self) {
-        unsafe {
-            let seq = self.seq.get();
-
-            atomic_xadd(seq, 1);
-
-            let _ = futex(seq, FUTEX_WAKE, 1, 0, ptr::null_mut());
-        }
-    }
-
-    #[inline]
-    pub fn notify_all(&self) {
-        unsafe {
-            let lock = self.lock.get();
-            let seq = self.seq.get();
-
-            if *lock == ptr::null_mut() {
-                return;
-            }
-
-            atomic_xadd(seq, 1);
-
-            let _ = futex(seq, FUTEX_REQUEUE, 1, crate::usize::MAX, *lock);
-        }
-    }
-
-    #[inline]
-    unsafe fn wait_inner(&self, mutex: &Mutex, timeout_ptr: *const TimeSpec) -> bool {
-        let lock = self.lock.get();
-        let seq = self.seq.get();
-
-        if *lock != mutex.lock.get() {
-            if *lock != ptr::null_mut() {
-                panic!("Condvar used with more than one Mutex");
-            }
-
-            atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize);
-        }
-
-        mutex_unlock(*lock);
-
-        let seq_before = atomic_load(seq);
-
-        let _ = futex(seq, FUTEX_WAIT, seq_before, timeout_ptr as usize, ptr::null_mut());
-
-        let seq_after = atomic_load(seq);
-
-        while atomic_xchg(*lock, 2) != 0 {
-            let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut());
-        }
-
-        seq_before != seq_after
-    }
-
-    #[inline]
-    pub fn wait(&self, mutex: &Mutex) {
-        unsafe {
-            assert!(self.wait_inner(mutex, ptr::null()));
-        }
-    }
-
-    #[inline]
-    pub fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        unsafe {
-            let timeout = TimeSpec {
-                tv_sec: dur.as_secs() as i64,
-                tv_nsec: dur.subsec_nanos() as i32
-            };
-
-            self.wait_inner(mutex, &timeout as *const TimeSpec)
-        }
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        *self.lock.get() = ptr::null_mut();
-        *self.seq.get() = 0;
-    }
-}
-
-unsafe impl Send for Condvar {}
-
-unsafe impl Sync for Condvar {}
diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs
deleted file mode 100644
index 671498bc390..00000000000
--- a/src/libstd/sys/redox/ext/ffi.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-//! Redox-specific extension to the primitives in the `std::ffi` module.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use crate::ffi::{OsStr, OsString};
-use crate::mem;
-use crate::sys::os_str::Buf;
-use crate::sys_common::{FromInner, IntoInner, AsInner};
-
-/// Redox-specific extensions to [`OsString`].
-///
-/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStringExt {
-    /// Creates an `OsString` from a byte vector.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_vec(vec: Vec<u8>) -> Self;
-
-    /// Yields the underlying byte vector of this `OsString`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn into_vec(self) -> Vec<u8>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStringExt for OsString {
-    fn from_vec(vec: Vec<u8>) -> OsString {
-        FromInner::from_inner(Buf { inner: vec })
-    }
-    fn into_vec(self) -> Vec<u8> {
-        self.into_inner().inner
-    }
-}
-
-/// Redox-specific extensions to [`OsStr`].
-///
-/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStrExt {
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_bytes(slice: &[u8]) -> &Self;
-
-    /// Gets the underlying byte view of the `OsStr` slice.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn as_bytes(&self) -> &[u8];
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStrExt for OsStr {
-    fn from_bytes(slice: &[u8]) -> &OsStr {
-        unsafe { mem::transmute(slice) }
-    }
-    fn as_bytes(&self) -> &[u8] {
-        &self.as_inner().inner
-    }
-}
diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs
deleted file mode 100644
index 53b9dd68f73..00000000000
--- a/src/libstd/sys/redox/ext/fs.rs
+++ /dev/null
@@ -1,339 +0,0 @@
-//! Redox-specific extensions to primitives in the `std::fs` module.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use crate::fs::{self, Permissions, OpenOptions};
-use crate::io;
-use crate::path::Path;
-use crate::sys;
-use crate::sys_common::{FromInner, AsInner, AsInnerMut};
-
-/// Redox-specific extensions to [`fs::Permissions`].
-///
-/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
-#[stable(feature = "fs_ext", since = "1.1.0")]
-pub trait PermissionsExt {
-    /// Returns the underlying raw `mode_t` bits that are the standard Redox
-    /// permissions for this file.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::os::redox::fs::PermissionsExt;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::create("foo.txt")?;
-    ///     let metadata = f.metadata()?;
-    ///     let permissions = metadata.permissions();
-    ///
-    ///     println!("permissions: {}", permissions.mode());
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "fs_ext", since = "1.1.0")]
-    fn mode(&self) -> u32;
-
-    /// Sets the underlying raw bits for this set of permissions.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::os::redox::fs::PermissionsExt;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f = File::create("foo.txt")?;
-    ///     let metadata = f.metadata()?;
-    ///     let mut permissions = metadata.permissions();
-    ///
-    ///     permissions.set_mode(0o644); // Read/write for owner and read for others.
-    ///     assert_eq!(permissions.mode(), 0o644);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "fs_ext", since = "1.1.0")]
-    fn set_mode(&mut self, mode: u32);
-
-    /// Creates a new instance of `Permissions` from the given set of Redox
-    /// permission bits.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::fs::Permissions;
-    /// use std::os::redox::fs::PermissionsExt;
-    ///
-    /// // Read/write for owner and read for others.
-    /// let permissions = Permissions::from_mode(0o644);
-    /// assert_eq!(permissions.mode(), 0o644);
-    /// ```
-    #[stable(feature = "fs_ext", since = "1.1.0")]
-    fn from_mode(mode: u32) -> Self;
-}
-
-#[stable(feature = "fs_ext", since = "1.1.0")]
-impl PermissionsExt for Permissions {
-    fn mode(&self) -> u32 {
-        self.as_inner().mode()
-    }
-
-    fn set_mode(&mut self, mode: u32) {
-        *self = Permissions::from_inner(FromInner::from_inner(mode));
-    }
-
-    fn from_mode(mode: u32) -> Permissions {
-        Permissions::from_inner(FromInner::from_inner(mode))
-    }
-}
-
-/// Redox-specific extensions to [`fs::OpenOptions`].
-///
-/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
-#[stable(feature = "fs_ext", since = "1.1.0")]
-pub trait OpenOptionsExt {
-    /// Sets the mode bits that a new file will be created with.
-    ///
-    /// If a new file is created as part of a `File::open_opts` call then this
-    /// specified `mode` will be used as the permission bits for the new file.
-    /// If no `mode` is set, the default of `0o666` will be used.
-    /// The operating system masks out bits with the systems `umask`, to produce
-    /// the final permissions.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// # #![feature(libc)]
-    /// extern crate libc;
-    /// use std::fs::OpenOptions;
-    /// use std::os::redox::fs::OpenOptionsExt;
-    ///
-    /// # fn main() {
-    /// let mut options = OpenOptions::new();
-    /// options.mode(0o644); // Give read/write for owner and read for others.
-    /// let file = options.open("foo.txt");
-    /// # }
-    /// ```
-    #[stable(feature = "fs_ext", since = "1.1.0")]
-    fn mode(&mut self, mode: u32) -> &mut Self;
-
-    /// Passes custom flags to the `flags` argument of `open`.
-    ///
-    /// The bits that define the access mode are masked out with `O_ACCMODE`, to
-    /// ensure they do not interfere with the access mode set by Rusts options.
-    ///
-    /// Custom flags can only set flags, not remove flags set by Rusts options.
-    /// This options overwrites any previously set custom flags.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// # #![feature(libc)]
-    /// extern crate libc;
-    /// use std::fs::OpenOptions;
-    /// use std::os::redox::fs::OpenOptionsExt;
-    ///
-    /// # fn main() {
-    /// let mut options = OpenOptions::new();
-    /// options.write(true);
-    /// if cfg!(target_os = "redox") {
-    ///     options.custom_flags(libc::O_NOFOLLOW);
-    /// }
-    /// let file = options.open("foo.txt");
-    /// # }
-    /// ```
-    #[stable(feature = "open_options_ext", since = "1.10.0")]
-    fn custom_flags(&mut self, flags: i32) -> &mut Self;
-}
-
-#[stable(feature = "fs_ext", since = "1.1.0")]
-impl OpenOptionsExt for OpenOptions {
-    fn mode(&mut self, mode: u32) -> &mut OpenOptions {
-        self.as_inner_mut().mode(mode); self
-    }
-
-    fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
-        self.as_inner_mut().custom_flags(flags); self
-    }
-}
-
-/// Redox-specific extensions to [`fs::Metadata`].
-///
-/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
-#[stable(feature = "metadata_ext", since = "1.1.0")]
-pub trait MetadataExt {
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn dev(&self) -> u64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn ino(&self) -> u64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn mode(&self) -> u32;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn nlink(&self) -> u64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn uid(&self) -> u32;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn gid(&self) -> u32;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn size(&self) -> u64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn atime(&self) -> i64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn atime_nsec(&self) -> i64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn mtime(&self) -> i64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn mtime_nsec(&self) -> i64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn ctime(&self) -> i64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn ctime_nsec(&self) -> i64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn blksize(&self) -> u64;
-    #[stable(feature = "metadata_ext", since = "1.1.0")]
-    fn blocks(&self) -> u64;
-}
-
-// Hm, why are there casts here to the returned type, shouldn't the types always
-// be the same? Right you are! Turns out, however, on android at least the types
-// in the raw `stat` structure are not the same as the types being returned. Who
-// knew!
-//
-// As a result to make sure this compiles for all platforms we do the manual
-// casts and rely on manual lowering to `stat` if the raw type is desired.
-#[stable(feature = "metadata_ext", since = "1.1.0")]
-impl MetadataExt for fs::Metadata {
-    fn dev(&self) -> u64 {
-        self.as_inner().as_inner().st_dev as u64
-    }
-    fn ino(&self) -> u64 {
-        self.as_inner().as_inner().st_ino as u64
-    }
-    fn mode(&self) -> u32 {
-        self.as_inner().as_inner().st_mode as u32
-    }
-    fn nlink(&self) -> u64 {
-        self.as_inner().as_inner().st_nlink as u64
-    }
-    fn uid(&self) -> u32 {
-        self.as_inner().as_inner().st_uid as u32
-    }
-    fn gid(&self) -> u32 {
-        self.as_inner().as_inner().st_gid as u32
-    }
-    fn size(&self) -> u64 {
-        self.as_inner().as_inner().st_size as u64
-    }
-    fn atime(&self) -> i64 {
-        self.as_inner().as_inner().st_atime as i64
-    }
-    fn atime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_atime_nsec as i64
-    }
-    fn mtime(&self) -> i64 {
-        self.as_inner().as_inner().st_mtime as i64
-    }
-    fn mtime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_mtime_nsec as i64
-    }
-    fn ctime(&self) -> i64 {
-        self.as_inner().as_inner().st_ctime as i64
-    }
-    fn ctime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_ctime_nsec as i64
-    }
-    fn blksize(&self) -> u64 {
-        self.as_inner().as_inner().st_blksize as u64
-    }
-    fn blocks(&self) -> u64 {
-        self.as_inner().as_inner().st_blocks as u64
-    }
-}
-
-/// Redox-specific extensions for [`FileType`].
-///
-/// Adds support for special Unix file types such as block/character devices,
-/// pipes, and sockets.
-///
-/// [`FileType`]: ../../../../std/fs/struct.FileType.html
-#[stable(feature = "file_type_ext", since = "1.5.0")]
-pub trait FileTypeExt {
-    /// Returns whether this file type is a block device.
-    #[stable(feature = "file_type_ext", since = "1.5.0")]
-    fn is_block_device(&self) -> bool;
-    /// Returns whether this file type is a char device.
-    #[stable(feature = "file_type_ext", since = "1.5.0")]
-    fn is_char_device(&self) -> bool;
-    /// Returns whether this file type is a fifo.
-    #[stable(feature = "file_type_ext", since = "1.5.0")]
-    fn is_fifo(&self) -> bool;
-    /// Returns whether this file type is a socket.
-    #[stable(feature = "file_type_ext", since = "1.5.0")]
-    fn is_socket(&self) -> bool;
-}
-
-#[stable(feature = "file_type_ext", since = "1.5.0")]
-impl FileTypeExt for fs::FileType {
-    fn is_block_device(&self) -> bool { false /*FIXME: Implement block device mode*/ }
-    fn is_char_device(&self) -> bool { false /*FIXME: Implement char device mode*/ }
-    fn is_fifo(&self) -> bool { false /*FIXME: Implement fifo mode*/ }
-    fn is_socket(&self) -> bool { false /*FIXME: Implement socket mode*/ }
-}
-
-/// Creates a new symbolic link on the filesystem.
-///
-/// The `dst` path will be a symbolic link pointing to the `src` path.
-///
-/// # Note
-///
-/// On Windows, you must specify whether a symbolic link points to a file
-/// or directory. Use `os::windows::fs::symlink_file` to create a
-/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
-/// symbolic link to a directory. Additionally, the process must have
-/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
-/// symbolic link.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::os::redox::fs;
-///
-/// fn main() -> std::io::Result<()> {
-///     fs::symlink("a.txt", "b.txt")?;
-///     Ok(())
-/// }
-/// ```
-#[stable(feature = "symlink", since = "1.1.0")]
-pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
-{
-    sys::fs::symlink(src.as_ref(), dst.as_ref())
-}
-
-/// Redox-specific extensions to [`fs::DirBuilder`].
-///
-/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
-#[stable(feature = "dir_builder", since = "1.6.0")]
-pub trait DirBuilderExt {
-    /// Sets the mode to create new directories with. This option defaults to
-    /// 0o777.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::DirBuilder;
-    /// use std::os::redox::fs::DirBuilderExt;
-    ///
-    /// let mut builder = DirBuilder::new();
-    /// builder.mode(0o755);
-    /// ```
-    #[stable(feature = "dir_builder", since = "1.6.0")]
-    fn mode(&mut self, mode: u32) -> &mut Self;
-}
-
-#[stable(feature = "dir_builder", since = "1.6.0")]
-impl DirBuilderExt for fs::DirBuilder {
-    fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
-        self.as_inner_mut().set_mode(mode);
-        self
-    }
-}
diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs
deleted file mode 100644
index 8a2d243c7ff..00000000000
--- a/src/libstd/sys/redox/ext/mod.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-//! Experimental extensions to `std` for Unix platforms.
-//!
-//! For now, this module is limited to extracting file descriptors,
-//! but its functionality will grow over time.
-//!
-//! # Examples
-//!
-//! ```no_run
-//! use std::fs::File;
-//! use std::os::unix::prelude::*;
-//!
-//! fn main() {
-//!     let f = File::create("foo.txt").unwrap();
-//!     let fd = f.as_raw_fd();
-//!
-//!     // use fd with native unix bindings
-//! }
-//! ```
-
-#![stable(feature = "rust1", since = "1.0.0")]
-#![doc(cfg(target_os = "redox"))]
-
-pub mod ffi;
-pub mod fs;
-pub mod io;
-pub mod net;
-pub mod process;
-pub mod thread;
-
-/// A prelude for conveniently writing platform-specific code.
-///
-/// Includes all extension traits, and some important type definitions.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod prelude {
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::ffi::{OsStrExt, OsStringExt};
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::fs::{FileTypeExt, PermissionsExt, OpenOptionsExt, MetadataExt};
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::thread::JoinHandleExt;
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::process::{CommandExt, ExitStatusExt};
-}
diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs
deleted file mode 100644
index 2c121787804..00000000000
--- a/src/libstd/sys/redox/ext/net.rs
+++ /dev/null
@@ -1,759 +0,0 @@
-#![stable(feature = "unix_socket_redox", since = "1.29")]
-
-//! Unix-specific networking functionality
-
-use crate::fmt;
-use crate::io::{self, Error, ErrorKind, Initializer};
-use crate::net::Shutdown;
-use crate::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
-use crate::path::Path;
-use crate::time::Duration;
-use crate::sys::{cvt, fd::FileDesc, syscall};
-
-/// An address associated with a Unix socket.
-///
-/// # Examples
-///
-/// ```
-/// use std::os::unix::net::UnixListener;
-///
-/// let socket = match UnixListener::bind("/tmp/sock") {
-///     Ok(sock) => sock,
-///     Err(e) => {
-///         println!("Couldn't bind: {:?}", e);
-///         return
-///     }
-/// };
-/// let addr = socket.local_addr().expect("Couldn't get local address");
-/// ```
-#[derive(Clone)]
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-pub struct SocketAddr(());
-
-impl SocketAddr {
-    /// Returns the contents of this address if it is a `pathname` address.
-    ///
-    /// # Examples
-    ///
-    /// With a pathname:
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    /// use std::path::Path;
-    ///
-    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
-    /// ```
-    ///
-    /// Without a pathname:
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let socket = UnixDatagram::unbound().unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.as_pathname(), None);
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn as_pathname(&self) -> Option<&Path> {
-        None
-    }
-
-    /// Returns `true` if the address is unnamed.
-    ///
-    /// # Examples
-    ///
-    /// A named address:
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.is_unnamed(), false);
-    /// ```
-    ///
-    /// An unnamed address:
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let socket = UnixDatagram::unbound().unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// assert_eq!(addr.is_unnamed(), true);
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn is_unnamed(&self) -> bool {
-        false
-    }
-}
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl fmt::Debug for SocketAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "SocketAddr")
-    }
-}
-
-/// A Unix stream socket.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::os::unix::net::UnixStream;
-/// use std::io::prelude::*;
-///
-/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap();
-/// stream.write_all(b"hello world").unwrap();
-/// let mut response = String::new();
-/// stream.read_to_string(&mut response).unwrap();
-/// println!("{}", response);
-/// ```
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-pub struct UnixStream(FileDesc);
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl fmt::Debug for UnixStream {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixStream");
-        builder.field("fd", &self.0.raw());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        if let Ok(addr) = self.peer_addr() {
-            builder.field("peer", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixStream {
-    /// Connects to the socket named by `path`.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = match UnixStream::connect("/tmp/sock") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't connect: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
-        if let Some(s) = path.as_ref().to_str() {
-            cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC))
-                .map(FileDesc::new)
-                .map(UnixStream)
-        } else {
-            Err(Error::new(
-                ErrorKind::Other,
-                "UnixStream::connect: non-utf8 paths not supported on redox"
-            ))
-        }
-    }
-
-    /// Creates an unnamed pair of connected sockets.
-    ///
-    /// Returns two `UnixStream`s which are connected to each other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let (sock1, sock2) = match UnixStream::pair() {
-    ///     Ok((sock1, sock2)) => (sock1, sock2),
-    ///     Err(e) => {
-    ///         println!("Couldn't create a pair of sockets: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
-        let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC))
-            .map(FileDesc::new)?;
-        let client = server.duplicate_path(b"connect")?;
-        let stream = server.duplicate_path(b"listen")?;
-        Ok((UnixStream(client), UnixStream(stream)))
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixStream` is a reference to the same stream that this
-    /// object references. Both handles will read and write the same stream of
-    /// data, and options set on one stream will be propagated to the other
-    /// stream.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn try_clone(&self) -> io::Result<UnixStream> {
-        self.0.duplicate().map(UnixStream)
-    }
-
-    /// Returns the socket address of the local half of this connection.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let addr = socket.local_addr().expect("Couldn't get local address");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox"))
-    }
-
-    /// Returns the socket address of the remote half of this connection.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let addr = socket.peer_addr().expect("Couldn't get peer address");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox"))
-    }
-
-    /// Sets the read timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`read`] calls will block
-    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
-    /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
-    /// [`Duration`]: ../../../../std/time/struct.Duration.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
-    /// let err = result.unwrap_err();
-    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn set_read_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
-        Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox"))
-    }
-
-    /// Sets the write timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`write`] calls will block
-    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
-    /// passed to this method.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
-    /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
-    /// [`Duration`]: ../../../../std/time/struct.Duration.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::net::UdpSocket;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
-    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
-    /// let err = result.unwrap_err();
-    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn set_write_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
-        Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox"))
-    }
-
-    /// Returns the read timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
-    /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox"))
-    }
-
-    /// Returns the write timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
-    /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox"))
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// if let Ok(Some(err)) = socket.take_error() {
-    ///     println!("Got error: {:?}", err);
-    /// }
-    /// ```
-    ///
-    /// # Platform specific
-    /// On Redox this always returns `None`.
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        Ok(None)
-    }
-
-    /// Shuts down the read, write, or both halves of this connection.
-    ///
-    /// This function will cause all pending and future I/O calls on the
-    /// specified portions to immediately return with an appropriate value
-    /// (see the documentation of [`Shutdown`]).
-    ///
-    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::net::Shutdown;
-    ///
-    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
-    /// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> {
-        Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox"))
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl io::Read for UnixStream {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        io::Read::read(&mut &*self, buf)
-    }
-
-    #[inline]
-    unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl<'a> io::Read for &'a UnixStream {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-
-    #[inline]
-    unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl io::Write for UnixStream {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        io::Write::write(&mut &*self, buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        io::Write::flush(&mut &*self)
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl<'a> io::Write for &'a UnixStream {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl AsRawFd for UnixStream {
-    fn as_raw_fd(&self) -> RawFd {
-        self.0.raw()
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl FromRawFd for UnixStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
-        UnixStream(FileDesc::new(fd))
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl IntoRawFd for UnixStream {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_raw()
-    }
-}
-
-/// A structure representing a Unix domain socket server.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::thread;
-/// use std::os::unix::net::{UnixStream, UnixListener};
-///
-/// fn handle_client(stream: UnixStream) {
-///     // ...
-/// }
-///
-/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-///
-/// // accept connections and process them, spawning a new thread for each one
-/// for stream in listener.incoming() {
-///     match stream {
-///         Ok(stream) => {
-///             /* connection succeeded */
-///             thread::spawn(|| handle_client(stream));
-///         }
-///         Err(err) => {
-///             /* connection failed */
-///             break;
-///         }
-///     }
-/// }
-/// ```
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-pub struct UnixListener(FileDesc);
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl fmt::Debug for UnixListener {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixListener");
-        builder.field("fd", &self.0.raw());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixListener {
-    /// Creates a new `UnixListener` bound to the specified socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = match UnixListener::bind("/path/to/the/socket") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't connect: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
-        if let Some(s) = path.as_ref().to_str() {
-            cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC))
-                .map(FileDesc::new)
-                .map(UnixListener)
-        } else {
-            Err(Error::new(
-                ErrorKind::Other,
-                "UnixListener::bind: non-utf8 paths not supported on redox"
-            ))
-        }
-    }
-
-    /// Accepts a new incoming connection to this listener.
-    ///
-    /// This function will block the calling thread until a new Unix connection
-    /// is established. When established, the corresponding [`UnixStream`] and
-    /// the remote peer's address will be returned.
-    ///
-    /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// match listener.accept() {
-    ///     Ok((socket, addr)) => println!("Got a client: {:?}", addr),
-    ///     Err(e) => println!("accept function failed: {:?}", e),
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
-        self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(())))
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixListener` is a reference to the same socket that this
-    /// object references. Both handles can be used to accept incoming
-    /// connections and options set on one listener will affect the other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// let listener_copy = listener.try_clone().expect("try_clone failed");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn try_clone(&self) -> io::Result<UnixListener> {
-        self.0.duplicate().map(UnixListener)
-    }
-
-    /// Returns the local socket address of this listener.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// let addr = listener.local_addr().expect("Couldn't get local address");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox"))
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// listener.set_nonblocking(true).expect("Couldn't set non blocking");
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = UnixListener::bind("/tmp/sock").unwrap();
-    ///
-    /// if let Ok(Some(err)) = listener.take_error() {
-    ///     println!("Got error: {:?}", err);
-    /// }
-    /// ```
-    ///
-    /// # Platform specific
-    /// On Redox this always returns `None`.
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        Ok(None)
-    }
-
-    /// Returns an iterator over incoming connections.
-    ///
-    /// The iterator will never return [`None`] and will also not yield the
-    /// peer's [`SocketAddr`] structure.
-    ///
-    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-    /// [`SocketAddr`]: struct.SocketAddr.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::thread;
-    /// use std::os::unix::net::{UnixStream, UnixListener};
-    ///
-    /// fn handle_client(stream: UnixStream) {
-    ///     // ...
-    /// }
-    ///
-    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-    ///
-    /// for stream in listener.incoming() {
-    ///     match stream {
-    ///         Ok(stream) => {
-    ///             thread::spawn(|| handle_client(stream));
-    ///         }
-    ///         Err(err) => {
-    ///             break;
-    ///         }
-    ///     }
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket_redox", since = "1.29")]
-    pub fn incoming<'a>(&'a self) -> Incoming<'a> {
-        Incoming { listener: self }
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl AsRawFd for UnixListener {
-    fn as_raw_fd(&self) -> RawFd {
-        self.0.raw()
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl FromRawFd for UnixListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
-        UnixListener(FileDesc::new(fd))
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl IntoRawFd for UnixListener {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_raw()
-    }
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl<'a> IntoIterator for &'a UnixListener {
-    type Item = io::Result<UnixStream>;
-    type IntoIter = Incoming<'a>;
-
-    fn into_iter(self) -> Incoming<'a> {
-        self.incoming()
-    }
-}
-
-/// An iterator over incoming connections to a [`UnixListener`].
-///
-/// It will never return [`None`].
-///
-/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
-/// [`UnixListener`]: struct.UnixListener.html
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::thread;
-/// use std::os::unix::net::{UnixStream, UnixListener};
-///
-/// fn handle_client(stream: UnixStream) {
-///     // ...
-/// }
-///
-/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
-///
-/// for stream in listener.incoming() {
-///     match stream {
-///         Ok(stream) => {
-///             thread::spawn(|| handle_client(stream));
-///         }
-///         Err(err) => {
-///             break;
-///         }
-///     }
-/// }
-/// ```
-#[derive(Debug)]
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-pub struct Incoming<'a> {
-    listener: &'a UnixListener,
-}
-
-#[stable(feature = "unix_socket_redox", since = "1.29")]
-impl<'a> Iterator for Incoming<'a> {
-    type Item = io::Result<UnixStream>;
-
-    fn next(&mut self) -> Option<io::Result<UnixStream>> {
-        Some(self.listener.accept().map(|s| s.0))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (usize::max_value(), None)
-    }
-}
diff --git a/src/libstd/sys/redox/ext/thread.rs b/src/libstd/sys/redox/ext/thread.rs
deleted file mode 100644
index 629eaef04ce..00000000000
--- a/src/libstd/sys/redox/ext/thread.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-//! Redox-specific extensions to primitives in the `std::thread` module.
-
-#![stable(feature = "thread_extensions", since = "1.9.0")]
-
-use crate::sys_common::{AsInner, IntoInner};
-use crate::thread::JoinHandle;
-
-#[stable(feature = "thread_extensions", since = "1.9.0")]
-#[allow(deprecated)]
-pub type RawPthread = usize;
-
-/// Redox-specific extensions to [`thread::JoinHandle`].
-///
-/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
-#[stable(feature = "thread_extensions", since = "1.9.0")]
-pub trait JoinHandleExt {
-    /// Extracts the raw pthread_t without taking ownership
-    #[stable(feature = "thread_extensions", since = "1.9.0")]
-    fn as_pthread_t(&self) -> RawPthread;
-
-    /// Consumes the thread, returning the raw pthread_t
-    ///
-    /// This function **transfers ownership** of the underlying pthread_t to
-    /// the caller. Callers are then the unique owners of the pthread_t and
-    /// must either detach or join the pthread_t once it's no longer needed.
-    #[stable(feature = "thread_extensions", since = "1.9.0")]
-    fn into_pthread_t(self) -> RawPthread;
-}
-
-#[stable(feature = "thread_extensions", since = "1.9.0")]
-impl<T> JoinHandleExt for JoinHandle<T> {
-    fn as_pthread_t(&self) -> RawPthread {
-        self.as_inner().id() as RawPthread
-    }
-
-    fn into_pthread_t(self) -> RawPthread {
-        self.into_inner().into_id() as RawPthread
-    }
-}
diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs
deleted file mode 100644
index 1202708a476..00000000000
--- a/src/libstd/sys/redox/fast_thread_local.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-#![cfg(target_thread_local)]
-#![unstable(feature = "thread_local_internals", issue = "0")]
-
-use crate::cell::{Cell, UnsafeCell};
-use crate::mem;
-use crate::ptr;
-
-
-pub struct Key<T> {
-    inner: UnsafeCell<Option<T>>,
-
-    // Metadata to keep track of the state of the destructor. Remember that
-    // these variables are thread-local, not global.
-    dtor_registered: Cell<bool>,
-    dtor_running: Cell<bool>,
-}
-
-unsafe impl<T> Sync for Key<T> { }
-
-impl<T> Key<T> {
-    pub const fn new() -> Key<T> {
-        Key {
-            inner: UnsafeCell::new(None),
-            dtor_registered: Cell::new(false),
-            dtor_running: Cell::new(false)
-        }
-    }
-
-    pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
-        unsafe {
-            if mem::needs_drop::<T>() && self.dtor_running.get() {
-                return None
-            }
-            self.register_dtor();
-        }
-        Some(&self.inner)
-    }
-
-    unsafe fn register_dtor(&self) {
-        if !mem::needs_drop::<T>() || self.dtor_registered.get() {
-            return
-        }
-
-        register_dtor(self as *const _ as *mut u8,
-                      destroy_value::<T>);
-        self.dtor_registered.set(true);
-    }
-}
-
-pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
-    // The fallback implementation uses a vanilla OS-based TLS key to track
-    // the list of destructors that need to be run for this thread. The key
-    // then has its own destructor which runs all the other destructors.
-    //
-    // The destructor for DTORS is a little special in that it has a `while`
-    // loop to continuously drain the list of registered destructors. It
-    // *should* be the case that this loop always terminates because we
-    // provide the guarantee that a TLS key cannot be set after it is
-    // flagged for destruction.
-    use crate::sys_common::thread_local as os;
-
-    static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors));
-    type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
-    if DTORS.get().is_null() {
-        let v: Box<List> = box Vec::new();
-        DTORS.set(Box::into_raw(v) as *mut u8);
-    }
-    let list: &mut List = &mut *(DTORS.get() as *mut List);
-    list.push((t, dtor));
-
-    unsafe extern fn run_dtors(mut ptr: *mut u8) {
-        while !ptr.is_null() {
-            let list: Box<List> = Box::from_raw(ptr as *mut List);
-            for (ptr, dtor) in list.into_iter() {
-                dtor(ptr);
-            }
-            ptr = DTORS.get();
-            DTORS.set(ptr::null_mut());
-        }
-    }
-}
-
-pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
-    let ptr = ptr as *mut Key<T>;
-    // Right before we run the user destructor be sure to flag the
-    // destructor as running for this thread so calls to `get` will return
-    // `None`.
-    (*ptr).dtor_running.set(true);
-
-    // The macOS implementation of TLS apparently had an odd aspect to it
-    // where the pointer we have may be overwritten while this destructor
-    // is running. Specifically if a TLS destructor re-accesses TLS it may
-    // trigger a re-initialization of all TLS variables, paving over at
-    // least some destroyed ones with initial values.
-    //
-    // This means that if we drop a TLS value in place on macOS that we could
-    // revert the value to its original state halfway through the
-    // destructor, which would be bad!
-    //
-    // Hence, we use `ptr::read` on macOS (to move to a "safe" location)
-    // instead of drop_in_place.
-    if cfg!(target_os = "macos") {
-        ptr::read((*ptr).inner.get());
-    } else {
-        ptr::drop_in_place((*ptr).inner.get());
-    }
-}
-
-pub fn requires_move_before_drop() -> bool {
-    false
-}
diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs
deleted file mode 100644
index a42e486db22..00000000000
--- a/src/libstd/sys/redox/fd.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-#![unstable(reason = "not public", issue = "0", feature = "fd")]
-
-use crate::io::{self, Read};
-use crate::mem;
-use crate::sys::{cvt, syscall};
-use crate::sys_common::AsInner;
-
-pub struct FileDesc {
-    fd: usize,
-}
-
-impl FileDesc {
-    pub fn new(fd: usize) -> FileDesc {
-        FileDesc { fd }
-    }
-
-    pub fn raw(&self) -> usize { self.fd }
-
-    /// Extracts the actual file descriptor without closing it.
-    pub fn into_raw(self) -> usize {
-        let fd = self.fd;
-        mem::forget(self);
-        fd
-    }
-
-    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        cvt(syscall::read(self.fd, buf))
-    }
-
-    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        let mut me = self;
-        (&mut me).read_to_end(buf)
-    }
-
-    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        cvt(syscall::write(self.fd, buf))
-    }
-
-    pub fn duplicate(&self) -> io::Result<FileDesc> {
-        self.duplicate_path(&[])
-    }
-    pub fn duplicate_path(&self, path: &[u8]) -> io::Result<FileDesc> {
-        let new_fd = cvt(syscall::dup(self.fd, path))?;
-        Ok(FileDesc::new(new_fd))
-    }
-
-    pub fn nonblocking(&self) -> io::Result<bool> {
-        let flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?;
-        Ok(flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK)
-    }
-
-    pub fn set_cloexec(&self) -> io::Result<()> {
-        let mut flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFD, 0))?;
-        flags |= syscall::O_CLOEXEC;
-        cvt(syscall::fcntl(self.fd, syscall::F_SETFD, flags)).and(Ok(()))
-    }
-
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        let mut flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?;
-        if nonblocking {
-            flags |= syscall::O_NONBLOCK;
-        } else {
-            flags &= !syscall::O_NONBLOCK;
-        }
-        cvt(syscall::fcntl(self.fd, syscall::F_SETFL, flags)).and(Ok(()))
-    }
-}
-
-impl<'a> Read for &'a FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        (**self).read(buf)
-    }
-}
-
-impl AsInner<usize> for FileDesc {
-    fn as_inner(&self) -> &usize { &self.fd }
-}
-
-impl Drop for FileDesc {
-    fn drop(&mut self) {
-        // Note that errors are ignored when closing a file descriptor. The
-        // reason for this is that if an error occurs we don't actually know if
-        // the file descriptor was closed or not, and if we retried (for
-        // something like EINTR), we might close another valid file descriptor
-        // (opened after we closed ours.
-        let _ = syscall::close(self.fd);
-    }
-}
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
deleted file mode 100644
index 159ee9911bd..00000000000
--- a/src/libstd/sys/redox/fs.rs
+++ /dev/null
@@ -1,473 +0,0 @@
-use crate::os::unix::prelude::*;
-
-use crate::ffi::{OsString, OsStr};
-use crate::fmt;
-use crate::io::{self, Error, ErrorKind, SeekFrom};
-use crate::path::{Path, PathBuf};
-use crate::sync::Arc;
-use crate::sys::fd::FileDesc;
-use crate::sys::time::SystemTime;
-use crate::sys::{cvt, syscall};
-use crate::sys_common::{AsInner, FromInner};
-
-pub struct File(FileDesc);
-
-#[derive(Clone)]
-pub struct FileAttr {
-    stat: syscall::Stat,
-}
-
-pub struct ReadDir {
-    data: Vec<u8>,
-    i: usize,
-    root: Arc<PathBuf>,
-}
-
-struct Dir(FileDesc);
-
-unsafe impl Send for Dir {}
-unsafe impl Sync for Dir {}
-
-pub struct DirEntry {
-    root: Arc<PathBuf>,
-    name: Box<[u8]>
-}
-
-#[derive(Clone, Debug)]
-pub struct OpenOptions {
-    // generic
-    read: bool,
-    write: bool,
-    append: bool,
-    truncate: bool,
-    create: bool,
-    create_new: bool,
-    // system-specific
-    custom_flags: i32,
-    mode: u16,
-}
-
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct FilePermissions { mode: u16 }
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub struct FileType { mode: u16 }
-
-#[derive(Debug)]
-pub struct DirBuilder { mode: u16 }
-
-impl FileAttr {
-    pub fn size(&self) -> u64 { self.stat.st_size as u64 }
-    pub fn perm(&self) -> FilePermissions {
-        FilePermissions { mode: (self.stat.st_mode as u16) & 0o777 }
-    }
-
-    pub fn file_type(&self) -> FileType {
-        FileType { mode: self.stat.st_mode as u16 }
-    }
-}
-
-impl FileAttr {
-    pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(syscall::TimeSpec {
-            tv_sec: self.stat.st_mtime as i64,
-            tv_nsec: self.stat.st_mtime_nsec as i32,
-        }))
-    }
-
-    pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(syscall::TimeSpec {
-            tv_sec: self.stat.st_atime as i64,
-            tv_nsec: self.stat.st_atime_nsec as i32,
-        }))
-    }
-
-    pub fn created(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(syscall::TimeSpec {
-            tv_sec: self.stat.st_ctime as i64,
-            tv_nsec: self.stat.st_ctime_nsec as i32,
-        }))
-    }
-}
-
-impl AsInner<syscall::Stat> for FileAttr {
-    fn as_inner(&self) -> &syscall::Stat { &self.stat }
-}
-
-impl FilePermissions {
-    pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
-    pub fn set_readonly(&mut self, readonly: bool) {
-        if readonly {
-            self.mode &= !0o222;
-        } else {
-            self.mode |= 0o222;
-        }
-    }
-    pub fn mode(&self) -> u32 { self.mode as u32 }
-}
-
-impl FileType {
-    pub fn is_dir(&self) -> bool { self.is(syscall::MODE_DIR) }
-    pub fn is_file(&self) -> bool { self.is(syscall::MODE_FILE) }
-    pub fn is_symlink(&self) -> bool { self.is(syscall::MODE_SYMLINK) }
-
-    pub fn is(&self, mode: u16) -> bool {
-        self.mode & syscall::MODE_TYPE == mode
-    }
-}
-
-impl FromInner<u32> for FilePermissions {
-    fn from_inner(mode: u32) -> FilePermissions {
-        FilePermissions { mode: mode as u16 }
-    }
-}
-
-impl fmt::Debug for ReadDir {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
-        // Thus the result will be e g 'ReadDir("/home")'
-        fmt::Debug::fmt(&*self.root, f)
-    }
-}
-
-impl Iterator for ReadDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        loop {
-            let start = self.i;
-            let mut i = self.i;
-            while i < self.data.len() {
-                self.i += 1;
-                if self.data[i] == b'\n' {
-                    break;
-                }
-                i += 1;
-            }
-            if start < self.i {
-                let ret = DirEntry {
-                    name: self.data[start .. i].to_owned().into_boxed_slice(),
-                    root: self.root.clone()
-                };
-                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
-                    return Some(Ok(ret))
-                }
-            } else {
-                return None;
-            }
-        }
-    }
-}
-
-impl DirEntry {
-    pub fn path(&self) -> PathBuf {
-        self.root.join(OsStr::from_bytes(self.name_bytes()))
-    }
-
-    pub fn file_name(&self) -> OsString {
-        OsStr::from_bytes(self.name_bytes()).to_os_string()
-    }
-
-    pub fn metadata(&self) -> io::Result<FileAttr> {
-        lstat(&self.path())
-    }
-
-    pub fn file_type(&self) -> io::Result<FileType> {
-        lstat(&self.path()).map(|m| m.file_type())
-    }
-
-    fn name_bytes(&self) -> &[u8] {
-        &*self.name
-    }
-}
-
-impl OpenOptions {
-    pub fn new() -> OpenOptions {
-        OpenOptions {
-            // generic
-            read: false,
-            write: false,
-            append: false,
-            truncate: false,
-            create: false,
-            create_new: false,
-            // system-specific
-            custom_flags: 0,
-            mode: 0o666,
-        }
-    }
-
-    pub fn read(&mut self, read: bool) { self.read = read; }
-    pub fn write(&mut self, write: bool) { self.write = write; }
-    pub fn append(&mut self, append: bool) { self.append = append; }
-    pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
-    pub fn create(&mut self, create: bool) { self.create = create; }
-    pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
-
-    pub fn custom_flags(&mut self, flags: i32) { self.custom_flags = flags; }
-    pub fn mode(&mut self, mode: u32) { self.mode = mode as u16; }
-
-    fn get_access_mode(&self) -> io::Result<usize> {
-        match (self.read, self.write, self.append) {
-            (true,  false, false) => Ok(syscall::O_RDONLY),
-            (false, true,  false) => Ok(syscall::O_WRONLY),
-            (true,  true,  false) => Ok(syscall::O_RDWR),
-            (false, _,     true)  => Ok(syscall::O_WRONLY | syscall::O_APPEND),
-            (true,  _,     true)  => Ok(syscall::O_RDWR | syscall::O_APPEND),
-            (false, false, false) => Err(Error::from_raw_os_error(syscall::EINVAL)),
-        }
-    }
-
-    fn get_creation_mode(&self) -> io::Result<usize> {
-        match (self.write, self.append) {
-            (true, false) => {}
-            (false, false) =>
-                if self.truncate || self.create || self.create_new {
-                    return Err(Error::from_raw_os_error(syscall::EINVAL));
-                },
-            (_, true) =>
-                if self.truncate && !self.create_new {
-                    return Err(Error::from_raw_os_error(syscall::EINVAL));
-                },
-        }
-
-        Ok(match (self.create, self.truncate, self.create_new) {
-                (false, false, false) => 0,
-                (true,  false, false) => syscall::O_CREAT,
-                (false, true,  false) => syscall::O_TRUNC,
-                (true,  true,  false) => syscall::O_CREAT | syscall::O_TRUNC,
-                (_,      _,    true)  => syscall::O_CREAT | syscall::O_EXCL,
-           })
-    }
-}
-
-impl File {
-    pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
-        let flags = syscall::O_CLOEXEC |
-                    opts.get_access_mode()? as usize |
-                    opts.get_creation_mode()? as usize |
-                    (opts.custom_flags as usize & !syscall::O_ACCMODE);
-        let fd = cvt(syscall::open(path.to_str().unwrap(), flags | opts.mode as usize))?;
-        Ok(File(FileDesc::new(fd)))
-    }
-
-    pub fn file_attr(&self) -> io::Result<FileAttr> {
-        let mut stat = syscall::Stat::default();
-        cvt(syscall::fstat(self.0.raw(), &mut stat))?;
-        Ok(FileAttr { stat })
-    }
-
-    pub fn fsync(&self) -> io::Result<()> {
-        cvt(syscall::fsync(self.0.raw()))?;
-        Ok(())
-    }
-
-    pub fn datasync(&self) -> io::Result<()> {
-        self.fsync()
-    }
-
-    pub fn truncate(&self, size: u64) -> io::Result<()> {
-        cvt(syscall::ftruncate(self.0.raw(), size as usize))?;
-        Ok(())
-    }
-
-    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-
-    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-
-    pub fn flush(&self) -> io::Result<()> { Ok(()) }
-
-    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
-        let (whence, pos) = match pos {
-            // Casting to `i64` is fine, too large values will end up as
-            // negative which will cause an error in `lseek64`.
-            SeekFrom::Start(off) => (syscall::SEEK_SET, off as i64),
-            SeekFrom::End(off) => (syscall::SEEK_END, off),
-            SeekFrom::Current(off) => (syscall::SEEK_CUR, off),
-        };
-        let n = cvt(syscall::lseek(self.0.raw(), pos as isize, whence))?;
-        Ok(n as u64)
-    }
-
-    pub fn duplicate(&self) -> io::Result<File> {
-        self.0.duplicate().map(File)
-    }
-
-    pub fn dup(&self, buf: &[u8]) -> io::Result<File> {
-        let fd = cvt(syscall::dup(*self.fd().as_inner() as usize, buf))?;
-        Ok(File(FileDesc::new(fd)))
-    }
-
-    pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
-        set_perm(&self.path()?, perm)
-    }
-
-    pub fn path(&self) -> io::Result<PathBuf> {
-        let mut buf: [u8; 4096] = [0; 4096];
-        let count = cvt(syscall::fpath(*self.fd().as_inner() as usize, &mut buf))?;
-        Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) }))
-    }
-
-    pub fn fd(&self) -> &FileDesc { &self.0 }
-
-    pub fn into_fd(self) -> FileDesc { self.0 }
-}
-
-impl DirBuilder {
-    pub fn new() -> DirBuilder {
-        DirBuilder { mode: 0o777 }
-    }
-
-    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
-        let flags = syscall::O_CREAT | syscall::O_CLOEXEC | syscall::O_DIRECTORY | syscall::O_EXCL;
-        let fd = cvt(syscall::open(p.to_str().unwrap(), flags | (self.mode as usize & 0o777)))?;
-        let _ = syscall::close(fd);
-        Ok(())
-    }
-
-    pub fn set_mode(&mut self, mode: u32) {
-        self.mode = mode as u16;
-    }
-}
-
-impl FromInner<usize> for File {
-    fn from_inner(fd: usize) -> File {
-        File(FileDesc::new(fd))
-    }
-}
-
-impl fmt::Debug for File {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let mut b = f.debug_struct("File");
-        b.field("fd", &self.0.raw());
-        if let Ok(path) = self.path() {
-            b.field("path", &path);
-        }
-        /*
-        if let Some((read, write)) = get_mode(fd) {
-            b.field("read", &read).field("write", &write);
-        }
-        */
-        b.finish()
-    }
-}
-
-pub fn readdir(p: &Path) -> io::Result<ReadDir> {
-    let root = Arc::new(p.to_path_buf());
-
-    let flags = syscall::O_CLOEXEC | syscall::O_RDONLY | syscall::O_DIRECTORY;
-    let fd = cvt(syscall::open(p.to_str().unwrap(), flags))?;
-    let file = FileDesc::new(fd);
-    let mut data = Vec::new();
-    file.read_to_end(&mut data)?;
-
-    Ok(ReadDir { data: data, i: 0, root: root })
-}
-
-pub fn unlink(p: &Path) -> io::Result<()> {
-    cvt(syscall::unlink(p.to_str().unwrap()))?;
-    Ok(())
-}
-
-pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
-    let fd = cvt(syscall::open(old.to_str().unwrap(),
-                               syscall::O_CLOEXEC | syscall::O_STAT | syscall::O_NOFOLLOW))?;
-    let res = cvt(syscall::frename(fd, new.to_str().unwrap()));
-    cvt(syscall::close(fd))?;
-    res?;
-    Ok(())
-}
-
-pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
-    cvt(syscall::chmod(p.to_str().unwrap(), perm.mode as usize))?;
-    Ok(())
-}
-
-pub fn rmdir(p: &Path) -> io::Result<()> {
-    cvt(syscall::rmdir(p.to_str().unwrap()))?;
-    Ok(())
-}
-
-pub fn remove_dir_all(path: &Path) -> io::Result<()> {
-    let filetype = lstat(path)?.file_type();
-    if filetype.is_symlink() {
-        unlink(path)
-    } else {
-        remove_dir_all_recursive(path)
-    }
-}
-
-fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
-    for child in readdir(path)? {
-        let child = child?;
-        if child.file_type()?.is_dir() {
-            remove_dir_all_recursive(&child.path())?;
-        } else {
-            unlink(&child.path())?;
-        }
-    }
-    rmdir(path)
-}
-
-pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    let fd = cvt(syscall::open(p.to_str().unwrap(),
-                               syscall::O_CLOEXEC | syscall::O_SYMLINK | syscall::O_RDONLY))?;
-    let mut buf: [u8; 4096] = [0; 4096];
-    let res = cvt(syscall::read(fd, &mut buf));
-    cvt(syscall::close(fd))?;
-    let count = res?;
-    Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) }))
-}
-
-pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let fd = cvt(syscall::open(dst.to_str().unwrap(),
-                               syscall::O_CLOEXEC | syscall::O_SYMLINK |
-                               syscall::O_CREAT | syscall::O_WRONLY | 0o777))?;
-    let res = cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()));
-    cvt(syscall::close(fd))?;
-    res?;
-    Ok(())
-}
-
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
-    Err(Error::from_raw_os_error(syscall::ENOSYS))
-}
-
-pub fn stat(p: &Path) -> io::Result<FileAttr> {
-    let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_STAT))?;
-    let file = File(FileDesc::new(fd));
-    file.file_attr()
-}
-
-pub fn lstat(p: &Path) -> io::Result<FileAttr> {
-    let fd = cvt(syscall::open(p.to_str().unwrap(),
-                               syscall::O_CLOEXEC | syscall::O_STAT | syscall::O_NOFOLLOW))?;
-    let file = File(FileDesc::new(fd));
-    file.file_attr()
-}
-
-pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
-    let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_STAT))?;
-    let file = File(FileDesc::new(fd));
-    file.path()
-}
-
-pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    use crate::fs::{File, set_permissions};
-    if !from.is_file() {
-        return Err(Error::new(ErrorKind::InvalidInput,
-                              "the source path is not an existing regular file"))
-    }
-
-    let mut reader = File::open(from)?;
-    let mut writer = File::create(to)?;
-    let perm = reader.metadata()?.permissions();
-
-    let ret = io::copy(&mut reader, &mut writer)?;
-    set_permissions(to, perm)?;
-    Ok(ret)
-}
diff --git a/src/libstd/sys/redox/io.rs b/src/libstd/sys/redox/io.rs
deleted file mode 100644
index 8b02d3fd19d..00000000000
--- a/src/libstd/sys/redox/io.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-pub struct IoVec<'a>(&'a [u8]);
-
-impl<'a> IoVec<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoVec<'a> {
-        IoVec(buf)
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-}
-
-pub struct IoVecMut<'a>(&'a mut [u8]);
-
-impl<'a> IoVecMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoVecMut<'a> {
-        IoVecMut(buf)
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        self.0
-    }
-}
diff --git a/src/libstd/sys/redox/memchr.rs b/src/libstd/sys/redox/memchr.rs
deleted file mode 100644
index d2bfcce86f4..00000000000
--- a/src/libstd/sys/redox/memchr.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-// Original implementation taken from rust-memchr.
-// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
-
-pub use core::slice::memchr::{memchr, memrchr};
diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs
deleted file mode 100644
index 7f3ac1f1bb5..00000000000
--- a/src/libstd/sys/redox/mod.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-#![allow(dead_code, missing_docs, nonstandard_style)]
-
-use crate::io::ErrorKind;
-
-pub use libc::strlen;
-pub use self::rand::hashmap_random_keys;
-
-#[path = "../unix/alloc.rs"]
-pub mod alloc;
-pub mod args;
-#[cfg(feature = "backtrace")]
-pub mod backtrace;
-pub mod cmath;
-pub mod condvar;
-pub mod env;
-pub mod ext;
-pub mod fast_thread_local;
-pub mod fd;
-pub mod fs;
-pub mod io;
-pub mod memchr;
-pub mod mutex;
-pub mod net;
-pub mod os;
-pub mod os_str;
-pub mod path;
-pub mod pipe;
-pub mod process;
-pub mod rand;
-pub mod rwlock;
-pub mod stack_overflow;
-pub mod stdio;
-pub mod syscall;
-pub mod thread;
-pub mod thread_local;
-pub mod time;
-
-#[cfg(not(test))]
-pub fn init() {}
-
-pub fn decode_error_kind(errno: i32) -> ErrorKind {
-    match errno {
-        syscall::ECONNREFUSED => ErrorKind::ConnectionRefused,
-        syscall::ECONNRESET => ErrorKind::ConnectionReset,
-        syscall::EPERM | syscall::EACCES => ErrorKind::PermissionDenied,
-        syscall::EPIPE => ErrorKind::BrokenPipe,
-        syscall::ENOTCONN => ErrorKind::NotConnected,
-        syscall::ECONNABORTED => ErrorKind::ConnectionAborted,
-        syscall::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
-        syscall::EADDRINUSE => ErrorKind::AddrInUse,
-        syscall::ENOENT => ErrorKind::NotFound,
-        syscall::EINTR => ErrorKind::Interrupted,
-        syscall::EINVAL => ErrorKind::InvalidInput,
-        syscall::ETIMEDOUT => ErrorKind::TimedOut,
-        syscall::EEXIST => ErrorKind::AlreadyExists,
-
-        // These two constants can have the same value on some systems,
-        // but different values on others, so we can't use a match
-        // clause
-        x if x == syscall::EAGAIN || x == syscall::EWOULDBLOCK =>
-            ErrorKind::WouldBlock,
-
-        _ => ErrorKind::Other,
-    }
-}
-
-pub fn cvt(result: Result<usize, syscall::Error>) -> crate::io::Result<usize> {
-    result.map_err(|err| crate::io::Error::from_raw_os_error(err.errno))
-}
-
-#[doc(hidden)]
-pub trait IsMinusOne {
-    fn is_minus_one(&self) -> bool;
-}
-
-macro_rules! impl_is_minus_one {
-    ($($t:ident)*) => ($(impl IsMinusOne for $t {
-        fn is_minus_one(&self) -> bool {
-            *self == -1
-        }
-    })*)
-}
-
-impl_is_minus_one! { i8 i16 i32 i64 isize }
-
-pub fn cvt_libc<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
-    if t.is_minus_one() {
-        Err(crate::io::Error::last_os_error())
-    } else {
-        Ok(t)
-    }
-}
-
-/// On Redox, use an illegal instruction to abort
-pub unsafe fn abort_internal() -> ! {
-    core::intrinsics::abort();
-}
diff --git a/src/libstd/sys/redox/mutex.rs b/src/libstd/sys/redox/mutex.rs
deleted file mode 100644
index 59399df0294..00000000000
--- a/src/libstd/sys/redox/mutex.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-use crate::cell::UnsafeCell;
-use crate::intrinsics::{atomic_cxchg, atomic_xchg};
-use crate::ptr;
-
-use crate::sys::syscall::{futex, getpid, FUTEX_WAIT, FUTEX_WAKE};
-
-pub unsafe fn mutex_try_lock(m: *mut i32) -> bool {
-    atomic_cxchg(m, 0, 1).0 == 0
-}
-
-pub unsafe fn mutex_lock(m: *mut i32) {
-    let mut c = 0;
-    //Set to larger value for longer spin test
-    for _i in 0..100 {
-        c = atomic_cxchg(m, 0, 1).0;
-        if c == 0 {
-            break;
-        }
-        //cpu_relax()
-    }
-    if c == 1 {
-        c = atomic_xchg(m, 2);
-    }
-    while c != 0 {
-        let _ = futex(m, FUTEX_WAIT, 2, 0, ptr::null_mut());
-        c = atomic_xchg(m, 2);
-    }
-}
-
-pub unsafe fn mutex_unlock(m: *mut i32) {
-    if *m == 2 {
-        *m = 0;
-    } else if atomic_xchg(m, 0) == 1 {
-        return;
-    }
-    //Set to larger value for longer spin test
-    for _i in 0..100 {
-        if *m != 0 {
-            if atomic_cxchg(m, 1, 2).0 != 0 {
-                return;
-            }
-        }
-        //cpu_relax()
-    }
-    let _ = futex(m, FUTEX_WAKE, 1, 0, ptr::null_mut());
-}
-
-pub struct Mutex {
-    pub lock: UnsafeCell<i32>,
-}
-
-impl Mutex {
-    /// Creates a new mutex.
-    pub const fn new() -> Self {
-        Mutex {
-            lock: UnsafeCell::new(0),
-        }
-    }
-
-    #[inline]
-    pub unsafe fn init(&self) {
-        *self.lock.get() = 0;
-    }
-
-    /// Try to lock the mutex
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        mutex_try_lock(self.lock.get())
-    }
-
-    /// Lock the mutex
-    #[inline]
-    pub unsafe fn lock(&self) {
-        mutex_lock(self.lock.get());
-    }
-
-    /// Unlock the mutex
-    #[inline]
-    pub unsafe fn unlock(&self) {
-        mutex_unlock(self.lock.get());
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        *self.lock.get() = 0;
-    }
-}
-
-unsafe impl Send for Mutex {}
-
-unsafe impl Sync for Mutex {}
-
-pub struct ReentrantMutex {
-    pub lock: UnsafeCell<i32>,
-    pub owner: UnsafeCell<usize>,
-    pub own_count: UnsafeCell<usize>,
-}
-
-impl ReentrantMutex {
-    pub const fn uninitialized() -> Self {
-        ReentrantMutex {
-            lock: UnsafeCell::new(0),
-            owner: UnsafeCell::new(0),
-            own_count: UnsafeCell::new(0),
-        }
-    }
-
-    #[inline]
-    pub unsafe fn init(&mut self) {
-        *self.lock.get() = 0;
-        *self.owner.get() = 0;
-        *self.own_count.get() = 0;
-    }
-
-    /// Try to lock the mutex
-    #[inline]
-    pub unsafe fn try_lock(&self) -> bool {
-        let pid = getpid().unwrap();
-        if *self.own_count.get() > 0 && *self.owner.get() == pid {
-            *self.own_count.get() += 1;
-            true
-        } else {
-            if mutex_try_lock(self.lock.get()) {
-                *self.owner.get() = pid;
-                *self.own_count.get() = 1;
-                true
-            } else {
-                false
-            }
-        }
-    }
-
-    /// Lock the mutex
-    #[inline]
-    pub unsafe fn lock(&self) {
-        let pid = getpid().unwrap();
-        if *self.own_count.get() > 0 && *self.owner.get() == pid {
-            *self.own_count.get() += 1;
-        } else {
-            mutex_lock(self.lock.get());
-            *self.owner.get() = pid;
-            *self.own_count.get() = 1;
-        }
-    }
-
-    /// Unlock the mutex
-    #[inline]
-    pub unsafe fn unlock(&self) {
-        let pid = getpid().unwrap();
-        if *self.own_count.get() > 0 && *self.owner.get() == pid {
-            *self.own_count.get() -= 1;
-            if *self.own_count.get() == 0 {
-                *self.owner.get() = 0;
-                mutex_unlock(self.lock.get());
-            }
-        }
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        *self.lock.get() = 0;
-        *self.owner.get() = 0;
-        *self.own_count.get() = 0;
-    }
-}
-
-unsafe impl Send for ReentrantMutex {}
-
-unsafe impl Sync for ReentrantMutex {}
diff --git a/src/libstd/sys/redox/net/dns/answer.rs b/src/libstd/sys/redox/net/dns/answer.rs
deleted file mode 100644
index e9b406bc685..00000000000
--- a/src/libstd/sys/redox/net/dns/answer.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-use crate::string::String;
-use crate::vec::Vec;
-
-#[derive(Clone, Debug)]
-pub struct DnsAnswer {
-    pub name: String,
-    pub a_type: u16,
-    pub a_class: u16,
-    pub ttl_a: u16,
-    pub ttl_b: u16,
-    pub data: Vec<u8>
-}
diff --git a/src/libstd/sys/redox/net/dns/mod.rs b/src/libstd/sys/redox/net/dns/mod.rs
deleted file mode 100644
index 6533e0d5efb..00000000000
--- a/src/libstd/sys/redox/net/dns/mod.rs
+++ /dev/null
@@ -1,205 +0,0 @@
-pub use self::answer::DnsAnswer;
-pub use self::query::DnsQuery;
-
-use crate::slice;
-use crate::u16;
-use crate::string::String;
-use crate::vec::Vec;
-
-mod answer;
-mod query;
-
-#[unstable(feature = "n16", issue="0")]
-#[allow(non_camel_case_types)]
-#[derive(Copy, Clone, Debug, Default)]
-#[repr(packed)]
-pub struct n16 {
-    inner: u16
-}
-
-impl n16 {
-    #[unstable(feature = "n16", issue="0")]
-    pub fn as_bytes(&self) -> &[u8] {
-        unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) }
-    }
-
-    #[unstable(feature = "n16", issue="0")]
-    pub fn from_bytes(bytes: &[u8]) -> Self {
-        n16 {
-            inner: unsafe { slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len()/2)[0] }
-        }
-    }
-}
-
-#[unstable(feature = "n16", issue="0")]
-impl From<u16> for n16 {
-    fn from(value: u16) -> Self {
-        n16 {
-            inner: value.to_be()
-        }
-    }
-}
-
-#[unstable(feature = "n16", issue="0")]
-impl From<n16> for u16 {
-    fn from(value: n16) -> Self {
-        u16::from_be(value.inner)
-    }
-}
-
-#[derive(Clone, Debug)]
-pub struct Dns {
-    pub transaction_id: u16,
-    pub flags: u16,
-    pub queries: Vec<DnsQuery>,
-    pub answers: Vec<DnsAnswer>
-}
-
-impl Dns {
-    pub fn compile(&self) -> Vec<u8> {
-        let mut data = Vec::new();
-
-        macro_rules! push_u8 {
-            ($value:expr) => {
-                data.push($value);
-            };
-        };
-
-        macro_rules! push_n16 {
-            ($value:expr) => {
-                data.extend_from_slice(n16::from($value).as_bytes());
-            };
-        };
-
-        push_n16!(self.transaction_id);
-        push_n16!(self.flags);
-        push_n16!(self.queries.len() as u16);
-        push_n16!(self.answers.len() as u16);
-        push_n16!(0);
-        push_n16!(0);
-
-        for query in self.queries.iter() {
-            for part in query.name.split('.') {
-                push_u8!(part.len() as u8);
-                data.extend_from_slice(part.as_bytes());
-            }
-            push_u8!(0);
-            push_n16!(query.q_type);
-            push_n16!(query.q_class);
-        }
-
-        data
-    }
-
-    pub fn parse(data: &[u8]) -> Result<Self, String> {
-        let name_ind = 0b11000000;
-        let mut i = 0;
-
-        macro_rules! pop_u8 {
-            () => {
-                {
-                    i += 1;
-                    if i > data.len() {
-                        return Err(format!("{}: {}: pop_u8", file!(), line!()));
-                    }
-                    data[i - 1]
-                }
-            };
-        };
-
-        macro_rules! pop_n16 {
-            () => {
-                {
-                    i += 2;
-                    if i > data.len() {
-                        return Err(format!("{}: {}: pop_n16", file!(), line!()));
-                    }
-                    u16::from(n16::from_bytes(&data[i - 2 .. i]))
-                }
-            };
-        };
-
-        macro_rules! pop_data {
-            () => {
-                {
-                    let mut data = Vec::new();
-
-                    let data_len = pop_n16!();
-                    for _data_i in 0..data_len {
-                        data.push(pop_u8!());
-                    }
-
-                    data
-                }
-            };
-        };
-
-        macro_rules! pop_name {
-            () => {
-                {
-                    let mut name = String::new();
-                    let old_i = i;
-
-                    loop {
-                        let name_len = pop_u8!();
-                        if name_len & name_ind == name_ind {
-                            i -= 1;
-                            i = (pop_n16!() - ((name_ind as u16) << 8)) as usize;
-                            continue;
-                        }
-                        if name_len == 0 {
-                            break;
-                        }
-                        if ! name.is_empty() {
-                            name.push('.');
-                        }
-                        for _name_i in 0..name_len {
-                            name.push(pop_u8!() as char);
-                        }
-                    }
-
-                    if i <= old_i {
-                        i = old_i + 2;
-                    }
-
-                    name
-                }
-            };
-        };
-
-        let transaction_id = pop_n16!();
-        let flags = pop_n16!();
-        let queries_len = pop_n16!();
-        let answers_len = pop_n16!();
-        pop_n16!();
-        pop_n16!();
-
-        let mut queries = Vec::new();
-        for _query_i in 0..queries_len {
-            queries.push(DnsQuery {
-                name: pop_name!(),
-                q_type: pop_n16!(),
-                q_class: pop_n16!()
-            });
-        }
-
-        let mut answers = Vec::new();
-        for _answer_i in 0..answers_len {
-            answers.push(DnsAnswer {
-                name: pop_name!(),
-                a_type: pop_n16!(),
-                a_class: pop_n16!(),
-                ttl_a: pop_n16!(),
-                ttl_b: pop_n16!(),
-                data: pop_data!()
-            });
-        }
-
-        Ok(Dns {
-            transaction_id,
-            flags,
-            queries,
-            answers,
-        })
-    }
-}
diff --git a/src/libstd/sys/redox/net/dns/query.rs b/src/libstd/sys/redox/net/dns/query.rs
deleted file mode 100644
index 65fb241b037..00000000000
--- a/src/libstd/sys/redox/net/dns/query.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use crate::string::String;
-
-#[derive(Clone, Debug)]
-pub struct DnsQuery {
-    pub name: String,
-    pub q_type: u16,
-    pub q_class: u16
-}
diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs
deleted file mode 100644
index dbaa140ed8a..00000000000
--- a/src/libstd/sys/redox/net/mod.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-use crate::fs::File;
-use crate::io::{Error, Read, self};
-use crate::iter::Iterator;
-use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
-use crate::str::FromStr;
-use crate::string::{String, ToString};
-use crate::sys::syscall::EINVAL;
-use crate::time::{self, Duration};
-use crate::vec::{IntoIter, Vec};
-use crate::convert::{TryFrom, TryInto};
-
-use self::dns::{Dns, DnsQuery};
-
-pub use self::tcp::{TcpStream, TcpListener};
-pub use self::udp::UdpSocket;
-
-pub mod netc;
-
-mod dns;
-mod tcp;
-mod udp;
-
-pub struct LookupHost(IntoIter<SocketAddr>, u16);
-
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        self.1
-    }
-}
-
-impl Iterator for LookupHost {
-    type Item = SocketAddr;
-    fn next(&mut self) -> Option<Self::Item> {
-        self.0.next()
-    }
-}
-
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(s: &str) -> io::Result<LookupHost> {
-        macro_rules! try_opt {
-            ($e:expr, $msg:expr) => (
-                match $e {
-                    Some(r) => r,
-                    None => return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                                      $msg)),
-                }
-            )
-        }
-
-        // split the string by ':' and convert the second part to u16
-        let mut parts_iter = s.rsplitn(2, ':');
-        let port_str = try_opt!(parts_iter.next(), "invalid socket address");
-        let host = try_opt!(parts_iter.next(), "invalid socket address");
-        let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
-
-        (host, port).try_into()
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
-        let mut ip_string = String::new();
-        File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?;
-        let ip: Vec<u8> = ip_string.trim().split('.').map(|part| part.parse::<u8>()
-                                   .unwrap_or(0)).collect();
-
-        let mut dns_string = String::new();
-        File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?;
-        let dns: Vec<u8> = dns_string.trim().split('.').map(|part| part.parse::<u8>()
-                                     .unwrap_or(0)).collect();
-
-        if ip.len() == 4 && dns.len() == 4 {
-            let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
-            let tid = (time.subsec_nanos() >> 16) as u16;
-
-            let packet = Dns {
-                transaction_id: tid,
-                flags: 0x0100,
-                queries: vec![DnsQuery {
-                    name: host.to_string(),
-                    q_type: 0x0001,
-                    q_class: 0x0001,
-                }],
-                answers: vec![]
-            };
-
-            let packet_data = packet.compile();
-
-            let my_ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]);
-            let dns_ip = Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]);
-            let socket = UdpSocket::bind(Ok(&SocketAddr::V4(SocketAddrV4::new(my_ip, 0))))?;
-            socket.set_read_timeout(Some(Duration::new(5, 0)))?;
-            socket.set_write_timeout(Some(Duration::new(5, 0)))?;
-            socket.connect(Ok(&SocketAddr::V4(SocketAddrV4::new(dns_ip, 53))))?;
-            socket.send(&packet_data)?;
-
-            let mut buf = [0; 65536];
-            let count = socket.recv(&mut buf)?;
-
-            match Dns::parse(&buf[.. count]) {
-                Ok(response) => {
-                    let mut addrs = vec![];
-                    for answer in response.answers.iter() {
-                        if answer.a_type == 0x0001 && answer.a_class == 0x0001
-                           && answer.data.len() == 4
-                        {
-                            let answer_ip = Ipv4Addr::new(answer.data[0],
-                                                          answer.data[1],
-                                                          answer.data[2],
-                                                          answer.data[3]);
-                            addrs.push(SocketAddr::V4(SocketAddrV4::new(answer_ip, 0)));
-                        }
-                    }
-                    Ok(LookupHost(addrs.into_iter(), port))
-                },
-                Err(_err) => Err(Error::from_raw_os_error(EINVAL))
-            }
-        } else {
-            Err(Error::from_raw_os_error(EINVAL))
-        }
-    }
-}
-
-fn path_to_peer_addr(path_str: &str) -> SocketAddr {
-    let mut parts = path_str.split('/').next().unwrap_or("").split(':').skip(1);
-    let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0));
-    let port = parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
-    SocketAddr::V4(SocketAddrV4::new(host, port))
-}
-
-fn path_to_local_addr(path_str: &str) -> SocketAddr {
-    let mut parts = path_str.split('/').nth(1).unwrap_or("").split(':');
-    let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0));
-    let port = parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
-    SocketAddr::V4(SocketAddrV4::new(host, port))
-}
diff --git a/src/libstd/sys/redox/net/netc.rs b/src/libstd/sys/redox/net/netc.rs
deleted file mode 100644
index 420a15a4063..00000000000
--- a/src/libstd/sys/redox/net/netc.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-pub type in_addr_t = u32;
-pub type in_port_t = u16;
-
-pub type socklen_t = u32;
-pub type sa_family_t = u16;
-
-pub const AF_INET: sa_family_t = 2;
-pub const AF_INET6: sa_family_t = 23;
-
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub struct in_addr {
-    pub s_addr: in_addr_t,
-}
-
-#[derive(Copy, Clone)]
-#[repr(align(4))]
-#[repr(C)]
-pub struct in6_addr {
-    pub s6_addr: [u8; 16],
-}
-
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub struct sockaddr {
-    pub sa_family: sa_family_t,
-    pub sa_data: [u8; 14],
-}
-
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub struct sockaddr_in {
-    pub sin_family: sa_family_t,
-    pub sin_port: in_port_t,
-    pub sin_addr: in_addr,
-    pub sin_zero: [u8; 8],
-}
-
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub struct sockaddr_in6 {
-    pub sin6_family: sa_family_t,
-    pub sin6_port: in_port_t,
-    pub sin6_flowinfo: u32,
-    pub sin6_addr: in6_addr,
-    pub sin6_scope_id: u32,
-}
diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs
deleted file mode 100644
index 5081c3de73c..00000000000
--- a/src/libstd/sys/redox/net/tcp.rs
+++ /dev/null
@@ -1,257 +0,0 @@
-use crate::cmp;
-use crate::io::{self, Error, ErrorKind, Result, IoVec, IoVecMut};
-use crate::mem;
-use crate::net::{SocketAddr, Shutdown};
-use crate::path::Path;
-use crate::sys::fs::{File, OpenOptions};
-use crate::sys::syscall::TimeSpec;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
-use crate::time::Duration;
-
-use super::{path_to_peer_addr, path_to_local_addr};
-
-#[derive(Debug)]
-pub struct TcpStream(File);
-
-impl TcpStream {
-    pub fn connect(addr: Result<&SocketAddr>) -> Result<TcpStream> {
-        let path = format!("tcp:{}", addr?);
-        let mut options = OpenOptions::new();
-        options.read(true);
-        options.write(true);
-        Ok(TcpStream(File::open(Path::new(path.as_str()), &options)?))
-    }
-
-    pub fn connect_timeout(_addr: &SocketAddr, _timeout: Duration) -> Result<TcpStream> {
-        Err(Error::new(ErrorKind::Other, "TcpStream::connect_timeout not implemented"))
-    }
-
-    pub fn duplicate(&self) -> Result<TcpStream> {
-        Ok(TcpStream(self.0.dup(&[])?))
-    }
-
-    pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
-        self.0.read(buf)
-    }
-
-    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
-        match bufs.iter_mut().find(|b| !b.is_empty()) {
-            Some(buf) => self.read(buf),
-            None => Ok(0),
-        }
-    }
-
-    pub fn write(&self, buf: &[u8]) -> Result<usize> {
-        self.0.write(buf)
-    }
-
-    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
-        match bufs.iter().find(|b| !b.is_empty()) {
-            Some(buf) => self.write(buf),
-            None => Ok(0),
-        }
-    }
-
-    pub fn take_error(&self) -> Result<Option<Error>> {
-        Ok(None)
-    }
-
-    pub fn peer_addr(&self) -> Result<SocketAddr> {
-        let path = self.0.path()?;
-        Ok(path_to_peer_addr(path.to_str().unwrap_or("")))
-    }
-
-    pub fn socket_addr(&self) -> Result<SocketAddr> {
-        let path = self.0.path()?;
-        Ok(path_to_local_addr(path.to_str().unwrap_or("")))
-    }
-
-    pub fn peek(&self, _buf: &mut [u8]) -> Result<usize> {
-        Err(Error::new(ErrorKind::Other, "TcpStream::peek not implemented"))
-    }
-
-    pub fn shutdown(&self, _how: Shutdown) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "TcpStream::shutdown not implemented"))
-    }
-
-    pub fn nodelay(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "TcpStream::nodelay not implemented"))
-    }
-
-    pub fn nonblocking(&self) -> Result<bool> {
-        self.0.fd().nonblocking()
-    }
-
-    pub fn only_v6(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "TcpStream::only_v6 not implemented"))
-    }
-
-    pub fn ttl(&self) -> Result<u32> {
-        let mut ttl = [0];
-        let file = self.0.dup(b"ttl")?;
-        file.read(&mut ttl)?;
-        Ok(ttl[0] as u32)
-    }
-
-    pub fn read_timeout(&self) -> Result<Option<Duration>> {
-        let mut time = TimeSpec::default();
-        let file = self.0.dup(b"read_timeout")?;
-        if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
-            Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
-        } else {
-            Ok(None)
-        }
-    }
-
-    pub fn write_timeout(&self) -> Result<Option<Duration>> {
-        let mut time = TimeSpec::default();
-        let file = self.0.dup(b"write_timeout")?;
-        if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
-            Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
-        } else {
-            Ok(None)
-        }
-    }
-
-    pub fn set_nodelay(&self, _nodelay: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "TcpStream::set_nodelay not implemented"))
-    }
-
-    pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> {
-        self.0.fd().set_nonblocking(nonblocking)
-    }
-
-    pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "TcpStream::set_only_v6 not implemented"))
-    }
-
-    pub fn set_ttl(&self, ttl: u32) -> Result<()> {
-        let file = self.0.dup(b"ttl")?;
-        file.write(&[cmp::min(ttl, 255) as u8])?;
-        Ok(())
-    }
-
-    pub fn set_read_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
-        let file = self.0.dup(b"read_timeout")?;
-        if let Some(duration) = duration_option {
-            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
-                return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                          "cannot set a 0 duration timeout"));
-            }
-            file.write(&TimeSpec {
-                tv_sec: duration.as_secs() as i64,
-                tv_nsec: duration.subsec_nanos() as i32
-            })?;
-        } else {
-            file.write(&[])?;
-        }
-        Ok(())
-    }
-
-    pub fn set_write_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
-        let file = self.0.dup(b"write_timeout")?;
-        if let Some(duration) = duration_option {
-            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
-                return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                          "cannot set a 0 duration timeout"));
-            }
-            file.write(&TimeSpec {
-                tv_sec: duration.as_secs() as i64,
-                tv_nsec: duration.subsec_nanos() as i32
-            })?;
-        } else {
-            file.write(&[])?;
-        }
-        Ok(())
-    }
-}
-
-impl AsInner<File> for TcpStream {
-    fn as_inner(&self) -> &File { &self.0 }
-}
-
-impl FromInner<File> for TcpStream {
-    fn from_inner(file: File) -> TcpStream {
-        TcpStream(file)
-    }
-}
-
-impl IntoInner<File> for TcpStream {
-    fn into_inner(self) -> File { self.0 }
-}
-
-#[derive(Debug)]
-pub struct TcpListener(File);
-
-impl TcpListener {
-    pub fn bind(addr: Result<&SocketAddr>) -> Result<TcpListener> {
-        let path = format!("tcp:/{}", addr?);
-        let mut options = OpenOptions::new();
-        options.read(true);
-        options.write(true);
-        Ok(TcpListener(File::open(Path::new(path.as_str()), &options)?))
-    }
-
-    pub fn accept(&self) -> Result<(TcpStream, SocketAddr)> {
-        let file = self.0.dup(b"listen")?;
-        let path = file.path()?;
-        let peer_addr = path_to_peer_addr(path.to_str().unwrap_or(""));
-        Ok((TcpStream(file), peer_addr))
-    }
-
-    pub fn duplicate(&self) -> Result<TcpListener> {
-        Ok(TcpListener(self.0.dup(&[])?))
-    }
-
-    pub fn take_error(&self) -> Result<Option<Error>> {
-        Ok(None)
-    }
-
-    pub fn socket_addr(&self) -> Result<SocketAddr> {
-        let path = self.0.path()?;
-        Ok(path_to_local_addr(path.to_str().unwrap_or("")))
-    }
-
-    pub fn nonblocking(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "TcpListener::nonblocking not implemented"))
-    }
-
-    pub fn only_v6(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "TcpListener::only_v6 not implemented"))
-    }
-
-    pub fn ttl(&self) -> Result<u32> {
-        let mut ttl = [0];
-        let file = self.0.dup(b"ttl")?;
-        file.read(&mut ttl)?;
-        Ok(ttl[0] as u32)
-    }
-
-    pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "TcpListener::set_nonblocking not implemented"))
-    }
-
-    pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "TcpListener::set_only_v6 not implemented"))
-    }
-
-    pub fn set_ttl(&self, ttl: u32) -> Result<()> {
-        let file = self.0.dup(b"ttl")?;
-        file.write(&[cmp::min(ttl, 255) as u8])?;
-        Ok(())
-    }
-}
-
-impl AsInner<File> for TcpListener {
-    fn as_inner(&self) -> &File { &self.0 }
-}
-
-impl FromInner<File> for TcpListener {
-    fn from_inner(file: File) -> TcpListener {
-        TcpListener(file)
-    }
-}
-
-impl IntoInner<File> for TcpListener {
-    fn into_inner(self) -> File { self.0 }
-}
diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs
deleted file mode 100644
index b1a60b14570..00000000000
--- a/src/libstd/sys/redox/net/udp.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-use crate::cell::UnsafeCell;
-use crate::cmp;
-use crate::io::{self, Error, ErrorKind, Result};
-use crate::mem;
-use crate::net::{SocketAddr, Ipv4Addr, Ipv6Addr};
-use crate::path::Path;
-use crate::sys::fs::{File, OpenOptions};
-use crate::sys::syscall::TimeSpec;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
-use crate::time::Duration;
-
-use super::{path_to_peer_addr, path_to_local_addr};
-
-#[derive(Debug)]
-pub struct UdpSocket(File, UnsafeCell<Option<SocketAddr>>);
-
-impl UdpSocket {
-    pub fn bind(addr: Result<&SocketAddr>) -> Result<UdpSocket> {
-        let path = format!("udp:/{}", addr?);
-        let mut options = OpenOptions::new();
-        options.read(true);
-        options.write(true);
-        Ok(UdpSocket(File::open(Path::new(path.as_str()), &options)?, UnsafeCell::new(None)))
-    }
-
-    fn get_conn(&self) -> &mut Option<SocketAddr> {
-        unsafe { &mut *(self.1.get()) }
-    }
-
-    pub fn connect(&self, addr: Result<&SocketAddr>) -> Result<()> {
-        unsafe { *self.1.get() = Some(*addr?) };
-        Ok(())
-    }
-
-    pub fn duplicate(&self) -> Result<UdpSocket> {
-        let new_bind = self.0.dup(&[])?;
-        let new_conn = *self.get_conn();
-        Ok(UdpSocket(new_bind, UnsafeCell::new(new_conn)))
-    }
-
-    pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
-        let from = self.0.dup(b"listen")?;
-        let path = from.path()?;
-        let peer_addr = path_to_peer_addr(path.to_str().unwrap_or(""));
-        let count = from.read(buf)?;
-        Ok((count, peer_addr))
-    }
-
-    pub fn recv(&self, buf: &mut [u8]) -> Result<usize> {
-        if let Some(addr) = *self.get_conn() {
-            let from = self.0.dup(addr.to_string().as_bytes())?;
-            from.read(buf)
-        } else {
-            Err(Error::new(ErrorKind::Other, "UdpSocket::recv not connected"))
-        }
-    }
-
-    pub fn send_to(&self, buf: &[u8], addr: &SocketAddr) -> Result<usize> {
-        let to = self.0.dup(format!("{}", addr).as_bytes())?;
-        to.write(buf)
-    }
-
-    pub fn send(&self, buf: &[u8]) -> Result<usize> {
-        if let Some(addr) = *self.get_conn() {
-            self.send_to(buf, &addr)
-        } else {
-            Err(Error::new(ErrorKind::Other, "UdpSocket::send not connected"))
-        }
-    }
-
-    pub fn take_error(&self) -> Result<Option<Error>> {
-        Ok(None)
-    }
-
-    pub fn socket_addr(&self) -> Result<SocketAddr> {
-        let path = self.0.path()?;
-        Ok(path_to_local_addr(path.to_str().unwrap_or("")))
-    }
-
-    pub fn peek(&self, _buf: &mut [u8]) -> Result<usize> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::peek not implemented"))
-    }
-
-    pub fn peek_from(&self, _buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::peek_from not implemented"))
-    }
-
-    pub fn broadcast(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::broadcast not implemented"))
-    }
-
-    pub fn multicast_loop_v4(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_loop_v4 not implemented"))
-    }
-
-    pub fn multicast_loop_v6(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_loop_v6 not implemented"))
-    }
-
-    pub fn multicast_ttl_v4(&self) -> Result<u32> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_ttl_v4 not implemented"))
-    }
-
-    pub fn nonblocking(&self) -> Result<bool> {
-        self.0.fd().nonblocking()
-    }
-
-    pub fn only_v6(&self) -> Result<bool> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::only_v6 not implemented"))
-    }
-
-    pub fn ttl(&self) -> Result<u32> {
-        let mut ttl = [0];
-        let file = self.0.dup(b"ttl")?;
-        file.read(&mut ttl)?;
-        Ok(ttl[0] as u32)
-    }
-
-    pub fn read_timeout(&self) -> Result<Option<Duration>> {
-        let mut time = TimeSpec::default();
-        let file = self.0.dup(b"read_timeout")?;
-        if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
-            Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
-        } else {
-            Ok(None)
-        }
-    }
-
-    pub fn write_timeout(&self) -> Result<Option<Duration>> {
-        let mut time = TimeSpec::default();
-        let file = self.0.dup(b"write_timeout")?;
-        if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
-            Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
-        } else {
-            Ok(None)
-        }
-    }
-
-    pub fn set_broadcast(&self, _broadcast: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::set_broadcast not implemented"))
-    }
-
-    pub fn set_multicast_loop_v4(&self, _multicast_loop_v4: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_loop_v4 not implemented"))
-    }
-
-    pub fn set_multicast_loop_v6(&self, _multicast_loop_v6: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_loop_v6 not implemented"))
-    }
-
-    pub fn set_multicast_ttl_v4(&self, _multicast_ttl_v4: u32) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_ttl_v4 not implemented"))
-    }
-
-    pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> {
-        self.0.fd().set_nonblocking(nonblocking)
-    }
-
-    pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::set_only_v6 not implemented"))
-    }
-
-    pub fn set_ttl(&self, ttl: u32) -> Result<()> {
-        let file = self.0.dup(b"ttl")?;
-        file.write(&[cmp::min(ttl, 255) as u8])?;
-        Ok(())
-    }
-
-    pub fn set_read_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
-        let file = self.0.dup(b"read_timeout")?;
-        if let Some(duration) = duration_option {
-            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
-                return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                          "cannot set a 0 duration timeout"));
-            }
-            file.write(&TimeSpec {
-                tv_sec: duration.as_secs() as i64,
-                tv_nsec: duration.subsec_nanos() as i32
-            })?;
-        } else {
-            file.write(&[])?;
-        }
-        Ok(())
-    }
-
-    pub fn set_write_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
-        let file = self.0.dup(b"write_timeout")?;
-        if let Some(duration) = duration_option {
-            if duration.as_secs() == 0 && duration.subsec_nanos() == 0 {
-                return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                          "cannot set a 0 duration timeout"));
-            }
-            file.write(&TimeSpec {
-                tv_sec: duration.as_secs() as i64,
-                tv_nsec: duration.subsec_nanos() as i32
-            })?;
-        } else {
-            file.write(&[])?;
-        }
-        Ok(())
-    }
-
-    pub fn join_multicast_v4(&self, _multiaddr: &Ipv4Addr, _interface: &Ipv4Addr) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::join_multicast_v4 not implemented"))
-    }
-
-    pub fn join_multicast_v6(&self, _multiaddr: &Ipv6Addr, _interface: u32) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::join_multicast_v6 not implemented"))
-    }
-
-    pub fn leave_multicast_v4(&self, _multiaddr: &Ipv4Addr, _interface: &Ipv4Addr) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v4 not implemented"))
-    }
-
-    pub fn leave_multicast_v6(&self, _multiaddr: &Ipv6Addr, _interface: u32) -> Result<()> {
-        Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v6 not implemented"))
-    }
-}
-
-impl AsInner<File> for UdpSocket {
-    fn as_inner(&self) -> &File { &self.0 }
-}
-
-impl FromInner<File> for UdpSocket {
-    fn from_inner(file: File) -> UdpSocket {
-        UdpSocket(file, UnsafeCell::new(None))
-    }
-}
-
-impl IntoInner<File> for UdpSocket {
-    fn into_inner(self) -> File { self.0 }
-}
diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs
deleted file mode 100644
index 79b43458d00..00000000000
--- a/src/libstd/sys/redox/os_str.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-/// The underlying OsString/OsStr implementation on Unix systems: just
-/// a `Vec<u8>`/`[u8]`.
-
-use crate::borrow::Cow;
-use crate::fmt;
-use crate::str;
-use crate::mem;
-use crate::rc::Rc;
-use crate::sync::Arc;
-use crate::sys_common::{AsInner, IntoInner};
-use crate::sys_common::bytestring::debug_fmt_bytestring;
-
-use core::str::lossy::Utf8Lossy;
-
-#[derive(Clone, Hash)]
-pub struct Buf {
-    pub inner: Vec<u8>
-}
-
-pub struct Slice {
-    pub inner: [u8]
-}
-
-impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        debug_fmt_bytestring(&self.inner, formatter)
-    }
-}
-
-impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
-    }
-}
-
-impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl IntoInner<Vec<u8>> for Buf {
-    fn into_inner(self) -> Vec<u8> {
-        self.inner
-    }
-}
-
-impl AsInner<[u8]> for Buf {
-    fn as_inner(&self) -> &[u8] {
-        &self.inner
-    }
-}
-
-
-impl Buf {
-    pub fn from_string(s: String) -> Buf {
-        Buf { inner: s.into_bytes() }
-    }
-
-    #[inline]
-    pub fn with_capacity(capacity: usize) -> Buf {
-        Buf {
-            inner: Vec::with_capacity(capacity)
-        }
-    }
-
-    #[inline]
-    pub fn clear(&mut self) {
-        self.inner.clear()
-    }
-
-    #[inline]
-    pub fn capacity(&self) -> usize {
-        self.inner.capacity()
-    }
-
-    #[inline]
-    pub fn reserve(&mut self, additional: usize) {
-        self.inner.reserve(additional)
-    }
-
-    #[inline]
-    pub fn reserve_exact(&mut self, additional: usize) {
-        self.inner.reserve_exact(additional)
-    }
-
-    #[inline]
-    pub fn shrink_to_fit(&mut self) {
-        self.inner.shrink_to_fit()
-    }
-
-    #[inline]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        self.inner.shrink_to(min_capacity)
-    }
-
-    pub fn as_slice(&self) -> &Slice {
-        unsafe { mem::transmute(&*self.inner) }
-    }
-
-    pub fn into_string(self) -> Result<String, Buf> {
-        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
-    }
-
-    pub fn push_slice(&mut self, s: &Slice) {
-        self.inner.extend_from_slice(&s.inner)
-    }
-
-    #[inline]
-    pub fn into_box(self) -> Box<Slice> {
-        unsafe { mem::transmute(self.inner.into_boxed_slice()) }
-    }
-
-    #[inline]
-    pub fn from_box(boxed: Box<Slice>) -> Buf {
-        let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
-        Buf { inner: inner.into_vec() }
-    }
-
-    #[inline]
-    pub fn into_arc(&self) -> Arc<Slice> {
-        self.as_slice().into_arc()
-    }
-
-    #[inline]
-    pub fn into_rc(&self) -> Rc<Slice> {
-        self.as_slice().into_rc()
-    }
-}
-
-impl Slice {
-    fn from_u8_slice(s: &[u8]) -> &Slice {
-        unsafe { mem::transmute(s) }
-    }
-
-    pub fn from_str(s: &str) -> &Slice {
-        Slice::from_u8_slice(s.as_bytes())
-    }
-
-    pub fn to_str(&self) -> Option<&str> {
-        str::from_utf8(&self.inner).ok()
-    }
-
-    pub fn to_string_lossy(&self) -> Cow<str> {
-        String::from_utf8_lossy(&self.inner)
-    }
-
-    pub fn to_owned(&self) -> Buf {
-        Buf { inner: self.inner.to_vec() }
-    }
-
-    #[inline]
-    pub fn into_box(&self) -> Box<Slice> {
-        let boxed: Box<[u8]> = self.inner.into();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    pub fn empty_box() -> Box<Slice> {
-        let boxed: Box<[u8]> = Default::default();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    #[inline]
-    pub fn into_arc(&self) -> Arc<Slice> {
-        let arc: Arc<[u8]> = Arc::from(&self.inner);
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
-    }
-
-    #[inline]
-    pub fn into_rc(&self) -> Rc<Slice> {
-        let rc: Rc<[u8]> = Rc::from(&self.inner);
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
-    }
-}
diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs
deleted file mode 100644
index 618d61e6fcb..00000000000
--- a/src/libstd/sys/redox/path.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use crate::ffi::OsStr;
-use crate::path::Prefix;
-
-#[inline]
-pub fn is_sep_byte(b: u8) -> bool {
-    b == b'/'
-}
-
-#[inline]
-pub fn is_verbatim_sep(b: u8) -> bool {
-    b == b'/'
-}
-
-pub fn parse_prefix(path: &OsStr) -> Option<Prefix> {
-    if let Some(path_str) = path.to_str() {
-        if let Some(_i) = path_str.find(':') {
-            // FIXME: Redox specific prefix
-            // Some(Prefix::Verbatim(OsStr::new(&path_str[..i])))
-            None
-        } else {
-            None
-        }
-    } else {
-        None
-    }
-}
-
-pub const MAIN_SEP_STR: &str = "/";
-pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs
deleted file mode 100644
index 911ba9c3f65..00000000000
--- a/src/libstd/sys/redox/pipe.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-use crate::io;
-use crate::sys::{cvt, syscall};
-use crate::sys::fd::FileDesc;
-
-////////////////////////////////////////////////////////////////////////////////
-// Anonymous pipes
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct AnonPipe(FileDesc);
-
-pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
-    let mut fds = [0; 2];
-    cvt(syscall::pipe2(&mut fds, syscall::O_CLOEXEC))?;
-    Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1]))))
-}
-
-impl AnonPipe {
-    pub fn from_fd(fd: FileDesc) -> io::Result<AnonPipe> {
-        fd.set_cloexec()?;
-        Ok(AnonPipe(fd))
-    }
-
-    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-
-    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-
-    pub fn fd(&self) -> &FileDesc { &self.0 }
-    pub fn into_fd(self) -> FileDesc { self.0 }
-}
-
-pub fn read2(p1: AnonPipe,
-             v1: &mut Vec<u8>,
-             p2: AnonPipe,
-             v2: &mut Vec<u8>) -> io::Result<()> {
-    //FIXME: Use event based I/O multiplexing
-    //unimplemented!()
-
-    p1.0.read_to_end(v1)?;
-    p2.0.read_to_end(v2)?;
-
-    Ok(())
-
-    /*
-    // Set both pipes into nonblocking mode as we're gonna be reading from both
-    // in the `select` loop below, and we wouldn't want one to block the other!
-    let p1 = p1.into_fd();
-    let p2 = p2.into_fd();
-    p1.set_nonblocking(true)?;
-    p2.set_nonblocking(true)?;
-
-    loop {
-        // wait for either pipe to become readable using `select`
-        cvt_r(|| unsafe {
-            let mut read: libc::fd_set = mem::zeroed();
-            libc::FD_SET(p1.raw(), &mut read);
-            libc::FD_SET(p2.raw(), &mut read);
-            libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(),
-                         ptr::null_mut())
-        })?;
-
-        // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
-        // EAGAIN. If we hit EOF, then this will happen because the underlying
-        // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
-        // this case we flip the other fd back into blocking mode and read
-        // whatever's leftover on that file descriptor.
-        let read = |fd: &FileDesc, dst: &mut Vec<u8>| {
-            match fd.read_to_end(dst) {
-                Ok(_) => Ok(true),
-                Err(e) => {
-                    if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
-                       e.raw_os_error() == Some(libc::EAGAIN) {
-                        Ok(false)
-                    } else {
-                        Err(e)
-                    }
-                }
-            }
-        };
-        if read(&p1, v1)? {
-            p2.set_nonblocking(false)?;
-            return p2.read_to_end(v2).map(|_| ());
-        }
-        if read(&p2, v2)? {
-            p1.set_nonblocking(false)?;
-            return p1.read_to_end(v1).map(|_| ());
-        }
-    }
-    */
-}
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
deleted file mode 100644
index 8830cdf333e..00000000000
--- a/src/libstd/sys/redox/process.rs
+++ /dev/null
@@ -1,614 +0,0 @@
-use crate::env::{self, split_paths};
-use crate::ffi::{CStr, OsStr};
-use crate::fmt;
-use crate::fs::File;
-use crate::io::{self, prelude::*, BufReader, Error, ErrorKind, SeekFrom};
-use crate::os::unix::ffi::OsStrExt;
-use crate::path::{Path, PathBuf};
-use crate::ptr;
-use crate::sys::ext::fs::MetadataExt;
-use crate::sys::ext::io::AsRawFd;
-use crate::sys::fd::FileDesc;
-use crate::sys::fs::{File as SysFile, OpenOptions};
-use crate::sys::os::{ENV_LOCK, environ};
-use crate::sys::pipe::{self, AnonPipe};
-use crate::sys::{cvt, syscall};
-use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
-
-use libc::{EXIT_SUCCESS, EXIT_FAILURE};
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    // Currently we try hard to ensure that the call to `.exec()` doesn't
-    // actually allocate any memory. While many platforms try to ensure that
-    // memory allocation works after a fork in a multithreaded process, it's
-    // been observed to be buggy and somewhat unreliable, so we do our best to
-    // just not do it at all!
-    //
-    // Along those lines, the `argv` and `envp` raw pointers here are exactly
-    // what's gonna get passed to `execvp`. The `argv` array starts with the
-    // `program` and ends with a NULL, and the `envp` pointer, if present, is
-    // also null-terminated.
-    //
-    // Right now we don't support removing arguments, so there's no much fancy
-    // support there, but we support adding and removing environment variables,
-    // so a side table is used to track where in the `envp` array each key is
-    // located. Whenever we add a key we update it in place if it's already
-    // present, and whenever we remove a key we update the locations of all
-    // other keys.
-    program: String,
-    args: Vec<String>,
-    env: CommandEnv<DefaultEnvKey>,
-
-    cwd: Option<String>,
-    uid: Option<u32>,
-    gid: Option<u32>,
-    saw_nul: bool,
-    closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
-    stdin: Option<Stdio>,
-    stdout: Option<Stdio>,
-    stderr: Option<Stdio>,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-// passed to do_exec() with configuration of what the child stdio should look
-// like
-struct ChildPipes {
-    stdin: ChildStdio,
-    stdout: ChildStdio,
-    stderr: ChildStdio,
-}
-
-enum ChildStdio {
-    Inherit,
-    Explicit(usize),
-    Owned(FileDesc),
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-    Fd(FileDesc),
-}
-
-impl Command {
-    pub fn new(program: &OsStr) -> Command {
-        Command {
-            program: program.to_str().unwrap().to_owned(),
-            args: Vec::new(),
-            env: Default::default(),
-            cwd: None,
-            uid: None,
-            gid: None,
-            saw_nul: false,
-            closures: Vec::new(),
-            stdin: None,
-            stdout: None,
-            stderr: None,
-        }
-    }
-
-    pub fn arg(&mut self, arg: &OsStr) {
-        self.args.push(arg.to_str().unwrap().to_owned());
-    }
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, dir: &OsStr) {
-        self.cwd = Some(dir.to_str().unwrap().to_owned());
-    }
-    pub fn uid(&mut self, id: u32) {
-        self.uid = Some(id);
-    }
-    pub fn gid(&mut self, id: u32) {
-        self.gid = Some(id);
-    }
-
-    pub unsafe fn pre_exec(
-        &mut self,
-        f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>,
-    ) {
-        self.closures.push(f);
-    }
-
-    pub fn stdin(&mut self, stdin: Stdio) {
-        self.stdin = Some(stdin);
-    }
-    pub fn stdout(&mut self, stdout: Stdio) {
-        self.stdout = Some(stdout);
-    }
-    pub fn stderr(&mut self, stderr: Stdio) {
-        self.stderr = Some(stderr);
-    }
-
-    pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
-                 -> io::Result<(Process, StdioPipes)> {
-         const CLOEXEC_MSG_FOOTER: &[u8] = b"NOEX";
-
-         if self.saw_nul {
-             return Err(io::Error::new(ErrorKind::InvalidInput,
-                                       "nul byte found in provided data"));
-         }
-
-         let (ours, theirs) = self.setup_io(default, needs_stdin)?;
-         let (input, output) = pipe::anon_pipe()?;
-
-         let pid = unsafe {
-             match cvt(syscall::clone(0))? {
-                 0 => {
-                     drop(input);
-                     let err = self.do_exec(theirs);
-                     let errno = err.raw_os_error().unwrap_or(syscall::EINVAL) as u32;
-                     let bytes = [
-                         (errno >> 24) as u8,
-                         (errno >> 16) as u8,
-                         (errno >>  8) as u8,
-                         (errno >>  0) as u8,
-                         CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
-                         CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
-                     ];
-                     // pipe I/O up to PIPE_BUF bytes should be atomic, and then
-                     // we want to be sure we *don't* run at_exit destructors as
-                     // we're being torn down regardless
-                     assert!(output.write(&bytes).is_ok());
-                     let _ = syscall::exit(1);
-                     panic!("failed to exit");
-                 }
-                 n => n,
-             }
-         };
-
-         let mut p = Process { pid: pid, status: None };
-         drop(output);
-         let mut bytes = [0; 8];
-
-         // loop to handle EINTR
-         loop {
-             match input.read(&mut bytes) {
-                 Ok(0) => return Ok((p, ours)),
-                 Ok(8) => {
-                     assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
-                             "Validation on the CLOEXEC pipe failed: {:?}", bytes);
-                     let errno = combine(&bytes[0.. 4]);
-                     assert!(p.wait().is_ok(),
-                             "wait() should either return Ok or panic");
-                     return Err(Error::from_raw_os_error(errno))
-                 }
-                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
-                 Err(e) => {
-                     assert!(p.wait().is_ok(),
-                             "wait() should either return Ok or panic");
-                     panic!("the CLOEXEC pipe failed: {:?}", e)
-                 },
-                 Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
-                     assert!(p.wait().is_ok(),
-                             "wait() should either return Ok or panic");
-                     panic!("short read on the CLOEXEC pipe")
-                 }
-             }
-         }
-
-         fn combine(arr: &[u8]) -> i32 {
-             let a = arr[0] as u32;
-             let b = arr[1] as u32;
-             let c = arr[2] as u32;
-             let d = arr[3] as u32;
-
-             ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
-         }
-    }
-
-    pub fn exec(&mut self, default: Stdio) -> io::Error {
-        if self.saw_nul {
-            return io::Error::new(ErrorKind::InvalidInput,
-                                  "nul byte found in provided data")
-        }
-
-        match self.setup_io(default, true) {
-            Ok((_, theirs)) => unsafe { self.do_exec(theirs) },
-            Err(e) => e,
-        }
-    }
-
-    // And at this point we've reached a special time in the life of the
-    // child. The child must now be considered hamstrung and unable to
-    // do anything other than syscalls really. Consider the following
-    // scenario:
-    //
-    //      1. Thread A of process 1 grabs the malloc() mutex
-    //      2. Thread B of process 1 forks(), creating thread C
-    //      3. Thread C of process 2 then attempts to malloc()
-    //      4. The memory of process 2 is the same as the memory of
-    //         process 1, so the mutex is locked.
-    //
-    // This situation looks a lot like deadlock, right? It turns out
-    // that this is what pthread_atfork() takes care of, which is
-    // presumably implemented across platforms. The first thing that
-    // threads to *before* forking is to do things like grab the malloc
-    // mutex, and then after the fork they unlock it.
-    //
-    // Despite this information, libnative's spawn has been witnessed to
-    // deadlock on both macOS and FreeBSD. I'm not entirely sure why, but
-    // all collected backtraces point at malloc/free traffic in the
-    // child spawned process.
-    //
-    // For this reason, the block of code below should contain 0
-    // invocations of either malloc of free (or their related friends).
-    //
-    // As an example of not having malloc/free traffic, we don't close
-    // this file descriptor by dropping the FileDesc (which contains an
-    // allocation). Instead we just close it manually. This will never
-    // have the drop glue anyway because this code never returns (the
-    // child will either exec() or invoke syscall::exit)
-    unsafe fn do_exec(&mut self, stdio: ChildPipes) -> io::Error {
-        macro_rules! t {
-            ($e:expr) => (match $e {
-                Ok(e) => e,
-                Err(e) => return e,
-            })
-        }
-
-        if let Some(fd) = stdio.stderr.fd() {
-            t!(cvt(syscall::dup2(fd, 2, &[])));
-            let mut flags = t!(cvt(syscall::fcntl(2, syscall::F_GETFD, 0)));
-            flags &= ! syscall::O_CLOEXEC;
-            t!(cvt(syscall::fcntl(2, syscall::F_SETFD, flags)));
-        }
-        if let Some(fd) = stdio.stdout.fd() {
-            t!(cvt(syscall::dup2(fd, 1, &[])));
-            let mut flags = t!(cvt(syscall::fcntl(1, syscall::F_GETFD, 0)));
-            flags &= ! syscall::O_CLOEXEC;
-            t!(cvt(syscall::fcntl(1, syscall::F_SETFD, flags)));
-        }
-        if let Some(fd) = stdio.stdin.fd() {
-            t!(cvt(syscall::dup2(fd, 0, &[])));
-            let mut flags = t!(cvt(syscall::fcntl(0, syscall::F_GETFD, 0)));
-            flags &= ! syscall::O_CLOEXEC;
-            t!(cvt(syscall::fcntl(0, syscall::F_SETFD, flags)));
-        }
-
-        if let Some(g) = self.gid {
-            t!(cvt(syscall::setregid(g as usize, g as usize)));
-        }
-        if let Some(u) = self.uid {
-            t!(cvt(syscall::setreuid(u as usize, u as usize)));
-        }
-        if let Some(ref cwd) = self.cwd {
-            t!(cvt(syscall::chdir(cwd)));
-        }
-
-        for callback in self.closures.iter_mut() {
-            t!(callback());
-        }
-
-        self.env.apply();
-
-        let program = if self.program.contains(':') || self.program.contains('/') {
-            Some(PathBuf::from(&self.program))
-        } else if let Ok(path_env) = env::var("PATH") {
-            let mut program = None;
-            for mut path in split_paths(&path_env) {
-                path.push(&self.program);
-                if path.exists() {
-                    program = Some(path);
-                    break;
-                }
-            }
-            program
-        } else {
-            None
-        };
-
-        let mut file = if let Some(program) = program {
-            t!(File::open(program.as_os_str()))
-        } else {
-            return io::Error::from_raw_os_error(syscall::ENOENT);
-        };
-
-        // Push all the arguments
-        let mut args: Vec<[usize; 2]> = Vec::with_capacity(1 + self.args.len());
-
-        let interpreter = {
-            let mut reader = BufReader::new(&file);
-
-            let mut shebang = [0; 2];
-            let mut read = 0;
-            loop {
-                match t!(reader.read(&mut shebang[read..])) {
-                    0 => break,
-                    n => read += n,
-                }
-            }
-
-            if &shebang == b"#!" {
-                // This is an interpreted script.
-                // First of all, since we'll be passing another file to
-                // fexec(), we need to manually check that we have permission
-                // to execute this file:
-                let uid = t!(cvt(syscall::getuid()));
-                let gid = t!(cvt(syscall::getgid()));
-                let meta = t!(file.metadata());
-
-                let mode = if uid == meta.uid() as usize {
-                    meta.mode() >> 3*2 & 0o7
-                } else if gid == meta.gid() as usize {
-                    meta.mode() >> 3*1 & 0o7
-                } else {
-                    meta.mode() & 0o7
-                };
-                if mode & 1 == 0 {
-                    return io::Error::from_raw_os_error(syscall::EPERM);
-                }
-
-                // Second of all, we need to actually read which interpreter it wants
-                let mut interpreter = Vec::new();
-                t!(reader.read_until(b'\n', &mut interpreter));
-                // Pop one trailing newline, if any
-                if interpreter.ends_with(&[b'\n']) {
-                    interpreter.pop().unwrap();
-                }
-
-                // FIXME: Here we could just reassign `file` directly, if it
-                // wasn't for lexical lifetimes. Remove the whole `let
-                // interpreter = { ... };` hack once NLL lands.
-                // NOTE: Although DO REMEMBER to make sure the interpreter path
-                // still lives long enough to reach fexec.
-                Some(interpreter)
-            } else {
-                None
-            }
-        };
-        if let Some(ref interpreter) = interpreter {
-            let path: &OsStr = OsStr::from_bytes(&interpreter);
-            file = t!(File::open(path));
-
-            args.push([interpreter.as_ptr() as usize, interpreter.len()]);
-        } else {
-            t!(file.seek(SeekFrom::Start(0)));
-        }
-
-        args.push([self.program.as_ptr() as usize, self.program.len()]);
-        args.extend(self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()]));
-
-        // Push all the variables
-        let mut vars: Vec<[usize; 2]> = Vec::new();
-        {
-            let _guard = ENV_LOCK.lock();
-            let mut environ = *environ();
-            while *environ != ptr::null() {
-                let var = CStr::from_ptr(*environ).to_bytes();
-                vars.push([var.as_ptr() as usize, var.len()]);
-                environ = environ.offset(1);
-            }
-        }
-
-        if let Err(err) = syscall::fexec(file.as_raw_fd(), &args, &vars) {
-            io::Error::from_raw_os_error(err.errno as i32)
-        } else {
-            panic!("return from exec without err");
-        }
-    }
-
-
-    fn setup_io(&self, default: Stdio, needs_stdin: bool)
-                -> io::Result<(StdioPipes, ChildPipes)> {
-        let null = Stdio::Null;
-        let default_stdin = if needs_stdin {&default} else {&null};
-        let stdin = self.stdin.as_ref().unwrap_or(default_stdin);
-        let stdout = self.stdout.as_ref().unwrap_or(&default);
-        let stderr = self.stderr.as_ref().unwrap_or(&default);
-        let (their_stdin, our_stdin) = stdin.to_child_stdio(true)?;
-        let (their_stdout, our_stdout) = stdout.to_child_stdio(false)?;
-        let (their_stderr, our_stderr) = stderr.to_child_stdio(false)?;
-        let ours = StdioPipes {
-            stdin: our_stdin,
-            stdout: our_stdout,
-            stderr: our_stderr,
-        };
-        let theirs = ChildPipes {
-            stdin: their_stdin,
-            stdout: their_stdout,
-            stderr: their_stderr,
-        };
-        Ok((ours, theirs))
-    }
-}
-
-impl Stdio {
-    fn to_child_stdio(&self, readable: bool)
-                      -> io::Result<(ChildStdio, Option<AnonPipe>)> {
-        match *self {
-            Stdio::Inherit => Ok((ChildStdio::Inherit, None)),
-
-            // Make sure that the source descriptors are not an stdio
-            // descriptor, otherwise the order which we set the child's
-            // descriptors may blow away a descriptor which we are hoping to
-            // save. For example, suppose we want the child's stderr to be the
-            // parent's stdout, and the child's stdout to be the parent's
-            // stderr. No matter which we dup first, the second will get
-            // overwritten prematurely.
-            Stdio::Fd(ref fd) => {
-                if fd.raw() <= 2 {
-                    Ok((ChildStdio::Owned(fd.duplicate()?), None))
-                } else {
-                    Ok((ChildStdio::Explicit(fd.raw()), None))
-                }
-            }
-
-            Stdio::MakePipe => {
-                let (reader, writer) = pipe::anon_pipe()?;
-                let (ours, theirs) = if readable {
-                    (writer, reader)
-                } else {
-                    (reader, writer)
-                };
-                Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours)))
-            }
-
-            Stdio::Null => {
-                let mut opts = OpenOptions::new();
-                opts.read(readable);
-                opts.write(!readable);
-                let fd = SysFile::open(Path::new("null:"), &opts)?;
-                Ok((ChildStdio::Owned(fd.into_fd()), None))
-            }
-        }
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        Stdio::Fd(pipe.into_fd())
-    }
-}
-
-impl From<SysFile> for Stdio {
-    fn from(file: SysFile) -> Stdio {
-        Stdio::Fd(file.into_fd())
-    }
-}
-
-impl ChildStdio {
-    fn fd(&self) -> Option<usize> {
-        match *self {
-            ChildStdio::Inherit => None,
-            ChildStdio::Explicit(fd) => Some(fd),
-            ChildStdio::Owned(ref fd) => Some(fd.raw()),
-        }
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{:?}", self.program)?;
-        for arg in &self.args {
-            write!(f, " {:?}", arg)?;
-        }
-        Ok(())
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Processes
-////////////////////////////////////////////////////////////////////////////////
-
-/// Unix exit statuses
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitStatus(i32);
-
-impl ExitStatus {
-    fn exited(&self) -> bool {
-        self.0 & 0x7F == 0
-    }
-
-    pub fn success(&self) -> bool {
-        self.code() == Some(0)
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        if self.exited() {
-            Some((self.0 >> 8) & 0xFF)
-        } else {
-            None
-        }
-    }
-
-    pub fn signal(&self) -> Option<i32> {
-        if !self.exited() {
-            Some(self.0 & 0x7F)
-        } else {
-            None
-        }
-    }
-}
-
-impl From<i32> for ExitStatus {
-    fn from(a: i32) -> ExitStatus {
-        ExitStatus(a)
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let Some(code) = self.code() {
-            write!(f, "exit code: {}", code)
-        } else {
-            let signal = self.signal().unwrap();
-            write!(f, "signal: {}", signal)
-        }
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(u8);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
-    pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-/// The unique ID of the process (this should never be negative).
-pub struct Process {
-    pid: usize,
-    status: Option<ExitStatus>,
-}
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        self.pid as u32
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        // If we've already waited on this process then the pid can be recycled
-        // and used for another process, and we probably shouldn't be killing
-        // random processes, so just return an error.
-        if self.status.is_some() {
-            Err(Error::new(ErrorKind::InvalidInput,
-                           "invalid argument: can't kill an exited process"))
-        } else {
-            cvt(syscall::kill(self.pid, syscall::SIGKILL))?;
-            Ok(())
-        }
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        if let Some(status) = self.status {
-            return Ok(status)
-        }
-        let mut status = 0;
-        cvt(syscall::waitpid(self.pid, &mut status, 0))?;
-        self.status = Some(ExitStatus(status as i32));
-        Ok(ExitStatus(status as i32))
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        if let Some(status) = self.status {
-            return Ok(Some(status))
-        }
-        let mut status = 0;
-        let pid = cvt(syscall::waitpid(self.pid, &mut status, syscall::WNOHANG))?;
-        if pid == 0 {
-            Ok(None)
-        } else {
-            self.status = Some(ExitStatus(status as i32));
-            Ok(Some(ExitStatus(status as i32)))
-        }
-    }
-}
diff --git a/src/libstd/sys/redox/rand.rs b/src/libstd/sys/redox/rand.rs
deleted file mode 100644
index 5b58d1782bf..00000000000
--- a/src/libstd/sys/redox/rand.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub fn hashmap_random_keys() -> (u64, u64) {
-    (0, 0)
-}
diff --git a/src/libstd/sys/redox/rwlock.rs b/src/libstd/sys/redox/rwlock.rs
deleted file mode 100644
index 990e7551114..00000000000
--- a/src/libstd/sys/redox/rwlock.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use super::mutex::Mutex;
-
-pub struct RWLock {
-    mutex: Mutex
-}
-
-unsafe impl Send for RWLock {}
-unsafe impl Sync for RWLock {}
-
-impl RWLock {
-    pub const fn new() -> RWLock {
-        RWLock {
-            mutex: Mutex::new()
-        }
-    }
-
-    #[inline]
-    pub unsafe fn read(&self) {
-        self.mutex.lock();
-    }
-
-    #[inline]
-    pub unsafe fn try_read(&self) -> bool {
-        self.mutex.try_lock()
-    }
-
-    #[inline]
-    pub unsafe fn write(&self) {
-        self.mutex.lock();
-    }
-
-    #[inline]
-    pub unsafe fn try_write(&self) -> bool {
-        self.mutex.try_lock()
-    }
-
-    #[inline]
-    pub unsafe fn read_unlock(&self) {
-        self.mutex.unlock();
-    }
-
-    #[inline]
-    pub unsafe fn write_unlock(&self) {
-        self.mutex.unlock();
-    }
-
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        self.mutex.destroy();
-    }
-}
diff --git a/src/libstd/sys/redox/syscall/arch/arm.rs b/src/libstd/sys/redox/syscall/arch/arm.rs
deleted file mode 100644
index e640f7ed376..00000000000
--- a/src/libstd/sys/redox/syscall/arch/arm.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-use super::error::{Error, Result};
-
-pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
-    asm!("swi $$0"
-        : "={r0}"(a)
-        : "{r7}"(a)
-        : "memory"
-        : "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
-    asm!("swi $$0"
-        : "={r0}"(a)
-        : "{r7}"(a), "{r0}"(b)
-        : "memory"
-        : "volatile");
-
-    Error::demux(a)
-}
-
-// Clobbers all registers - special for clone
-pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
-    asm!("swi $$0"
-        : "={r0}"(a)
-        : "{r7}"(a), "{r0}"(b)
-        : "memory", "r0", "r1", "r2", "r3", "r4"
-        : "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
-    asm!("swi $$0"
-        : "={r0}"(a)
-        : "{r7}"(a), "{r0}"(b), "{r1}"(c)
-        : "memory"
-        : "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
-    asm!("swi $$0"
-        : "={r0}"(a)
-        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d)
-        : "memory"
-        : "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
-    asm!("swi $$0"
-        : "={r0}"(a)
-        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e)
-        : "memory"
-        : "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
-                       -> Result<usize> {
-    asm!("swi $$0"
-        : "={r0}"(a)
-        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e), "{r4}"(f)
-        : "memory"
-        : "volatile");
-
-    Error::demux(a)
-}
diff --git a/src/libstd/sys/redox/syscall/arch/x86.rs b/src/libstd/sys/redox/syscall/arch/x86.rs
deleted file mode 100644
index 0cd6409bb06..00000000000
--- a/src/libstd/sys/redox/syscall/arch/x86.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-use super::error::{Error, Result};
-
-pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={eax}"(a)
-        : "{eax}"(a)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={eax}"(a)
-        : "{eax}"(a), "{ebx}"(b)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-// Clobbers all registers - special for clone
-pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={eax}"(a)
-        : "{eax}"(a), "{ebx}"(b)
-        : "memory", "ebx", "ecx", "edx", "esi", "edi"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={eax}"(a)
-        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={eax}"(a)
-        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={eax}"(a)
-        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
-                       -> Result<usize> {
-    asm!("int 0x80"
-        : "={eax}"(a)
-        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
diff --git a/src/libstd/sys/redox/syscall/arch/x86_64.rs b/src/libstd/sys/redox/syscall/arch/x86_64.rs
deleted file mode 100644
index 52ad01bd4a8..00000000000
--- a/src/libstd/sys/redox/syscall/arch/x86_64.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use super::error::{Error, Result};
-
-pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={rax}"(a)
-        : "{rax}"(a)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={rax}"(a)
-        : "{rax}"(a), "{rbx}"(b)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-// Clobbers all registers - special for clone
-pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={rax}"(a)
-        : "{rax}"(a), "{rbx}"(b)
-        : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8",
-          "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={rax}"(a)
-        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={rax}"(a)
-        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
-    asm!("int 0x80"
-        : "={rax}"(a)
-        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
-
-pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
-                       -> Result<usize> {
-    asm!("int 0x80"
-        : "={rax}"(a)
-        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f)
-        : "memory"
-        : "intel", "volatile");
-
-    Error::demux(a)
-}
diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs
deleted file mode 100644
index b9abb48a8d3..00000000000
--- a/src/libstd/sys/redox/syscall/call.rs
+++ /dev/null
@@ -1,348 +0,0 @@
-use super::arch::*;
-use super::data::{SigAction, Stat, StatVfs, TimeSpec};
-use super::error::Result;
-use super::number::*;
-
-use core::{mem, ptr};
-
-// Signal restorer
-extern "C" fn restorer() -> ! {
-    sigreturn().unwrap();
-    unreachable!();
-}
-
-/// Set the end of the process's heap
-///
-/// When `addr` is `0`, this function will return the current break.
-///
-/// When `addr` is nonzero, this function will attempt to set the end of the process's
-/// heap to `addr` and return the new program break. The new program break should be
-/// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page
-/// boundary.
-///
-/// On error, `Err(ENOMEM)` will be returned indicating that no memory is available
-pub unsafe fn brk(addr: usize) -> Result<usize> {
-    syscall1(SYS_BRK, addr)
-}
-
-/// Changes the process's working directory.
-///
-/// This function will attempt to set the process's working directory to `path`, which can be
-/// either a relative, scheme relative, or absolute path.
-///
-/// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned.
-///
-/// # Errors
-///
-/// * `EACCES` - permission is denied for one of the components of `path`, or `path`
-/// * `EFAULT` - `path` does not point to the process's addressable memory
-/// * `EIO` - an I/O error occurred
-/// * `ENOENT` - `path` does not exit
-/// * `ENOTDIR` - `path` is not a directory
-pub fn chdir<T: AsRef<[u8]>>(path: T) -> Result<usize> {
-    unsafe { syscall2(SYS_CHDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
-}
-
-pub fn chmod<T: AsRef<[u8]>>(path: T, mode: usize) -> Result<usize> {
-    unsafe { syscall3(SYS_CHMOD, path.as_ref().as_ptr() as usize, path.as_ref().len(), mode) }
-}
-
-/// Produces a fork of the current process, or a new process thread.
-pub unsafe fn clone(flags: usize) -> Result<usize> {
-    syscall1_clobber(SYS_CLONE, flags)
-}
-
-/// Closes a file.
-pub fn close(fd: usize) -> Result<usize> {
-    unsafe { syscall1(SYS_CLOSE, fd) }
-}
-
-/// Gets the current system time.
-pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
-    unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
-}
-
-/// Copies and transforms a file descriptor.
-pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
-    unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
-}
-
-/// Copies and transforms a file descriptor.
-pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> {
-    unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) }
-}
-
-/// Exits the current process.
-pub fn exit(status: usize) -> Result<usize> {
-    unsafe { syscall1(SYS_EXIT, status) }
-}
-
-/// Changes file permissions.
-pub fn fchmod(fd: usize, mode: u16) -> Result<usize> {
-    unsafe { syscall2(SYS_FCHMOD, fd, mode as usize) }
-
-}
-
-/// Changes file ownership.
-pub fn fchown(fd: usize, uid: u32, gid: u32) -> Result<usize> {
-    unsafe { syscall3(SYS_FCHOWN, fd, uid as usize, gid as usize) }
-
-}
-
-/// Changes file descriptor flags.
-pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
-    unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
-}
-
-/// Replaces the current process with a new executable.
-pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize> {
-    unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(),
-                      vars.as_ptr() as usize, vars.len()) }
-}
-
-/// Maps a file into memory.
-pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result<usize> {
-    syscall3(SYS_FMAP, fd, offset, size)
-}
-
-/// Unmaps a memory-mapped file.
-pub unsafe fn funmap(addr: usize) -> Result<usize> {
-    syscall1(SYS_FUNMAP, addr)
-}
-
-/// Retrieves the canonical path of a file.
-pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
-    unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
-}
-
-/// Renames a file.
-pub fn frename<T: AsRef<[u8]>>(fd: usize, path: T) -> Result<usize> {
-    unsafe { syscall3(SYS_FRENAME, fd, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
-}
-
-/// Gets metadata about a file.
-pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
-    unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::<Stat>()) }
-}
-
-/// Gets metadata about a filesystem.
-pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
-    unsafe { syscall3(SYS_FSTATVFS, fd, stat as *mut StatVfs as usize, mem::size_of::<StatVfs>()) }
-}
-
-/// Syncs a file descriptor to its underlying medium.
-pub fn fsync(fd: usize) -> Result<usize> {
-    unsafe { syscall1(SYS_FSYNC, fd) }
-}
-
-/// Truncate or extend a file to a specified length
-pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
-}
-
-// Change modify and/or access times
-pub fn futimens(fd: usize, times: &[TimeSpec]) -> Result<usize> {
-    unsafe { syscall3(SYS_FUTIMENS, fd, times.as_ptr() as usize,
-                      times.len() * mem::size_of::<TimeSpec>()) }
-}
-
-/// Fast userspace mutex
-pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32)
-                    -> Result<usize> {
-    syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize)
-}
-
-/// Gets the current working directory.
-pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
-    unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) }
-}
-
-/// Gets the effective group ID.
-pub fn getegid() -> Result<usize> {
-    unsafe { syscall0(SYS_GETEGID) }
-}
-
-/// Gets the effective namespace.
-pub fn getens() -> Result<usize> {
-    unsafe { syscall0(SYS_GETENS) }
-}
-
-/// Gets the effective user ID.
-pub fn geteuid() -> Result<usize> {
-    unsafe { syscall0(SYS_GETEUID) }
-}
-
-/// Gets the current group ID.
-pub fn getgid() -> Result<usize> {
-    unsafe { syscall0(SYS_GETGID) }
-}
-
-/// Gets the current namespace.
-pub fn getns() -> Result<usize> {
-    unsafe { syscall0(SYS_GETNS) }
-}
-
-/// Gets the current process ID.
-pub fn getpid() -> Result<usize> {
-    unsafe { syscall0(SYS_GETPID) }
-}
-
-/// Gets the process group ID.
-pub fn getpgid(pid: usize) -> Result<usize> {
-    unsafe { syscall1(SYS_GETPGID, pid) }
-}
-
-/// Gets the parent process ID.
-pub fn getppid() -> Result<usize> {
-    unsafe { syscall0(SYS_GETPPID) }
-}
-
-/// Gets the current user ID.
-pub fn getuid() -> Result<usize> {
-    unsafe { syscall0(SYS_GETUID) }
-}
-
-/// Sets the I/O privilege level
-pub unsafe fn iopl(level: usize) -> Result<usize> {
-    syscall1(SYS_IOPL, level)
-}
-
-/// Sends a signal `sig` to the process identified by `pid`.
-pub fn kill(pid: usize, sig: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_KILL, pid, sig) }
-}
-
-/// Creates a link to a file.
-pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
-    syscall2(SYS_LINK, old as usize, new as usize)
-}
-
-/// Seeks to `offset` bytes in a file descriptor.
-pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
-    unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
-}
-
-/// Makes a new scheme namespace.
-pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
-    unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
-}
-
-/// Sleeps for the time specified in `req`.
-pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
-    unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize,
-                                     rem as *mut TimeSpec as usize) }
-}
-
-/// Opens a file.
-pub fn open<T: AsRef<[u8]>>(path: T, flags: usize) -> Result<usize> {
-    unsafe { syscall3(SYS_OPEN, path.as_ref().as_ptr() as usize, path.as_ref().len(), flags) }
-}
-
-/// Allocates pages, linearly in physical memory.
-pub unsafe fn physalloc(size: usize) -> Result<usize> {
-    syscall1(SYS_PHYSALLOC, size)
-}
-
-/// Frees physically allocated pages.
-pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> {
-    syscall2(SYS_PHYSFREE, physical_address, size)
-}
-
-/// Maps physical memory to virtual memory.
-pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
-    syscall3(SYS_PHYSMAP, physical_address, size, flags)
-}
-
-/// Unmaps previously mapped physical memory.
-pub unsafe fn physunmap(virtual_address: usize) -> Result<usize> {
-    syscall1(SYS_PHYSUNMAP, virtual_address)
-}
-
-/// Creates a pair of file descriptors referencing the read and write ends of a pipe.
-pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) }
-}
-
-/// Read from a file descriptor into a buffer
-pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
-    unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
-}
-
-/// Removes a directory.
-pub fn rmdir<T: AsRef<[u8]>>(path: T) -> Result<usize> {
-    unsafe { syscall2(SYS_RMDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
-}
-
-/// Sets the process group ID.
-pub fn setpgid(pid: usize, pgid: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_SETPGID, pid, pgid) }
-}
-
-/// Sets the current process group IDs.
-pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_SETREGID, rgid, egid) }
-}
-
-/// Makes a new scheme namespace.
-pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_SETRENS, rns, ens) }
-}
-
-/// Sets the current process user IDs.
-pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
-    unsafe { syscall2(SYS_SETREUID, ruid, euid) }
-}
-
-/// Sets up a signal handler.
-pub fn sigaction(sig: usize, act: Option<&SigAction>, oldact: Option<&mut SigAction>)
--> Result<usize> {
-    unsafe { syscall4(SYS_SIGACTION, sig,
-                      act.map(|x| x as *const _).unwrap_or_else(ptr::null) as usize,
-                      oldact.map(|x| x as *mut _).unwrap_or_else(ptr::null_mut) as usize,
-                      restorer as usize) }
-}
-
-/// Returns from signal handler.
-pub fn sigreturn() -> Result<usize> {
-    unsafe { syscall0(SYS_SIGRETURN) }
-}
-
-/// Removes a file.
-pub fn unlink<T: AsRef<[u8]>>(path: T) -> Result<usize> {
-    unsafe { syscall2(SYS_UNLINK, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
-}
-
-/// Converts a virtual address to a physical one.
-pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
-    syscall1(SYS_VIRTTOPHYS, virtual_address)
-}
-
-/// Checks if a child process has exited or received a signal.
-pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize> {
-    unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) }
-}
-
-/// Writes a buffer to a file descriptor.
-///
-/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
-/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
-/// were written.
-///
-/// # Errors
-///
-/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
-/// * `EBADF` - the file descriptor is not valid or is not open for writing
-/// * `EFAULT` - `buf` does not point to the process's addressable memory
-/// * `EIO` - an I/O error occurred
-/// * `ENOSPC` - the device containing the file descriptor has no room for data
-/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
-pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
-    unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
-}
-
-/// Yields the process's time slice to the kernel.
-///
-/// This function will return Ok(0) on success
-pub fn sched_yield() -> Result<usize> {
-    unsafe { syscall0(SYS_YIELD) }
-}
diff --git a/src/libstd/sys/redox/syscall/data.rs b/src/libstd/sys/redox/syscall/data.rs
deleted file mode 100644
index 0b458ea89b8..00000000000
--- a/src/libstd/sys/redox/syscall/data.rs
+++ /dev/null
@@ -1,191 +0,0 @@
-use core::ops::{Deref, DerefMut};
-use core::{mem, slice};
-
-#[derive(Copy, Clone, Debug, Default)]
-pub struct Event {
-    pub id: usize,
-    pub flags: usize,
-    pub data: usize
-}
-
-impl Deref for Event {
-    type Target = [u8];
-    fn deref(&self) -> &[u8] {
-        unsafe {
-            slice::from_raw_parts(
-                self as *const Event as *const u8,
-                mem::size_of::<Event>()
-            ) as &[u8]
-        }
-    }
-}
-
-impl DerefMut for Event {
-    fn deref_mut(&mut self) -> &mut [u8] {
-        unsafe {
-            slice::from_raw_parts_mut(
-                self as *mut Event as *mut u8,
-                mem::size_of::<Event>()
-            ) as &mut [u8]
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, Default)]
-#[repr(C)]
-pub struct Packet {
-    pub id: u64,
-    pub pid: usize,
-    pub uid: u32,
-    pub gid: u32,
-    pub a: usize,
-    pub b: usize,
-    pub c: usize,
-    pub d: usize
-}
-
-impl Deref for Packet {
-    type Target = [u8];
-    fn deref(&self) -> &[u8] {
-        unsafe {
-            slice::from_raw_parts(
-                self as *const Packet as *const u8,
-                mem::size_of::<Packet>()
-            ) as &[u8]
-        }
-    }
-}
-
-impl DerefMut for Packet {
-    fn deref_mut(&mut self) -> &mut [u8] {
-        unsafe {
-            slice::from_raw_parts_mut(
-                self as *mut Packet as *mut u8,
-                mem::size_of::<Packet>()
-            ) as &mut [u8]
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug)]
-#[repr(C)]
-pub struct SigAction {
-    pub sa_handler: extern "C" fn(usize),
-    pub sa_mask: [u64; 2],
-    pub sa_flags: usize,
-}
-
-impl Default for SigAction {
-    fn default() -> Self {
-        Self {
-            sa_handler: unsafe { mem::transmute(0usize) },
-            sa_mask: [0; 2],
-            sa_flags: 0,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, Default)]
-#[repr(C)]
-pub struct Stat {
-    pub st_dev: u64,
-    pub st_ino: u64,
-    pub st_mode: u16,
-    pub st_nlink: u32,
-    pub st_uid: u32,
-    pub st_gid: u32,
-    pub st_size: u64,
-    pub st_blksize: u32,
-    pub st_blocks: u64,
-    pub st_mtime: u64,
-    pub st_mtime_nsec: u32,
-    pub st_atime: u64,
-    pub st_atime_nsec: u32,
-    pub st_ctime: u64,
-    pub st_ctime_nsec: u32,
-}
-
-impl Deref for Stat {
-    type Target = [u8];
-    fn deref(&self) -> &[u8] {
-        unsafe {
-            slice::from_raw_parts(
-                self as *const Stat as *const u8,
-                mem::size_of::<Stat>()
-            ) as &[u8]
-        }
-    }
-}
-
-impl DerefMut for Stat {
-    fn deref_mut(&mut self) -> &mut [u8] {
-        unsafe {
-            slice::from_raw_parts_mut(
-                self as *mut Stat as *mut u8,
-                mem::size_of::<Stat>()
-            ) as &mut [u8]
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, Default)]
-#[repr(C)]
-pub struct StatVfs {
-    pub f_bsize: u32,
-    pub f_blocks: u64,
-    pub f_bfree: u64,
-    pub f_bavail: u64,
-}
-
-impl Deref for StatVfs {
-    type Target = [u8];
-    fn deref(&self) -> &[u8] {
-        unsafe {
-            slice::from_raw_parts(
-                self as *const StatVfs as *const u8,
-                mem::size_of::<StatVfs>()
-            ) as &[u8]
-        }
-    }
-}
-
-impl DerefMut for StatVfs {
-    fn deref_mut(&mut self) -> &mut [u8] {
-        unsafe {
-            slice::from_raw_parts_mut(
-                self as *mut StatVfs as *mut u8,
-                mem::size_of::<StatVfs>()
-            ) as &mut [u8]
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, Default)]
-#[repr(C)]
-pub struct TimeSpec {
-    pub tv_sec: i64,
-    pub tv_nsec: i32,
-}
-
-impl Deref for TimeSpec {
-    type Target = [u8];
-    fn deref(&self) -> &[u8] {
-        unsafe {
-            slice::from_raw_parts(
-                self as *const TimeSpec as *const u8,
-                mem::size_of::<TimeSpec>()
-            ) as &[u8]
-        }
-    }
-}
-
-impl DerefMut for TimeSpec {
-    fn deref_mut(&mut self) -> &mut [u8] {
-        unsafe {
-            slice::from_raw_parts_mut(
-                self as *mut TimeSpec as *mut u8,
-                mem::size_of::<TimeSpec>()
-            ) as &mut [u8]
-        }
-    }
-}
diff --git a/src/libstd/sys/redox/syscall/error.rs b/src/libstd/sys/redox/syscall/error.rs
deleted file mode 100644
index f5b7bf75f30..00000000000
--- a/src/libstd/sys/redox/syscall/error.rs
+++ /dev/null
@@ -1,315 +0,0 @@
-use core::{fmt, result};
-
-#[derive(Eq, PartialEq)]
-pub struct Error {
-    pub errno: i32,
-}
-
-pub type Result<T> = result::Result<T, Error>;
-
-impl Error {
-    pub fn new(errno: i32) -> Error {
-        Error { errno }
-    }
-
-    pub fn mux(result: Result<usize>) -> usize {
-        match result {
-            Ok(value) => value,
-            Err(error) => -error.errno as usize,
-        }
-    }
-
-    pub fn demux(value: usize) -> Result<usize> {
-        let errno = -(value as i32);
-        if errno >= 1 && errno < STR_ERROR.len() as i32 {
-            Err(Error::new(errno))
-        } else {
-            Ok(value)
-        }
-    }
-
-    pub fn text(&self) -> &str {
-        if let Some(description) = STR_ERROR.get(self.errno as usize) {
-            description
-        } else {
-            "Unknown Error"
-        }
-    }
-}
-
-impl fmt::Debug for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.write_str(self.text())
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.write_str(self.text())
-    }
-}
-
-pub const EPERM: i32 = 1;  /* Operation not permitted */
-pub const ENOENT: i32 = 2;  /* No such file or directory */
-pub const ESRCH: i32 = 3;  /* No such process */
-pub const EINTR: i32 = 4;  /* Interrupted system call */
-pub const EIO: i32 = 5;  /* I/O error */
-pub const ENXIO: i32 = 6;  /* No such device or address */
-pub const E2BIG: i32 = 7;  /* Argument list too long */
-pub const ENOEXEC: i32 = 8;  /* Exec format error */
-pub const EBADF: i32 = 9;  /* Bad file number */
-pub const ECHILD: i32 = 10;  /* No child processes */
-pub const EAGAIN: i32 = 11;  /* Try again */
-pub const ENOMEM: i32 = 12;  /* Out of memory */
-pub const EACCES: i32 = 13;  /* Permission denied */
-pub const EFAULT: i32 = 14;  /* Bad address */
-pub const ENOTBLK: i32 = 15;  /* Block device required */
-pub const EBUSY: i32 = 16;  /* Device or resource busy */
-pub const EEXIST: i32 = 17;  /* File exists */
-pub const EXDEV: i32 = 18;  /* Cross-device link */
-pub const ENODEV: i32 = 19;  /* No such device */
-pub const ENOTDIR: i32 = 20;  /* Not a directory */
-pub const EISDIR: i32 = 21;  /* Is a directory */
-pub const EINVAL: i32 = 22;  /* Invalid argument */
-pub const ENFILE: i32 = 23;  /* File table overflow */
-pub const EMFILE: i32 = 24;  /* Too many open files */
-pub const ENOTTY: i32 = 25;  /* Not a typewriter */
-pub const ETXTBSY: i32 = 26;  /* Text file busy */
-pub const EFBIG: i32 = 27;  /* File too large */
-pub const ENOSPC: i32 = 28;  /* No space left on device */
-pub const ESPIPE: i32 = 29;  /* Illegal seek */
-pub const EROFS: i32 = 30;  /* Read-only file system */
-pub const EMLINK: i32 = 31;  /* Too many links */
-pub const EPIPE: i32 = 32;  /* Broken pipe */
-pub const EDOM: i32 = 33;  /* Math argument out of domain of func */
-pub const ERANGE: i32 = 34;  /* Math result not representable */
-pub const EDEADLK: i32 = 35;  /* Resource deadlock would occur */
-pub const ENAMETOOLONG: i32 = 36;  /* File name too long */
-pub const ENOLCK: i32 = 37;  /* No record locks available */
-pub const ENOSYS: i32 = 38;  /* Function not implemented */
-pub const ENOTEMPTY: i32 = 39;  /* Directory not empty */
-pub const ELOOP: i32 = 40;  /* Too many symbolic links encountered */
-pub const EWOULDBLOCK: i32 = 41;  /* Operation would block */
-pub const ENOMSG: i32 = 42;  /* No message of desired type */
-pub const EIDRM: i32 = 43;  /* Identifier removed */
-pub const ECHRNG: i32 = 44;  /* Channel number out of range */
-pub const EL2NSYNC: i32 = 45;  /* Level 2 not synchronized */
-pub const EL3HLT: i32 = 46;  /* Level 3 halted */
-pub const EL3RST: i32 = 47;  /* Level 3 reset */
-pub const ELNRNG: i32 = 48;  /* Link number out of range */
-pub const EUNATCH: i32 = 49;  /* Protocol driver not attached */
-pub const ENOCSI: i32 = 50;  /* No CSI structure available */
-pub const EL2HLT: i32 = 51;  /* Level 2 halted */
-pub const EBADE: i32 = 52;  /* Invalid exchange */
-pub const EBADR: i32 = 53;  /* Invalid request descriptor */
-pub const EXFULL: i32 = 54;  /* Exchange full */
-pub const ENOANO: i32 = 55;  /* No anode */
-pub const EBADRQC: i32 = 56;  /* Invalid request code */
-pub const EBADSLT: i32 = 57;  /* Invalid slot */
-pub const EDEADLOCK: i32 = 58; /* Resource deadlock would occur */
-pub const EBFONT: i32 = 59;  /* Bad font file format */
-pub const ENOSTR: i32 = 60;  /* Device not a stream */
-pub const ENODATA: i32 = 61;  /* No data available */
-pub const ETIME: i32 = 62;  /* Timer expired */
-pub const ENOSR: i32 = 63;  /* Out of streams resources */
-pub const ENONET: i32 = 64;  /* Machine is not on the network */
-pub const ENOPKG: i32 = 65;  /* Package not installed */
-pub const EREMOTE: i32 = 66;  /* Object is remote */
-pub const ENOLINK: i32 = 67;  /* Link has been severed */
-pub const EADV: i32 = 68;  /* Advertise error */
-pub const ESRMNT: i32 = 69;  /* Srmount error */
-pub const ECOMM: i32 = 70;  /* Communication error on send */
-pub const EPROTO: i32 = 71;  /* Protocol error */
-pub const EMULTIHOP: i32 = 72;  /* Multihop attempted */
-pub const EDOTDOT: i32 = 73;  /* RFS specific error */
-pub const EBADMSG: i32 = 74;  /* Not a data message */
-pub const EOVERFLOW: i32 = 75;  /* Value too large for defined data type */
-pub const ENOTUNIQ: i32 = 76;  /* Name not unique on network */
-pub const EBADFD: i32 = 77;  /* File descriptor in bad state */
-pub const EREMCHG: i32 = 78;  /* Remote address changed */
-pub const ELIBACC: i32 = 79;  /* Can not access a needed shared library */
-pub const ELIBBAD: i32 = 80;  /* Accessing a corrupted shared library */
-pub const ELIBSCN: i32 = 81;  /* .lib section in a.out corrupted */
-pub const ELIBMAX: i32 = 82;  /* Attempting to link in too many shared libraries */
-pub const ELIBEXEC: i32 = 83;  /* Cannot exec a shared library directly */
-pub const EILSEQ: i32 = 84;  /* Illegal byte sequence */
-pub const ERESTART: i32 = 85;  /* Interrupted system call should be restarted */
-pub const ESTRPIPE: i32 = 86;  /* Streams pipe error */
-pub const EUSERS: i32 = 87;  /* Too many users */
-pub const ENOTSOCK: i32 = 88;  /* Socket operation on non-socket */
-pub const EDESTADDRREQ: i32 = 89;  /* Destination address required */
-pub const EMSGSIZE: i32 = 90;  /* Message too long */
-pub const EPROTOTYPE: i32 = 91;  /* Protocol wrong type for socket */
-pub const ENOPROTOOPT: i32 = 92;  /* Protocol not available */
-pub const EPROTONOSUPPORT: i32 = 93;  /* Protocol not supported */
-pub const ESOCKTNOSUPPORT: i32 = 94;  /* Socket type not supported */
-pub const EOPNOTSUPP: i32 = 95;  /* Operation not supported on transport endpoint */
-pub const EPFNOSUPPORT: i32 = 96;  /* Protocol family not supported */
-pub const EAFNOSUPPORT: i32 = 97;  /* Address family not supported by protocol */
-pub const EADDRINUSE: i32 = 98;  /* Address already in use */
-pub const EADDRNOTAVAIL: i32 = 99;  /* Cannot assign requested address */
-pub const ENETDOWN: i32 = 100; /* Network is down */
-pub const ENETUNREACH: i32 = 101; /* Network is unreachable */
-pub const ENETRESET: i32 = 102; /* Network dropped connection because of reset */
-pub const ECONNABORTED: i32 = 103; /* Software caused connection abort */
-pub const ECONNRESET: i32 = 104; /* Connection reset by peer */
-pub const ENOBUFS: i32 = 105; /* No buffer space available */
-pub const EISCONN: i32 = 106; /* Transport endpoint is already connected */
-pub const ENOTCONN: i32 = 107; /* Transport endpoint is not connected */
-pub const ESHUTDOWN: i32 = 108; /* Cannot send after transport endpoint shutdown */
-pub const ETOOMANYREFS: i32 = 109; /* Too many references: cannot splice */
-pub const ETIMEDOUT: i32 = 110; /* Connection timed out */
-pub const ECONNREFUSED: i32 = 111; /* Connection refused */
-pub const EHOSTDOWN: i32 = 112; /* Host is down */
-pub const EHOSTUNREACH: i32 = 113; /* No route to host */
-pub const EALREADY: i32 = 114; /* Operation already in progress */
-pub const EINPROGRESS: i32 = 115; /* Operation now in progress */
-pub const ESTALE: i32 = 116; /* Stale NFS file handle */
-pub const EUCLEAN: i32 = 117; /* Structure needs cleaning */
-pub const ENOTNAM: i32 = 118; /* Not a XENIX named type file */
-pub const ENAVAIL: i32 = 119; /* No XENIX semaphores available */
-pub const EISNAM: i32 = 120; /* Is a named type file */
-pub const EREMOTEIO: i32 = 121; /* Remote I/O error */
-pub const EDQUOT: i32 = 122; /* Quota exceeded */
-pub const ENOMEDIUM: i32 = 123; /* No medium found */
-pub const EMEDIUMTYPE: i32 = 124; /* Wrong medium type */
-pub const ECANCELED: i32 = 125; /* Operation Canceled */
-pub const ENOKEY: i32 = 126; /* Required key not available */
-pub const EKEYEXPIRED: i32 = 127; /* Key has expired */
-pub const EKEYREVOKED: i32 = 128; /* Key has been revoked */
-pub const EKEYREJECTED: i32 = 129; /* Key was rejected by service */
-pub const EOWNERDEAD: i32 = 130; /* Owner died */
-pub const ENOTRECOVERABLE: i32 = 131; /* State not recoverable */
-
-pub static STR_ERROR: [&'static str; 132] = ["Success",
-                                             "Operation not permitted",
-                                             "No such file or directory",
-                                             "No such process",
-                                             "Interrupted system call",
-                                             "I/O error",
-                                             "No such device or address",
-                                             "Argument list too long",
-                                             "Exec format error",
-                                             "Bad file number",
-                                             "No child processes",
-                                             "Try again",
-                                             "Out of memory",
-                                             "Permission denied",
-                                             "Bad address",
-                                             "Block device required",
-                                             "Device or resource busy",
-                                             "File exists",
-                                             "Cross-device link",
-                                             "No such device",
-                                             "Not a directory",
-                                             "Is a directory",
-                                             "Invalid argument",
-                                             "File table overflow",
-                                             "Too many open files",
-                                             "Not a typewriter",
-                                             "Text file busy",
-                                             "File too large",
-                                             "No space left on device",
-                                             "Illegal seek",
-                                             "Read-only file system",
-                                             "Too many links",
-                                             "Broken pipe",
-                                             "Math argument out of domain of func",
-                                             "Math result not representable",
-                                             "Resource deadlock would occur",
-                                             "File name too long",
-                                             "No record locks available",
-                                             "Function not implemented",
-                                             "Directory not empty",
-                                             "Too many symbolic links encountered",
-                                             "Operation would block",
-                                             "No message of desired type",
-                                             "Identifier removed",
-                                             "Channel number out of range",
-                                             "Level 2 not synchronized",
-                                             "Level 3 halted",
-                                             "Level 3 reset",
-                                             "Link number out of range",
-                                             "Protocol driver not attached",
-                                             "No CSI structure available",
-                                             "Level 2 halted",
-                                             "Invalid exchange",
-                                             "Invalid request descriptor",
-                                             "Exchange full",
-                                             "No anode",
-                                             "Invalid request code",
-                                             "Invalid slot",
-                                             "Resource deadlock would occur",
-                                             "Bad font file format",
-                                             "Device not a stream",
-                                             "No data available",
-                                             "Timer expired",
-                                             "Out of streams resources",
-                                             "Machine is not on the network",
-                                             "Package not installed",
-                                             "Object is remote",
-                                             "Link has been severed",
-                                             "Advertise error",
-                                             "Srmount error",
-                                             "Communication error on send",
-                                             "Protocol error",
-                                             "Multihop attempted",
-                                             "RFS specific error",
-                                             "Not a data message",
-                                             "Value too large for defined data type",
-                                             "Name not unique on network",
-                                             "File descriptor in bad state",
-                                             "Remote address changed",
-                                             "Can not access a needed shared library",
-                                             "Accessing a corrupted shared library",
-                                             ".lib section in a.out corrupted",
-                                             "Attempting to link in too many shared libraries",
-                                             "Cannot exec a shared library directly",
-                                             "Illegal byte sequence",
-                                             "Interrupted system call should be restarted",
-                                             "Streams pipe error",
-                                             "Too many users",
-                                             "Socket operation on non-socket",
-                                             "Destination address required",
-                                             "Message too long",
-                                             "Protocol wrong type for socket",
-                                             "Protocol not available",
-                                             "Protocol not supported",
-                                             "Socket type not supported",
-                                             "Operation not supported on transport endpoint",
-                                             "Protocol family not supported",
-                                             "Address family not supported by protocol",
-                                             "Address already in use",
-                                             "Cannot assign requested address",
-                                             "Network is down",
-                                             "Network is unreachable",
-                                             "Network dropped connection because of reset",
-                                             "Software caused connection abort",
-                                             "Connection reset by peer",
-                                             "No buffer space available",
-                                             "Transport endpoint is already connected",
-                                             "Transport endpoint is not connected",
-                                             "Cannot send after transport endpoint shutdown",
-                                             "Too many references: cannot splice",
-                                             "Connection timed out",
-                                             "Connection refused",
-                                             "Host is down",
-                                             "No route to host",
-                                             "Operation already in progress",
-                                             "Operation now in progress",
-                                             "Stale NFS file handle",
-                                             "Structure needs cleaning",
-                                             "Not a XENIX named type file",
-                                             "No XENIX semaphores available",
-                                             "Is a named type file",
-                                             "Remote I/O error",
-                                             "Quota exceeded",
-                                             "No medium found",
-                                             "Wrong medium type",
-                                             "Operation Canceled",
-                                             "Required key not available",
-                                             "Key has expired",
-                                             "Key has been revoked",
-                                             "Key was rejected by service",
-                                             "Owner died",
-                                             "State not recoverable"];
diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs
deleted file mode 100644
index 5820f1ad03a..00000000000
--- a/src/libstd/sys/redox/syscall/flag.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-pub const CLONE_VM: usize = 0x100;
-pub const CLONE_FS: usize = 0x200;
-pub const CLONE_FILES: usize = 0x400;
-pub const CLONE_SIGHAND: usize = 0x800;
-pub const CLONE_VFORK: usize = 0x4000;
-pub const CLONE_THREAD: usize = 0x10000;
-
-pub const CLOCK_REALTIME: usize = 1;
-pub const CLOCK_MONOTONIC: usize = 4;
-
-pub const EVENT_NONE: usize = 0;
-pub const EVENT_READ: usize = 1;
-pub const EVENT_WRITE: usize = 2;
-
-pub const F_DUPFD: usize = 0;
-pub const F_GETFD: usize = 1;
-pub const F_SETFD: usize = 2;
-pub const F_GETFL: usize = 3;
-pub const F_SETFL: usize = 4;
-
-pub const FUTEX_WAIT: usize = 0;
-pub const FUTEX_WAKE: usize = 1;
-pub const FUTEX_REQUEUE: usize = 2;
-
-pub const MAP_WRITE: usize = 1;
-pub const MAP_WRITE_COMBINE: usize = 2;
-
-pub const MODE_TYPE: u16 = 0xF000;
-pub const MODE_DIR: u16 = 0x4000;
-pub const MODE_FILE: u16 = 0x8000;
-pub const MODE_SYMLINK: u16 = 0xA000;
-pub const MODE_FIFO: u16 = 0x1000;
-pub const MODE_CHR: u16 = 0x2000;
-
-pub const MODE_PERM: u16 = 0x0FFF;
-pub const MODE_SETUID: u16 = 0o4000;
-pub const MODE_SETGID: u16 = 0o2000;
-
-pub const O_RDONLY: usize =     0x0001_0000;
-pub const O_WRONLY: usize =     0x0002_0000;
-pub const O_RDWR: usize =       0x0003_0000;
-pub const O_NONBLOCK: usize =   0x0004_0000;
-pub const O_APPEND: usize =     0x0008_0000;
-pub const O_SHLOCK: usize =     0x0010_0000;
-pub const O_EXLOCK: usize =     0x0020_0000;
-pub const O_ASYNC: usize =      0x0040_0000;
-pub const O_FSYNC: usize =      0x0080_0000;
-pub const O_CLOEXEC: usize =    0x0100_0000;
-pub const O_CREAT: usize =      0x0200_0000;
-pub const O_TRUNC: usize =      0x0400_0000;
-pub const O_EXCL: usize =       0x0800_0000;
-pub const O_DIRECTORY: usize =  0x1000_0000;
-pub const O_STAT: usize =       0x2000_0000;
-pub const O_SYMLINK: usize =    0x4000_0000;
-pub const O_NOFOLLOW: usize =   0x8000_0000;
-pub const O_ACCMODE: usize =    O_RDONLY | O_WRONLY | O_RDWR;
-
-pub const SEEK_SET: usize = 0;
-pub const SEEK_CUR: usize = 1;
-pub const SEEK_END: usize = 2;
-
-pub const SIGHUP: usize =   1;
-pub const SIGINT: usize =   2;
-pub const SIGQUIT: usize =  3;
-pub const SIGILL: usize =   4;
-pub const SIGTRAP: usize =  5;
-pub const SIGABRT: usize =  6;
-pub const SIGBUS: usize =   7;
-pub const SIGFPE: usize =   8;
-pub const SIGKILL: usize =  9;
-pub const SIGUSR1: usize =  10;
-pub const SIGSEGV: usize =  11;
-pub const SIGUSR2: usize =  12;
-pub const SIGPIPE: usize =  13;
-pub const SIGALRM: usize =  14;
-pub const SIGTERM: usize =  15;
-pub const SIGSTKFLT: usize= 16;
-pub const SIGCHLD: usize =  17;
-pub const SIGCONT: usize =  18;
-pub const SIGSTOP: usize =  19;
-pub const SIGTSTP: usize =  20;
-pub const SIGTTIN: usize =  21;
-pub const SIGTTOU: usize =  22;
-pub const SIGURG: usize =   23;
-pub const SIGXCPU: usize =  24;
-pub const SIGXFSZ: usize =  25;
-pub const SIGVTALRM: usize= 26;
-pub const SIGPROF: usize =  27;
-pub const SIGWINCH: usize = 28;
-pub const SIGIO: usize =    29;
-pub const SIGPWR: usize =   30;
-pub const SIGSYS: usize =   31;
-
-pub const SIG_DFL: usize = 0;
-pub const SIG_IGN: usize = 1;
-
-pub const SA_NOCLDSTOP: usize = 0x00000001;
-pub const SA_NOCLDWAIT: usize = 0x00000002;
-pub const SA_SIGINFO: usize =   0x00000004;
-pub const SA_RESTORER: usize =  0x04000000;
-pub const SA_ONSTACK: usize =   0x08000000;
-pub const SA_RESTART: usize =   0x10000000;
-pub const SA_NODEFER: usize =   0x40000000;
-pub const SA_RESETHAND: usize = 0x80000000;
-
-pub const WNOHANG: usize =    0x01;
-pub const WUNTRACED: usize =  0x02;
-pub const WCONTINUED: usize = 0x08;
-
-/// Returns `true` if status indicates the child is stopped.
-pub fn wifstopped(status: usize) -> bool {
-    (status & 0xff) == 0x7f
-}
-
-/// If wifstopped(status), returns the signal that stopped the child.
-pub fn wstopsig(status: usize) -> usize {
-    (status >> 8) & 0xff
-}
-
-/// Returns `true` if status indicates the child continued after a stop.
-pub fn wifcontinued(status: usize) -> bool {
-    status == 0xffff
-}
-
-/// Returns `true` if status indicates termination by a signal.
-pub fn wifsignaled(status: usize) -> bool {
-    ((status & 0x7f) + 1) as i8 >= 2
-}
-
-/// If wifsignaled(status), returns the terminating signal.
-pub fn wtermsig(status: usize) -> usize {
-    status & 0x7f
-}
-
-/// Returns `true` if status indicates normal termination.
-pub fn wifexited(status: usize) -> bool {
-    wtermsig(status) == 0
-}
-
-/// If wifexited(status), returns the exit status.
-pub fn wexitstatus(status: usize) -> usize {
-    (status >> 8) & 0xff
-}
-
-/// Returns `true` if status indicates a core dump was created.
-pub fn wcoredump(status: usize) -> bool {
-    (status & 0x80) != 0
-}
diff --git a/src/libstd/sys/redox/syscall/mod.rs b/src/libstd/sys/redox/syscall/mod.rs
deleted file mode 100644
index b16f5dbd918..00000000000
--- a/src/libstd/sys/redox/syscall/mod.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-pub use self::arch::*;
-pub use self::call::*;
-pub use self::data::*;
-pub use self::error::*;
-pub use self::flag::*;
-pub use self::number::*;
-
-#[cfg(target_arch = "arm")]
-#[path="arch/arm.rs"]
-mod arch;
-
-#[cfg(target_arch = "x86")]
-#[path="arch/x86.rs"]
-mod arch;
-
-#[cfg(target_arch = "x86_64")]
-#[path="arch/x86_64.rs"]
-mod arch;
-
-/// Function definitions
-pub mod call;
-
-/// Complex structures that are used for some system calls
-pub mod data;
-
-/// All errors that can be generated by a system call
-pub mod error;
-
-/// Flags used as an argument to many system calls
-pub mod flag;
-
-/// Call numbers used by each system call
-pub mod number;
diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs
deleted file mode 100644
index f8884aa2ed8..00000000000
--- a/src/libstd/sys/redox/syscall/number.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-pub const SYS_CLASS: usize =    0xF000_0000;
-pub const SYS_CLASS_PATH: usize=0x1000_0000;
-pub const SYS_CLASS_FILE: usize=0x2000_0000;
-
-pub const SYS_ARG: usize =      0x0F00_0000;
-pub const SYS_ARG_SLICE: usize =0x0100_0000;
-pub const SYS_ARG_MSLICE: usize=0x0200_0000;
-pub const SYS_ARG_PATH: usize = 0x0300_0000;
-
-pub const SYS_RET: usize =      0x00F0_0000;
-pub const SYS_RET_FILE: usize = 0x0010_0000;
-
-pub const SYS_LINK: usize =     SYS_CLASS_PATH | SYS_ARG_PATH | 9;
-pub const SYS_OPEN: usize =     SYS_CLASS_PATH | SYS_RET_FILE | 5;
-pub const SYS_CHMOD: usize =    SYS_CLASS_PATH | 15;
-pub const SYS_RMDIR: usize =    SYS_CLASS_PATH | 84;
-pub const SYS_UNLINK: usize =   SYS_CLASS_PATH | 10;
-
-pub const SYS_CLOSE: usize =    SYS_CLASS_FILE | 6;
-pub const SYS_DUP: usize =      SYS_CLASS_FILE | SYS_RET_FILE | 41;
-pub const SYS_DUP2: usize =     SYS_CLASS_FILE | SYS_RET_FILE | 63;
-pub const SYS_READ: usize =     SYS_CLASS_FILE | SYS_ARG_MSLICE | 3;
-pub const SYS_WRITE: usize =    SYS_CLASS_FILE | SYS_ARG_SLICE | 4;
-pub const SYS_LSEEK: usize =    SYS_CLASS_FILE | 19;
-pub const SYS_FCHMOD: usize =   SYS_CLASS_FILE | 94;
-pub const SYS_FCHOWN: usize =   SYS_CLASS_FILE | 207;
-pub const SYS_FCNTL: usize =    SYS_CLASS_FILE | 55;
-pub const SYS_FEVENT: usize =   SYS_CLASS_FILE | 927;
-pub const SYS_FEXEC: usize =    SYS_CLASS_FILE | 11;
-pub const SYS_FMAP: usize =     SYS_CLASS_FILE | 90;
-pub const SYS_FUNMAP: usize =   SYS_CLASS_FILE | 91;
-pub const SYS_FPATH: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
-pub const SYS_FRENAME: usize =  SYS_CLASS_FILE | SYS_ARG_PATH | 38;
-pub const SYS_FSTAT: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 28;
-pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100;
-pub const SYS_FSYNC: usize =    SYS_CLASS_FILE | 118;
-pub const SYS_FTRUNCATE: usize =SYS_CLASS_FILE | 93;
-pub const SYS_FUTIMENS: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 320;
-
-pub const SYS_BRK: usize =      45;
-pub const SYS_CHDIR: usize =    12;
-pub const SYS_CLOCK_GETTIME: usize = 265;
-pub const SYS_CLONE: usize =    120;
-pub const SYS_EXIT: usize =     1;
-pub const SYS_FUTEX: usize =    240;
-pub const SYS_GETCWD: usize =   183;
-pub const SYS_GETEGID: usize =  202;
-pub const SYS_GETENS: usize =   951;
-pub const SYS_GETEUID: usize =  201;
-pub const SYS_GETGID: usize =   200;
-pub const SYS_GETNS: usize =    950;
-pub const SYS_GETPID: usize =   20;
-pub const SYS_GETPGID: usize =  132;
-pub const SYS_GETPPID: usize =  64;
-pub const SYS_GETUID: usize =   199;
-pub const SYS_IOPL: usize =     110;
-pub const SYS_KILL: usize =     37;
-pub const SYS_MKNS: usize =     984;
-pub const SYS_NANOSLEEP: usize =162;
-pub const SYS_PHYSALLOC: usize =945;
-pub const SYS_PHYSFREE: usize = 946;
-pub const SYS_PHYSMAP: usize =  947;
-pub const SYS_PHYSUNMAP: usize =948;
-pub const SYS_VIRTTOPHYS: usize=949;
-pub const SYS_PIPE2: usize =    331;
-pub const SYS_SETPGID: usize =  57;
-pub const SYS_SETREGID: usize = 204;
-pub const SYS_SETRENS: usize =  952;
-pub const SYS_SETREUID: usize = 203;
-pub const SYS_SIGACTION: usize =67;
-pub const SYS_SIGRETURN: usize =119;
-pub const SYS_WAITPID: usize =  7;
-pub const SYS_YIELD: usize =    158;
diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs
deleted file mode 100644
index ae0b91b4d6c..00000000000
--- a/src/libstd/sys/redox/thread.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-use crate::boxed::FnBox;
-use crate::ffi::CStr;
-use crate::io;
-use crate::mem;
-use crate::sys_common::thread::start_thread;
-use crate::sys::{cvt, syscall};
-use crate::time::Duration;
-
-pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
-
-pub struct Thread {
-    id: usize,
-}
-
-// Some platforms may have pthread_t as a pointer in which case we still want
-// a thread to be Send/Sync
-unsafe impl Send for Thread {}
-unsafe impl Sync for Thread {}
-
-impl Thread {
-    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, p: Box<dyn FnBox()>) -> io::Result<Thread> {
-        let p = box p;
-
-        let id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?;
-        if id == 0 {
-            start_thread(&*p as *const _ as *mut _);
-            let _ = syscall::exit(0);
-            panic!("thread failed to exit");
-        } else {
-            mem::forget(p);
-            Ok(Thread { id })
-        }
-    }
-
-    pub fn yield_now() {
-        let ret = syscall::sched_yield().expect("failed to sched_yield");
-        debug_assert_eq!(ret, 0);
-    }
-
-    pub fn set_name(_name: &CStr) {
-
-    }
-
-    pub fn sleep(dur: Duration) {
-        let mut secs = dur.as_secs();
-        let mut nsecs = dur.subsec_nanos() as i32;
-
-        // If we're awoken with a signal then the return value will be -1 and
-        // nanosleep will fill in `ts` with the remaining time.
-        while secs > 0 || nsecs > 0 {
-            let req = syscall::TimeSpec {
-                tv_sec: secs as i64,
-                tv_nsec: nsecs,
-            };
-            secs -= req.tv_sec as u64;
-            let mut rem = syscall::TimeSpec::default();
-            if syscall::nanosleep(&req, &mut rem).is_err() {
-                secs += rem.tv_sec as u64;
-                nsecs = rem.tv_nsec;
-            } else {
-                nsecs = 0;
-            }
-        }
-    }
-
-    pub fn join(self) {
-        let mut status = 0;
-        syscall::waitpid(self.id, &mut status, 0).unwrap();
-    }
-
-    pub fn id(&self) -> usize { self.id }
-
-    pub fn into_id(self) -> usize {
-        let id = self.id;
-        mem::forget(self);
-        id
-    }
-}
-
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> { None }
-    pub unsafe fn init() -> Option<Guard> { None }
-}
diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs
deleted file mode 100644
index 4bc8c4d5883..00000000000
--- a/src/libstd/sys/redox/thread_local.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-#![allow(dead_code)] // not used on all platforms
-
-use crate::collections::BTreeMap;
-use crate::ptr;
-use crate::sync::atomic::{AtomicUsize, Ordering};
-
-pub type Key = usize;
-
-type Dtor = unsafe extern fn(*mut u8);
-
-static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
-
-static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();
-
-#[thread_local]
-static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
-
-unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
-    if KEYS == ptr::null_mut() {
-        KEYS = Box::into_raw(Box::new(BTreeMap::new()));
-    }
-    &mut *KEYS
-}
-
-unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
-    if LOCALS == ptr::null_mut() {
-        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
-    }
-    &mut *LOCALS
-}
-
-#[inline]
-pub unsafe fn create(dtor: Option<Dtor>) -> Key {
-    let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
-    keys().insert(key, dtor);
-    key
-}
-
-#[inline]
-pub unsafe fn get(key: Key) -> *mut u8 {
-    if let Some(&entry) = locals().get(&key) {
-        entry
-    } else {
-        ptr::null_mut()
-    }
-}
-
-#[inline]
-pub unsafe fn set(key: Key, value: *mut u8) {
-    locals().insert(key, value);
-}
-
-#[inline]
-pub unsafe fn destroy(key: Key) {
-    keys().remove(&key);
-}
-
-#[inline]
-pub fn requires_synchronized_create() -> bool {
-    false
-}
diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs
deleted file mode 100644
index 9db3e85ca9c..00000000000
--- a/src/libstd/sys/redox/time.rs
+++ /dev/null
@@ -1,209 +0,0 @@
-use crate::cmp::Ordering;
-use crate::fmt;
-use crate::sys::{cvt, syscall};
-use crate::time::Duration;
-use crate::convert::TryInto;
-
-use core::hash::{Hash, Hasher};
-
-const NSEC_PER_SEC: u64 = 1_000_000_000;
-
-#[derive(Copy, Clone)]
-struct Timespec {
-    t: syscall::TimeSpec,
-}
-
-impl Timespec {
-    fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
-        if self >= other {
-            Ok(if self.t.tv_nsec >= other.t.tv_nsec {
-                Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
-                              (self.t.tv_nsec - other.t.tv_nsec) as u32)
-            } else {
-                Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
-                              self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
-                              other.t.tv_nsec as u32)
-            })
-        } else {
-            match other.sub_timespec(self) {
-                Ok(d) => Err(d),
-                Err(d) => Ok(d),
-            }
-        }
-    }
-
-    fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
-        let mut secs = other
-            .as_secs()
-            .try_into() // <- target type would be `i64`
-            .ok()
-            .and_then(|secs| self.t.tv_sec.checked_add(secs))?;
-
-        // Nano calculations can't overflow because nanos are <1B which fit
-        // in a u32.
-        let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
-        if nsec >= NSEC_PER_SEC as u32 {
-            nsec -= NSEC_PER_SEC as u32;
-            secs = secs.checked_add(1)?;
-        }
-        Some(Timespec {
-            t: syscall::TimeSpec {
-                tv_sec: secs,
-                tv_nsec: nsec as i32,
-            },
-        })
-    }
-
-    fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
-        let mut secs = other
-            .as_secs()
-            .try_into() // <- target type would be `i64`
-            .ok()
-            .and_then(|secs| self.t.tv_sec.checked_sub(secs))?;
-
-        // Similar to above, nanos can't overflow.
-        let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
-        if nsec < 0 {
-            nsec += NSEC_PER_SEC as i32;
-            secs = secs.checked_sub(1)?;
-        }
-        Some(Timespec {
-            t: syscall::TimeSpec {
-                tv_sec: secs,
-                tv_nsec: nsec as i32,
-            },
-        })
-    }
-}
-
-impl PartialEq for Timespec {
-    fn eq(&self, other: &Timespec) -> bool {
-        self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
-    }
-}
-
-impl Eq for Timespec {}
-
-impl PartialOrd for Timespec {
-    fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-impl Ord for Timespec {
-    fn cmp(&self, other: &Timespec) -> Ordering {
-        let me = (self.t.tv_sec, self.t.tv_nsec);
-        let other = (other.t.tv_sec, other.t.tv_nsec);
-        me.cmp(&other)
-    }
-}
-
-impl Hash for Timespec {
-    fn hash<H : Hasher>(&self, state: &mut H) {
-        self.t.tv_sec.hash(state);
-        self.t.tv_nsec.hash(state);
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct Instant {
-    t: Timespec,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct SystemTime {
-    t: Timespec,
-}
-
-pub const UNIX_EPOCH: SystemTime = SystemTime {
-    t: Timespec {
-        t: syscall::TimeSpec {
-            tv_sec: 0,
-            tv_nsec: 0,
-        },
-    },
-};
-
-impl Instant {
-    pub fn now() -> Instant {
-        Instant { t: now(syscall::CLOCK_MONOTONIC) }
-    }
-
-    pub const fn zero() -> Instant {
-        Instant { t: Timespec { t: syscall::TimeSpec { tv_sec: 0, tv_nsec: 0 } } }
-    }
-
-    pub fn actually_monotonic() -> bool {
-        false
-    }
-
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-            panic!("specified instant was later than self")
-        })
-    }
-
-    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
-        Some(Instant { t: self.t.checked_add_duration(other)? })
-    }
-
-    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
-        Some(Instant { t: self.t.checked_sub_duration(other)? })
-    }
-}
-
-impl fmt::Debug for Instant {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Instant")
-         .field("tv_sec", &self.t.t.tv_sec)
-         .field("tv_nsec", &self.t.t.tv_nsec)
-         .finish()
-    }
-}
-
-impl SystemTime {
-    pub fn now() -> SystemTime {
-        SystemTime { t: now(syscall::CLOCK_REALTIME) }
-    }
-
-    pub fn sub_time(&self, other: &SystemTime)
-                    -> Result<Duration, Duration> {
-        self.t.sub_timespec(&other.t)
-    }
-
-    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
-        Some(SystemTime { t: self.t.checked_add_duration(other)? })
-    }
-
-    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
-        Some(SystemTime { t: self.t.checked_sub_duration(other)? })
-    }
-}
-
-impl From<syscall::TimeSpec> for SystemTime {
-    fn from(t: syscall::TimeSpec) -> SystemTime {
-        SystemTime { t: Timespec { t } }
-    }
-}
-
-impl fmt::Debug for SystemTime {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("SystemTime")
-         .field("tv_sec", &self.t.t.tv_sec)
-         .field("tv_nsec", &self.t.t.tv_nsec)
-         .finish()
-    }
-}
-
-pub type clock_t = usize;
-
-fn now(clock: clock_t) -> Timespec {
-    let mut t = Timespec {
-        t: syscall::TimeSpec {
-            tv_sec: 0,
-            tv_nsec: 0,
-        }
-    };
-    cvt(syscall::clock_gettime(clock, &mut t.t)).unwrap();
-    t
-}
diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S
index c03e3869aa3..c35e49b1dc6 100644
--- a/src/libstd/sys/sgx/abi/entry.S
+++ b/src/libstd/sys/sgx/abi/entry.S
@@ -65,10 +65,6 @@ IMAGE_BASE:
     /*  The size in bytes of enclacve EH_FRM_HDR section */
     globvar EH_FRM_HDR_SIZE 8
 
-.Lreentry_panic_msg:
-    .asciz "Re-entered aborted enclave!"
-.Lreentry_panic_msg_end:
-
 .org .Lxsave_clear+512
 .Lxsave_header:
     .int 0, 0 /*  XSTATE_BV */
@@ -210,10 +206,8 @@ sgx_entry:
 /*  end sgx_entry */
 
 .Lreentry_panic:
-    lea .Lreentry_panic_msg(%rip),%rdi
-    mov $.Lreentry_panic_msg_end-.Lreentry_panic_msg,%esi
     orq $8,%rsp
-    jmp panic_msg
+    jmp abort_reentry
 
 /*  This *MUST* be called with 6 parameters, otherwise register information */
 /*  might leak! */
@@ -279,10 +273,8 @@ usercall:
 /*
 The following functions need to be defined externally:
 ```
-// Called by entry code when it needs to panic
-extern "C" fn panic_msg(msg: &'static str) -> ! {
-    panic!(msg)
-}
+// Called by entry code on re-entry after exit
+extern "C" fn abort_reentry() -> !;
 
 // Called once when a TCS is first entered
 extern "C" fn tcs_init(secondary: bool);
diff --git a/src/libstd/sys/sgx/abi/mem.rs b/src/libstd/sys/sgx/abi/mem.rs
index 808f1ce3ff2..d9051733da2 100644
--- a/src/libstd/sys/sgx/abi/mem.rs
+++ b/src/libstd/sys/sgx/abi/mem.rs
@@ -27,19 +27,23 @@ pub fn image_base() -> u64 {
 }
 
 /// Returns `true` if the specified memory range is in the enclave.
+///
+/// `p + len` must not overflow.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn is_enclave_range(p: *const u8, len: usize) -> bool {
-    let start=p as u64;
-    let end=start + (len as u64);
+    let start = p as u64;
+    let end = start + (len as u64);
     start >= image_base() &&
         end <= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant
 }
 
 /// Returns `true` if the specified memory range is in userspace.
+///
+/// `p + len` must not overflow.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn is_user_range(p: *const u8, len: usize) -> bool {
-    let start=p as u64;
-    let end=start + (len as u64);
+    let start = p as u64;
+    let end = start + (len as u64);
     end <= image_base() ||
         start >= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant
 }
diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs
index 7426f7be9e9..0f107de83f0 100644
--- a/src/libstd/sys/sgx/abi/mod.rs
+++ b/src/libstd/sys/sgx/abi/mod.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
+
 use core::sync::atomic::{AtomicUsize, Ordering};
 use crate::io::Write;
 
@@ -12,8 +14,10 @@ pub mod tls;
 #[macro_use]
 pub mod usercalls;
 
+#[cfg(not(test))]
 global_asm!(include_str!("entry.S"));
 
+#[cfg(not(test))]
 #[no_mangle]
 unsafe extern "C" fn tcs_init(secondary: bool) {
     // Be very careful when changing this code: it runs before the binary has been
@@ -25,7 +29,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
     static RELOC_STATE: AtomicUsize = AtomicUsize::new(UNINIT);
 
     if secondary && RELOC_STATE.load(Ordering::Relaxed) != DONE {
-        panic::panic_msg("Entered secondary TCS before main TCS!")
+        rtabort!("Entered secondary TCS before main TCS!")
     }
 
     // Try to atomically swap UNINIT with BUSY. The returned state can be:
@@ -48,6 +52,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
 // FIXME: this item should only exist if this is linked into an executable
 // (main function exists). If this is a library, the crate author should be
 // able to specify this
+#[cfg(not(test))]
 #[no_mangle]
 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) {
     // FIXME: how to support TLS in library mode?
@@ -64,9 +69,9 @@ extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64
         }
 
         // check entry is being called according to ABI
-        assert_eq!(p3, 0);
-        assert_eq!(p4, 0);
-        assert_eq!(p5, 0);
+        rtassert!(p3 == 0);
+        rtassert!(p4 == 0);
+        rtassert!(p5 == 0);
 
         unsafe {
             // The actual types of these arguments are `p1: *const Arg, p2:
@@ -87,3 +92,9 @@ pub(super) fn exit_with_code(code: isize) -> ! {
     }
     usercalls::exit(code != 0);
 }
+
+#[cfg(not(test))]
+#[no_mangle]
+extern "C" fn abort_reentry() -> ! {
+    usercalls::exit(false)
+}
diff --git a/src/libstd/sys/sgx/abi/panic.rs b/src/libstd/sys/sgx/abi/panic.rs
index 83411cb5b4c..2401476716f 100644
--- a/src/libstd/sys/sgx/abi/panic.rs
+++ b/src/libstd/sys/sgx/abi/panic.rs
@@ -1,4 +1,4 @@
-use super::usercalls::{alloc::UserRef, self};
+use super::usercalls::alloc::UserRef;
 use crate::cmp;
 use crate::io::{self, Write};
 use crate::mem;
@@ -48,9 +48,3 @@ impl Write for SgxPanicOutput {
         Ok(())
     }
 }
-
-#[no_mangle]
-pub extern "C" fn panic_msg(msg: &str) -> ! {
-    let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
-    usercalls::exit(true)
-}
diff --git a/src/libstd/sys/sgx/abi/reloc.rs b/src/libstd/sys/sgx/abi/reloc.rs
index a39841bc36f..6dd24c524fc 100644
--- a/src/libstd/sys/sgx/abi/reloc.rs
+++ b/src/libstd/sys/sgx/abi/reloc.rs
@@ -23,7 +23,7 @@ pub fn relocate_elf_rela() {
     };
     for rela in relas {
         if rela.info != (/*0 << 32 |*/ R_X86_64_RELATIVE as u64) {
-            panic!("Invalid relocation");
+            rtabort!("Invalid relocation");
         }
         unsafe { *mem::rel_ptr_mut::<*const ()>(rela.offset) = mem::rel_ptr(rela.addend) };
     }
diff --git a/src/libstd/sys/sgx/abi/thread.rs b/src/libstd/sys/sgx/abi/thread.rs
index 86fe09d0035..c17fa2d0015 100644
--- a/src/libstd/sys/sgx/abi/thread.rs
+++ b/src/libstd/sys/sgx/abi/thread.rs
@@ -4,6 +4,7 @@ use fortanix_sgx_abi::Tcs;
 /// all currently running threads in the enclave, and it is guaranteed to be
 /// constant for the lifetime of the thread. More specifically for SGX, there
 /// is a one-to-one correspondence of the ID to the address of the TCS.
+#[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn current() -> Tcs {
     extern "C" { fn get_tcs_addr() -> Tcs; }
     unsafe { get_tcs_addr() }
diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs
index b2a812c7231..03e08ad547d 100644
--- a/src/libstd/sys/sgx/abi/tls.rs
+++ b/src/libstd/sys/sgx/abi/tls.rs
@@ -10,45 +10,16 @@ const USIZE_BITS: usize = 64;
 const TLS_KEYS: usize = 128; // Same as POSIX minimum
 const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"]
 static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
 macro_rules! dup {
     ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
     (() $($val:tt)*) => ([$($val),*])
 }
-static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = [
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-];
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"]
+static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
 
 extern "C" {
     fn get_tls_ptr() -> *const u8;
@@ -113,7 +84,7 @@ impl Tls {
         Tls { data: dup!((* * * * * * *) (Cell::new(ptr::null_mut()))) }
     }
 
-    pub unsafe fn activate(&self) -> ActiveTls {
+    pub unsafe fn activate(&self) -> ActiveTls<'_> {
         set_tls_ptr(self as *const Tls as _);
         ActiveTls { tls: self }
     }
@@ -129,20 +100,24 @@ impl Tls {
     }
 
     pub fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
-        let index = TLS_KEY_IN_USE.set().expect("TLS limit exceeded");
+        let index = if let Some(index) = TLS_KEY_IN_USE.set() {
+            index
+        } else {
+            rtabort!("TLS limit exceeded")
+        };
         TLS_DESTRUCTOR[index].store(dtor.map_or(0, |f| f as usize), Ordering::Relaxed);
         Key::from_index(index)
     }
 
     pub fn set(key: Key, value: *mut u8) {
         let index = key.to_index();
-        assert!(TLS_KEY_IN_USE.get(index));
+        rtassert!(TLS_KEY_IN_USE.get(index));
         unsafe { Self::current() }.data[index].set(value);
     }
 
     pub fn get(key: Key) -> *mut u8 {
         let index = key.to_index();
-        assert!(TLS_KEY_IN_USE.get(index));
+        rtassert!(TLS_KEY_IN_USE.get(index));
         unsafe { Self::current() }.data[index].get()
     }
 
@@ -170,7 +145,7 @@ mod sync_bitset {
         }
 
         /// Not atomic.
-        pub fn iter(&self) -> SyncBitsetIter {
+        pub fn iter(&self) -> SyncBitsetIter<'_> {
             SyncBitsetIter {
                 iter: self.0.iter().enumerate().peekable(),
                 elem_idx: 0,
diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs
index b787bd1a5ab..c9ff53d0a4f 100644
--- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs
@@ -85,8 +85,10 @@ pub unsafe trait UserSafe {
     ///
     /// * the pointer is not aligned.
     /// * the pointer is null.
+    /// * the pointed-to range does not fit in the address space.
     /// * the pointed-to range is not in user memory.
     unsafe fn from_raw_sized(ptr: *mut u8, size: usize) -> NonNull<Self> {
+        assert!(ptr.wrapping_add(size) >= ptr);
         let ret = Self::from_raw_sized_unchecked(ptr, size);
         Self::check_ptr(ret);
         NonNull::new_unchecked(ret as _)
@@ -188,8 +190,17 @@ impl<T: ?Sized> User<T> where T: UserSafe {
     // from outside as obtained by `super::alloc`.
     fn new_uninit_bytes(size: usize) -> Self {
         unsafe {
-            let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed");
-            User(NonNull::new_userref(T::from_raw_sized(ptr as _, size)))
+            // Mustn't call alloc with size 0.
+            let ptr = if size > 0 {
+                rtunwrap!(Ok, super::alloc(size, T::align_of())) as _
+            } else {
+                T::align_of() as _ // dangling pointer ok for size 0
+            };
+            if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) {
+                User(NonNull::new_userref(v))
+            } else {
+                rtabort!("Got invalid pointer from alloc() usercall")
+            }
         }
     }
 
@@ -259,6 +270,7 @@ impl<T> User<[T]> where [T]: UserSafe {
     ///
     /// * The pointer is not aligned
     /// * The pointer is null
+    /// * The pointed-to range does not fit in the address space
     /// * The pointed-to range is not in user memory
     pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
         User(NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>())))
@@ -363,6 +375,7 @@ impl<T> UserRef<[T]> where [T]: UserSafe {
     ///
     /// * The pointer is not aligned
     /// * The pointer is null
+    /// * The pointed-to range does not fit in the address space
     /// * The pointed-to range is not in user memory
     pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self {
         &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self)
@@ -380,6 +393,7 @@ impl<T> UserRef<[T]> where [T]: UserSafe {
     ///
     /// * The pointer is not aligned
     /// * The pointer is null
+    /// * The pointed-to range does not fit in the address space
     /// * The pointed-to range is not in user memory
     pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self {
         &mut*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self)
@@ -424,7 +438,7 @@ impl<T> UserRef<[T]> where [T]: UserSafe {
     }
 
     /// Returns an iterator over the slice.
-    pub fn iter(&self) -> Iter<T>
+    pub fn iter(&self) -> Iter<'_, T>
         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
     {
         unsafe {
@@ -433,7 +447,7 @@ impl<T> UserRef<[T]> where [T]: UserSafe {
     }
 
     /// Returns an iterator that allows modifying each value.
-    pub fn iter_mut(&mut self) -> IterMut<T>
+    pub fn iter_mut(&mut self) -> IterMut<'_, T>
         where T: UserSafe // FIXME: should be implied by [T]: UserSafe?
     {
         unsafe {
@@ -514,7 +528,11 @@ impl<T, I: SliceIndex<[T]>> Index<I> for UserRef<[T]> where [T]: UserSafe, I::Ou
     #[inline]
     fn index(&self, index: I) -> &UserRef<I::Output> {
         unsafe {
-            UserRef::from_ptr(index.index(&*self.as_raw_ptr()))
+            if let Some(slice) = index.get(&*self.as_raw_ptr()) {
+                UserRef::from_ptr(slice)
+            } else {
+                rtabort!("index out of range for user slice");
+            }
         }
     }
 }
@@ -524,7 +542,11 @@ impl<T, I: SliceIndex<[T]>> IndexMut<I> for UserRef<[T]> where [T]: UserSafe, I:
     #[inline]
     fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
         unsafe {
-            UserRef::from_mut_ptr(index.index_mut(&mut*self.as_raw_mut_ptr()))
+            if let Some(slice) = index.get_mut(&mut*self.as_raw_mut_ptr()) {
+                UserRef::from_mut_ptr(slice)
+            } else {
+                rtabort!("index out of range for user slice");
+            }
         }
     }
 }
@@ -535,10 +557,11 @@ impl UserRef<super::raw::ByteBuffer> {
     /// enclave memory.
     ///
     /// # Panics
-    /// This function panics if:
+    /// This function panics if, in the user `ByteBuffer`:
     ///
-    /// * The pointer in the user `ByteBuffer` is null
-    /// * The pointed-to range in the user `ByteBuffer` is not in user memory
+    /// * The pointer is null
+    /// * The pointed-to range does not fit in the address space
+    /// * The pointed-to range is not in user memory
     pub fn copy_user_buffer(&self) -> Vec<u8> {
         unsafe {
             let buf = self.to_enclave();
diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs
index d84b6154cbe..fca62e028de 100644
--- a/src/libstd/sys/sgx/abi/usercalls/mod.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs
@@ -1,4 +1,5 @@
-use crate::io::{Error as IoError, Result as IoResult};
+use crate::cmp;
+use crate::io::{Error as IoError, Result as IoResult, IoSlice, IoSliceMut};
 use crate::time::Duration;
 
 pub(crate) mod alloc;
@@ -8,13 +9,27 @@ pub(crate) mod raw;
 use self::raw::*;
 
 /// Usercall `read`. See the ABI documentation for more information.
+///
+/// This will do a single `read` usercall and scatter the read data among
+/// `bufs`. To read to a single buffer, just pass a slice of length one.
 #[unstable(feature = "sgx_platform", issue = "56975")]
-pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
+pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
     unsafe {
-        let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
-        let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
-        userbuf[..len].copy_to_enclave(&mut buf[..len]);
-        Ok(len)
+        let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
+        let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
+        let ret_len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
+        let userbuf = &userbuf[..ret_len];
+        let mut index = 0;
+        for buf in bufs {
+            let end = cmp::min(index + buf.len(), userbuf.len());
+            if let Some(buflen) = end.checked_sub(index) {
+                userbuf[index..end].copy_to_enclave(&mut buf[..buflen]);
+                index += buf.len();
+            } else {
+                break
+            }
+        }
+        Ok(userbuf.len())
     }
 }
 
@@ -30,10 +45,24 @@ pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
 }
 
 /// Usercall `write`. See the ABI documentation for more information.
+///
+/// This will do a single `write` usercall and gather the written data from
+/// `bufs`. To write from a single buffer, just pass a slice of length one.
 #[unstable(feature = "sgx_platform", issue = "56975")]
-pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
+pub fn write(fd: Fd, bufs: &[IoSlice<'_>]) -> IoResult<usize> {
     unsafe {
-        let userbuf = alloc::User::new_from_enclave(buf);
+        let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
+        let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
+        let mut index = 0;
+        for buf in bufs {
+            let end = cmp::min(index + buf.len(), userbuf.len());
+            if let Some(buflen) = end.checked_sub(index) {
+                userbuf[index..end].copy_from_enclave(&buf[..buflen]);
+                index += buf.len();
+            } else {
+                break
+            }
+        }
         raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
     }
 }
@@ -52,7 +81,7 @@ pub fn close(fd: Fd) {
 
 fn string_from_bytebuffer(buf: &alloc::UserRef<ByteBuffer>, usercall: &str, arg: &str) -> String {
     String::from_utf8(buf.copy_user_buffer())
-        .unwrap_or_else(|_| panic!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
+        .unwrap_or_else(|_| rtabort!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
 }
 
 /// Usercall `bind_stream`. See the ABI documentation for more information.
@@ -176,7 +205,7 @@ fn check_os_error(err: Result) -> i32 {
     {
         err
     } else {
-        panic!("Usercall: returned invalid error value {}", err)
+        rtabort!("Usercall: returned invalid error value {}", err)
     }
 }
 
diff --git a/src/libstd/sys/sgx/abi/usercalls/raw.rs b/src/libstd/sys/sgx/abi/usercalls/raw.rs
index ad0b6d7b3d8..e4694a8827a 100644
--- a/src/libstd/sys/sgx/abi/usercalls/raw.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/raw.rs
@@ -131,22 +131,22 @@ impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
 
 impl ReturnValue for ! {
     fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
-        panic!("Usercall {}: did not expect to be re-entered", call);
+        rtabort!("Usercall {}: did not expect to be re-entered", call);
     }
 }
 
 impl ReturnValue for () {
-    fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
-        assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st");
-        assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
+    fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
+        rtassert!(usercall_retval.0 == 0);
+        rtassert!(usercall_retval.1 == 0);
         ()
     }
 }
 
 impl<T: RegisterArgument> ReturnValue for T {
-    fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
-        assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
-        T::from_register(regs.0)
+    fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
+        rtassert!(usercall_retval.1 == 0);
+        T::from_register(usercall_retval.0)
     }
 }
 
@@ -174,8 +174,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
@@ -191,8 +190,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
@@ -208,8 +206,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 0,0,
@@ -224,8 +221,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 0,0,0,
                 return_type_is_abort!($r)
@@ -239,8 +235,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f() -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 0,0,0,0,
                 return_type_is_abort!($r)
             ))
diff --git a/src/libstd/sys/sgx/alloc.rs b/src/libstd/sys/sgx/alloc.rs
index 94dc8ec25b5..40daec758a9 100644
--- a/src/libstd/sys/sgx/alloc.rs
+++ b/src/libstd/sys/sgx/alloc.rs
@@ -4,6 +4,8 @@ use super::waitqueue::SpinMutex;
 
 // Using a SpinMutex because we never want to exit the enclave waiting for the
 // allocator.
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE"]
 static DLMALLOC: SpinMutex<dlmalloc::Dlmalloc> = SpinMutex::new(dlmalloc::DLMALLOC_INIT);
 
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
@@ -28,3 +30,17 @@ unsafe impl GlobalAlloc for System {
         DLMALLOC.lock().realloc(ptr, layout.size(), layout.align(), new_size)
     }
 }
+
+// The following functions are needed by libunwind. These symbols are named
+// in pre-link args for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
+    crate::alloc::alloc(Layout::from_size_align_unchecked(size, align))
+}
+
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
+    crate::alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
+}
diff --git a/src/libstd/sys/sgx/args.rs b/src/libstd/sys/sgx/args.rs
index b73bf9213b7..a84ab413876 100644
--- a/src/libstd/sys/sgx/args.rs
+++ b/src/libstd/sys/sgx/args.rs
@@ -5,9 +5,12 @@ use crate::sys::os_str::Buf;
 use crate::sys_common::FromInner;
 use crate::slice;
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
 static ARGS: AtomicUsize = AtomicUsize::new(0);
 type ArgsStore = Vec<OsString>;
 
+#[cfg_attr(test, allow(dead_code))]
 pub unsafe fn init(argc: isize, argv: *const *const u8) {
     if argc != 0 {
         let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _);
diff --git a/src/libstd/sys/sgx/backtrace.rs b/src/libstd/sys/sgx/backtrace.rs
deleted file mode 100644
index d0361574e39..00000000000
--- a/src/libstd/sys/sgx/backtrace.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-use crate::io;
-use crate::error::Error;
-use crate::fmt;
-use crate::sys_common::backtrace::Frame;
-use crate::sys::sgx::abi::mem::image_base;
-
-use unwind as uw;
-
-pub struct BacktraceContext;
-
-struct Context<'a> {
-    idx: usize,
-    frames: &'a mut [Frame],
-}
-
-#[derive(Debug)]
-struct UnwindError(uw::_Unwind_Reason_Code);
-
-impl Error for UnwindError {
-    fn description(&self) -> &'static str {
-        "unexpected return value while unwinding"
-    }
-}
-
-impl fmt::Display for UnwindError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}: {:?}", self.description(), self.0)
-    }
-}
-
-#[inline(never)] // this function call can be skipped it when tracing.
-pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
-    let mut cx = Context { idx: 0, frames };
-    let result_unwind =
-        unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) };
-    // See libunwind:src/unwind/Backtrace.c for the return values.
-    // No, there is no doc.
-    let res = match result_unwind {
-        // These return codes seem to be benign and need to be ignored for backtraces
-        // to show up properly on all tested platforms.
-        uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
-            Ok((cx.idx, BacktraceContext))
-        }
-        _ => Err(io::Error::new(
-            io::ErrorKind::Other,
-            UnwindError(result_unwind),
-        )),
-    };
-    res
-}
-
-extern "C" fn trace_fn(
-    ctx: *mut uw::_Unwind_Context,
-    arg: *mut libc::c_void,
-) -> uw::_Unwind_Reason_Code {
-    let cx = unsafe { &mut *(arg as *mut Context) };
-    if cx.idx >= cx.frames.len() {
-        return uw::_URC_NORMAL_STOP;
-    }
-
-    let mut ip_before_insn = 0;
-    let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
-    if !ip.is_null() && ip_before_insn == 0 {
-        // this is a non-signaling frame, so `ip` refers to the address
-        // after the calling instruction. account for that.
-        ip = (ip as usize - 1) as *mut _;
-    }
-
-    let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
-    cx.frames[cx.idx] = Frame {
-        symbol_addr: symaddr as *mut u8,
-        exact_position: ip as *mut u8,
-        inline_context: 0,
-    };
-    cx.idx += 1;
-
-    uw::_URC_NO_REASON
-}
-
-// To reduce TCB size in Sgx enclave, we do not want to implement resolve_symname functionality.
-// Rather, we print the offset of the address here, which could be later mapped to correct function.
-pub fn resolve_symname<F>(frame: Frame,
-                          callback: F,
-                          _: &BacktraceContext) -> io::Result<()>
-    where F: FnOnce(Option<&str>) -> io::Result<()>
-{
-    callback(Some(&format!("0x{:x}",
-            (frame.symbol_addr.wrapping_offset_from(image_base() as _)))))
-}
-
-pub fn foreach_symbol_fileline<F>(_: Frame,
-                                  _: F,
-                                  _: &BacktraceContext) -> io::Result<bool>
-    where F: FnMut(&[u8], u32) -> io::Result<()>
-{
-    Ok(false)
-}
diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs
index e9a7684f74d..000bb19f269 100644
--- a/src/libstd/sys/sgx/condvar.rs
+++ b/src/libstd/sys/sgx/condvar.rs
@@ -33,7 +33,7 @@ impl Condvar {
     }
 
     pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
-        panic!("timeout not supported in SGX");
+        rtabort!("timeout not supported in SGX");
     }
 
     #[inline]
diff --git a/src/libstd/sys/sgx/ext/arch.rs b/src/libstd/sys/sgx/ext/arch.rs
index 53fb371947a..5056e388112 100644
--- a/src/libstd/sys/sgx/ext/arch.rs
+++ b/src/libstd/sys/sgx/ext/arch.rs
@@ -28,7 +28,7 @@ const ENCLU_EGETKEY: u32 = 1;
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
     unsafe {
-        let mut out = MaybeUninit::uninitialized();
+        let mut out = MaybeUninit::uninit();
         let error;
 
         asm!(
@@ -41,7 +41,7 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32>
         );
 
         match error {
-            0 => Ok(out.into_initialized()),
+            0 => Ok(out.assume_init()),
             err => Err(err),
         }
     }
@@ -58,7 +58,7 @@ pub fn ereport(
     reportdata: &Align128<[u8; 64]>,
 ) -> Align512<[u8; 432]> {
     unsafe {
-        let mut report = MaybeUninit::uninitialized();
+        let mut report = MaybeUninit::uninit();
 
         asm!(
             "enclu"
@@ -69,6 +69,6 @@ pub fn ereport(
               "{rdx}"(report.as_mut_ptr())
         );
 
-        report.into_initialized()
+        report.assume_init()
     }
 }
diff --git a/src/libstd/sys/sgx/ext/ffi.rs b/src/libstd/sys/sgx/ext/ffi.rs
index ad7ade9b17d..63fc5ff2866 100644
--- a/src/libstd/sys/sgx/ext/ffi.rs
+++ b/src/libstd/sys/sgx/ext/ffi.rs
@@ -1,109 +1,38 @@
 //! SGX-specific extension to the primitives in the `std::ffi` module
+//!
+//! # Examples
+//!
+//! ```
+//! use std::ffi::OsString;
+//! use std::os::fortanix_sgx::ffi::OsStringExt;
+//!
+//! let bytes = b"foo".to_vec();
+//!
+//! // OsStringExt::from_vec
+//! let os_string = OsString::from_vec(bytes);
+//! assert_eq!(os_string.to_str(), Some("foo"));
+//!
+//! // OsStringExt::into_vec
+//! let bytes = os_string.into_vec();
+//! assert_eq!(bytes, b"foo");
+//! ```
+//!
+//! ```
+//! use std::ffi::OsStr;
+//! use std::os::fortanix_sgx::ffi::OsStrExt;
+//!
+//! let bytes = b"foo";
+//!
+//! // OsStrExt::from_bytes
+//! let os_str = OsStr::from_bytes(bytes);
+//! assert_eq!(os_str.to_str(), Some("foo"));
+//!
+//! // OsStrExt::as_bytes
+//! let bytes = os_str.as_bytes();
+//! assert_eq!(bytes, b"foo");
+//! ```
 
 #![unstable(feature = "sgx_platform", issue = "56975")]
 
-use crate::ffi::{OsStr, OsString};
-use crate::mem;
-use crate::sys::os_str::Buf;
-use crate::sys_common::{FromInner, IntoInner, AsInner};
-
-/// SGX-specific extensions to [`OsString`].
-///
-/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
-#[unstable(feature = "sgx_platform", issue = "56975")]
-pub trait OsStringExt {
-    /// Creates an [`OsString`] from a byte vector.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsString;
-    /// use std::os::unix::ffi::OsStringExt;
-    ///
-    /// let bytes = b"foo".to_vec();
-    /// let os_string = OsString::from_vec(bytes);
-    /// assert_eq!(os_string.to_str(), Some("foo"));
-    /// ```
-    ///
-    /// [`OsString`]: ../../../ffi/struct.OsString.html
-    #[unstable(feature = "sgx_platform", issue = "56975")]
-    fn from_vec(vec: Vec<u8>) -> Self;
-
-    /// Yields the underlying byte vector of this [`OsString`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsString;
-    /// use std::os::unix::ffi::OsStringExt;
-    ///
-    /// let mut os_string = OsString::new();
-    /// os_string.push("foo");
-    /// let bytes = os_string.into_vec();
-    /// assert_eq!(bytes, b"foo");
-    /// ```
-    ///
-    /// [`OsString`]: ../../../ffi/struct.OsString.html
-    #[unstable(feature = "sgx_platform", issue = "56975")]
-    fn into_vec(self) -> Vec<u8>;
-}
-
-#[unstable(feature = "sgx_platform", issue = "56975")]
-impl OsStringExt for OsString {
-    fn from_vec(vec: Vec<u8>) -> OsString {
-        FromInner::from_inner(Buf { inner: vec })
-    }
-    fn into_vec(self) -> Vec<u8> {
-        self.into_inner().inner
-    }
-}
-
-/// SGX-specific extensions to [`OsStr`].
-///
-/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
-#[unstable(feature = "sgx_platform", issue = "56975")]
-pub trait OsStrExt {
-    #[unstable(feature = "sgx_platform", issue = "56975")]
-    /// Creates an [`OsStr`] from a byte slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsStr;
-    /// use std::os::unix::ffi::OsStrExt;
-    ///
-    /// let bytes = b"foo";
-    /// let os_str = OsStr::from_bytes(bytes);
-    /// assert_eq!(os_str.to_str(), Some("foo"));
-    /// ```
-    ///
-    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
-    fn from_bytes(slice: &[u8]) -> &Self;
-
-    /// Gets the underlying byte view of the [`OsStr`] slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsStr;
-    /// use std::os::unix::ffi::OsStrExt;
-    ///
-    /// let mut os_str = OsStr::new("foo");
-    /// let bytes = os_str.as_bytes();
-    /// assert_eq!(bytes, b"foo");
-    /// ```
-    ///
-    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
-    #[unstable(feature = "sgx_platform", issue = "56975")]
-    fn as_bytes(&self) -> &[u8];
-}
-
 #[unstable(feature = "sgx_platform", issue = "56975")]
-impl OsStrExt for OsStr {
-    fn from_bytes(slice: &[u8]) -> &OsStr {
-        unsafe { mem::transmute(slice) }
-    }
-    fn as_bytes(&self) -> &[u8] {
-        &self.as_inner().inner
-    }
-}
+pub use crate::sys_common::os_str_bytes::*;
diff --git a/src/libstd/sys/sgx/fd.rs b/src/libstd/sys/sgx/fd.rs
index a9924f55f12..a1c4af81966 100644
--- a/src/libstd/sys/sgx/fd.rs
+++ b/src/libstd/sys/sgx/fd.rs
@@ -1,6 +1,6 @@
 use fortanix_sgx_abi::Fd;
 
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::sys::{AsInner, FromInner, IntoInner};
 use super::abi::usercalls;
@@ -25,11 +25,19 @@ impl FileDesc {
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        usercalls::read(self.fd, buf)
+        usercalls::read(self.fd, &mut [IoSliceMut::new(buf)])
+    }
+
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        usercalls::read(self.fd, bufs)
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        usercalls::write(self.fd, buf)
+        usercalls::write(self.fd, &[IoSlice::new(buf)])
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        usercalls::write(self.fd, bufs)
     }
 
     pub fn flush(&self) -> io::Result<()> {
diff --git a/src/libstd/sys/sgx/fs.rs b/src/libstd/sys/sgx/fs.rs
index 485d2c87fbd..e9095b375fe 100644
--- a/src/libstd/sys/sgx/fs.rs
+++ b/src/libstd/sys/sgx/fs.rs
@@ -1,7 +1,7 @@
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::io::{self, SeekFrom};
+use crate::io::{self, SeekFrom, IoSlice, IoSliceMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::{unsupported, Void};
@@ -82,7 +82,7 @@ impl Eq for FilePermissions {
 }
 
 impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -125,13 +125,13 @@ impl Hash for FileType {
 }
 
 impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
 
 impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -200,10 +200,18 @@ impl File {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
@@ -236,7 +244,7 @@ impl DirBuilder {
 }
 
 impl fmt::Debug for File {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/sgx/io.rs b/src/libstd/sys/sgx/io.rs
index 8b02d3fd19d..976e122463d 100644
--- a/src/libstd/sys/sgx/io.rs
+++ b/src/libstd/sys/sgx/io.rs
@@ -1,9 +1,16 @@
-pub struct IoVec<'a>(&'a [u8]);
+use crate::mem;
+
+pub struct IoSlice<'a>(&'a [u8]);
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice(buf)
+    }
 
-impl<'a> IoVec<'a> {
     #[inline]
-    pub fn new(buf: &'a [u8]) -> IoVec<'a> {
-        IoVec(buf)
+    pub fn advance(&mut self, n: usize) {
+        self.0 = &self.0[n..]
     }
 
     #[inline]
@@ -12,12 +19,19 @@ impl<'a> IoVec<'a> {
     }
 }
 
-pub struct IoVecMut<'a>(&'a mut [u8]);
+pub struct IoSliceMut<'a>(&'a mut [u8]);
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut(buf)
+    }
 
-impl<'a> IoVecMut<'a> {
     #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoVecMut<'a> {
-        IoVecMut(buf)
+    pub fn advance(&mut self, n: usize) {
+        let slice = mem::replace(&mut self.0, &mut []);
+        let (_, remaining) = slice.split_at_mut(n);
+        self.0 = remaining;
     }
 
     #[inline]
diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs
index 325df7688f3..601957acd5c 100644
--- a/src/libstd/sys/sgx/mod.rs
+++ b/src/libstd/sys/sgx/mod.rs
@@ -12,8 +12,6 @@ mod waitqueue;
 
 pub mod alloc;
 pub mod args;
-#[cfg(feature = "backtrace")]
-pub mod backtrace;
 pub mod cmath;
 pub mod condvar;
 pub mod env;
@@ -25,7 +23,6 @@ pub mod memchr;
 pub mod mutex;
 pub mod net;
 pub mod os;
-pub mod os_str;
 pub mod path;
 pub mod pipe;
 pub mod process;
@@ -36,6 +33,8 @@ pub mod thread_local;
 pub mod time;
 pub mod stdio;
 
+pub use crate::sys_common::os_str_bytes as os_str;
+
 #[cfg(not(test))]
 pub fn init() {
 }
@@ -129,16 +128,25 @@ pub unsafe fn abort_internal() -> ! {
     abi::usercalls::exit(true)
 }
 
+// This function is needed by the panic runtime. The symbol is named in
+// pre-link args for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+// NB. used by both libunwind and libpanic_abort
+pub unsafe extern "C" fn __rust_abort() {
+    abort_internal();
+}
+
 pub fn hashmap_random_keys() -> (u64, u64) {
     fn rdrand64() -> u64 {
         unsafe {
-            let mut ret: u64 = crate::mem::uninitialized();
+            let mut ret: u64 = 0;
             for _ in 0..10 {
                 if crate::arch::x86_64::_rdrand64_step(&mut ret) == 1 {
                     return ret;
                 }
             }
-            panic!("Failed to obtain random data");
+            rtabort!("Failed to obtain random data");
         }
     }
     (rdrand64(), rdrand64())
diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs
index e5e42e3d0b0..f9eca9f4cb3 100644
--- a/src/libstd/sys/sgx/net.rs
+++ b/src/libstd/sys/sgx/net.rs
@@ -1,5 +1,5 @@
 use crate::fmt;
-use crate::io::{self, IoVec, IoVecMut};
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
 use crate::time::Duration;
 use crate::sys::{unsupported, Void, sgx_ineffective, AsInner, FromInner, IntoInner, TryIntoInner};
@@ -41,12 +41,29 @@ impl FromInner<FileDesc> for Socket {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct TcpStream {
     inner: Socket,
     peer_addr: Option<String>,
 }
 
+impl fmt::Debug for TcpStream {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut res = f.debug_struct("TcpStream");
+
+        if let Some(ref addr) = self.inner.local_addr {
+            res.field("addr", addr);
+        }
+
+        if let Some(ref peer) = self.peer_addr {
+            res.field("peer", peer);
+        }
+
+        res.field("fd", &self.inner.inner.as_inner())
+            .finish()
+    }
+}
+
 fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
     match result {
         Ok(saddr) => Ok(saddr.to_string()),
@@ -75,16 +92,32 @@ impl TcpStream {
         Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
     }
 
-    pub fn connect_timeout(addr: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+    pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
+        if dur == Duration::default() {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                      "cannot set a 0 duration timeout"));
+        }
         Self::connect(Ok(addr)) // FIXME: ignoring timeout
     }
 
-    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        sgx_ineffective(())
+    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        match dur {
+            Some(dur) if dur == Duration::default() => {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
+            _ => sgx_ineffective(())
+        }
     }
 
-    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        sgx_ineffective(())
+    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        match dur {
+            Some(dur) if dur == Duration::default() => {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
+            _ => sgx_ineffective(())
+        }
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
@@ -103,24 +136,16 @@ impl TcpStream {
         self.inner.inner.read(buf)
     }
 
-    pub fn read_vectored(&self, buf: &mut [IoVecMut<'_>]) -> io::Result<usize> {
-        let buf = match buf.get_mut(0) {
-            Some(buf) => buf,
-            None => return Ok(0),
-        };
-        self.read(buf)
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.inner.inner.read_vectored(bufs)
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.inner.inner.write(buf)
     }
 
-    pub fn write_vectored(&self, buf: &[IoVec<'_>]) -> io::Result<usize> {
-        let buf = match buf.get(0) {
-            Some(buf) => buf,
-            None => return Ok(0),
-        };
-        self.write(buf)
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.inner.inner.write_vectored(bufs)
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
@@ -182,11 +207,24 @@ impl FromInner<(Socket, Option<String>)> for TcpStream {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct TcpListener {
     inner: Socket,
 }
 
+impl fmt::Debug for TcpListener {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut res = f.debug_struct("TcpListener");
+
+        if let Some(ref addr) = self.inner.local_addr {
+            res.field("addr", addr);
+        }
+
+        res.field("fd", &self.inner.inner.as_inner())
+            .finish()
+    }
+}
+
 impl TcpListener {
     pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
         let addr = io_err_to_addr(addr)?;
@@ -257,6 +295,10 @@ impl UdpSocket {
         unsupported()
     }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
@@ -379,7 +421,7 @@ impl UdpSocket {
 }
 
 impl fmt::Debug for UdpSocket {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -396,7 +438,7 @@ impl error::Error for NonIpSockAddr {
 }
 
 impl fmt::Display for NonIpSockAddr {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "Failed to convert address to SocketAddr: {}", self.host)
     }
 }
diff --git a/src/libstd/sys/sgx/os.rs b/src/libstd/sys/sgx/os.rs
index 2725e66ce5d..8b12c49edba 100644
--- a/src/libstd/sys/sgx/os.rs
+++ b/src/libstd/sys/sgx/os.rs
@@ -37,7 +37,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> {
 
 pub struct SplitPaths<'a>(&'a Void);
 
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
     panic!("unsupported")
 }
 
@@ -58,7 +58,7 @@ pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
 }
 
 impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "not supported in SGX yet".fmt(f)
     }
 }
@@ -73,7 +73,11 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE"]
 static ENV: AtomicUsize = AtomicUsize::new(0);
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE"]
 static ENV_INIT: Once = Once::new();
 type EnvStore = Mutex<HashMap<OsString, OsString>>;
 
diff --git a/src/libstd/sys/sgx/os_str.rs b/src/libstd/sys/sgx/os_str.rs
deleted file mode 100644
index 79b43458d00..00000000000
--- a/src/libstd/sys/sgx/os_str.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-/// The underlying OsString/OsStr implementation on Unix systems: just
-/// a `Vec<u8>`/`[u8]`.
-
-use crate::borrow::Cow;
-use crate::fmt;
-use crate::str;
-use crate::mem;
-use crate::rc::Rc;
-use crate::sync::Arc;
-use crate::sys_common::{AsInner, IntoInner};
-use crate::sys_common::bytestring::debug_fmt_bytestring;
-
-use core::str::lossy::Utf8Lossy;
-
-#[derive(Clone, Hash)]
-pub struct Buf {
-    pub inner: Vec<u8>
-}
-
-pub struct Slice {
-    pub inner: [u8]
-}
-
-impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        debug_fmt_bytestring(&self.inner, formatter)
-    }
-}
-
-impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
-    }
-}
-
-impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl IntoInner<Vec<u8>> for Buf {
-    fn into_inner(self) -> Vec<u8> {
-        self.inner
-    }
-}
-
-impl AsInner<[u8]> for Buf {
-    fn as_inner(&self) -> &[u8] {
-        &self.inner
-    }
-}
-
-
-impl Buf {
-    pub fn from_string(s: String) -> Buf {
-        Buf { inner: s.into_bytes() }
-    }
-
-    #[inline]
-    pub fn with_capacity(capacity: usize) -> Buf {
-        Buf {
-            inner: Vec::with_capacity(capacity)
-        }
-    }
-
-    #[inline]
-    pub fn clear(&mut self) {
-        self.inner.clear()
-    }
-
-    #[inline]
-    pub fn capacity(&self) -> usize {
-        self.inner.capacity()
-    }
-
-    #[inline]
-    pub fn reserve(&mut self, additional: usize) {
-        self.inner.reserve(additional)
-    }
-
-    #[inline]
-    pub fn reserve_exact(&mut self, additional: usize) {
-        self.inner.reserve_exact(additional)
-    }
-
-    #[inline]
-    pub fn shrink_to_fit(&mut self) {
-        self.inner.shrink_to_fit()
-    }
-
-    #[inline]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        self.inner.shrink_to(min_capacity)
-    }
-
-    pub fn as_slice(&self) -> &Slice {
-        unsafe { mem::transmute(&*self.inner) }
-    }
-
-    pub fn into_string(self) -> Result<String, Buf> {
-        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
-    }
-
-    pub fn push_slice(&mut self, s: &Slice) {
-        self.inner.extend_from_slice(&s.inner)
-    }
-
-    #[inline]
-    pub fn into_box(self) -> Box<Slice> {
-        unsafe { mem::transmute(self.inner.into_boxed_slice()) }
-    }
-
-    #[inline]
-    pub fn from_box(boxed: Box<Slice>) -> Buf {
-        let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
-        Buf { inner: inner.into_vec() }
-    }
-
-    #[inline]
-    pub fn into_arc(&self) -> Arc<Slice> {
-        self.as_slice().into_arc()
-    }
-
-    #[inline]
-    pub fn into_rc(&self) -> Rc<Slice> {
-        self.as_slice().into_rc()
-    }
-}
-
-impl Slice {
-    fn from_u8_slice(s: &[u8]) -> &Slice {
-        unsafe { mem::transmute(s) }
-    }
-
-    pub fn from_str(s: &str) -> &Slice {
-        Slice::from_u8_slice(s.as_bytes())
-    }
-
-    pub fn to_str(&self) -> Option<&str> {
-        str::from_utf8(&self.inner).ok()
-    }
-
-    pub fn to_string_lossy(&self) -> Cow<str> {
-        String::from_utf8_lossy(&self.inner)
-    }
-
-    pub fn to_owned(&self) -> Buf {
-        Buf { inner: self.inner.to_vec() }
-    }
-
-    #[inline]
-    pub fn into_box(&self) -> Box<Slice> {
-        let boxed: Box<[u8]> = self.inner.into();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    pub fn empty_box() -> Box<Slice> {
-        let boxed: Box<[u8]> = Default::default();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    #[inline]
-    pub fn into_arc(&self) -> Arc<Slice> {
-        let arc: Arc<[u8]> = Arc::from(&self.inner);
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
-    }
-
-    #[inline]
-    pub fn into_rc(&self) -> Rc<Slice> {
-        let rc: Rc<[u8]> = Rc::from(&self.inner);
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
-    }
-}
diff --git a/src/libstd/sys/sgx/path.rs b/src/libstd/sys/sgx/path.rs
index 1115de1fbe5..b5fd7e3ae6d 100644
--- a/src/libstd/sys/sgx/path.rs
+++ b/src/libstd/sys/sgx/path.rs
@@ -11,7 +11,7 @@ pub fn is_verbatim_sep(b: u8) -> bool {
     b == b'/'
 }
 
-pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
+pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
     None
 }
 
diff --git a/src/libstd/sys/sgx/pipe.rs b/src/libstd/sys/sgx/pipe.rs
index 2582b993b60..fb14dc59101 100644
--- a/src/libstd/sys/sgx/pipe.rs
+++ b/src/libstd/sys/sgx/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::sys::Void;
 
 pub struct AnonPipe(Void);
@@ -8,18 +8,23 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
 }
 
-pub fn read2(p1: AnonPipe,
-             _v1: &mut Vec<u8>,
-             _p2: AnonPipe,
-             _v2: &mut Vec<u8>) -> io::Result<()> {
+pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
     match p1.0 {}
 }
diff --git a/src/libstd/sys/sgx/process.rs b/src/libstd/sys/sgx/process.rs
index c49daaa1632..a02e009d953 100644
--- a/src/libstd/sys/sgx/process.rs
+++ b/src/libstd/sys/sgx/process.rs
@@ -73,7 +73,7 @@ impl From<File> for Stdio {
 }
 
 impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         Ok(())
     }
 }
@@ -108,13 +108,13 @@ impl Eq for ExitStatus {
 }
 
 impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
 
 impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs
index 372760bbf26..30c47e44eef 100644
--- a/src/libstd/sys/sgx/rwlock.rs
+++ b/src/libstd/sys/sgx/rwlock.rs
@@ -1,7 +1,4 @@
-use crate::alloc::{self, Layout};
 use crate::num::NonZeroUsize;
-use crate::slice;
-use crate::str;
 
 use super::waitqueue::{
     try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
@@ -90,8 +87,8 @@ impl RWLock {
     #[inline]
     unsafe fn __read_unlock(
         &self,
-        mut rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
-        wguard: SpinMutexGuard<WaitVariable<bool>>,
+        mut rguard: SpinMutexGuard<'_, WaitVariable<Option<NonZeroUsize>>>,
+        wguard: SpinMutexGuard<'_, WaitVariable<bool>>,
     ) {
         *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1);
         if rguard.lock_var().is_some() {
@@ -102,7 +99,7 @@ impl RWLock {
                 *wguard.lock_var_mut() = true;
             } else {
                 // No writers were waiting, the lock is released
-                assert!(rguard.queue_empty());
+                rtassert!(rguard.queue_empty());
             }
         }
     }
@@ -117,8 +114,8 @@ impl RWLock {
     #[inline]
     unsafe fn __write_unlock(
         &self,
-        rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
-        wguard: SpinMutexGuard<WaitVariable<bool>>,
+        rguard: SpinMutexGuard<'_, WaitVariable<Option<NonZeroUsize>>>,
+        wguard: SpinMutexGuard<'_, WaitVariable<bool>>,
     ) {
         if let Err(mut wguard) = WaitQueue::notify_one(wguard) {
             // No writers waiting, release the write lock
@@ -147,6 +144,7 @@ impl RWLock {
 
     // only used by __rust_rwlock_unlock below
     #[inline]
+    #[cfg_attr(test, allow(dead_code))]
     unsafe fn unlock(&self) {
         let rguard = self.readers.lock();
         let wguard = self.writer.lock();
@@ -161,9 +159,12 @@ impl RWLock {
     pub unsafe fn destroy(&self) {}
 }
 
+// The following functions are needed by libunwind. These symbols are named
+// in pre-link args for the target specification, so keep that in sync.
+#[cfg(not(test))]
 const EINVAL: i32 = 22;
 
-// used by libunwind port
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -173,6 +174,7 @@ pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
     return 0;
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -181,6 +183,7 @@ pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
     (*p).write();
     return 0;
 }
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -190,46 +193,15 @@ pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
     return 0;
 }
 
-// the following functions are also used by the libunwind port. They're
-// included here to make sure parallel codegen and LTO don't mess things up.
-#[no_mangle]
-pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
-    if s < 0 {
-        return;
-    }
-    let buf = slice::from_raw_parts(m as *const u8, s as _);
-    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
-        eprint!("{}", s);
-    }
-}
-
-#[no_mangle]
-// NB. used by both libunwind and libpanic_abort
-pub unsafe extern "C" fn __rust_abort() {
-    crate::sys::abort_internal();
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
-    alloc::alloc(Layout::from_size_align_unchecked(size, align))
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
-    alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
-}
-
 #[cfg(test)]
 mod tests {
-
     use super::*;
     use core::array::FixedSizeArray;
-    use crate::mem::MaybeUninit;
-    use crate::{mem, ptr};
+    use crate::mem::{self, MaybeUninit};
 
-    // The below test verifies that the bytes of initialized RWLock are the ones
-    // we use in libunwind.
-    // If they change we need to update src/UnwindRustSgx.h in libunwind.
+    // Verify that the bytes of initialized RWLock are the same as in
+    // libunwind. If they change, `src/UnwindRustSgx.h` in libunwind needs to
+    // be changed too.
     #[test]
     fn test_c_rwlock_initializer() {
         const RWLOCK_INIT: &[u8] = &[
@@ -251,11 +223,28 @@ mod tests {
             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
         ];
 
-        let mut init = MaybeUninit::<RWLock>::zeroed();
-        init.set(RWLock::new());
-        assert_eq!(
-            mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(),
-            RWLOCK_INIT
-        );
+        #[inline(never)]
+        fn zero_stack() {
+            test::black_box(MaybeUninit::<[RWLock; 16]>::zeroed());
+        }
+
+        #[inline(never)]
+        unsafe fn rwlock_new(init: &mut MaybeUninit<RWLock>) {
+            init.write(RWLock::new());
+        }
+
+        unsafe {
+            // try hard to make sure that the padding/unused bytes in RWLock
+            // get initialized as 0. If the assertion below fails, that might
+            // just be an issue with the test code and not with the value of
+            // RWLOCK_INIT.
+            zero_stack();
+            let mut init = MaybeUninit::<RWLock>::zeroed();
+            rwlock_new(&mut init);
+            assert_eq!(
+                mem::transmute::<_, [u8; 128]>(init.assume_init()).as_slice(),
+                RWLOCK_INIT
+            )
+        };
     }
 }
diff --git a/src/libstd/sys/sgx/stack_overflow.rs b/src/libstd/sys/sgx/stack_overflow.rs
index c0e7c824615..e63fa2bed65 100644
--- a/src/libstd/sys/sgx/stack_overflow.rs
+++ b/src/libstd/sys/sgx/stack_overflow.rs
@@ -6,6 +6,7 @@ impl Handler {
     }
 }
 
+#[cfg_attr(test, allow(dead_code))]
 pub unsafe fn init() {
 }
 
diff --git a/src/libstd/sys/sgx/stdio.rs b/src/libstd/sys/sgx/stdio.rs
index f2c6892bfb7..a575401f5f6 100644
--- a/src/libstd/sys/sgx/stdio.rs
+++ b/src/libstd/sys/sgx/stdio.rs
@@ -2,6 +2,10 @@ use fortanix_sgx_abi as abi;
 
 use crate::io;
 use crate::sys::fd::FileDesc;
+#[cfg(not(test))]
+use crate::slice;
+#[cfg(not(test))]
+use crate::str;
 
 pub struct Stdin(());
 pub struct Stdout(());
@@ -62,3 +66,17 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub fn panic_output() -> Option<impl io::Write> {
     super::abi::panic::SgxPanicOutput::new()
 }
+
+// This function is needed by libunwind. The symbol is named in pre-link args
+// for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
+    if s < 0 {
+        return;
+    }
+    let buf = slice::from_raw_parts(m as *const u8, s as _);
+    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
+        eprint!("{}", s);
+    }
+}
diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs
index 13569062ac1..b9f42d4ad1c 100644
--- a/src/libstd/sys/sgx/thread.rs
+++ b/src/libstd/sys/sgx/thread.rs
@@ -1,4 +1,4 @@
-use crate::boxed::FnBox;
+#![cfg_attr(test, allow(dead_code))] // why is this necessary?
 use crate::ffi::CStr;
 use crate::io;
 use crate::time::Duration;
@@ -12,17 +12,16 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 mod task_queue {
     use crate::sync::{Mutex, MutexGuard, Once};
     use crate::sync::mpsc;
-    use crate::boxed::FnBox;
 
     pub type JoinHandle = mpsc::Receiver<()>;
 
     pub(super) struct Task {
-        p: Box<dyn FnBox()>,
+        p: Box<dyn FnOnce()>,
         done: mpsc::Sender<()>,
     }
 
     impl Task {
-        pub(super) fn new(p: Box<dyn FnBox()>) -> (Task, JoinHandle) {
+        pub(super) fn new(p: Box<dyn FnOnce()>) -> (Task, JoinHandle) {
             let (done, recv) = mpsc::channel();
             (Task { p, done }, recv)
         }
@@ -33,7 +32,11 @@ mod task_queue {
         }
     }
 
+    #[cfg_attr(test, linkage = "available_externally")]
+    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"]
     static TASK_QUEUE_INIT: Once = Once::new();
+    #[cfg_attr(test, linkage = "available_externally")]
+    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
     static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
 
     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
@@ -46,7 +49,7 @@ mod task_queue {
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, p: Box<dyn FnBox()>)
+    pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce()>)
         -> io::Result<Thread>
     {
         let mut queue_lock = task_queue::lock();
@@ -57,17 +60,15 @@ impl Thread {
     }
 
     pub(super) fn entry() {
-        let mut guard = task_queue::lock();
-        let task = guard.pop().expect("Thread started but no tasks pending");
-        drop(guard); // make sure to not hold the task queue lock longer than necessary
+        let mut pending_tasks = task_queue::lock();
+        let task = rtunwrap!(Some, pending_tasks.pop());
+        drop(pending_tasks); // make sure to not hold the task queue lock longer than necessary
         task.run()
     }
 
     pub fn yield_now() {
-        assert_eq!(
-            usercalls::wait(0, usercalls::raw::WAIT_NO).unwrap_err().kind(),
-            io::ErrorKind::WouldBlock
-        );
+        let wait_error = rtunwrap!(Err, usercalls::wait(0, usercalls::raw::WAIT_NO));
+        rtassert!(wait_error.kind() == io::ErrorKind::WouldBlock);
     }
 
     pub fn set_name(_name: &CStr) {
@@ -75,7 +76,7 @@ impl Thread {
     }
 
     pub fn sleep(_dur: Duration) {
-        panic!("can't sleep"); // FIXME
+        rtabort!("can't sleep"); // FIXME
     }
 
     pub fn join(self) {
diff --git a/src/libstd/sys/sgx/time.rs b/src/libstd/sys/sgx/time.rs
index e4f789c3e36..4659f7ba71f 100644
--- a/src/libstd/sys/sgx/time.rs
+++ b/src/libstd/sys/sgx/time.rs
@@ -14,8 +14,8 @@ impl Instant {
         Instant(usercalls::insecure_time())
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        self.0 - other.0
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        self.0.checked_sub(other.0)
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs
index 1dbf2afbf49..d542f9b4101 100644
--- a/src/libstd/sys/sgx/waitqueue.rs
+++ b/src/libstd/sys/sgx/waitqueue.rs
@@ -121,7 +121,7 @@ impl<'a, T> Drop for WaitGuard<'a, T> {
             NotifiedTcs::Single(tcs) => Some(tcs),
             NotifiedTcs::All { .. } => None
         };
-        usercalls::send(EV_UNPARK, target_tcs).unwrap();
+        rtunwrap!(Ok, usercalls::send(EV_UNPARK, target_tcs));
     }
 }
 
@@ -140,7 +140,8 @@ impl WaitQueue {
     /// until a wakeup event.
     ///
     /// This function does not return until this thread has been awoken.
-    pub fn wait<T>(mut guard: SpinMutexGuard<WaitVariable<T>>) {
+    pub fn wait<T>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>) {
+        // very unsafe: check requirements of UnsafeList::push
         unsafe {
             let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry {
                 tcs: thread::current(),
@@ -149,10 +150,9 @@ impl WaitQueue {
             let entry = guard.queue.inner.push(&mut entry);
             drop(guard);
             while !entry.lock().wake {
-                assert_eq!(
-                    usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap() & EV_UNPARK,
-                    EV_UNPARK
-                );
+                // don't panic, this would invalidate `entry` during unwinding
+                let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE));
+                rtassert!(eventset & EV_UNPARK == EV_UNPARK);
             }
         }
     }
@@ -162,8 +162,8 @@ impl WaitQueue {
     ///
     /// If a waiter is found, a `WaitGuard` is returned which will notify the
     /// waiter when it is dropped.
-    pub fn notify_one<T>(mut guard: SpinMutexGuard<WaitVariable<T>>)
-        -> Result<WaitGuard<T>, SpinMutexGuard<WaitVariable<T>>>
+    pub fn notify_one<T>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>)
+        -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>>
     {
         unsafe {
             if let Some(entry) = guard.queue.inner.pop() {
@@ -186,8 +186,8 @@ impl WaitQueue {
     ///
     /// If at least one waiter is found, a `WaitGuard` is returned which will
     /// notify all waiters when it is dropped.
-    pub fn notify_all<T>(mut guard: SpinMutexGuard<WaitVariable<T>>)
-        -> Result<WaitGuard<T>, SpinMutexGuard<WaitVariable<T>>>
+    pub fn notify_all<T>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>)
+        -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>>
     {
         unsafe {
             let mut count = 0;
@@ -269,7 +269,7 @@ mod unsafe_list {
                         // ,-------> /---------\ next ---,
                         // |         |head_tail|         |
                         // `--- prev \---------/ <-------`
-                        assert_eq!(self.head_tail.as_ref().prev, first);
+                        rtassert!(self.head_tail.as_ref().prev == first);
                         true
                     } else {
                         false
@@ -285,7 +285,9 @@ mod unsafe_list {
         /// # Safety
         ///
         /// The entry must remain allocated until the entry is removed from the
-        /// list AND the caller who popped is done using the entry.
+        /// list AND the caller who popped is done using the entry. Special
+        /// care must be taken in the caller of `push` to ensure unwinding does
+        /// not destroy the stack frame containing the entry.
         pub unsafe fn push<'a>(&mut self, entry: &'a mut UnsafeListEntry<T>) -> &'a T {
             self.init();
 
@@ -303,6 +305,7 @@ mod unsafe_list {
             entry.as_mut().prev = prev_tail;
             entry.as_mut().next = self.head_tail;
             prev_tail.as_mut().next = entry;
+            // unwrap ok: always `Some` on non-dummy entries
             (*entry.as_ptr()).value.as_ref().unwrap()
         }
 
@@ -333,6 +336,7 @@ mod unsafe_list {
                 second.as_mut().prev = self.head_tail;
                 first.as_mut().next = NonNull::dangling();
                 first.as_mut().prev = NonNull::dangling();
+                // unwrap ok: always `Some` on non-dummy entries
                 Some((*first.as_ptr()).value.as_ref().unwrap())
             }
         }
@@ -433,7 +437,7 @@ mod spin_mutex {
         }
 
         #[inline(always)]
-        pub fn lock(&self) -> SpinMutexGuard<T> {
+        pub fn lock(&self) -> SpinMutexGuard<'_, T> {
             loop {
                 match self.try_lock() {
                     None => while self.lock.load(Ordering::Relaxed) {
@@ -445,7 +449,7 @@ mod spin_mutex {
         }
 
         #[inline(always)]
-        pub fn try_lock(&self) -> Option<SpinMutexGuard<T>> {
+        pub fn try_lock(&self) -> Option<SpinMutexGuard<'_, T>> {
             if !self.lock.compare_and_swap(false, true, Ordering::Acquire) {
                 Some(SpinMutexGuard {
                     mutex: self,
@@ -498,6 +502,7 @@ mod spin_mutex {
         use super::*;
         use crate::sync::Arc;
         use crate::thread;
+        use crate::time::{SystemTime, Duration};
 
         #[test]
         fn sleep() {
@@ -507,7 +512,13 @@ mod spin_mutex {
             let t1 = thread::spawn(move || {
                 *mutex2.lock() = 1;
             });
-            thread::sleep_ms(50);
+
+            // "sleep" for 50ms
+            // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+            let start = SystemTime::now();
+            let max = Duration::from_millis(50);
+            while start.elapsed().unwrap() < max {}
+
             assert_eq!(*guard, 0);
             drop(guard);
             t1.join().unwrap();
@@ -530,7 +541,8 @@ mod tests {
         let locked = wq.lock();
 
         let t1 = thread::spawn(move || {
-            assert!(WaitQueue::notify_one(wq2.lock()).is_none())
+            // if we obtain the lock, the main thread should be waiting
+            assert!(WaitQueue::notify_one(wq2.lock()).is_ok());
         });
 
         WaitQueue::wait(locked);
diff --git a/src/libstd/sys/unix/alloc.rs b/src/libstd/sys/unix/alloc.rs
index 8e8f5017da7..f47dc92d2de 100644
--- a/src/libstd/sys/unix/alloc.rs
+++ b/src/libstd/sys/unix/alloc.rs
@@ -6,6 +6,10 @@ use crate::alloc::{GlobalAlloc, Layout, System};
 unsafe impl GlobalAlloc for System {
     #[inline]
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        // jemalloc provides alignment less than MIN_ALIGN for small allocations.
+        // So only rely on MIN_ALIGN if size >= align.
+        // Also see <https://github.com/rust-lang/rust/issues/45955> and
+        // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>.
         if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
             libc::malloc(layout.size()) as *mut u8
         } else {
@@ -21,10 +25,11 @@ unsafe impl GlobalAlloc for System {
 
     #[inline]
     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        // See the comment above in `alloc` for why this check looks the way it does.
         if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
             libc::calloc(layout.size(), 1) as *mut u8
         } else {
-            let ptr = self.alloc(layout.clone());
+            let ptr = self.alloc(layout);
             if !ptr.is_null() {
                 ptr::write_bytes(ptr, 0, layout.size());
             }
@@ -80,7 +85,10 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
 #[inline]
 unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
     let mut out = ptr::null_mut();
-    let ret = libc::posix_memalign(&mut out, layout.align(), layout.size());
+    // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
+    // Since these are all powers of 2, we can just use max.
+    let align = layout.align().max(crate::mem::size_of::<usize>());
+    let ret = libc::posix_memalign(&mut out, align, layout.size());
     if ret != 0 {
         ptr::null_mut()
     } else {
diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs
index 18de1096df2..288e9b5c126 100644
--- a/src/libstd/sys/unix/args.rs
+++ b/src/libstd/sys/unix/args.rs
@@ -49,7 +49,6 @@ impl DoubleEndedIterator for Args {
           target_os = "android",
           target_os = "freebsd",
           target_os = "dragonfly",
-          target_os = "bitrig",
           target_os = "netbsd",
           target_os = "openbsd",
           target_os = "solaris",
@@ -57,7 +56,8 @@ impl DoubleEndedIterator for Args {
           target_os = "haiku",
           target_os = "l4re",
           target_os = "fuchsia",
-          target_os = "hermit"))]
+          target_os = "hermit",
+          target_os = "redox"))]
 mod imp {
     use crate::os::unix::prelude::*;
     use crate::ptr;
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index 47fb6792f08..0a93fbf8ea7 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -31,24 +31,26 @@ impl Condvar {
               target_os = "ios",
               target_os = "l4re",
               target_os = "android",
-              target_os = "hermit"))]
+              target_os = "hermit",
+              target_os = "redox"))]
     pub unsafe fn init(&mut self) {}
 
     #[cfg(not(any(target_os = "macos",
                   target_os = "ios",
                   target_os = "l4re",
                   target_os = "android",
-                  target_os = "hermit")))]
+                  target_os = "hermit",
+                  target_os = "redox")))]
     pub unsafe fn init(&mut self) {
-        use crate::mem;
-        let mut attr: libc::pthread_condattr_t = mem::uninitialized();
-        let r = libc::pthread_condattr_init(&mut attr);
+        use crate::mem::MaybeUninit;
+        let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
+        let r = libc::pthread_condattr_init(attr.as_mut_ptr());
         assert_eq!(r, 0);
-        let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC);
+        let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC);
         assert_eq!(r, 0);
-        let r = libc::pthread_cond_init(self.inner.get(), &attr);
+        let r = libc::pthread_cond_init(self.inner.get(), attr.as_ptr());
         assert_eq!(r, 0);
-        let r = libc::pthread_condattr_destroy(&mut attr);
+        let r = libc::pthread_condattr_destroy(attr.as_mut_ptr());
         assert_eq!(r, 0);
     }
 
diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs
index f9592d5c45f..d724eeb8b3f 100644
--- a/src/libstd/sys/unix/env.rs
+++ b/src/libstd/sys/unix/env.rs
@@ -53,17 +53,6 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "";
 }
 
-#[cfg(target_os = "bitrig")]
-pub mod os {
-    pub const FAMILY: &str = "unix";
-    pub const OS: &str = "bitrig";
-    pub const DLL_PREFIX: &str = "lib";
-    pub const DLL_SUFFIX: &str = ".so";
-    pub const DLL_EXTENSION: &str = "so";
-    pub const EXE_SUFFIX: &str = "";
-    pub const EXE_EXTENSION: &str = "";
-}
-
 #[cfg(target_os = "netbsd")]
 pub mod os {
     pub const FAMILY: &str = "unix";
@@ -173,3 +162,14 @@ pub mod os {
     pub const EXE_SUFFIX: &str = "";
     pub const EXE_EXTENSION: &str = "";
 }
+
+#[cfg(target_os = "redox")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "redox";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs
index 0c023239815..76b34a6b5d8 100644
--- a/src/libstd/sys/unix/ext/ffi.rs
+++ b/src/libstd/sys/unix/ext/ffi.rs
@@ -1,109 +1,38 @@
 //! Unix-specific extension to the primitives in the `std::ffi` module
+//!
+//! # Examples
+//!
+//! ```
+//! use std::ffi::OsString;
+//! use std::os::unix::ffi::OsStringExt;
+//!
+//! let bytes = b"foo".to_vec();
+//!
+//! // OsStringExt::from_vec
+//! let os_string = OsString::from_vec(bytes);
+//! assert_eq!(os_string.to_str(), Some("foo"));
+//!
+//! // OsStringExt::into_vec
+//! let bytes = os_string.into_vec();
+//! assert_eq!(bytes, b"foo");
+//! ```
+//!
+//! ```
+//! use std::ffi::OsStr;
+//! use std::os::unix::ffi::OsStrExt;
+//!
+//! let bytes = b"foo";
+//!
+//! // OsStrExt::from_bytes
+//! let os_str = OsStr::from_bytes(bytes);
+//! assert_eq!(os_str.to_str(), Some("foo"));
+//!
+//! // OsStrExt::as_bytes
+//! let bytes = os_str.as_bytes();
+//! assert_eq!(bytes, b"foo");
+//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::ffi::{OsStr, OsString};
-use crate::mem;
-use crate::sys::os_str::Buf;
-use crate::sys_common::{FromInner, IntoInner, AsInner};
-
-/// Unix-specific extensions to [`OsString`].
-///
-/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStringExt {
-    /// Creates an [`OsString`] from a byte vector.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsString;
-    /// use std::os::unix::ffi::OsStringExt;
-    ///
-    /// let bytes = b"foo".to_vec();
-    /// let os_string = OsString::from_vec(bytes);
-    /// assert_eq!(os_string.to_str(), Some("foo"));
-    /// ```
-    ///
-    /// [`OsString`]: ../../../ffi/struct.OsString.html
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_vec(vec: Vec<u8>) -> Self;
-
-    /// Yields the underlying byte vector of this [`OsString`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsString;
-    /// use std::os::unix::ffi::OsStringExt;
-    ///
-    /// let mut os_string = OsString::new();
-    /// os_string.push("foo");
-    /// let bytes = os_string.into_vec();
-    /// assert_eq!(bytes, b"foo");
-    /// ```
-    ///
-    /// [`OsString`]: ../../../ffi/struct.OsString.html
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn into_vec(self) -> Vec<u8>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStringExt for OsString {
-    fn from_vec(vec: Vec<u8>) -> OsString {
-        FromInner::from_inner(Buf { inner: vec })
-    }
-    fn into_vec(self) -> Vec<u8> {
-        self.into_inner().inner
-    }
-}
-
-/// Unix-specific extensions to [`OsStr`].
-///
-/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStrExt {
-    #[stable(feature = "rust1", since = "1.0.0")]
-    /// Creates an [`OsStr`] from a byte slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsStr;
-    /// use std::os::unix::ffi::OsStrExt;
-    ///
-    /// let bytes = b"foo";
-    /// let os_str = OsStr::from_bytes(bytes);
-    /// assert_eq!(os_str.to_str(), Some("foo"));
-    /// ```
-    ///
-    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
-    fn from_bytes(slice: &[u8]) -> &Self;
-
-    /// Gets the underlying byte view of the [`OsStr`] slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::OsStr;
-    /// use std::os::unix::ffi::OsStrExt;
-    ///
-    /// let mut os_str = OsStr::new("foo");
-    /// let bytes = os_str.as_bytes();
-    /// assert_eq!(bytes, b"foo");
-    /// ```
-    ///
-    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn as_bytes(&self) -> &[u8];
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
-impl OsStrExt for OsStr {
-    fn from_bytes(slice: &[u8]) -> &OsStr {
-        unsafe { mem::transmute(slice) }
-    }
-    fn as_bytes(&self) -> &[u8] {
-        &self.as_inner().inner
-    }
-}
+pub use crate::sys_common::os_str_bytes::*;
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index d9baac993c4..c033c60cbe9 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -238,7 +238,7 @@ pub trait PermissionsExt {
     ///     let metadata = f.metadata()?;
     ///     let permissions = metadata.permissions();
     ///
-    ///     println!("permissions: {}", permissions.mode());
+    ///     println!("permissions: {:o}", permissions.mode());
     ///     Ok(()) }
     /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
diff --git a/src/libstd/sys/unix/ext/io.rs b/src/libstd/sys/unix/ext/io.rs
index 1a0b3b8962b..6bcc59495e3 100644
--- a/src/libstd/sys/unix/ext/io.rs
+++ b/src/libstd/sys/unix/ext/io.rs
@@ -95,3 +95,18 @@ impl AsRawFd for io::Stdout {
 impl AsRawFd for io::Stderr {
     fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO }
 }
+
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawFd for io::StdinLock<'a> {
+    fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO }
+}
+
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawFd for io::StdoutLock<'a> {
+    fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO }
+}
+
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawFd for io::StderrLock<'a> {
+    fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO }
+}
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 4fc79efe7ce..42edd5dbbea 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -18,7 +18,7 @@ mod libc {
 use crate::ascii;
 use crate::ffi::OsStr;
 use crate::fmt;
-use crate::io::{self, Initializer, IoVec, IoVecMut};
+use crate::io::{self, Initializer, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::net::{self, Shutdown};
 use crate::os::unix::ffi::OsStrExt;
@@ -32,18 +32,17 @@ use crate::sys_common::{self, AsInner, FromInner, IntoInner};
 #[cfg(any(target_os = "linux", target_os = "android",
           target_os = "dragonfly", target_os = "freebsd",
           target_os = "openbsd", target_os = "netbsd",
-          target_os = "haiku", target_os = "bitrig"))]
+          target_os = "haiku"))]
 use libc::MSG_NOSIGNAL;
 #[cfg(not(any(target_os = "linux", target_os = "android",
               target_os = "dragonfly", target_os = "freebsd",
               target_os = "openbsd", target_os = "netbsd",
-              target_os = "haiku", target_os = "bitrig")))]
+              target_os = "haiku")))]
 const MSG_NOSIGNAL: libc::c_int = 0x0;
 
-fn sun_path_offset() -> usize {
+fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
     // Work with an actual instance of the type since using a null pointer is UB
-    let addr: libc::sockaddr_un = unsafe { mem::uninitialized() };
-    let base = &addr as *const _ as usize;
+    let base = addr as *const _ as usize;
     let path = &addr.sun_path as *const _ as usize;
     path - base
 }
@@ -69,7 +68,7 @@ unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::sockl
     // null byte for pathname addresses is already there because we zeroed the
     // struct
 
-    let mut len = sun_path_offset() + bytes.len();
+    let mut len = sun_path_offset(&addr) + bytes.len();
     match bytes.get(0) {
         Some(&0) | None => {}
         Some(_) => len += 1,
@@ -122,7 +121,7 @@ impl SocketAddr {
         if len == 0 {
             // When there is a datagram from unnamed unix socket
             // linux returns zero bytes of address
-            len = sun_path_offset() as libc::socklen_t;  // i.e., zero-length address
+            len = sun_path_offset(&addr) as libc::socklen_t;  // i.e., zero-length address
         } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
             return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                       "file descriptor did not correspond to a Unix socket"));
@@ -199,8 +198,8 @@ impl SocketAddr {
         }
     }
 
-    fn address<'a>(&'a self) -> AddressKind<'a> {
-        let len = self.len as usize - sun_path_offset();
+    fn address(&self) -> AddressKind<'_> {
+        let len = self.len as usize - sun_path_offset(&self.addr);
         let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
 
         // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
@@ -219,7 +218,7 @@ impl SocketAddr {
 
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for SocketAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.address() {
             AddressKind::Unnamed => write!(fmt, "(unnamed)"),
             AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
@@ -231,7 +230,7 @@ impl fmt::Debug for SocketAddr {
 struct AsciiEscaped<'a>(&'a [u8]);
 
 impl<'a> fmt::Display for AsciiEscaped<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(fmt, "\"")?;
         for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
             write!(fmt, "{}", byte as char)?;
@@ -259,7 +258,7 @@ pub struct UnixStream(Socket);
 
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for UnixStream {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut builder = fmt.debug_struct("UnixStream");
         builder.field("fd", self.0.as_inner());
         if let Ok(addr) = self.local_addr() {
@@ -551,7 +550,7 @@ impl io::Read for UnixStream {
         io::Read::read(&mut &*self, buf)
     }
 
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         io::Read::read_vectored(&mut &*self, bufs)
     }
 
@@ -567,7 +566,7 @@ impl<'a> io::Read for &'a UnixStream {
         self.0.read(buf)
     }
 
-    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         self.0.read_vectored(bufs)
     }
 
@@ -583,7 +582,7 @@ impl io::Write for UnixStream {
         io::Write::write(&mut &*self, buf)
     }
 
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         io::Write::write_vectored(&mut &*self, bufs)
     }
 
@@ -598,7 +597,7 @@ impl<'a> io::Write for &'a UnixStream {
         self.0.write(buf)
     }
 
-    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         self.0.write_vectored(bufs)
     }
 
@@ -719,7 +718,7 @@ pub struct UnixListener(Socket);
 
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for UnixListener {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut builder = fmt.debug_struct("UnixListener");
         builder.field("fd", self.0.as_inner());
         if let Ok(addr) = self.local_addr() {
@@ -895,7 +894,7 @@ impl UnixListener {
     /// }
     /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn incoming<'a>(&'a self) -> Incoming<'a> {
+    pub fn incoming(&self) -> Incoming<'_> {
         Incoming { listener: self }
     }
 }
@@ -998,7 +997,7 @@ pub struct UnixDatagram(Socket);
 
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for UnixDatagram {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut builder = fmt.debug_struct("UnixDatagram");
         builder.field("fd", self.0.as_inner());
         if let Ok(addr) = self.local_addr() {
@@ -1531,14 +1530,14 @@ mod test {
         let (mut s1, mut s2) = or_panic!(UnixStream::pair());
 
         let len = or_panic!(s1.write_vectored(
-            &[IoVec::new(b"hello"), IoVec::new(b" "), IoVec::new(b"world!")],
+            &[IoSlice::new(b"hello"), IoSlice::new(b" "), IoSlice::new(b"world!")],
         ));
         assert_eq!(len, 12);
 
         let mut buf1 = [0; 6];
         let mut buf2 = [0; 7];
         let len = or_panic!(s2.read_vectored(
-            &mut [IoVecMut::new(&mut buf1), IoVecMut::new(&mut buf2)],
+            &mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],
         ));
         assert_eq!(len, 12);
         assert_eq!(&buf1, b"hello ");
diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index 17478dce4fe..952ba40ee87 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -10,7 +10,7 @@
 // fallback implementation to use as well.
 //
 // Due to rust-lang/rust#18804, make sure this is not generic!
-#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
+#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox"))]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
     use crate::mem;
     use crate::sys_common::thread_local::register_dtor_fallback;
@@ -82,7 +82,3 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
         }
     }
 }
-
-pub fn requires_move_before_drop() -> bool {
-    false
-}
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index c274ad26cb1..ac43526b50f 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -1,7 +1,7 @@
 #![unstable(reason = "not public", issue = "0", feature = "fd")]
 
 use crate::cmp;
-use crate::io::{self, Read, Initializer, IoVec, IoVecMut};
+use crate::io::{self, Read, Initializer, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::cvt;
@@ -53,7 +53,7 @@ impl FileDesc {
         Ok(ret as usize)
     }
 
-    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::readv(self.fd,
                         bufs.as_ptr() as *const libc::iovec,
@@ -115,7 +115,7 @@ impl FileDesc {
         Ok(ret as usize)
     }
 
-    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::writev(self.fd,
                          bufs.as_ptr() as *const libc::iovec,
@@ -175,7 +175,9 @@ impl FileDesc {
                   target_os = "emscripten",
                   target_os = "fuchsia",
                   target_os = "l4re",
-                  target_os = "haiku")))]
+                  target_os = "linux",
+                  target_os = "haiku",
+                  target_os = "redox")))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
             cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
@@ -187,7 +189,9 @@ impl FileDesc {
               target_os = "emscripten",
               target_os = "fuchsia",
               target_os = "l4re",
-              target_os = "haiku"))]
+              target_os = "linux",
+              target_os = "haiku",
+              target_os = "redox"))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
             let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 3b80b475a93..3b1eb86b84f 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -2,7 +2,7 @@ use crate::os::unix::prelude::*;
 
 use crate::ffi::{CString, CStr, OsString, OsStr};
 use crate::fmt;
-use crate::io::{self, Error, ErrorKind, SeekFrom};
+use crate::io::{self, Error, ErrorKind, SeekFrom, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::path::{Path, PathBuf};
 use crate::ptr;
@@ -33,9 +33,12 @@ use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
               target_os = "emscripten",
               target_os = "solaris",
               target_os = "l4re",
-              target_os = "fuchsia")))]
+              target_os = "fuchsia",
+              target_os = "redox")))]
 use libc::{readdir_r as readdir64_r};
 
+pub use crate::sys_common::fs::remove_dir_all;
+
 pub struct File(FileDesc);
 
 #[derive(Clone)]
@@ -67,7 +70,7 @@ pub struct DirEntry {
     // on Solaris and Fuchsia because a) it uses a zero-length
     // array to store the name, b) its lifetime between readdir
     // calls is not guaranteed.
-    #[cfg(any(target_os = "solaris", target_os = "fuchsia"))]
+    #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))]
     name: Box<[u8]>
 }
 
@@ -145,8 +148,7 @@ impl FileAttr {
         }))
     }
 
-    #[cfg(any(target_os = "bitrig",
-              target_os = "freebsd",
+    #[cfg(any(target_os = "freebsd",
               target_os = "openbsd",
               target_os = "macos",
               target_os = "ios"))]
@@ -157,8 +159,7 @@ impl FileAttr {
         }))
     }
 
-    #[cfg(not(any(target_os = "bitrig",
-                  target_os = "freebsd",
+    #[cfg(not(any(target_os = "freebsd",
                   target_os = "openbsd",
                   target_os = "macos",
                   target_os = "ios")))]
@@ -206,7 +207,7 @@ impl FromInner<u32> for FilePermissions {
 }
 
 impl fmt::Debug for ReadDir {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
         // Thus the result will be e g 'ReadDir("/home")'
         fmt::Debug::fmt(&*self.inner.root, f)
@@ -216,7 +217,7 @@ impl fmt::Debug for ReadDir {
 impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
-    #[cfg(any(target_os = "solaris", target_os = "fuchsia"))]
+    #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         use crate::slice;
 
@@ -253,7 +254,7 @@ impl Iterator for ReadDir {
         }
     }
 
-    #[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))]
+    #[cfg(not(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox")))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         if self.end_of_stream {
             return None;
@@ -346,14 +347,14 @@ impl DirEntry {
               target_os = "haiku",
               target_os = "l4re",
               target_os = "fuchsia",
-              target_os = "hermit"))]
+              target_os = "hermit",
+              target_os = "redox"))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
     }
 
     #[cfg(any(target_os = "freebsd",
               target_os = "openbsd",
-              target_os = "bitrig",
               target_os = "netbsd",
               target_os = "dragonfly"))]
     pub fn ino(&self) -> u64 {
@@ -365,8 +366,7 @@ impl DirEntry {
               target_os = "netbsd",
               target_os = "openbsd",
               target_os = "freebsd",
-              target_os = "dragonfly",
-              target_os = "bitrig"))]
+              target_os = "dragonfly"))]
     fn name_bytes(&self) -> &[u8] {
         use crate::slice;
         unsafe {
@@ -386,7 +386,8 @@ impl DirEntry {
         }
     }
     #[cfg(any(target_os = "solaris",
-              target_os = "fuchsia"))]
+              target_os = "fuchsia",
+              target_os = "redox"))]
     fn name_bytes(&self) -> &[u8] {
         &*self.name
     }
@@ -524,8 +525,15 @@ impl File {
     }
 
     pub fn fsync(&self) -> io::Result<()> {
-        cvt_r(|| unsafe { libc::fsync(self.0.raw()) })?;
-        Ok(())
+        cvt_r(|| unsafe { os_fsync(self.0.raw()) })?;
+        return Ok(());
+
+        #[cfg(any(target_os = "macos", target_os = "ios"))]
+        unsafe fn os_fsync(fd: c_int) -> c_int {
+            libc::fcntl(fd, libc::F_FULLFSYNC)
+        }
+        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
+        unsafe fn os_fsync(fd: c_int) -> c_int { libc::fsync(fd) }
     }
 
     pub fn datasync(&self) -> io::Result<()> {
@@ -549,15 +557,25 @@ impl File {
         return crate::sys::android::ftruncate64(self.0.raw(), size);
 
         #[cfg(not(target_os = "android"))]
-        return cvt_r(|| unsafe {
-            ftruncate64(self.0.raw(), size as off64_t)
-        }).map(|_| ());
+        {
+            use crate::convert::TryInto;
+            let size: off64_t = size
+                .try_into()
+                .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
+            cvt_r(|| unsafe {
+                ftruncate64(self.0.raw(), size)
+            }).map(|_| ())
+        }
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.0.read_at(buf, offset)
     }
@@ -566,6 +584,10 @@ impl File {
         self.0.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.0.write_at(buf, offset)
     }
@@ -627,7 +649,7 @@ impl FromInner<c_int> for File {
 }
 
 impl fmt::Debug for File {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         #[cfg(target_os = "linux")]
         fn get_path(fd: c_int) -> Option<PathBuf> {
             let mut p = PathBuf::from("/proc/self/fd");
@@ -734,27 +756,6 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
     Ok(())
 }
 
-pub fn remove_dir_all(path: &Path) -> io::Result<()> {
-    let filetype = lstat(path)?.file_type();
-    if filetype.is_symlink() {
-        unlink(path)
-    } else {
-        remove_dir_all_recursive(path)
-    }
-}
-
-fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
-    for child in readdir(path)? {
-        let child = child?;
-        if child.file_type()?.is_dir() {
-            remove_dir_all_recursive(&child.path())?;
-        } else {
-            unlink(&child.path())?;
-        }
-    }
-    rmdir(path)
-}
-
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
     let c_path = cstr(p)?;
     let p = c_path.as_ptr();
@@ -827,27 +828,59 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
     Ok(PathBuf::from(OsString::from_vec(buf)))
 }
 
-#[cfg(not(any(target_os = "linux", target_os = "android")))]
-pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
     use crate::fs::File;
-    if !from.is_file() {
-        return Err(Error::new(ErrorKind::InvalidInput,
-                              "the source path is not an existing regular file"))
+
+    let reader = File::open(from)?;
+    let metadata = reader.metadata()?;
+    if !metadata.is_file() {
+        return Err(Error::new(
+            ErrorKind::InvalidInput,
+            "the source path is not an existing regular file",
+        ));
     }
+    Ok((reader, metadata))
+}
+
+fn open_to_and_set_permissions(
+    to: &Path,
+    reader_metadata: crate::fs::Metadata,
+) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
+    use crate::fs::OpenOptions;
+    use crate::os::unix::fs::{OpenOptionsExt, PermissionsExt};
+
+    let perm = reader_metadata.permissions();
+    let writer = OpenOptions::new()
+        // create the file with the correct mode right away
+        .mode(perm.mode())
+        .write(true)
+        .create(true)
+        .truncate(true)
+        .open(to)?;
+    let writer_metadata = writer.metadata()?;
+    if writer_metadata.is_file() {
+        // Set the correct file permissions, in case the file already existed.
+        // Don't set the permissions on already existing non-files like
+        // pipes/FIFOs or device nodes.
+        writer.set_permissions(perm)?;
+    }
+    Ok((writer, writer_metadata))
+}
 
-    let mut reader = File::open(from)?;
-    let mut writer = File::create(to)?;
-    let perm = reader.metadata()?.permissions();
+#[cfg(not(any(target_os = "linux",
+              target_os = "android",
+              target_os = "macos",
+              target_os = "ios")))]
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    let (mut reader, reader_metadata) = open_from(from)?;
+    let (mut writer, _) = open_to_and_set_permissions(to, reader_metadata)?;
 
-    let ret = io::copy(&mut reader, &mut writer)?;
-    writer.set_permissions(perm)?;
-    Ok(ret)
+    io::copy(&mut reader, &mut writer)
 }
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use crate::cmp;
-    use crate::fs::File;
     use crate::sync::atomic::{AtomicBool, Ordering};
 
     // Kernel prior to 4.5 don't have copy_file_range
@@ -873,17 +906,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
         )
     }
 
-    if !from.is_file() {
-        return Err(Error::new(ErrorKind::InvalidInput,
-                              "the source path is not an existing regular file"))
-    }
-
-    let mut reader = File::open(from)?;
-    let mut writer = File::create(to)?;
-    let (perm, len) = {
-        let metadata = reader.metadata()?;
-        (metadata.permissions(), metadata.size())
-    };
+    let (mut reader, reader_metadata) = open_from(from)?;
+    let len = reader_metadata.len();
+    let (mut writer, _) = open_to_and_set_permissions(to, reader_metadata)?;
 
     let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed);
     let mut written = 0u64;
@@ -893,13 +918,14 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
             let copy_result = unsafe {
                 // We actually don't have to adjust the offsets,
                 // because copy_file_range adjusts the file offset automatically
-                cvt(copy_file_range(reader.as_raw_fd(),
-                                    ptr::null_mut(),
-                                    writer.as_raw_fd(),
-                                    ptr::null_mut(),
-                                    bytes_to_copy,
-                                    0)
-                    )
+                cvt(copy_file_range(
+                    reader.as_raw_fd(),
+                    ptr::null_mut(),
+                    writer.as_raw_fd(),
+                    ptr::null_mut(),
+                    bytes_to_copy,
+                    0,
+                ))
             };
             if let Err(ref copy_err) = copy_result {
                 match copy_err.raw_os_error() {
@@ -917,23 +943,152 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
             Ok(ret) => written += ret as u64,
             Err(err) => {
                 match err.raw_os_error() {
-                    Some(os_err) if os_err == libc::ENOSYS
-                                 || os_err == libc::EXDEV
-                                 || os_err == libc::EPERM => {
-                        // Try fallback io::copy if either:
-                        // - Kernel version is < 4.5 (ENOSYS)
-                        // - Files are mounted on different fs (EXDEV)
-                        // - copy_file_range is disallowed, for example by seccomp (EPERM)
-                        assert_eq!(written, 0);
-                        let ret = io::copy(&mut reader, &mut writer)?;
-                        writer.set_permissions(perm)?;
-                        return Ok(ret)
-                    },
+                    Some(os_err)
+                    if os_err == libc::ENOSYS
+                        || os_err == libc::EXDEV
+                        || os_err == libc::EINVAL
+                        || os_err == libc::EPERM =>
+                        {
+                            // Try fallback io::copy if either:
+                            // - Kernel version is < 4.5 (ENOSYS)
+                            // - Files are mounted on different fs (EXDEV)
+                            // - copy_file_range is disallowed, for example by seccomp (EPERM)
+                            // - copy_file_range cannot be used with pipes or device nodes (EINVAL)
+                            assert_eq!(written, 0);
+                            return io::copy(&mut reader, &mut writer);
+                        }
                     _ => return Err(err),
                 }
             }
         }
     }
-    writer.set_permissions(perm)?;
     Ok(written)
 }
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    use crate::sync::atomic::{AtomicBool, Ordering};
+
+    const COPYFILE_ACL: u32 = 1 << 0;
+    const COPYFILE_STAT: u32 = 1 << 1;
+    const COPYFILE_XATTR: u32 = 1 << 2;
+    const COPYFILE_DATA: u32 = 1 << 3;
+
+    const COPYFILE_SECURITY: u32 = COPYFILE_STAT | COPYFILE_ACL;
+    const COPYFILE_METADATA: u32 = COPYFILE_SECURITY | COPYFILE_XATTR;
+    const COPYFILE_ALL: u32 = COPYFILE_METADATA | COPYFILE_DATA;
+
+    const COPYFILE_STATE_COPIED: u32 = 8;
+
+    #[allow(non_camel_case_types)]
+    type copyfile_state_t = *mut libc::c_void;
+    #[allow(non_camel_case_types)]
+    type copyfile_flags_t = u32;
+
+    extern "C" {
+        fn fcopyfile(
+            from: libc::c_int,
+            to: libc::c_int,
+            state: copyfile_state_t,
+            flags: copyfile_flags_t,
+        ) -> libc::c_int;
+        fn copyfile_state_alloc() -> copyfile_state_t;
+        fn copyfile_state_free(state: copyfile_state_t) -> libc::c_int;
+        fn copyfile_state_get(
+            state: copyfile_state_t,
+            flag: u32,
+            dst: *mut libc::c_void,
+        ) -> libc::c_int;
+    }
+
+    struct FreeOnDrop(copyfile_state_t);
+    impl Drop for FreeOnDrop {
+        fn drop(&mut self) {
+            // The code below ensures that `FreeOnDrop` is never a null pointer
+            unsafe {
+                // `copyfile_state_free` returns -1 if the `to` or `from` files
+                // cannot be closed. However, this is not considerd this an
+                // error.
+                copyfile_state_free(self.0);
+            }
+        }
+    }
+
+    // MacOS prior to 10.12 don't support `fclonefileat`
+    // We store the availability in a global to avoid unnecessary syscalls
+    static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);
+    syscall! {
+        fn fclonefileat(
+            srcfd: libc::c_int,
+            dst_dirfd: libc::c_int,
+            dst: *const libc::c_char,
+            flags: libc::c_int
+        ) -> libc::c_int
+    }
+
+    let (reader, reader_metadata) = open_from(from)?;
+
+    // Opportunistically attempt to create a copy-on-write clone of `from`
+    // using `fclonefileat`.
+    if HAS_FCLONEFILEAT.load(Ordering::Relaxed) {
+        let to = cstr(to)?;
+        let clonefile_result = cvt(unsafe {
+            fclonefileat(
+                reader.as_raw_fd(),
+                libc::AT_FDCWD,
+                to.as_ptr(),
+                0,
+            )
+        });
+        match clonefile_result {
+            Ok(_) => return Ok(reader_metadata.len()),
+            Err(err) => match err.raw_os_error() {
+                // `fclonefileat` will fail on non-APFS volumes, if the
+                // destination already exists, or if the source and destination
+                // are on different devices. In all these cases `fcopyfile`
+                // should succeed.
+                Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (),
+                Some(libc::ENOSYS) => HAS_FCLONEFILEAT.store(false, Ordering::Relaxed),
+                _ => return Err(err),
+            }
+        }
+    }
+
+    // Fall back to using `fcopyfile` if `fclonefileat` does not succeed.
+    let (writer, writer_metadata) = open_to_and_set_permissions(to, reader_metadata)?;
+
+    // We ensure that `FreeOnDrop` never contains a null pointer so it is
+    // always safe to call `copyfile_state_free`
+    let state = unsafe {
+        let state = copyfile_state_alloc();
+        if state.is_null() {
+            return Err(crate::io::Error::last_os_error());
+        }
+        FreeOnDrop(state)
+    };
+
+    let flags = if writer_metadata.is_file() {
+        COPYFILE_ALL
+    } else {
+        COPYFILE_DATA
+    };
+
+    cvt(unsafe {
+        fcopyfile(
+            reader.as_raw_fd(),
+            writer.as_raw_fd(),
+            state.0,
+            flags,
+        )
+    })?;
+
+    let mut bytes_copied: libc::off_t = 0;
+    cvt(unsafe {
+        copyfile_state_get(
+            state.0,
+            COPYFILE_STATE_COPIED,
+            &mut bytes_copied as *mut libc::off_t as *mut libc::c_void,
+        )
+    })?;
+    Ok(bytes_copied as u64)
+}
diff --git a/src/libstd/sys/unix/io.rs b/src/libstd/sys/unix/io.rs
index eb3fa470a65..a3a72919176 100644
--- a/src/libstd/sys/unix/io.rs
+++ b/src/libstd/sys/unix/io.rs
@@ -4,15 +4,15 @@ use crate::slice;
 use libc::{iovec, c_void};
 
 #[repr(transparent)]
-pub struct IoVec<'a> {
+pub struct IoSlice<'a> {
     vec: iovec,
     _p: PhantomData<&'a [u8]>,
 }
 
-impl<'a> IoVec<'a> {
+impl<'a> IoSlice<'a> {
     #[inline]
-    pub fn new(buf: &'a [u8]) -> IoVec<'a> {
-        IoVec {
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice {
             vec: iovec {
                 iov_base: buf.as_ptr() as *mut u8 as *mut c_void,
                 iov_len: buf.len()
@@ -22,6 +22,18 @@ impl<'a> IoVec<'a> {
     }
 
     #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
     pub fn as_slice(&self) -> &[u8] {
         unsafe {
             slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len)
@@ -29,15 +41,16 @@ impl<'a> IoVec<'a> {
     }
 }
 
-pub struct IoVecMut<'a> {
+#[repr(transparent)]
+pub struct IoSliceMut<'a> {
     vec: iovec,
     _p: PhantomData<&'a mut [u8]>,
 }
 
-impl<'a> IoVecMut<'a> {
+impl<'a> IoSliceMut<'a> {
     #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoVecMut<'a> {
-        IoVecMut {
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut {
             vec: iovec {
                 iov_base: buf.as_mut_ptr() as *mut c_void,
                 iov_len: buf.len()
@@ -47,6 +60,18 @@ impl<'a> IoVecMut<'a> {
     }
 
     #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSliceMut beyond its length");
+        }
+
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
     pub fn as_slice(&self) -> &[u8] {
         unsafe {
             slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len)
diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs
index b9e725371a3..2c6f21aa21a 100644
--- a/src/libstd/sys/unix/l4re.rs
+++ b/src/libstd/sys/unix/l4re.rs
@@ -5,7 +5,7 @@ macro_rules! unimpl {
 pub mod net {
     #![allow(warnings)]
     use crate::fmt;
-    use crate::io::{self, IoVec, IoVecMut};
+    use crate::io::{self, IoSlice, IoSliceMut};
     use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
     use crate::sys_common::{AsInner, FromInner, IntoInner};
     use crate::sys::fd::FileDesc;
@@ -46,7 +46,7 @@ pub mod net {
             unimpl!();
         }
 
-        pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
             unimpl!();
         }
 
@@ -66,7 +66,7 @@ pub mod net {
             unimpl!();
         }
 
-        pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
+        pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
             unimpl!();
         }
 
@@ -152,7 +152,7 @@ pub mod net {
             unimpl!();
         }
 
-        pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
             unimpl!();
         }
 
@@ -160,7 +160,7 @@ pub mod net {
             unimpl!();
         }
 
-        pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
+        pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
             unimpl!();
         }
 
@@ -212,7 +212,7 @@ pub mod net {
     }
 
     impl fmt::Debug for TcpStream {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             write!(f, "No networking support available on L4Re")
         }
     }
@@ -274,7 +274,7 @@ pub mod net {
     }
 
     impl fmt::Debug for TcpListener {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             write!(f, "No networking support available on L4Re.")
         }
     }
@@ -292,6 +292,10 @@ pub mod net {
 
         pub fn into_socket(self) -> Socket { self.inner }
 
+        pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+            unimpl!();
+        }
+
         pub fn socket_addr(&self) -> io::Result<SocketAddr> {
             unimpl!();
         }
@@ -420,7 +424,7 @@ pub mod net {
     }
 
     impl fmt::Debug for UdpSocket {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             write!(f, "No networking support on L4Re available.")
         }
     }
@@ -463,4 +467,3 @@ pub mod net {
         }
     }
 }
-
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index fbe3444311e..b1f7aac8b4b 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -5,7 +5,6 @@ use crate::io::ErrorKind;
 #[cfg(any(rustdoc, target_os = "linux"))] pub use crate::os::linux as platform;
 
 #[cfg(all(not(rustdoc), target_os = "android"))]   pub use crate::os::android as platform;
-#[cfg(all(not(rustdoc), target_os = "bitrig"))]    pub use crate::os::bitrig as platform;
 #[cfg(all(not(rustdoc), target_os = "dragonfly"))] pub use crate::os::dragonfly as platform;
 #[cfg(all(not(rustdoc), target_os = "freebsd"))]   pub use crate::os::freebsd as platform;
 #[cfg(all(not(rustdoc), target_os = "haiku"))]     pub use crate::os::haiku as platform;
@@ -18,6 +17,7 @@ use crate::io::ErrorKind;
 #[cfg(all(not(rustdoc), target_os = "fuchsia"))]   pub use crate::os::fuchsia as platform;
 #[cfg(all(not(rustdoc), target_os = "l4re"))]      pub use crate::os::linux as platform;
 #[cfg(all(not(rustdoc), target_os = "hermit"))]    pub use crate::os::hermit as platform;
+#[cfg(all(not(rustdoc), target_os = "redox"))]      pub use crate::os::redox as platform;
 
 pub use self::rand::hashmap_random_keys;
 pub use libc::strlen;
@@ -28,8 +28,6 @@ pub mod weak;
 pub mod alloc;
 pub mod args;
 pub mod android;
-#[cfg(feature = "backtrace")]
-pub mod backtrace;
 pub mod cmath;
 pub mod condvar;
 pub mod env;
@@ -47,7 +45,6 @@ mod l4re;
 #[cfg(target_os = "l4re")]
 pub use self::l4re::net;
 pub mod os;
-pub mod os_str;
 pub mod path;
 pub mod pipe;
 pub mod process;
@@ -59,6 +56,8 @@ pub mod thread_local;
 pub mod time;
 pub mod stdio;
 
+pub use crate::sys_common::os_str_bytes as os_str;
+
 #[cfg(not(test))]
 pub fn init() {
     // By default, some platforms will send a *signal* when an EPIPE error
diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs
index b6a22e1962a..b43af8fdcaa 100644
--- a/src/libstd/sys/unix/mutex.rs
+++ b/src/libstd/sys/unix/mutex.rs
@@ -1,5 +1,5 @@
 use crate::cell::UnsafeCell;
-use crate::mem;
+use crate::mem::MaybeUninit;
 
 pub struct Mutex { inner: UnsafeCell<libc::pthread_mutex_t> }
 
@@ -40,14 +40,14 @@ impl Mutex {
         // references, we instead create the mutex with type
         // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
         // re-lock it from the same thread, thus avoiding undefined behavior.
-        let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
-        let r = libc::pthread_mutexattr_init(&mut attr);
+        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
+        let r = libc::pthread_mutexattr_init(attr.as_mut_ptr());
         debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutexattr_settype(&mut attr, libc::PTHREAD_MUTEX_NORMAL);
+        let r = libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL);
         debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutex_init(self.inner.get(), &attr);
+        let r = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
         debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutexattr_destroy(&mut attr);
+        let r = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
         debug_assert_eq!(r, 0);
     }
     #[inline]
@@ -89,19 +89,19 @@ unsafe impl Sync for ReentrantMutex {}
 
 impl ReentrantMutex {
     pub unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: mem::uninitialized() }
+        ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
     }
 
     pub unsafe fn init(&mut self) {
-        let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
-        let result = libc::pthread_mutexattr_init(&mut attr as *mut _);
+        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
+        let result = libc::pthread_mutexattr_init(attr.as_mut_ptr());
         debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutexattr_settype(&mut attr as *mut _,
+        let result = libc::pthread_mutexattr_settype(attr.as_mut_ptr(),
                                                     libc::PTHREAD_MUTEX_RECURSIVE);
         debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutex_init(self.inner.get(), &attr as *const _);
+        let result = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
         debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutexattr_destroy(&mut attr as *mut _);
+        let result = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
         debug_assert_eq!(result, 0);
     }
 
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index 7712a41ded4..75750b5c4e5 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -1,5 +1,5 @@
 use crate::ffi::CStr;
-use crate::io::{self, IoVec, IoVecMut};
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::net::{SocketAddr, Shutdown};
 use crate::str;
@@ -244,7 +244,7 @@ impl Socket {
         self.recv_with_flags(buf, MSG_PEEK)
     }
 
-    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         self.0.read_vectored(bufs)
     }
 
@@ -276,7 +276,7 @@ impl Socket {
         self.0.write(buf)
     }
 
-    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         self.0.write_vectored(bufs)
     }
 
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index e16d50d437b..169bb57ef78 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -25,6 +25,13 @@ use libc::{c_int, c_char, c_void};
 
 const TMPBUF_SZ: usize = 128;
 
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "redox")] {
+        const PATH_SEPARATOR: u8 = b';';
+    } else {
+        const PATH_SEPARATOR: u8 = b':';
+    }
+}
 
 extern {
     #[cfg(not(target_os = "dragonfly"))]
@@ -33,11 +40,11 @@ extern {
                    target_os = "fuchsia",
                    target_os = "l4re"),
                link_name = "__errno_location")]
-    #[cfg_attr(any(target_os = "bitrig",
-                   target_os = "netbsd",
+    #[cfg_attr(any(target_os = "netbsd",
                    target_os = "openbsd",
                    target_os = "android",
                    target_os = "hermit",
+                   target_os = "redox",
                    target_env = "newlib"),
                link_name = "__errno")]
     #[cfg_attr(target_os = "solaris", link_name = "___errno")]
@@ -152,14 +159,14 @@ pub struct SplitPaths<'a> {
                     fn(&'a [u8]) -> PathBuf>,
 }
 
-pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
+pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> {
     fn bytes_to_path(b: &[u8]) -> PathBuf {
         PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
     }
-    fn is_colon(b: &u8) -> bool { *b == b':' }
+    fn is_separator(b: &u8) -> bool { *b == PATH_SEPARATOR }
     let unparsed = unparsed.as_bytes();
     SplitPaths {
-        iter: unparsed.split(is_colon as fn(&u8) -> bool)
+        iter: unparsed.split(is_separator as fn(&u8) -> bool)
                       .map(bytes_to_path as fn(&[u8]) -> PathBuf)
     }
 }
@@ -177,12 +184,11 @@ pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
     where I: Iterator<Item=T>, T: AsRef<OsStr>
 {
     let mut joined = Vec::new();
-    let sep = b':';
 
     for (i, path) in paths.enumerate() {
         let path = path.as_ref().as_bytes();
-        if i > 0 { joined.push(sep) }
-        if path.contains(&sep) {
+        if i > 0 { joined.push(PATH_SEPARATOR) }
+        if path.contains(&PATH_SEPARATOR) {
             return Err(JoinPathsError)
         }
         joined.extend_from_slice(path);
@@ -191,8 +197,8 @@ pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
 }
 
 impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        "path segment contains separator `:`".fmt(f)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "path segment contains separator `{}`", PATH_SEPARATOR)
     }
 }
 
@@ -257,7 +263,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     sysctl().or_else(|_| procfs())
 }
 
-#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+#[cfg(target_os = "openbsd")]
 pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         let mut mib = [libc::CTL_KERN,
@@ -383,6 +389,11 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
+#[cfg(target_os = "redox")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    crate::fs::read_to_string("sys:exe").map(PathBuf::from)
+}
+
 #[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     use crate::io::ErrorKind;
@@ -512,11 +523,13 @@ pub fn home_dir() -> Option<PathBuf> {
 
     #[cfg(any(target_os = "android",
               target_os = "ios",
-              target_os = "emscripten"))]
+              target_os = "emscripten",
+              target_os = "redox"))]
     unsafe fn fallback() -> Option<OsString> { None }
     #[cfg(not(any(target_os = "android",
                   target_os = "ios",
-                  target_os = "emscripten")))]
+                  target_os = "emscripten",
+                  target_os = "redox")))]
     unsafe fn fallback() -> Option<OsString> {
         let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
             n if n < 0 => 512 as usize,
diff --git a/src/libstd/sys/unix/path.rs b/src/libstd/sys/unix/path.rs
index 5c062e7c97c..7a183956107 100644
--- a/src/libstd/sys/unix/path.rs
+++ b/src/libstd/sys/unix/path.rs
@@ -11,7 +11,7 @@ pub fn is_verbatim_sep(b: u8) -> bool {
     b == b'/'
 }
 
-pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
+pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
     None
 }
 
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index bc3c026adab..029f4216b7e 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::fd::FileDesc;
@@ -26,7 +26,8 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
                 target_os = "freebsd",
                 target_os = "linux",
                 target_os = "netbsd",
-                target_os = "openbsd")) &&
+                target_os = "openbsd",
+                target_os = "redox")) &&
        !INVALID.load(Ordering::SeqCst)
     {
 
@@ -60,10 +61,18 @@ impl AnonPipe {
         self.0.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     pub fn fd(&self) -> &FileDesc { &self.0 }
     pub fn into_fd(self) -> FileDesc { self.0 }
 }
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index 856d202be03..6bb20bbe087 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -12,6 +12,14 @@ use crate::collections::BTreeMap;
 
 use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
 
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "redox")] {
+        const DEV_NULL: &'static str = "null:\0";
+    } else {
+        const DEV_NULL: &'static str = "/dev/null\0";
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
@@ -298,7 +306,7 @@ impl Stdio {
                 opts.read(readable);
                 opts.write(!readable);
                 let path = unsafe {
-                    CStr::from_ptr("/dev/null\0".as_ptr() as *const _)
+                    CStr::from_ptr(DEV_NULL.as_ptr() as *const _)
                 };
                 let fd = File::open_c(&path, &opts)?;
                 Ok((ChildStdio::Owned(fd.into_fd()), None))
@@ -330,7 +338,7 @@ impl ChildStdio {
 }
 
 impl fmt::Debug for Command {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self.program)?;
         for arg in &self.args {
             write!(f, " {:?}", arg)?;
@@ -380,7 +388,7 @@ impl From<c_int> for ExitStatus {
 }
 
 impl fmt::Display for ExitStatus {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         if let Some(code) = self.code() {
             write!(f, "exit code: {}", code)
         } else {
@@ -437,7 +445,7 @@ mod tests {
 
     #[cfg(target_os = "android")]
     unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
-        libc::memset(set as *mut _, 0, mem::size_of::<libc::sigset_t>());
+        set.write_bytes(0u8, 1);
         return 0;
     }
 
@@ -466,11 +474,11 @@ mod tests {
             // Test to make sure that a signal mask does not get inherited.
             let mut cmd = Command::new(OsStr::new("cat"));
 
-            let mut set: libc::sigset_t = mem::uninitialized();
-            let mut old_set: libc::sigset_t = mem::uninitialized();
-            t!(cvt(sigemptyset(&mut set)));
-            t!(cvt(sigaddset(&mut set, libc::SIGINT)));
-            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set)));
+            let mut set = mem::MaybeUninit::<libc::sigset_t>::uninit();
+            let mut old_set = mem::MaybeUninit::<libc::sigset_t>::uninit();
+            t!(cvt(sigemptyset(set.as_mut_ptr())));
+            t!(cvt(sigaddset(set.as_mut_ptr(), libc::SIGINT)));
+            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
 
             cmd.stdin(Stdio::MakePipe);
             cmd.stdout(Stdio::MakePipe);
@@ -479,7 +487,7 @@ mod tests {
             let stdin_write = pipes.stdin.take().unwrap();
             let stdout_read = pipes.stdout.take().unwrap();
 
-            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set,
+            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(),
                                          ptr::null_mut())));
 
             t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 220b1fd4531..327d82e60cf 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -47,7 +47,7 @@ impl Command {
             match result {
                 0 => {
                     drop(input);
-                    let err = self.do_exec(theirs, envp.as_ref());
+                    let Err(err) = self.do_exec(theirs, envp.as_ref());
                     let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
                     let bytes = [
                         (errno >> 24) as u8,
@@ -123,7 +123,8 @@ impl Command {
                     // environment lock before we try to exec.
                     let _lock = sys::os::env_lock();
 
-                    self.do_exec(theirs, envp.as_ref())
+                    let Err(e) = self.do_exec(theirs, envp.as_ref());
+                    e
                 }
             }
             Err(e) => e,
@@ -164,51 +165,47 @@ impl Command {
         &mut self,
         stdio: ChildPipes,
         maybe_envp: Option<&CStringArray>
-    ) -> io::Error {
+    ) -> Result<!, io::Error> {
         use crate::sys::{self, cvt_r};
 
-        macro_rules! t {
-            ($e:expr) => (match $e {
-                Ok(e) => e,
-                Err(e) => return e,
-            })
-        }
-
         if let Some(fd) = stdio.stdin.fd() {
-            t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO)));
+            cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO))?;
         }
         if let Some(fd) = stdio.stdout.fd() {
-            t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO)));
+            cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO))?;
         }
         if let Some(fd) = stdio.stderr.fd() {
-            t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO)));
+            cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))?;
         }
 
         if cfg!(not(any(target_os = "l4re"))) {
             if let Some(u) = self.get_gid() {
-                t!(cvt(libc::setgid(u as gid_t)));
+                cvt(libc::setgid(u as gid_t))?;
             }
             if let Some(u) = self.get_uid() {
-                // When dropping privileges from root, the `setgroups` call
-                // will remove any extraneous groups. If we don't call this,
-                // then even though our uid has dropped, we may still have
-                // groups that enable us to do super-user things. This will
-                // fail if we aren't root, so don't bother checking the
-                // return value, this is just done as an optimistic
-                // privilege dropping function.
-                let _ = libc::setgroups(0, ptr::null());
-
-                t!(cvt(libc::setuid(u as uid_t)));
+                //FIXME: Redox kernel does not support setgroups yet
+                if cfg!(not(target_os = "redox")) {
+                    // When dropping privileges from root, the `setgroups` call
+                    // will remove any extraneous groups. If we don't call this,
+                    // then even though our uid has dropped, we may still have
+                    // groups that enable us to do super-user things. This will
+                    // fail if we aren't root, so don't bother checking the
+                    // return value, this is just done as an optimistic
+                    // privilege dropping function.
+                    let _ = libc::setgroups(0, ptr::null());
+                }
+
+                cvt(libc::setuid(u as uid_t))?;
             }
         }
         if let Some(ref cwd) = *self.get_cwd() {
-            t!(cvt(libc::chdir(cwd.as_ptr())));
+            cvt(libc::chdir(cwd.as_ptr()))?;
         }
 
         // emscripten has no signal support.
         #[cfg(not(any(target_os = "emscripten")))]
         {
-            use crate::mem;
+            use crate::mem::MaybeUninit;
             // Reset signal handling so the child process starts in a
             // standardized state. libstd ignores SIGPIPE, and signal-handling
             // libraries often set a mask. Child processes inherit ignored
@@ -216,27 +213,25 @@ impl Command {
             // UNIX programs do not reset these things on their own, so we
             // need to clean things up now to avoid confusing the program
             // we're about to run.
-            let mut set: libc::sigset_t = mem::uninitialized();
+            let mut set = MaybeUninit::<libc::sigset_t>::uninit();
             if cfg!(target_os = "android") {
                 // Implementing sigemptyset allow us to support older Android
                 // versions. See the comment about Android and sig* functions in
                 // process_common.rs
-                libc::memset(&mut set as *mut _ as *mut _,
-                             0,
-                             mem::size_of::<libc::sigset_t>());
+                set.as_mut_ptr().write_bytes(0u8, 1);
             } else {
-                t!(cvt(libc::sigemptyset(&mut set)));
+                cvt(libc::sigemptyset(set.as_mut_ptr()))?;
             }
-            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
-                                         ptr::null_mut())));
+            cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(),
+                                         ptr::null_mut()))?;
             let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
             if ret == libc::SIG_ERR {
-                return io::Error::last_os_error()
+                return Err(io::Error::last_os_error())
             }
         }
 
         for callback in self.get_closures().iter_mut() {
-            t!(callback());
+            callback()?;
         }
 
         // Although we're performing an exec here we may also return with an
@@ -261,7 +256,7 @@ impl Command {
         }
 
         libc::execvp(self.get_argv()[0], self.get_argv().as_ptr());
-        io::Error::last_os_error()
+        Err(io::Error::last_os_error())
     }
 
     #[cfg(not(any(target_os = "macos", target_os = "freebsd",
@@ -279,13 +274,13 @@ impl Command {
     fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
         -> io::Result<Option<Process>>
     {
-        use crate::mem;
+        use crate::mem::MaybeUninit;
         use crate::sys;
 
         if self.get_gid().is_some() ||
             self.get_uid().is_some() ||
             self.env_saw_path() ||
-            self.get_closures().len() != 0 {
+            !self.get_closures().is_empty() {
             return Ok(None)
         }
 
@@ -321,63 +316,63 @@ impl Command {
 
         let mut p = Process { pid: 0, status: None };
 
-        struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
+        struct PosixSpawnFileActions(MaybeUninit<libc::posix_spawn_file_actions_t>);
 
         impl Drop for PosixSpawnFileActions {
             fn drop(&mut self) {
                 unsafe {
-                    libc::posix_spawn_file_actions_destroy(&mut self.0);
+                    libc::posix_spawn_file_actions_destroy(self.0.as_mut_ptr());
                 }
             }
         }
 
-        struct PosixSpawnattr(libc::posix_spawnattr_t);
+        struct PosixSpawnattr(MaybeUninit<libc::posix_spawnattr_t>);
 
         impl Drop for PosixSpawnattr {
             fn drop(&mut self) {
                 unsafe {
-                    libc::posix_spawnattr_destroy(&mut self.0);
+                    libc::posix_spawnattr_destroy(self.0.as_mut_ptr());
                 }
             }
         }
 
         unsafe {
-            let mut file_actions = PosixSpawnFileActions(mem::uninitialized());
-            let mut attrs = PosixSpawnattr(mem::uninitialized());
+            let mut file_actions = PosixSpawnFileActions(MaybeUninit::uninit());
+            let mut attrs = PosixSpawnattr(MaybeUninit::uninit());
 
-            libc::posix_spawnattr_init(&mut attrs.0);
-            libc::posix_spawn_file_actions_init(&mut file_actions.0);
+            libc::posix_spawnattr_init(attrs.0.as_mut_ptr());
+            libc::posix_spawn_file_actions_init(file_actions.0.as_mut_ptr());
 
             if let Some(fd) = stdio.stdin.fd() {
-                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
                                                            fd,
                                                            libc::STDIN_FILENO))?;
             }
             if let Some(fd) = stdio.stdout.fd() {
-                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
                                                            fd,
                                                            libc::STDOUT_FILENO))?;
             }
             if let Some(fd) = stdio.stderr.fd() {
-                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
                                                            fd,
                                                            libc::STDERR_FILENO))?;
             }
             if let Some((f, cwd)) = addchdir {
-                cvt(f(&mut file_actions.0, cwd.as_ptr()))?;
+                cvt(f(file_actions.0.as_mut_ptr(), cwd.as_ptr()))?;
             }
 
-            let mut set: libc::sigset_t = mem::uninitialized();
-            cvt(libc::sigemptyset(&mut set))?;
-            cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0,
-                                                 &set))?;
-            cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?;
-            cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0,
-                                                    &set))?;
+            let mut set = MaybeUninit::<libc::sigset_t>::uninit();
+            cvt(libc::sigemptyset(set.as_mut_ptr()))?;
+            cvt(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(),
+                                                 set.as_ptr()))?;
+            cvt(libc::sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
+            cvt(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(),
+                                                    set.as_ptr()))?;
 
             let flags = libc::POSIX_SPAWN_SETSIGDEF |
                 libc::POSIX_SPAWN_SETSIGMASK;
-            cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?;
+            cvt(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
 
             // Make sure we synchronize access to the global `environ` resource
             let _env_lock = sys::os::env_lock();
@@ -386,8 +381,8 @@ impl Command {
             let ret = libc::posix_spawnp(
                 &mut p.pid,
                 self.get_argv()[0],
-                &file_actions.0,
-                &attrs.0,
+                file_actions.0.as_ptr(),
+                attrs.0.as_ptr(),
                 self.get_argv().as_ptr() as *const _,
                 envp as *const _,
             );
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index 122f22b37a2..c5be1763302 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -15,7 +15,8 @@ pub fn hashmap_random_keys() -> (u64, u64) {
           not(target_os = "ios"),
           not(target_os = "openbsd"),
           not(target_os = "freebsd"),
-          not(target_os = "fuchsia")))]
+          not(target_os = "fuchsia"),
+          not(target_os = "redox")))]
 mod imp {
     use crate::fs::File;
     use crate::io::Read;
@@ -47,7 +48,12 @@ mod imp {
                 let err = errno() as libc::c_int;
                 if err == libc::EINTR {
                     continue;
-                } else if err == libc::ENOSYS {
+                } else if err == libc::ENOSYS || err == libc::EPERM {
+                    // Fall back to reading /dev/urandom if `getrandom` is not
+                    // supported on the current kernel.
+                    //
+                    // Also fall back in case it is disabled by something like
+                    // seccomp or inside of virtual machines.
                     GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
                     return false;
                 } else if err == libc::EAGAIN {
@@ -99,6 +105,13 @@ mod imp {
     }
 }
 
+// On iOS and MacOS `SecRandomCopyBytes` calls `CCRandomCopyBytes` with
+// `kCCRandomDefault`. `CCRandomCopyBytes` manages a CSPRNG which is seeded
+// from `/dev/random` and which runs on its own thread accessed via GCD.
+// This seems needlessly heavyweight for the purposes of generating two u64s
+// once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
+// only used on iOS where direct access to `/dev/urandom` is blocked by the
+// sandbox.
 #[cfg(target_os = "ios")]
 mod imp {
     use crate::io;
@@ -162,3 +175,15 @@ mod imp {
         unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
     }
 }
+
+#[cfg(target_os = "redox")]
+mod imp {
+    use crate::fs::File;
+    use crate::io::Read;
+
+    pub fn fill_bytes(v: &mut [u8]) {
+        // Open rand:, read from it, and close it again.
+        let mut file = File::open("rand:").expect("failed to open rand:");
+        file.read_exact(v).expect("failed to read rand:")
+    }
+}
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 8c60bddc238..fe1095fa0c2 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -25,7 +25,6 @@ impl Drop for Handler {
 
 #[cfg(any(target_os = "linux",
           target_os = "macos",
-          target_os = "bitrig",
           target_os = "dragonfly",
           target_os = "freebsd",
           target_os = "solaris",
@@ -139,7 +138,7 @@ mod imp {
 
     #[cfg(any(target_os = "linux",
               target_os = "macos",
-              target_os = "bitrig",
+              target_os = "freebsd",
               target_os = "netbsd",
               target_os = "openbsd",
               target_os = "solaris"))]
@@ -147,8 +146,7 @@ mod imp {
         libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ }
     }
 
-    #[cfg(any(target_os = "freebsd",
-              target_os = "dragonfly"))]
+    #[cfg(target_os = "dragonfly")]
     unsafe fn get_stack() -> libc::stack_t {
         libc::stack_t { ss_sp: get_stackp() as *mut i8, ss_flags: 0, ss_size: SIGSTKSZ }
     }
@@ -185,7 +183,6 @@ mod imp {
 
 #[cfg(not(any(target_os = "linux",
               target_os = "macos",
-              target_os = "bitrig",
               target_os = "dragonfly",
               target_os = "freebsd",
               target_os = "solaris",
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index 35f163bbdb1..f9b017df240 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -1,5 +1,6 @@
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::sys::fd::FileDesc;
+use crate::mem::ManuallyDrop;
 
 pub struct Stdin(());
 pub struct Stdout(());
@@ -11,10 +12,11 @@ impl Stdin {
 
 impl io::Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(libc::STDIN_FILENO);
-        let ret = fd.read(buf);
-        fd.into_raw(); // do not close this FD
-        ret
+        ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read(buf)
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read_vectored(bufs)
     }
 }
 
@@ -24,10 +26,11 @@ impl Stdout {
 
 impl io::Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(libc::STDOUT_FILENO);
-        let ret = fd.write(buf);
-        fd.into_raw(); // do not close this FD
-        ret
+        ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write(buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write_vectored(bufs)
     }
 
     fn flush(&mut self) -> io::Result<()> {
@@ -41,10 +44,11 @@ impl Stderr {
 
 impl io::Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(libc::STDERR_FILENO);
-        let ret = fd.write(buf);
-        fd.into_raw(); // do not close this FD
-        ret
+        ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write(buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write_vectored(bufs)
     }
 
     fn flush(&mut self) -> io::Result<()> {
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index feb15e8f585..988881e3596 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::cmp;
 use crate::ffi::CStr;
 use crate::io;
@@ -39,7 +38,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t,
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnBox()>)
+    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>)
                           -> io::Result<Thread> {
         let p = box p;
         let mut native: libc::pthread_t = mem::zeroed();
@@ -100,7 +99,6 @@ impl Thread {
 
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
-              target_os = "bitrig",
               target_os = "openbsd"))]
     pub fn set_name(name: &CStr) {
         unsafe {
@@ -124,12 +122,26 @@ impl Thread {
                                      name.as_ptr() as *mut libc::c_void);
         }
     }
+
+    #[cfg(target_os = "solaris")]
+    pub fn set_name(name: &CStr) {
+        weak! {
+            fn pthread_setname_np(
+                libc::pthread_t, *const libc::c_char
+            ) -> libc::c_int
+        }
+
+        if let Some(f) = pthread_setname_np.get() {
+            unsafe { f(libc::pthread_self(), name.as_ptr()); }
+        }
+    }
+
     #[cfg(any(target_env = "newlib",
-              target_os = "solaris",
               target_os = "haiku",
               target_os = "l4re",
               target_os = "emscripten",
-              target_os = "hermit"))]
+              target_os = "hermit",
+              target_os = "redox"))]
     pub fn set_name(_name: &CStr) {
         // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
     }
@@ -190,7 +202,6 @@ impl Drop for Thread {
 #[cfg(all(not(all(target_os = "linux", not(target_env = "musl"))),
           not(target_os = "freebsd"),
           not(target_os = "macos"),
-          not(target_os = "bitrig"),
           not(all(target_os = "netbsd", not(target_vendor = "rumprun"))),
           not(target_os = "openbsd"),
           not(target_os = "solaris")))]
@@ -206,7 +217,6 @@ pub mod guard {
 #[cfg(any(all(target_os = "linux", not(target_env = "musl")),
           target_os = "freebsd",
           target_os = "macos",
-          target_os = "bitrig",
           all(target_os = "netbsd", not(target_vendor = "rumprun")),
           target_os = "openbsd",
           target_os = "solaris"))]
@@ -237,16 +247,15 @@ pub mod guard {
         Some(stackaddr as *mut libc::c_void)
     }
 
-    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
+    #[cfg(target_os = "openbsd")]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         let mut current_stack: libc::stack_t = crate::mem::zeroed();
         assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
                                              &mut current_stack), 0);
 
-        let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE;
         let stackaddr = if libc::pthread_main_np() == 1 {
             // main thread
-            current_stack.ss_sp as usize - current_stack.ss_size + extra
+            current_stack.ss_sp as usize - current_stack.ss_size + PAGE_SIZE
         } else {
             // new thread
             current_stack.ss_sp as usize - current_stack.ss_size
@@ -344,7 +353,6 @@ pub mod guard {
     }
 
     #[cfg(any(target_os = "macos",
-              target_os = "bitrig",
               target_os = "openbsd",
               target_os = "solaris"))]
     pub unsafe fn current() -> Option<Guard> {
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index cbb0615911a..02f377d55c9 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -114,7 +114,8 @@ impl Hash for Timespec {
 #[cfg(any(target_os = "macos", target_os = "ios"))]
 mod inner {
     use crate::fmt;
-    use crate::sync::Once;
+    use crate::mem;
+    use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
     use crate::sys::cvt;
     use crate::sys_common::mul_div_u64;
     use crate::time::Duration;
@@ -136,9 +137,21 @@ mod inner {
         t: Timespec::zero(),
     };
 
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    struct mach_timebase_info {
+        numer: u32,
+        denom: u32,
+    }
+    type mach_timebase_info_t = *mut mach_timebase_info;
+    type kern_return_t = libc::c_int;
+
     impl Instant {
         pub fn now() -> Instant {
-            Instant { t: unsafe { libc::mach_absolute_time() } }
+            extern "C" {
+                fn mach_absolute_time() -> u64;
+            }
+            Instant { t: unsafe { mach_absolute_time() } }
         }
 
         pub const fn zero() -> Instant {
@@ -149,12 +162,11 @@ mod inner {
             true
         }
 
-        pub fn sub_instant(&self, other: &Instant) -> Duration {
+        pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+            let diff = self.t.checked_sub(other.t)?;
             let info = info();
-            let diff = self.t.checked_sub(other.t)
-                           .expect("second instant is later than self");
             let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
-            Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
+            Some(Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32))
         }
 
         pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
@@ -214,7 +226,7 @@ mod inner {
     }
 
     impl fmt::Debug for SystemTime {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             f.debug_struct("SystemTime")
              .field("tv_sec", &self.t.t.tv_sec)
              .field("tv_nsec", &self.t.t.tv_nsec)
@@ -230,18 +242,35 @@ mod inner {
         Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
     }
 
-    fn info() -> &'static libc::mach_timebase_info {
-        static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
+    fn info() -> mach_timebase_info {
+        static mut INFO: mach_timebase_info = mach_timebase_info {
             numer: 0,
             denom: 0,
         };
-        static ONCE: Once = Once::new();
+        static STATE: AtomicUsize = AtomicUsize::new(0);
 
         unsafe {
-            ONCE.call_once(|| {
-                libc::mach_timebase_info(&mut INFO);
-            });
-            &INFO
+            // If a previous thread has filled in this global state, use that.
+            if STATE.load(SeqCst) == 2 {
+                return INFO;
+            }
+
+            // ... otherwise learn for ourselves ...
+            let mut info = mem::zeroed();
+            extern "C" {
+                fn mach_timebase_info(info: mach_timebase_info_t)
+                                      -> kern_return_t;
+            }
+
+            mach_timebase_info(&mut info);
+
+            // ... and attempt to be the one thread that stores it globally for
+            // all other threads
+            if STATE.compare_exchange(0, 1, SeqCst, SeqCst).is_ok() {
+                INFO = info;
+                STATE.store(2, SeqCst);
+            }
+            return info;
         }
     }
 }
@@ -285,10 +314,8 @@ mod inner {
             false // last clause, used so `||` is always trailing above
         }
 
-        pub fn sub_instant(&self, other: &Instant) -> Duration {
-            self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-                panic!("specified instant was later than self")
-            })
+        pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+            self.t.sub_timespec(&other.t).ok()
         }
 
         pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
@@ -301,7 +328,7 @@ mod inner {
     }
 
     impl fmt::Debug for Instant {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             f.debug_struct("Instant")
              .field("tv_sec", &self.t.t.tv_sec)
              .field("tv_nsec", &self.t.t.tv_nsec)
@@ -335,7 +362,7 @@ mod inner {
     }
 
     impl fmt::Debug for SystemTime {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             f.debug_struct("SystemTime")
              .field("tv_sec", &self.t.t.tv_sec)
              .field("tv_nsec", &self.t.t.tv_nsec)
diff --git a/src/libstd/sys/vxworks/alloc.rs b/src/libstd/sys/vxworks/alloc.rs
new file mode 100644
index 00000000000..e0c560b9214
--- /dev/null
+++ b/src/libstd/sys/vxworks/alloc.rs
@@ -0,0 +1,53 @@
+use crate::ptr;
+use crate::sys_common::alloc::{MIN_ALIGN, realloc_fallback};
+use crate::alloc::{GlobalAlloc, Layout, System};
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+unsafe impl GlobalAlloc for System {
+    #[inline]
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+            libc::malloc(layout.size()) as *mut u8
+        } else {
+            aligned_malloc(&layout)
+        }
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+            libc::calloc(layout.size(), 1) as *mut u8
+        } else {
+            let ptr = self.alloc(layout.clone());
+            if !ptr.is_null() {
+                ptr::write_bytes(ptr, 0, layout.size());
+            }
+            ptr
+        }
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
+        libc::free(ptr as *mut libc::c_void)
+    }
+
+    #[inline]
+    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
+            libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
+        } else {
+            realloc_fallback(self, ptr, layout, new_size)
+        }
+    }
+}
+
+#[inline]
+unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+    let mut out = ptr::null_mut();
+    let ret = libc::posix_memalign(&mut out, layout.align(), layout.size());
+    if ret != 0 {
+        ptr::null_mut()
+    } else {
+        out as *mut u8
+    }
+}
diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/vxworks/args.rs
index f9e2f5ba311..11c3cb78819 100644
--- a/src/libstd/sys/redox/args.rs
+++ b/src/libstd/sys/vxworks/args.rs
@@ -1,10 +1,4 @@
-//! Global initialization and retrieval of command line arguments.
-//!
-//! On some platforms these are stored during runtime startup,
-//! and on some they are retrieved from the system on demand.
-
 #![allow(dead_code)] // runtime init functions not used during testing
-
 use crate::ffi::OsString;
 use crate::marker::PhantomData;
 use crate::vec;
@@ -46,51 +40,46 @@ impl DoubleEndedIterator for Args {
 }
 
 mod imp {
-    use crate::os::unix::prelude::*;
-    use crate::mem;
+    use crate::ptr;
     use crate::ffi::{CStr, OsString};
     use crate::marker::PhantomData;
+    use libc;
     use super::Args;
 
     use crate::sys_common::mutex::Mutex;
 
-    static mut GLOBAL_ARGS_PTR: usize = 0;
+    static mut ARGC: isize = 0;
+    static mut ARGV: *const *const u8 = ptr::null();
     static LOCK: Mutex = Mutex::new();
 
     pub unsafe fn init(argc: isize, argv: *const *const u8) {
-        let args = (0..argc).map(|i| {
-            CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
-        }).collect();
-
         let _guard = LOCK.lock();
-        let ptr = get_global_ptr();
-        assert!((*ptr).is_none());
-        (*ptr) = Some(box args);
+        ARGC = argc;
+        ARGV = argv;
     }
 
     pub unsafe fn cleanup() {
         let _guard = LOCK.lock();
-        *get_global_ptr() = None;
+        ARGC = 0;
+        ARGV = ptr::null();
     }
 
     pub fn args() -> Args {
-        let bytes = clone().unwrap_or_default();
-        let v: Vec<OsString> = bytes.into_iter().map(|v| {
-            OsStringExt::from_vec(v)
-        }).collect();
-        Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
+        Args {
+            iter: clone().into_iter(),
+            _dont_send_or_sync_me: PhantomData
+        }
     }
 
-    fn clone() -> Option<Vec<Vec<u8>>> {
+    fn clone() -> Vec<OsString> {
         unsafe {
             let _guard = LOCK.lock();
-            let ptr = get_global_ptr();
-            (*ptr).as_ref().map(|s| (**s).clone())
+            let ret = (0..ARGC).map(|i| {
+                let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
+                use crate::sys::vxworks::ext::ffi::OsStringExt;
+                OsStringExt::from_vec(cstr.to_bytes().to_vec())
+            }).collect();
+            return ret
         }
     }
-
-    unsafe fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
-        mem::transmute(&GLOBAL_ARGS_PTR)
-    }
-
 }
diff --git a/src/libstd/sys/unix/backtrace/mod.rs b/src/libstd/sys/vxworks/backtrace/mod.rs
index 0887e5a4df9..0887e5a4df9 100644
--- a/src/libstd/sys/unix/backtrace/mod.rs
+++ b/src/libstd/sys/vxworks/backtrace/mod.rs
diff --git a/src/libstd/sys/unix/backtrace/printing/dladdr.rs b/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs
index cf3bda640e9..202164dd3c4 100644
--- a/src/libstd/sys/unix/backtrace/printing/dladdr.rs
+++ b/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs
@@ -30,5 +30,6 @@ struct Dl_info {
 }
 
 extern {
+    #[ link_name = "_rtld_dladdr" ]
     fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
 }
diff --git a/src/libstd/sys/unix/backtrace/printing/mod.rs b/src/libstd/sys/vxworks/backtrace/printing/mod.rs
index d090caede43..d090caede43 100644
--- a/src/libstd/sys/unix/backtrace/printing/mod.rs
+++ b/src/libstd/sys/vxworks/backtrace/printing/mod.rs
diff --git a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs
index a628d107ad6..a628d107ad6 100644
--- a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs
+++ b/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs
diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs
index abbeca0fde6..e6379132baf 100644
--- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
+++ b/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs
@@ -21,7 +21,7 @@ impl Error for UnwindError {
 }
 
 impl fmt::Display for UnwindError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}: {:?}", self.description(), self.0)
     }
 }
@@ -37,7 +37,7 @@ pub fn unwind_backtrace(frames: &mut [Frame])
     };
     let result_unwind = unsafe {
         uw::_Unwind_Backtrace(trace_fn,
-                              &mut cx as *mut Context
+                              &mut cx as *mut Context<'_>
                               as *mut libc::c_void)
     };
     // See libunwind:src/unwind/Backtrace.c for the return values.
@@ -57,7 +57,7 @@ pub fn unwind_backtrace(frames: &mut [Frame])
 
 extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
                    arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
-    let cx = unsafe { &mut *(arg as *mut Context) };
+    let cx = unsafe { &mut *(arg as *mut Context<'_>) };
     if cx.idx >= cx.frames.len() {
         return uw::_URC_NORMAL_STOP;
     }
diff --git a/src/libstd/sys/unix/backtrace/tracing/mod.rs b/src/libstd/sys/vxworks/backtrace/tracing/mod.rs
index 11863e64545..11863e64545 100644
--- a/src/libstd/sys/unix/backtrace/tracing/mod.rs
+++ b/src/libstd/sys/vxworks/backtrace/tracing/mod.rs
diff --git a/src/libstd/sys/redox/cmath.rs b/src/libstd/sys/vxworks/cmath.rs
index f6bb58934fc..f6bb58934fc 100644
--- a/src/libstd/sys/redox/cmath.rs
+++ b/src/libstd/sys/vxworks/cmath.rs
diff --git a/src/libstd/sys/vxworks/condvar.rs b/src/libstd/sys/vxworks/condvar.rs
new file mode 100644
index 00000000000..783c3eb7c76
--- /dev/null
+++ b/src/libstd/sys/vxworks/condvar.rs
@@ -0,0 +1,96 @@
+use crate::cell::UnsafeCell;
+use crate::sys::mutex::{self, Mutex};
+use crate::time::Duration;
+
+pub struct Condvar { inner: UnsafeCell<libc::pthread_cond_t> }
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+const TIMESPEC_MAX: libc::timespec = libc::timespec {
+    tv_sec: <libc::time_t>::max_value(),
+    tv_nsec: 1_000_000_000 - 1,
+};
+
+fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
+    if value > <libc::time_t>::max_value() as u64 {
+        <libc::time_t>::max_value()
+    } else {
+        value as libc::time_t
+    }
+}
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        // Might be moved and address is changing it is better to avoid
+        // initialization of potentially opaque OS data before it landed
+        Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) }
+    }
+
+    pub unsafe fn init(&mut self) {
+        use crate::mem::MaybeUninit;
+        let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
+        let r = libc::pthread_condattr_init(attr.as_mut_ptr());
+        assert_eq!(r, 0);
+        let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC);
+        assert_eq!(r, 0);
+        let r = libc::pthread_cond_init(self.inner.get(), attr.as_ptr());
+        assert_eq!(r, 0);
+        let r = libc::pthread_condattr_destroy(attr.as_mut_ptr());
+        assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn notify_one(&self) {
+        let r = libc::pthread_cond_signal(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) {
+        let r = libc::pthread_cond_broadcast(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        let r = libc::pthread_cond_wait(self.inner.get(), mutex::raw(mutex));
+        debug_assert_eq!(r, 0);
+    }
+
+    // This implementation is used on systems that support pthread_condattr_setclock
+    // where we configure condition variable to use monotonic clock (instead of
+    // default system clock). This approach avoids all problems that result
+    // from changes made to the system time.
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        use crate::mem;
+
+        let mut now: libc::timespec = mem::zeroed();
+        let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
+        assert_eq!(r, 0);
+
+        // Nanosecond calculations can't overflow because both values are below 1e9.
+        let nsec = dur.subsec_nanos() + now.tv_nsec as u32;
+
+        let sec = saturating_cast_to_time_t(dur.as_secs())
+            .checked_add((nsec / 1_000_000_000) as libc::time_t)
+            .and_then(|s| s.checked_add(now.tv_sec));
+        let nsec = nsec % 1_000_000_000;
+
+        let timeout = sec.map(|s| {
+            libc::timespec { tv_sec: s, tv_nsec: nsec as _}
+        }).unwrap_or(TIMESPEC_MAX);
+
+        let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
+                                            &timeout);
+        assert!(r == libc::ETIMEDOUT || r == 0);
+        r == 0
+    }
+
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = libc::pthread_cond_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/redox/env.rs b/src/libstd/sys/vxworks/env.rs
index bcc0e126b9d..fe1aedd5859 100644
--- a/src/libstd/sys/redox/env.rs
+++ b/src/libstd/sys/vxworks/env.rs
@@ -1,6 +1,6 @@
 pub mod os {
-    pub const FAMILY: &str = "redox";
-    pub const OS: &str = "redox";
+    pub const FAMILY: &str = "vxworks";
+    pub const OS: &str = "vxworks";
     pub const DLL_PREFIX: &str = "lib";
     pub const DLL_SUFFIX: &str = ".so";
     pub const DLL_EXTENSION: &str = "so";
diff --git a/src/libstd/sys/vxworks/ext/ffi.rs b/src/libstd/sys/vxworks/ext/ffi.rs
new file mode 100644
index 00000000000..76b34a6b5d8
--- /dev/null
+++ b/src/libstd/sys/vxworks/ext/ffi.rs
@@ -0,0 +1,38 @@
+//! Unix-specific extension to the primitives in the `std::ffi` module
+//!
+//! # Examples
+//!
+//! ```
+//! use std::ffi::OsString;
+//! use std::os::unix::ffi::OsStringExt;
+//!
+//! let bytes = b"foo".to_vec();
+//!
+//! // OsStringExt::from_vec
+//! let os_string = OsString::from_vec(bytes);
+//! assert_eq!(os_string.to_str(), Some("foo"));
+//!
+//! // OsStringExt::into_vec
+//! let bytes = os_string.into_vec();
+//! assert_eq!(bytes, b"foo");
+//! ```
+//!
+//! ```
+//! use std::ffi::OsStr;
+//! use std::os::unix::ffi::OsStrExt;
+//!
+//! let bytes = b"foo";
+//!
+//! // OsStrExt::from_bytes
+//! let os_str = OsStr::from_bytes(bytes);
+//! assert_eq!(os_str.to_str(), Some("foo"));
+//!
+//! // OsStrExt::as_bytes
+//! let bytes = os_str.as_bytes();
+//! assert_eq!(bytes, b"foo");
+//! ```
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::sys_common::os_str_bytes::*;
diff --git a/src/libstd/sys/vxworks/ext/fs.rs b/src/libstd/sys/vxworks/ext/fs.rs
new file mode 100644
index 00000000000..7ab7f2a1a26
--- /dev/null
+++ b/src/libstd/sys/vxworks/ext/fs.rs
@@ -0,0 +1,801 @@
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use crate::fs::{self, Permissions};
+use crate::io;
+use libc;
+use crate::path::Path;
+use crate::sys;
+use crate::sys_common::{FromInner, AsInner, AsInnerMut};
+use crate::sys::platform::fs::MetadataExt as UnixMetadataExt;
+
+/// Unix-specific extensions to [`File`].
+///
+/// [`File`]: ../../../../std/fs/struct.File.html
+#[stable(feature = "file_offset", since = "1.15.0")]
+pub trait FileExt {
+    /// Reads a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes read.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Note that similar to [`File::read`], it is not an error to return with a
+    /// short read.
+    ///
+    /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs::File;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut buf = [0u8; 8];
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now read 8 bytes from the offset 10.
+    ///     let num_bytes_read = file.read_at(&mut buf, 10)?;
+    ///     println!("read {} bytes: {:?}", num_bytes_read, buf);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "file_offset", since = "1.15.0")]
+    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
+
+    /// Reads the exact number of byte required to fill `buf` from the given offset.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
+    ///
+    /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
+    /// [`read_at`]: #tymethod.read_at
+    ///
+    /// # Errors
+    ///
+    /// If this function encounters an error of the kind
+    /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
+    /// will continue.
+    ///
+    /// If this function encounters an "end of file" before completely filling
+    /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
+    /// The contents of `buf` are unspecified in this case.
+    ///
+    /// If any other read error is encountered then this function immediately
+    /// returns. The contents of `buf` are unspecified in this case.
+    ///
+    /// If this function returns an error, it is unspecified how many bytes it
+    /// has read, but it will never read more than would be necessary to
+    /// completely fill the buffer.
+    ///
+    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(rw_exact_all_at)]
+    /// use std::io;
+    /// use std::fs::File;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let mut buf = [0u8; 8];
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now read exactly 8 bytes from the offset 10.
+    ///     file.read_exact_at(&mut buf, 10)?;
+    ///     println!("read {} bytes: {:?}", buf.len(), buf);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
+    fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
+        while !buf.is_empty() {
+            match self.read_at(buf, offset) {
+                Ok(0) => break,
+                Ok(n) => {
+                    let tmp = buf;
+                    buf = &mut tmp[n..];
+                    offset += n as u64;
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+        if !buf.is_empty() {
+            Err(io::Error::new(io::ErrorKind::UnexpectedEof,
+                               "failed to fill whole buffer"))
+        } else {
+            Ok(())
+        }
+    }
+
+    /// Writes a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes written.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// When writing beyond the end of the file, the file is appropriately
+    /// extended and the intermediate bytes are initialized with the value 0.
+    ///
+    /// Note that similar to [`File::write`], it is not an error to return a
+    /// short write.
+    ///
+    /// [`File::write`]: ../../../../std/fs/struct.File.html#write.v
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now write at the offset 10.
+    ///     file.write_at(b"sushi", 10)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "file_offset", since = "1.15.0")]
+    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+
+    /// Attempts to write an entire buffer starting from a given offset.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// This method will continuously call [`write_at`] until there is no more data
+    /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
+    /// returned. This method will not return until the entire buffer has been
+    /// successfully written or such an error occurs. The first error that is
+    /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
+    /// returned.
+    ///
+    /// # Errors
+    ///
+    /// This function will return the first error of
+    /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
+    ///
+    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`write_at`]: #tymethod.write_at
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(rw_exact_all_at)]
+    /// use std::fs::File;
+    /// use std::io;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let file = File::open("foo.txt")?;
+    ///
+    ///     // We now write at the offset 10.
+    ///     file.write_all_at(b"sushi", 10)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
+    fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
+        while !buf.is_empty() {
+            match self.write_at(buf, offset) {
+                Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero,
+                                                   "failed to write whole buffer")),
+                Ok(n) => {
+                    buf = &buf[n..];
+                    offset += n as u64
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(e),
+            }
+        }
+        Ok(())
+    }
+}
+
+#[stable(feature = "file_offset", since = "1.15.0")]
+impl FileExt for fs::File {
+    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().read_at(buf, offset)
+    }
+    fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.as_inner().write_at(buf, offset)
+    }
+}
+
+/// Unix-specific extensions to [`fs::Permissions`].
+///
+/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
+#[stable(feature = "fs_ext", since = "1.1.0")]
+pub trait PermissionsExt {
+    /// Returns the underlying raw `st_mode` bits that contain the standard
+    /// Unix permissions for this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     let permissions = metadata.permissions();
+    ///
+    ///     println!("permissions: {}", permissions.mode());
+    ///     Ok(()) }
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn mode(&self) -> u32;
+
+    /// Sets the underlying raw bits for this set of permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let f = File::create("foo.txt")?;
+    ///     let metadata = f.metadata()?;
+    ///     let mut permissions = metadata.permissions();
+    ///
+    ///     permissions.set_mode(0o644); // Read/write for owner and read for others.
+    ///     assert_eq!(permissions.mode(), 0o644);
+    ///     Ok(()) }
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn set_mode(&mut self, mode: u32);
+
+    /// Creates a new instance of `Permissions` from the given set of Unix
+    /// permission bits.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs::Permissions;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// // Read/write for owner and read for others.
+    /// let permissions = Permissions::from_mode(0o644);
+    /// assert_eq!(permissions.mode(), 0o644);
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn from_mode(mode: u32) -> Self;
+}
+
+#[stable(feature = "fs_ext", since = "1.1.0")]
+impl PermissionsExt for Permissions {
+    fn mode(&self) -> u32 {
+        self.as_inner().mode()
+    }
+
+    fn set_mode(&mut self, mode: u32) {
+        *self = Permissions::from_inner(FromInner::from_inner(mode));
+    }
+
+    fn from_mode(mode: u32) -> Permissions {
+        Permissions::from_inner(FromInner::from_inner(mode))
+    }
+}
+
+/// Unix-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
+#[stable(feature = "fs_ext", since = "1.1.0")]
+pub trait OpenOptionsExt {
+    /// Sets the mode bits that a new file will be created with.
+    ///
+    /// If a new file is created as part of a `File::open_opts` call then this
+    /// specified `mode` will be used as the permission bits for the new file.
+    /// If no `mode` is set, the default of `0o666` will be used.
+    /// The operating system masks out bits with the systems `umask`, to produce
+    /// the final permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// # fn main() {
+    /// let mut options = OpenOptions::new();
+    /// options.mode(0o644); // Give read/write for owner and read for others.
+    /// let file = options.open("foo.txt");
+    /// # }
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn mode(&mut self, mode: u32) -> &mut Self;
+
+    /// Pass custom flags to the `flags` argument of `open`.
+    ///
+    /// The bits that define the access mode are masked out with `O_ACCMODE`, to
+    /// ensure they do not interfere with the access mode set by Rusts options.
+    ///
+    /// Custom flags can only set flags, not remove flags set by Rusts options.
+    /// This options overwrites any previously set custom flags.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// # #![feature(libc)]
+    /// extern crate libc;
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// # fn main() {
+    /// let mut options = OpenOptions::new();
+    /// options.write(true);
+    /// if cfg!(unix) {
+    ///     options.custom_flags(libc::O_NOFOLLOW);
+    /// }
+    /// let file = options.open("foo.txt");
+    /// # }
+    /// ```
+    #[stable(feature = "open_options_ext", since = "1.10.0")]
+    fn custom_flags(&mut self, flags: i32) -> &mut Self;
+}
+
+/*#[stable(feature = "fs_ext", since = "1.1.0")]
+impl OpenOptionsExt for OpenOptions {
+    fn mode(&mut self, mode: u32) -> &mut OpenOptions {
+        self.as_inner_mut().mode(mode); self
+    }
+
+    fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
+        self.as_inner_mut().custom_flags(flags); self
+    }
+}
+*/
+
+/// Unix-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    /// Returns the ID of the device containing the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let dev_id = meta.dev();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn dev(&self) -> u64;
+    /// Returns the inode number.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let inode = meta.ino();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn ino(&self) -> u64;
+    /// Returns the rights applied to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let mode = meta.mode();
+    ///     let user_has_write_access      = mode & 0o200;
+    ///     let user_has_read_write_access = mode & 0o600;
+    ///     let group_has_read_access      = mode & 0o040;
+    ///     let others_have_exec_access    = mode & 0o001;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn mode(&self) -> u32;
+    /// Returns the number of hard links pointing to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///  use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let nb_hard_links = meta.nlink();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn nlink(&self) -> u64;
+    /// Returns the user ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let user_id = meta.uid();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn uid(&self) -> u32;
+    /// Returns the group ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let group_id = meta.gid();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn gid(&self) -> u32;
+    /// Returns the device ID of this file (if it is a special one).
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let device_id = meta.rdev();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn rdev(&self) -> u64;
+    /// Returns the total size of this file in bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let file_size = meta.size();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn size(&self) -> u64;
+    /// Returns the time of the last access to the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let last_access_time = meta.atime();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn atime(&self) -> i64;
+    /// Returns the time of the last access to the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let nano_last_access_time = meta.atime_nsec();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn mtime(&self) -> i64;
+    /// Returns the time of the last modification of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let nano_last_modification_time = meta.mtime_nsec();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn ctime(&self) -> i64;
+    /// Returns the time of the last status change of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let nano_last_status_change_time = meta.ctime_nsec();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn blksize(&self) -> u64;
+    /// Returns the number of blocks allocated to the file, in 512-byte units.
+    ///
+    /// Please note that this may be smaller than `st_size / 512` when the file has holes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("some_file")?;
+    ///     let blocks = meta.blocks();
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn blocks(&self) -> u64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn attrib(&self) -> u8;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for fs::Metadata {
+    fn dev(&self) -> u64 { self.st_dev() }
+    fn ino(&self) -> u64 { self.st_ino() }
+    fn mode(&self) -> u32 { self.st_mode() }
+    fn nlink(&self) -> u64 { self.st_nlink() }
+    fn uid(&self) -> u32 { self.st_uid() }
+    fn gid(&self) -> u32 { self.st_gid() }
+    fn rdev(&self) -> u64 { self.st_rdev() }
+    fn size(&self) -> u64 { self.st_size() }
+    fn atime(&self) -> i64 { self.st_atime() }
+    fn mtime(&self) -> i64 { self.st_mtime() }
+    fn ctime(&self) -> i64 { self.st_ctime() }
+    fn blksize(&self) -> u64 { self.st_blksize() }
+    fn blocks(&self) -> u64 { self.st_blocks() }
+    fn attrib(&self) -> u8 {self.st_attrib() }
+}
+
+/// Unix-specific extensions for [`FileType`].
+///
+/// Adds support for special Unix file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
+#[stable(feature = "file_type_ext", since = "1.5.0")]
+pub trait FileTypeExt {
+    /// Returns whether this file type is a block device.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("block_device_file")?;
+    ///     let file_type = meta.file_type();
+    ///     assert!(file_type.is_block_device());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_block_device(&self) -> bool;
+    /// Returns whether this file type is a char device.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("char_device_file")?;
+    ///     let file_type = meta.file_type();
+    ///     assert!(file_type.is_char_device());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_char_device(&self) -> bool;
+    /// Returns whether this file type is a fifo.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("fifo_file")?;
+    ///     let file_type = meta.file_type();
+    ///     assert!(file_type.is_fifo());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_fifo(&self) -> bool;
+    /// Returns whether this file type is a socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    /// use std::io;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     let meta = fs::metadata("unix.socket")?;
+    ///     let file_type = meta.file_type();
+    ///     assert!(file_type.is_socket());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_socket(&self) -> bool;
+}
+
+#[stable(feature = "file_type_ext", since = "1.5.0")]
+impl FileTypeExt for fs::FileType {
+    fn is_block_device(&self) -> bool { self.as_inner().is(libc::S_IFBLK) }
+    fn is_char_device(&self) -> bool { self.as_inner().is(libc::S_IFCHR) }
+    fn is_fifo(&self) -> bool { self.as_inner().is(libc::S_IFIFO) }
+    fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) }
+}
+
+/// Unix-specific extension methods for [`fs::DirEntry`].
+///
+/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
+#[stable(feature = "dir_entry_ext", since = "1.1.0")]
+pub trait DirEntryExt {
+    /// Returns the underlying `d_ino` field in the contained `dirent`
+    /// structure.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::DirEntryExt;
+    ///
+    /// if let Ok(entries) = fs::read_dir(".") {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `DirEntry`.
+    ///             println!("{:?}: {}", entry.file_name(), entry.ino());
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "dir_entry_ext", since = "1.1.0")]
+    fn ino(&self) -> u64;
+}
+
+#[stable(feature = "dir_entry_ext", since = "1.1.0")]
+impl DirEntryExt for fs::DirEntry {
+    fn ino(&self) -> u64 { self.as_inner().ino() }
+}
+
+/// Creates a new symbolic link on the filesystem.
+///
+/// The `dst` path will be a symbolic link pointing to the `src` path.
+///
+/// # Note
+///
+/// On Windows, you must specify whether a symbolic link points to a file
+/// or directory.  Use `os::windows::fs::symlink_file` to create a
+/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
+/// symbolic link to a directory.  Additionally, the process must have
+/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
+/// symbolic link.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::os::unix::fs;
+///
+/// fn main() -> std::io::Result<()> {
+///     fs::symlink("a.txt", "b.txt")?;
+///     Ok(())
+/// }
+/// ```
+#[stable(feature = "symlink", since = "1.1.0")]
+pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
+{
+    sys::fs::symlink(src.as_ref(), dst.as_ref())
+}
+
+/// Unix-specific extensions to [`fs::DirBuilder`].
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
+#[stable(feature = "dir_builder", since = "1.6.0")]
+pub trait DirBuilderExt {
+    /// Sets the mode to create new directories with. This option defaults to
+    /// 0o777.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::DirBuilder;
+    /// use std::os::unix::fs::DirBuilderExt;
+    ///
+    /// let mut builder = DirBuilder::new();
+    /// builder.mode(0o755);
+    /// ```
+    #[stable(feature = "dir_builder", since = "1.6.0")]
+    fn mode(&mut self, mode: u32) -> &mut Self;
+}
+
+#[stable(feature = "dir_builder", since = "1.6.0")]
+impl DirBuilderExt for fs::DirBuilder {
+    fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
+        self.as_inner_mut().set_mode(mode);
+        self
+    }
+}
diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/vxworks/ext/io.rs
index f431f96c541..6bcc59495e3 100644
--- a/src/libstd/sys/redox/ext/io.rs
+++ b/src/libstd/sys/vxworks/ext/io.rs
@@ -3,14 +3,14 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::fs;
-use crate::net;
+use crate::os::raw;
 use crate::sys;
 use crate::io;
-use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 /// Raw file descriptors.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub type RawFd = usize;
+pub type RawFd = raw::c_int;
 
 /// A trait to extract the raw unix file descriptor from an underlying
 /// object.
@@ -33,7 +33,7 @@ pub trait AsRawFd {
 /// descriptor.
 #[stable(feature = "from_raw_os", since = "1.1.0")]
 pub trait FromRawFd {
-    /// Constructs a new instances of `Self` from the given raw file
+    /// Constructs a new instance of `Self` from the given raw file
     /// descriptor.
     ///
     /// This function **consumes ownership** of the specified file
@@ -81,77 +81,32 @@ impl IntoRawFd for fs::File {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpStream {
-    fn as_raw_fd(&self) -> RawFd {
-        self.as_inner().as_inner().fd().raw()
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpListener {
-    fn as_raw_fd(&self) -> RawFd {
-        self.as_inner().as_inner().fd().raw()
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::UdpSocket {
-    fn as_raw_fd(&self) -> RawFd {
-        self.as_inner().as_inner().fd().raw()
-    }
-}
-
 #[stable(feature = "asraw_stdio", since = "1.21.0")]
 impl AsRawFd for io::Stdin {
-    fn as_raw_fd(&self) -> RawFd { 0 }
+    fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO }
 }
 
 #[stable(feature = "asraw_stdio", since = "1.21.0")]
 impl AsRawFd for io::Stdout {
-    fn as_raw_fd(&self) -> RawFd { 1 }
+    fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO }
 }
 
 #[stable(feature = "asraw_stdio", since = "1.21.0")]
 impl AsRawFd for io::Stderr {
-    fn as_raw_fd(&self) -> RawFd { 2 }
+    fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO }
 }
 
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
-        let file = sys::fs::File::from_inner(fd);
-        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(file))
-    }
-}
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
-        let file = sys::fs::File::from_inner(fd);
-        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(file))
-    }
-}
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::UdpSocket {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
-        let file = sys::fs::File::from_inner(fd);
-        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(file))
-    }
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawFd for io::StdinLock<'a> {
+    fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO }
 }
 
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpStream {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_inner().into_fd().into_raw()
-    }
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawFd for io::StdoutLock<'a> {
+    fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO }
 }
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpListener {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_inner().into_fd().into_raw()
-    }
-}
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::UdpSocket {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_inner().into_fd().into_raw()
-    }
+
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawFd for io::StderrLock<'a> {
+    fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO }
 }
diff --git a/src/libstd/sys/vxworks/ext/mod.rs b/src/libstd/sys/vxworks/ext/mod.rs
new file mode 100644
index 00000000000..c2ebc38c300
--- /dev/null
+++ b/src/libstd/sys/vxworks/ext/mod.rs
@@ -0,0 +1,20 @@
+// Uhhh
+#![stable(feature = "rust1", since = "1.0.0")]
+#![allow(missing_docs)]
+
+pub mod io;
+pub mod ffi;
+pub mod fs;
+pub mod raw;
+pub mod process;
+pub mod net;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod prelude {
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::ffi::{OsStrExt, OsStringExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt};
+}
diff --git a/src/libstd/sys/vxworks/ext/net.rs b/src/libstd/sys/vxworks/ext/net.rs
new file mode 100644
index 00000000000..3f0a7e9e843
--- /dev/null
+++ b/src/libstd/sys/vxworks/ext/net.rs
@@ -0,0 +1,1825 @@
+#![stable(feature = "unix_socket", since = "1.10.0")]
+
+//! Unix-specific networking functionality
+
+#[cfg(unix)]
+use libc;
+
+use crate::ascii;
+use crate::ffi::OsStr;
+use crate::fmt;
+use crate::io::{self, Initializer, IoSlice, IoSliceMut};
+use crate::mem;
+use crate::net::{self, Shutdown};
+use crate::os::unix::ffi::OsStrExt;
+use crate::os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
+use crate::path::Path;
+use crate::time::Duration;
+use crate::sys::{self, cvt};
+use crate::sys::net::Socket;
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+
+const MSG_NOSIGNAL: libc::c_int = 0x0;
+
+fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
+    // Work with an actual instance of the type since using a null pointer is UB
+    let base = addr as *const _ as usize;
+    let path = &addr.sun_path as *const _ as usize;
+    path - base
+}
+
+unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
+    let mut addr: libc::sockaddr_un = mem::zeroed();
+    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;
+
+    let bytes = path.as_os_str().as_bytes();
+
+    if bytes.contains(&0) {
+        return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                  "paths may not contain interior null bytes"));
+    }
+
+    if bytes.len() >= addr.sun_path.len() {
+        return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                  "path must be shorter than SUN_LEN"));
+    }
+    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
+        *dst = *src as libc::c_char;
+    }
+    // null byte for pathname addresses is already there because we zeroed the
+    // struct
+
+    let mut len = sun_path_offset(&addr) + bytes.len();
+    match bytes.get(0) {
+        Some(&0) | None => {}
+        Some(_) => len += 1,
+    }
+    Ok((addr, len as libc::socklen_t))
+}
+
+enum AddressKind<'a> {
+    Unnamed,
+    Pathname(&'a Path),
+    Abstract(&'a [u8]),
+}
+
+/// An address associated with a Unix socket.
+///
+/// # Examples
+///
+/// ```
+/// use std::os::unix::net::UnixListener;
+///
+/// let socket = match UnixListener::bind("/tmp/sock") {
+///     Ok(sock) => sock,
+///     Err(e) => {
+///         println!("Couldn't bind: {:?}", e);
+///         return
+///     }
+/// };
+/// let addr = socket.local_addr().expect("Couldn't get local address");
+/// ```
+#[derive(Clone)]
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct SocketAddr {
+    addr: libc::sockaddr_un,
+    len: libc::socklen_t,
+}
+
+impl SocketAddr {
+    fn new<F>(f: F) -> io::Result<SocketAddr>
+        where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int
+    {
+        unsafe {
+            let mut addr: libc::sockaddr_un = mem::zeroed();
+            let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
+            cvt(f(&mut addr as *mut _ as *mut _, &mut len))?;
+            SocketAddr::from_parts(addr, len)
+        }
+    }
+
+    fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result<SocketAddr> {
+        if len == 0 {
+            // When there is a datagram from unnamed unix socket
+            // linux returns zero bytes of address
+            len = sun_path_offset(&addr) as libc::socklen_t;  // i.e., zero-length address
+        } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                      "file descriptor did not correspond to a Unix socket"));
+        }
+
+        Ok(SocketAddr {
+            addr,
+            len,
+        })
+    }
+
+    /// Returns `true` if the address is unnamed.
+    ///
+    /// # Examples
+    ///
+    /// A named address:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.is_unnamed(), false);
+    /// ```
+    ///
+    /// An unnamed address:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.is_unnamed(), true);
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn is_unnamed(&self) -> bool {
+        if let AddressKind::Unnamed = self.address() {
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Returns the contents of this address if it is a `pathname` address.
+    ///
+    /// # Examples
+    ///
+    /// With a pathname:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    /// use std::path::Path;
+    ///
+    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
+    /// ```
+    ///
+    /// Without a pathname:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.as_pathname(), None);
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn as_pathname(&self) -> Option<&Path> {
+        if let AddressKind::Pathname(path) = self.address() {
+            Some(path)
+        } else {
+            None
+        }
+    }
+
+    fn address<'a>(&'a self) -> AddressKind<'a> {
+        let len = self.len as usize - sun_path_offset(&self.addr);
+        let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
+
+        if self.addr.sun_path[0] == 0 {
+            AddressKind::Abstract(&path[1..len])
+        } else {
+            AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
+        }
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for SocketAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.address() {
+            AddressKind::Unnamed => write!(fmt, "(unnamed)"),
+            AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
+            AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path),
+        }
+    }
+}
+
+struct AsciiEscaped<'a>(&'a [u8]);
+
+impl<'a> fmt::Display for AsciiEscaped<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "\"")?;
+        for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
+            write!(fmt, "{}", byte as char)?;
+        }
+        write!(fmt, "\"")
+    }
+}
+
+/// A Unix stream socket.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::os::unix::net::UnixStream;
+/// use std::io::prelude::*;
+///
+/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap();
+/// stream.write_all(b"hello world").unwrap();
+/// let mut response = String::new();
+/// stream.read_to_string(&mut response).unwrap();
+/// println!("{}", response);
+/// ```
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct UnixStream(Socket);
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for UnixStream {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixStream");
+        builder.field("fd", self.0.as_inner());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        if let Ok(addr) = self.peer_addr() {
+            builder.field("peer", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixStream {
+    /// Connects to the socket named by `path`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = match UnixStream::connect("/tmp/sock") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
+        fn inner(path: &Path) -> io::Result<UnixStream> {
+            unsafe {
+                let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
+                let (addr, len) = sockaddr_un(path)?;
+
+                cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?;
+                Ok(UnixStream(inner))
+            }
+        }
+        inner(path.as_ref())
+    }
+
+    /// Creates an unnamed pair of connected sockets.
+    ///
+    /// Returns two `UnixStream`s which are connected to each other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let (sock1, sock2) = match UnixStream::pair() {
+    ///     Ok((sock1, sock2)) => (sock1, sock2),
+    ///     Err(e) => {
+    ///         println!("Couldn't create a pair of sockets: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
+        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?;
+        Ok((UnixStream(i1), UnixStream(i2)))
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixStream` is a reference to the same stream that this
+    /// object references. Both handles will read and write the same stream of
+    /// data, and options set on one stream will be propagated to the other
+    /// stream.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn try_clone(&self) -> io::Result<UnixStream> {
+        self.0.duplicate().map(UnixStream)
+    }
+
+    /// Returns the socket address of the local half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Returns the socket address of the remote half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let addr = socket.peer_addr().expect("Couldn't get peer address");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Sets the read timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`read`] calls will block
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
+    /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
+    }
+
+    /// Sets the write timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`write`] calls will block
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
+    /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
+    }
+
+    /// Returns the read timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_RCVTIMEO)
+    }
+
+    /// Returns the write timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
+    /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_SNDTIMEO)
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// if let Ok(Some(err)) = socket.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns `None`.
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.0.take_error()
+    }
+
+    /// Shuts down the read, write, or both halves of this connection.
+    ///
+    /// This function will cause all pending and future I/O calls on the
+    /// specified portions to immediately return with an appropriate value
+    /// (see the documentation of [`Shutdown`]).
+    ///
+    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::net::Shutdown;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
+        self.0.shutdown(how)
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl io::Read for UnixStream {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        io::Read::read(&mut &*self, buf)
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        io::Read::read_vectored(&mut &*self, bufs)
+    }
+
+    #[inline]
+    unsafe fn initializer(&self) -> Initializer {
+        Initializer::nop()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> io::Read for &'a UnixStream {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
+    #[inline]
+    unsafe fn initializer(&self) -> Initializer {
+        Initializer::nop()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl io::Write for UnixStream {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        io::Write::write(&mut &*self, buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        io::Write::write_vectored(&mut &*self, bufs)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        io::Write::flush(&mut &*self)
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> io::Write for &'a UnixStream {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl AsRawFd for UnixStream {
+    fn as_raw_fd(&self) -> RawFd {
+        *self.0.as_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl FromRawFd for UnixStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
+        UnixStream(Socket::from_inner(fd))
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl IntoRawFd for UnixStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_inner()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::UdpSocket {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::UdpSocket {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
+    }
+}
+
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::UdpSocket {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+
+/// A structure representing a Unix domain socket server.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+/// use std::os::unix::net::{UnixStream, UnixListener};
+///
+/// fn handle_client(stream: UnixStream) {
+///     // ...
+/// }
+///
+/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+///
+/// // accept connections and process them, spawning a new thread for each one
+/// for stream in listener.incoming() {
+///     match stream {
+///         Ok(stream) => {
+///             /* connection succeeded */
+///             thread::spawn(|| handle_client(stream));
+///         }
+///         Err(err) => {
+///             /* connection failed */
+///             break;
+///         }
+///     }
+/// }
+/// ```
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct UnixListener(Socket);
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for UnixListener {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixListener");
+        builder.field("fd", self.0.as_inner());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixListener {
+    /// Creates a new `UnixListener` bound to the specified socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = match UnixListener::bind("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
+        fn inner(path: &Path) -> io::Result<UnixListener> {
+            unsafe {
+                let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
+                let (addr, len) = sockaddr_un(path)?;
+
+                cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
+                cvt(libc::listen(*inner.as_inner(), 128))?;
+
+                Ok(UnixListener(inner))
+            }
+        }
+        inner(path.as_ref())
+    }
+
+    /// Accepts a new incoming connection to this listener.
+    ///
+    /// This function will block the calling thread until a new Unix connection
+    /// is established. When established, the corresponding [`UnixStream`] and
+    /// the remote peer's address will be returned.
+    ///
+    /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// match listener.accept() {
+    ///     Ok((socket, addr)) => println!("Got a client: {:?}", addr),
+    ///     Err(e) => println!("accept function failed: {:?}", e),
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
+        let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
+        let mut len = mem::size_of_val(&storage) as libc::socklen_t;
+        let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?;
+        let addr = SocketAddr::from_parts(storage, len)?;
+        Ok((UnixStream(sock), addr))
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixListener` is a reference to the same socket that this
+    /// object references. Both handles can be used to accept incoming
+    /// connections and options set on one listener will affect the other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let listener_copy = listener.try_clone().expect("try_clone failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn try_clone(&self) -> io::Result<UnixListener> {
+        self.0.duplicate().map(UnixListener)
+    }
+
+    /// Returns the local socket address of this listener.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let addr = listener.local_addr().expect("Couldn't get local address");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// listener.set_nonblocking(true).expect("Couldn't set non blocking");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/tmp/sock").unwrap();
+    ///
+    /// if let Ok(Some(err)) = listener.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns `None`.
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.0.take_error()
+    }
+
+    /// Returns an iterator over incoming connections.
+    ///
+    /// The iterator will never return [`None`] and will also not yield the
+    /// peer's [`SocketAddr`] structure.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`SocketAddr`]: struct.SocketAddr.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::thread;
+    /// use std::os::unix::net::{UnixStream, UnixListener};
+    ///
+    /// fn handle_client(stream: UnixStream) {
+    ///     // ...
+    /// }
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// for stream in listener.incoming() {
+    ///     match stream {
+    ///         Ok(stream) => {
+    ///             thread::spawn(|| handle_client(stream));
+    ///         }
+    ///         Err(err) => {
+    ///             break;
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn incoming<'a>(&'a self) -> Incoming<'a> {
+        Incoming { listener: self }
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl AsRawFd for UnixListener {
+    fn as_raw_fd(&self) -> RawFd {
+        *self.0.as_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl FromRawFd for UnixListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
+        UnixListener(Socket::from_inner(fd))
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl IntoRawFd for UnixListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> IntoIterator for &'a UnixListener {
+    type Item = io::Result<UnixStream>;
+    type IntoIter = Incoming<'a>;
+
+    fn into_iter(self) -> Incoming<'a> {
+        self.incoming()
+    }
+}
+
+/// An iterator over incoming connections to a [`UnixListener`].
+///
+/// It will never return [`None`].
+///
+/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+/// [`UnixListener`]: struct.UnixListener.html
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+/// use std::os::unix::net::{UnixStream, UnixListener};
+///
+/// fn handle_client(stream: UnixStream) {
+///     // ...
+/// }
+///
+/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+///
+/// for stream in listener.incoming() {
+///     match stream {
+///         Ok(stream) => {
+///             thread::spawn(|| handle_client(stream));
+///         }
+///         Err(err) => {
+///             break;
+///         }
+///     }
+/// }
+/// ```
+#[derive(Debug)]
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct Incoming<'a> {
+    listener: &'a UnixListener,
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> Iterator for Incoming<'a> {
+    type Item = io::Result<UnixStream>;
+
+    fn next(&mut self) -> Option<io::Result<UnixStream>> {
+        Some(self.listener.accept().map(|s| s.0))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (usize::max_value(), None)
+    }
+}
+
+/// A Unix datagram socket.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::os::unix::net::UnixDatagram;
+///
+/// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap();
+/// socket.send_to(b"hello world", "/path/to/other/socket").unwrap();
+/// let mut buf = [0; 100];
+/// let (count, address) = socket.recv_from(&mut buf).unwrap();
+/// println!("socket {:?} sent {:?}", address, &buf[..count]);
+/// ```
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct UnixDatagram(Socket);
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for UnixDatagram {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixDatagram");
+        builder.field("fd", self.0.as_inner());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        if let Ok(addr) = self.peer_addr() {
+            builder.field("peer", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixDatagram {
+    /// Creates a Unix datagram socket bound to the given path.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = match UnixDatagram::bind("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't bind: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
+        fn inner(path: &Path) -> io::Result<UnixDatagram> {
+            unsafe {
+                let socket = UnixDatagram::unbound()?;
+                let (addr, len) = sockaddr_un(path)?;
+
+                cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
+
+                Ok(socket)
+            }
+        }
+        inner(path.as_ref())
+    }
+
+    /// Creates a Unix Datagram socket which is not bound to any address.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = match UnixDatagram::unbound() {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't unbound: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn unbound() -> io::Result<UnixDatagram> {
+        let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?;
+        Ok(UnixDatagram(inner))
+    }
+
+    /// Creates an unnamed pair of connected sockets.
+    ///
+    /// Returns two `UnixDatagrams`s which are connected to each other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let (sock1, sock2) = match UnixDatagram::pair() {
+    ///     Ok((sock1, sock2)) => (sock1, sock2),
+    ///     Err(e) => {
+    ///         println!("Couldn't unbound: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
+        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
+        Ok((UnixDatagram(i1), UnixDatagram(i2)))
+    }
+
+    /// Connects the socket to the specified address.
+    ///
+    /// The [`send`] method may be used to send data to the specified address.
+    /// [`recv`] and [`recv_from`] will only receive data from that address.
+    ///
+    /// [`send`]: #method.send
+    /// [`recv`]: #method.recv
+    /// [`recv_from`]: #method.recv_from
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// match sock.connect("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+        fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> {
+            unsafe {
+                let (addr, len) = sockaddr_un(path)?;
+
+                cvt(libc::connect(*d.0.as_inner(), &addr as *const _ as *const _, len))?;
+
+                Ok(())
+            }
+        }
+        inner(self, path.as_ref())
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixDatagram` is a reference to the same socket that this
+    /// object references. Both handles can be used to accept incoming
+    /// connections and options set on one side will affect the other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let sock_copy = sock.try_clone().expect("try_clone failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn try_clone(&self) -> io::Result<UnixDatagram> {
+        self.0.duplicate().map(UnixDatagram)
+    }
+
+    /// Returns the address of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let addr = sock.local_addr().expect("Couldn't get local address");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Returns the address of this socket's peer.
+    ///
+    /// The [`connect`] method will connect the socket to a peer.
+    ///
+    /// [`connect`]: #method.connect
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.connect("/path/to/the/socket").unwrap();
+    ///
+    /// let addr = sock.peer_addr().expect("Couldn't get peer address");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Receives data from the socket.
+    ///
+    /// On success, returns the number of bytes read and the address from
+    /// whence the data came.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// let mut buf = vec![0; 10];
+    /// match sock.recv_from(buf.as_mut_slice()) {
+    ///     Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender),
+    ///     Err(e) => println!("recv_from function failed: {:?}", e),
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        let mut count = 0;
+        let addr = SocketAddr::new(|addr, len| {
+            unsafe {
+                count = libc::recvfrom(*self.0.as_inner(),
+                                       buf.as_mut_ptr() as *mut _,
+                                       buf.len(),
+                                       0,
+                                       addr,
+                                       len);
+                if count > 0 {
+                    1
+                } else if count == 0 {
+                    0
+                } else {
+                    -1
+                }
+            }
+        })?;
+
+        Ok((count as usize, addr))
+    }
+
+    /// Receives data from the socket.
+    ///
+    /// On success, returns the number of bytes read.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
+    /// let mut buf = vec![0; 10];
+    /// sock.recv(buf.as_mut_slice()).expect("recv function failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    /// Sends data on the socket to the specified address.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
+        fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> {
+            unsafe {
+                let (addr, len) = sockaddr_un(path)?;
+
+                let count = cvt(libc::sendto(*d.0.as_inner(),
+                                             buf.as_ptr() as *const _,
+                                             buf.len(),
+                                             MSG_NOSIGNAL,
+                                             &addr as *const _ as *const _,
+                                             len))?;
+                Ok(count as usize)
+            }
+        }
+        inner(self, buf, path.as_ref())
+    }
+
+    /// Sends data on the socket to the socket's peer.
+    ///
+    /// The peer address may be set by the `connect` method, and this method
+    /// will return an error if the socket has not already been connected.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.connect("/some/sock").expect("Couldn't connect");
+    /// sock.send(b"omelette au fromage").expect("send_to function failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    /// Sets the read timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
+    /// is passed to this method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
+    /// [`recv`]: #method.recv
+    /// [`recv_from`]: #method.recv_from
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
+    }
+
+    /// Sets the write timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`send`]: #method.send
+    /// [`send_to`]: #method.send_to
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_write_timeout(Some(Duration::new(1, 0)))
+    ///     .expect("set_write_timeout function failed");
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
+    }
+
+    /// Returns the read timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
+    /// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_RCVTIMEO)
+    }
+
+    /// Returns the write timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_write_timeout(Some(Duration::new(1, 0)))
+    ///     .expect("set_write_timeout function failed");
+    /// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_SNDTIMEO)
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_nonblocking(true).expect("set_nonblocking function failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// if let Ok(Some(err)) = sock.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.0.take_error()
+    }
+
+    /// Shut down the read, write, or both halves of this connection.
+    ///
+    /// This function will cause all pending and future I/O calls on the
+    /// specified portions to immediately return with an appropriate value
+    /// (see the documentation of [`Shutdown`]).
+    ///
+    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::net::Shutdown;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.shutdown(Shutdown::Both).expect("shutdown function failed");
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
+        self.0.shutdown(how)
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl AsRawFd for UnixDatagram {
+    fn as_raw_fd(&self) -> RawFd {
+        *self.0.as_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl FromRawFd for UnixDatagram {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
+        UnixDatagram(Socket::from_inner(fd))
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl IntoRawFd for UnixDatagram {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_inner()
+    }
+}
+
+#[cfg(all(test, not(target_os = "emscripten")))]
+mod test {
+    use crate::thread;
+    use crate::io::{self, ErrorKind};
+    use crate::io::prelude::*;
+    use crate::time::Duration;
+    use crate::sys_common::io::test::tmpdir;
+
+    use super::*;
+
+    macro_rules! or_panic {
+        ($e:expr) => {
+            match $e {
+                Ok(e) => e,
+                Err(e) => panic!("{}", e),
+            }
+        }
+    }
+
+    #[test]
+    fn basic() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+        let msg1 = b"hello";
+        let msg2 = b"world!";
+
+        let listener = or_panic!(UnixListener::bind(&socket_path));
+        let thread = thread::spawn(move || {
+            let mut stream = or_panic!(listener.accept()).0;
+            let mut buf = [0; 5];
+            or_panic!(stream.read(&mut buf));
+            assert_eq!(&msg1[..], &buf[..]);
+            or_panic!(stream.write_all(msg2));
+        });
+
+        let mut stream = or_panic!(UnixStream::connect(&socket_path));
+        assert_eq!(Some(&*socket_path),
+                   stream.peer_addr().unwrap().as_pathname());
+        or_panic!(stream.write_all(msg1));
+        let mut buf = vec![];
+        or_panic!(stream.read_to_end(&mut buf));
+        assert_eq!(&msg2[..], &buf[..]);
+        drop(stream);
+
+        thread.join().unwrap();
+    }
+
+    #[test]
+    fn vectored() {
+        let (mut s1, mut s2) = or_panic!(UnixStream::pair());
+
+        let len = or_panic!(s1.write_vectored(
+            &[IoSlice::new(b"hello"), IoSlice::new(b" "), IoSlice::new(b"world!")],
+        ));
+        assert_eq!(len, 12);
+
+        let mut buf1 = [0; 6];
+        let mut buf2 = [0; 7];
+        let len = or_panic!(s2.read_vectored(
+            &mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],
+        ));
+        assert_eq!(len, 12);
+        assert_eq!(&buf1, b"hello ");
+        assert_eq!(&buf2, b"world!\0");
+    }
+
+    #[test]
+    fn pair() {
+        let msg1 = b"hello";
+        let msg2 = b"world!";
+
+        let (mut s1, mut s2) = or_panic!(UnixStream::pair());
+        let thread = thread::spawn(move || {
+            // s1 must be moved in or the test will hang!
+            let mut buf = [0; 5];
+            or_panic!(s1.read(&mut buf));
+            assert_eq!(&msg1[..], &buf[..]);
+            or_panic!(s1.write_all(msg2));
+        });
+
+        or_panic!(s2.write_all(msg1));
+        let mut buf = vec![];
+        or_panic!(s2.read_to_end(&mut buf));
+        assert_eq!(&msg2[..], &buf[..]);
+        drop(s2);
+
+        thread.join().unwrap();
+    }
+
+    #[test]
+    fn try_clone() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+        let msg1 = b"hello";
+        let msg2 = b"world";
+
+        let listener = or_panic!(UnixListener::bind(&socket_path));
+        let thread = thread::spawn(move || {
+            let mut stream = or_panic!(listener.accept()).0;
+            or_panic!(stream.write_all(msg1));
+            or_panic!(stream.write_all(msg2));
+        });
+
+        let mut stream = or_panic!(UnixStream::connect(&socket_path));
+        let mut stream2 = or_panic!(stream.try_clone());
+
+        let mut buf = [0; 5];
+        or_panic!(stream.read(&mut buf));
+        assert_eq!(&msg1[..], &buf[..]);
+        or_panic!(stream2.read(&mut buf));
+        assert_eq!(&msg2[..], &buf[..]);
+
+        thread.join().unwrap();
+    }
+
+    #[test]
+    fn iter() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+
+        let listener = or_panic!(UnixListener::bind(&socket_path));
+        let thread = thread::spawn(move || {
+            for stream in listener.incoming().take(2) {
+                let mut stream = or_panic!(stream);
+                let mut buf = [0];
+                or_panic!(stream.read(&mut buf));
+            }
+        });
+
+        for _ in 0..2 {
+            let mut stream = or_panic!(UnixStream::connect(&socket_path));
+            or_panic!(stream.write_all(&[0]));
+        }
+
+        thread.join().unwrap();
+    }
+
+    #[test]
+    fn long_path() {
+        let dir = tmpdir();
+        let socket_path = dir.path()
+                             .join("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa\
+                                    sasdfasdfasdasdfasdfasdfadfasdfasdfasdfasdfasdf");
+        match UnixStream::connect(&socket_path) {
+            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
+            Err(e) => panic!("unexpected error {}", e),
+            Ok(_) => panic!("unexpected success"),
+        }
+
+        match UnixListener::bind(&socket_path) {
+            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
+            Err(e) => panic!("unexpected error {}", e),
+            Ok(_) => panic!("unexpected success"),
+        }
+
+        match UnixDatagram::bind(&socket_path) {
+            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
+            Err(e) => panic!("unexpected error {}", e),
+            Ok(_) => panic!("unexpected success"),
+        }
+    }
+
+    #[test]
+    fn timeouts() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+
+        let _listener = or_panic!(UnixListener::bind(&socket_path));
+
+        let stream = or_panic!(UnixStream::connect(&socket_path));
+        let dur = Duration::new(15410, 0);
+
+        assert_eq!(None, or_panic!(stream.read_timeout()));
+
+        or_panic!(stream.set_read_timeout(Some(dur)));
+        assert_eq!(Some(dur), or_panic!(stream.read_timeout()));
+
+        assert_eq!(None, or_panic!(stream.write_timeout()));
+
+        or_panic!(stream.set_write_timeout(Some(dur)));
+        assert_eq!(Some(dur), or_panic!(stream.write_timeout()));
+
+        or_panic!(stream.set_read_timeout(None));
+        assert_eq!(None, or_panic!(stream.read_timeout()));
+
+        or_panic!(stream.set_write_timeout(None));
+        assert_eq!(None, or_panic!(stream.write_timeout()));
+    }
+
+    #[test]
+    fn test_read_timeout() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+
+        let _listener = or_panic!(UnixListener::bind(&socket_path));
+
+        let mut stream = or_panic!(UnixStream::connect(&socket_path));
+        or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+        let mut buf = [0; 10];
+        let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
+        assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
+                "unexpected_error: {:?}", kind);
+    }
+
+    #[test]
+    fn test_read_with_timeout() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+
+        let listener = or_panic!(UnixListener::bind(&socket_path));
+
+        let mut stream = or_panic!(UnixStream::connect(&socket_path));
+        or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
+
+        let mut other_end = or_panic!(listener.accept()).0;
+        or_panic!(other_end.write_all(b"hello world"));
+
+        let mut buf = [0; 11];
+        or_panic!(stream.read(&mut buf));
+        assert_eq!(b"hello world", &buf[..]);
+
+        let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
+        assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
+                "unexpected_error: {:?}", kind);
+    }
+
+    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+    // when passed zero Durations
+    #[test]
+    fn test_unix_stream_timeout_zero_duration() {
+        let dir = tmpdir();
+        let socket_path = dir.path().join("sock");
+
+        let listener = or_panic!(UnixListener::bind(&socket_path));
+        let stream = or_panic!(UnixStream::connect(&socket_path));
+
+        let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        drop(listener);
+    }
+
+    #[test]
+    fn test_unix_datagram() {
+        let dir = tmpdir();
+        let path1 = dir.path().join("sock1");
+        let path2 = dir.path().join("sock2");
+
+        let sock1 = or_panic!(UnixDatagram::bind(&path1));
+        let sock2 = or_panic!(UnixDatagram::bind(&path2));
+
+        let msg = b"hello world";
+        or_panic!(sock1.send_to(msg, &path2));
+        let mut buf = [0; 11];
+        or_panic!(sock2.recv_from(&mut buf));
+        assert_eq!(msg, &buf[..]);
+    }
+
+    #[test]
+    fn test_unnamed_unix_datagram() {
+        let dir = tmpdir();
+        let path1 = dir.path().join("sock1");
+
+        let sock1 = or_panic!(UnixDatagram::bind(&path1));
+        let sock2 = or_panic!(UnixDatagram::unbound());
+
+        let msg = b"hello world";
+        or_panic!(sock2.send_to(msg, &path1));
+        let mut buf = [0; 11];
+        let (usize, addr) = or_panic!(sock1.recv_from(&mut buf));
+        assert_eq!(usize, 11);
+        assert!(addr.is_unnamed());
+        assert_eq!(msg, &buf[..]);
+    }
+
+    #[test]
+    fn test_connect_unix_datagram() {
+        let dir = tmpdir();
+        let path1 = dir.path().join("sock1");
+        let path2 = dir.path().join("sock2");
+
+        let bsock1 = or_panic!(UnixDatagram::bind(&path1));
+        let bsock2 = or_panic!(UnixDatagram::bind(&path2));
+        let sock = or_panic!(UnixDatagram::unbound());
+        or_panic!(sock.connect(&path1));
+
+        // Check send()
+        let msg = b"hello there";
+        or_panic!(sock.send(msg));
+        let mut buf = [0; 11];
+        let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf));
+        assert_eq!(usize, 11);
+        assert!(addr.is_unnamed());
+        assert_eq!(msg, &buf[..]);
+
+        // Changing default socket works too
+        or_panic!(sock.connect(&path2));
+        or_panic!(sock.send(msg));
+        or_panic!(bsock2.recv_from(&mut buf));
+    }
+
+    #[test]
+    fn test_unix_datagram_recv() {
+        let dir = tmpdir();
+        let path1 = dir.path().join("sock1");
+
+        let sock1 = or_panic!(UnixDatagram::bind(&path1));
+        let sock2 = or_panic!(UnixDatagram::unbound());
+        or_panic!(sock2.connect(&path1));
+
+        let msg = b"hello world";
+        or_panic!(sock2.send(msg));
+        let mut buf = [0; 11];
+        let size = or_panic!(sock1.recv(&mut buf));
+        assert_eq!(size, 11);
+        assert_eq!(msg, &buf[..]);
+    }
+
+    #[test]
+    fn datagram_pair() {
+        let msg1 = b"hello";
+        let msg2 = b"world!";
+
+        let (s1, s2) = or_panic!(UnixDatagram::pair());
+        let thread = thread::spawn(move || {
+            // s1 must be moved in or the test will hang!
+            let mut buf = [0; 5];
+            or_panic!(s1.recv(&mut buf));
+            assert_eq!(&msg1[..], &buf[..]);
+            or_panic!(s1.send(msg2));
+        });
+
+        or_panic!(s2.send(msg1));
+        let mut buf = [0; 6];
+        or_panic!(s2.recv(&mut buf));
+        assert_eq!(&msg2[..], &buf[..]);
+        drop(s2);
+
+        thread.join().unwrap();
+    }
+
+    // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+    // when passed zero Durations
+    #[test]
+    fn test_unix_datagram_timeout_zero_duration() {
+        let dir = tmpdir();
+        let path = dir.path().join("sock");
+
+        let datagram = or_panic!(UnixDatagram::bind(&path));
+
+        let result = datagram.set_write_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+        let result = datagram.set_read_timeout(Some(Duration::new(0, 0)));
+        let err = result.unwrap_err();
+        assert_eq!(err.kind(), ErrorKind::InvalidInput);
+    }
+
+    #[test]
+    fn abstract_namespace_not_allowed() {
+        assert!(UnixStream::connect("\0asdf").is_err());
+    }
+}
diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/vxworks/ext/process.rs
index e981cb93d44..4de72fa1816 100644
--- a/src/libstd/sys/redox/ext/process.rs
+++ b/src/libstd/sys/vxworks/ext/process.rs
@@ -1,14 +1,14 @@
-//! Redox-specific extensions to primitives in the `std::process` module.
+//! Unix-specific extensions to primitives in the `std::process` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::io;
-use crate::os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
+use crate::sys::vxworks::ext::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
 use crate::process;
 use crate::sys;
 use crate::sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
 
-/// Redox-specific extensions to the [`process::Command`] builder,
+/// Unix-specific extensions to the [`process::Command`] builder.
 ///
 /// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -17,12 +17,12 @@ pub trait CommandExt {
     /// `setuid` call in the child process. Failure in the `setuid`
     /// call will cause the spawn to fail.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn uid(&mut self, id: u32) -> &mut process::Command;
+    fn uid(&mut self, id: u16) -> &mut process::Command;
 
     /// Similar to `uid`, but sets the group ID of the child process. This has
     /// the same semantics as the `uid` field.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn gid(&mut self, id: u32) -> &mut process::Command;
+    fn gid(&mut self, id: u16) -> &mut process::Command;
 
     /// Schedules a closure to be run just before the `exec` function is
     /// invoked.
@@ -79,10 +79,20 @@ pub trait CommandExt {
     /// an error indicating why the exec (or another part of the setup of the
     /// `Command`) failed.
     ///
+    /// `exec` not returning has the same implications as calling
+    /// [`process::exit`] – no destructors on the current stack or any other
+    /// thread’s stack will be run. Therefore, it is recommended to only call
+    /// `exec` at a point where it is fine to not run any destructors. Note,
+    /// that the `execvp` syscall independently guarantees that all memory is
+    /// freed and all file descriptors with the `CLOEXEC` option (set by default
+    /// on all file descriptors opened by the standard library) are closed.
+    ///
     /// This function, unlike `spawn`, will **not** `fork` the process to create
     /// a new child. Like spawn, however, the default behavior for the stdio
     /// descriptors will be to inherited from the current process.
     ///
+    /// [`process::exit`]: ../../../process/fn.exit.html
+    ///
     /// # Notes
     ///
     /// The process may be in a "broken state" if this function returns in
@@ -97,12 +107,12 @@ pub trait CommandExt {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl CommandExt for process::Command {
-    fn uid(&mut self, id: u32) -> &mut process::Command {
+    fn uid(&mut self, id: u16) -> &mut process::Command {
         self.as_inner_mut().uid(id);
         self
     }
 
-    fn gid(&mut self, id: u32) -> &mut process::Command {
+    fn gid(&mut self, id: u16) -> &mut process::Command {
         self.as_inner_mut().gid(id);
         self
     }
@@ -119,7 +129,7 @@ impl CommandExt for process::Command {
     }
 }
 
-/// Redox-specific extensions to [`process::ExitStatus`].
+/// Unix-specific extensions to [`process::ExitStatus`].
 ///
 /// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -195,3 +205,9 @@ impl IntoRawFd for process::ChildStderr {
         self.into_inner().into_fd().into_raw()
     }
 }
+
+/// Returns the OS-assigned process identifier associated with this process's parent.
+#[stable(feature = "unix_ppid", since = "1.27.0")]
+pub fn parent_id() -> u32 {
+    crate::sys::os::getppid()
+}
diff --git a/src/libstd/sys/vxworks/ext/raw.rs b/src/libstd/sys/vxworks/ext/raw.rs
new file mode 100644
index 00000000000..1f134f4e2d1
--- /dev/null
+++ b/src/libstd/sys/vxworks/ext/raw.rs
@@ -0,0 +1,5 @@
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+#[doc(inline)]
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub use crate::sys::platform::raw::pthread_t;
diff --git a/src/libstd/sys/vxworks/fast_thread_local.rs b/src/libstd/sys/vxworks/fast_thread_local.rs
new file mode 100644
index 00000000000..f5a2e263d25
--- /dev/null
+++ b/src/libstd/sys/vxworks/fast_thread_local.rs
@@ -0,0 +1,36 @@
+#![cfg(target_thread_local)]
+#![unstable(feature = "thread_local_internals", issue = "0")]
+
+// Since what appears to be glibc 2.18 this symbol has been shipped which
+// GCC and clang both use to invoke destructors in thread_local globals, so
+// let's do the same!
+//
+// Note, however, that we run on lots older linuxes, as well as cross
+// compiling from a newer linux to an older linux, so we also have a
+// fallback implementation to use as well.
+//
+// Due to rust-lang/rust#18804, make sure this is not generic!
+pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+    use crate::mem;
+    use crate::sys_common::thread_local::register_dtor_fallback;
+
+    extern {
+        #[linkage = "extern_weak"]
+        static __dso_handle: *mut u8;
+        #[linkage = "extern_weak"]
+        static __cxa_thread_atexit_impl: *const libc::c_void;
+    }
+    if !__cxa_thread_atexit_impl.is_null() {
+        type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8),
+                                  arg: *mut u8,
+                                  dso_handle: *mut u8) -> libc::c_int;
+        mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)
+            (dtor, t, &__dso_handle as *const _ as *mut _);
+        return
+    }
+    register_dtor_fallback(t, dtor);
+}
+
+pub fn requires_move_before_drop() -> bool {
+    false
+}
diff --git a/src/libstd/sys/vxworks/fd.rs b/src/libstd/sys/vxworks/fd.rs
new file mode 100644
index 00000000000..db2865d2529
--- /dev/null
+++ b/src/libstd/sys/vxworks/fd.rs
@@ -0,0 +1,188 @@
+#![unstable(reason = "not public", issue = "0", feature = "fd")]
+
+use crate::cmp;
+use crate::io::{self, Read, Initializer, IoSlice, IoSliceMut};
+use crate::mem;
+use crate::sys::cvt;
+use crate::sys_common::AsInner;
+
+use libc::{self, c_int, c_void, ssize_t};
+
+#[derive(Debug)]
+pub struct FileDesc {
+    fd: c_int,
+}
+
+fn max_len() -> usize {
+    // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
+    // with the man page quoting that if the count of bytes to read is
+    // greater than `SSIZE_MAX` the result is "unspecified".
+    <ssize_t>::max_value() as usize
+}
+
+impl FileDesc {
+    pub fn new(fd: c_int) -> FileDesc {
+        FileDesc { fd: fd }
+    }
+
+    pub fn raw(&self) -> c_int { self.fd }
+
+    /// Extracts the actual filedescriptor without closing it.
+    pub fn into_raw(self) -> c_int {
+        let fd = self.fd;
+        mem::forget(self);
+        fd
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::read(self.fd,
+                       buf.as_mut_ptr() as *mut c_void,
+                       cmp::min(buf.len(), max_len()))
+        })?;
+        Ok(ret as usize)
+    }
+
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::readv(self.fd,
+                        bufs.as_ptr() as *const libc::iovec,
+                        cmp::min(bufs.len(), c_int::max_value() as usize) as c_int)
+        })?;
+        Ok(ret as usize)
+    }
+
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        let mut me = self;
+        (&mut me).read_to_end(buf)
+    }
+
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        unsafe fn cvt_pread(fd: c_int, buf: *mut c_void, count: usize, offset: i64)
+            -> io::Result<isize>
+        {
+            use libc::pread;
+            cvt(pread(fd, buf, count, offset))
+        }
+
+        unsafe {
+            cvt_pread(self.fd,
+                buf.as_mut_ptr() as *mut c_void,
+                cmp::min(buf.len(), max_len()),
+                offset as i64)
+            .map(|n| n as usize)
+        }
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::write(self.fd,
+            buf.as_ptr() as *const c_void,
+            cmp::min(buf.len(), max_len()))
+        })?;
+        Ok(ret as usize)
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::writev(self.fd,
+                         bufs.as_ptr() as *const libc::iovec,
+                         cmp::min(bufs.len(), c_int::max_value() as usize) as c_int)
+        })?;
+        Ok(ret as usize)
+    }
+
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        unsafe fn cvt_pwrite(fd: c_int, buf: *const c_void, count: usize, offset: i64)
+            -> io::Result<isize>
+        {
+            use libc::pwrite;
+            cvt(pwrite(fd, buf, count, offset))
+        }
+
+        unsafe {
+            cvt_pwrite(self.fd,
+                buf.as_ptr() as *const c_void,
+                cmp::min(buf.len(), max_len()),
+                offset as i64)
+                .map(|n| n as usize)
+        }
+    }
+
+    pub fn get_cloexec(&self) -> io::Result<bool> {
+        unsafe {
+            Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0)
+        }
+    }
+
+    pub fn set_cloexec(&self) -> io::Result<()> {
+        unsafe {
+            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
+            let new = previous | libc::FD_CLOEXEC;
+            if new != previous {
+                cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
+            }
+            Ok(())
+        }
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        unsafe {
+            let v = nonblocking as c_int;
+            cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
+            Ok(())
+        }
+    }
+
+    // refer to pxPipeDrv library documentation.
+    // VxWorks uses fcntl to set O_NONBLOCK to the pipes
+    pub fn set_nonblocking_pipe(&self, nonblocking: bool) -> io::Result<()> {
+        unsafe {
+            let mut flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?;
+            flags = if nonblocking {
+                flags | libc::O_NONBLOCK
+            } else {
+                flags & !libc::O_NONBLOCK
+            };
+            cvt(libc::fcntl(self.fd, libc::F_SETFL, flags))?;
+            Ok(())
+        }
+    }
+
+
+    pub fn duplicate(&self) -> io::Result<FileDesc> {
+        let fd = self.raw();
+        match cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, 0) }) {
+            Ok(newfd) => {
+                Ok(FileDesc::new(newfd))
+            }
+            Err(e) => return Err(e),
+        }
+    }
+}
+
+impl<'a> Read for &'a FileDesc {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        (**self).read(buf)
+    }
+
+    #[inline]
+    unsafe fn initializer(&self) -> Initializer {
+        Initializer::nop()
+    }
+}
+
+impl AsInner<c_int> for FileDesc {
+    fn as_inner(&self) -> &c_int { &self.fd }
+}
+
+impl Drop for FileDesc {
+    fn drop(&mut self) {
+        // Note that errors are ignored when closing a file descriptor. The
+        // reason for this is that if an error occurs we don't actually know if
+        // the file descriptor was closed or not, and if we retried (for
+        // something like EINTR), we might close another valid file descriptor
+        // (opened after we closed ours.
+        let _ = unsafe { libc::close(self.fd) };
+    }
+}
diff --git a/src/libstd/sys/vxworks/fs.rs b/src/libstd/sys/vxworks/fs.rs
new file mode 100644
index 00000000000..d537d2258fd
--- /dev/null
+++ b/src/libstd/sys/vxworks/fs.rs
@@ -0,0 +1,575 @@
+// copies from linuxx
+use crate::ffi::{CString, CStr, OsString, OsStr};
+use crate::sys::vxworks::ext::ffi::OsStrExt;
+use crate::fmt;
+use crate::io::{self, Error, ErrorKind, SeekFrom, IoSlice, IoSliceMut};
+use crate::mem;
+use crate::path::{Path, PathBuf};
+use crate::ptr;
+use crate::sync::Arc;
+use crate::sys::fd::FileDesc;
+use crate::sys::time::SystemTime;
+use crate::sys::{cvt, cvt_r};
+use crate::sys_common::{AsInner, FromInner};
+use libc::{self, c_int, mode_t, stat64, off_t};
+use libc::{ftruncate, lseek, dirent, readdir_r as readdir64_r, open};
+use crate::sys::vxworks::ext::ffi::OsStringExt;
+pub struct File(FileDesc);
+
+#[derive(Clone)]
+pub struct FileAttr {
+    stat: stat64,
+}
+
+// all DirEntry's will have a reference to this struct
+struct InnerReadDir {
+    dirp: Dir,
+    root: PathBuf,
+}
+
+#[derive(Clone)]
+pub struct ReadDir {
+    inner: Arc<InnerReadDir>,
+    end_of_stream: bool,
+}
+
+struct Dir(*mut libc::DIR);
+
+unsafe impl Send for Dir {}
+unsafe impl Sync for Dir {}
+
+pub struct DirEntry {
+    entry: dirent,
+    dir: ReadDir,
+}
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions {
+    // generic
+    read: bool,
+    write: bool,
+    append: bool,
+    truncate: bool,
+    create: bool,
+    create_new: bool,
+    // system-specific
+    custom_flags: i32,
+    mode: mode_t,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FilePermissions { mode: mode_t }
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct FileType { mode: mode_t }
+
+#[derive(Debug)]
+pub struct DirBuilder { mode: mode_t }
+
+impl FileAttr {
+    pub fn size(&self) -> u64 { self.stat.st_size as u64 }
+    pub fn perm(&self) -> FilePermissions {
+        FilePermissions { mode: (self.stat.st_mode as mode_t) }
+    }
+
+    pub fn file_type(&self) -> FileType {
+        FileType { mode: self.stat.st_mode as mode_t }
+    }
+
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(libc::timespec {
+            tv_sec: self.stat.st_mtime as libc::time_t,
+            tv_nsec: 0, // hack 2.0;
+        }))
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(libc::timespec {
+        tv_sec: self.stat.st_atime as libc::time_t,
+        tv_nsec: 0, // hack - a proper fix would be better
+        }))
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        Err(io::Error::new(io::ErrorKind::Other,
+                           "creation time is not available on this platform currently"))
+    }
+
+}
+
+impl AsInner<stat64> for FileAttr {
+    fn as_inner(&self) -> &stat64 { &self.stat }
+}
+
+impl FilePermissions {
+    pub fn readonly(&self) -> bool {
+        // check if any class (owner, group, others) has write permission
+        self.mode & 0o222 == 0
+    }
+
+    pub fn set_readonly(&mut self, readonly: bool) {
+        if readonly {
+            // remove write permission for all classes; equivalent to `chmod a-w <file>`
+            self.mode &= !0o222;
+        } else {
+            // add write permission for all classes; equivalent to `chmod a+w <file>`
+            self.mode |= 0o222;
+        }
+    }
+    pub fn mode(&self) -> u32 { self.mode as u32 }
+}
+
+impl FileType {
+    pub fn is_dir(&self) -> bool { self.is(libc::S_IFDIR) }
+    pub fn is_file(&self) -> bool { self.is(libc::S_IFREG) }
+    pub fn is_symlink(&self) -> bool { self.is(libc::S_IFLNK) }
+
+    pub fn is(&self, mode: mode_t) -> bool { self.mode & libc::S_IFMT == mode }
+}
+
+impl FromInner<u32> for FilePermissions {
+    fn from_inner(mode: u32) -> FilePermissions {
+        FilePermissions { mode: mode as mode_t }
+    }
+}
+
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
+        // Thus the result will be e g 'ReadDir("/home")'
+        fmt::Debug::fmt(&*self.inner.root, f)
+    }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        if self.end_of_stream {
+            return None;
+        }
+
+        unsafe {
+            let mut ret = DirEntry {
+                entry: mem::zeroed(),
+                dir: self.clone(),
+            };
+            let mut entry_ptr = ptr::null_mut();
+            loop {
+                if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                    if entry_ptr.is_null() {
+                        // We encountered an error (which will be returned in this iteration), but
+                        // we also reached the end of the directory stream. The `end_of_stream`
+                        // flag is enabled to make sure that we return `None` in the next iteration
+                        // (instead of looping forever)
+                        self.end_of_stream = true;
+                    }
+                    return Some(Err(Error::last_os_error()))
+                }
+                if entry_ptr.is_null() {
+                    return None
+                }
+                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
+                    return Some(Ok(ret))
+                }
+            }
+        }
+    }
+}
+
+impl Drop for Dir {
+    fn drop(&mut self) {
+        let r = unsafe { libc::closedir(self.0) };
+        debug_assert_eq!(r, 0);
+    }
+}
+
+impl DirEntry {
+    pub fn path(&self) -> PathBuf {
+            use crate::sys::vxworks::ext::ffi::OsStrExt;
+            self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes()))
+    }
+
+    pub fn file_name(&self) -> OsString {
+        OsStr::from_bytes(self.name_bytes()).to_os_string()
+    }
+
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        lstat(&self.path())
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        lstat(&self.path()).map(|m| m.file_type())
+
+    }
+
+    pub fn ino(&self) -> u64 {
+        self.entry.d_ino as u64
+    }
+
+    fn name_bytes(&self) -> &[u8] {
+        unsafe {
+            //&*self.name
+            CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
+        }
+    }
+}
+
+impl OpenOptions {
+    pub fn new() -> OpenOptions {
+        OpenOptions {
+            // generic
+            read: false,
+            write: false,
+            append: false,
+            truncate: false,
+            create: false,
+            create_new: false,
+            // system-specific
+            custom_flags: 0,
+            mode: 0o666,
+        }
+    }
+
+    pub fn read(&mut self, read: bool) { self.read = read; }
+    pub fn write(&mut self, write: bool) { self.write = write; }
+    pub fn append(&mut self, append: bool) { self.append = append; }
+    pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
+    pub fn create(&mut self, create: bool) { self.create = create; }
+    pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
+    pub fn mode(&mut self, mode: u32) { self.mode = mode as mode_t; }
+
+    fn get_access_mode(&self) -> io::Result<c_int> {
+        match (self.read, self.write, self.append) {
+            (true,  false, false) => Ok(libc::O_RDONLY),
+            (false, true,  false) => Ok(libc::O_WRONLY),
+            (true,  true,  false) => Ok(libc::O_RDWR),
+            (false, _,     true)  => Ok(libc::O_WRONLY | libc::O_APPEND),
+            (true,  _,     true)  => Ok(libc::O_RDWR | libc::O_APPEND),
+            (false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)),
+        }
+    }
+
+    fn get_creation_mode(&self) -> io::Result<c_int> {
+        match (self.write, self.append) {
+            (true, false) => {}
+            (false, false) =>
+                if self.truncate || self.create || self.create_new {
+                    return Err(Error::from_raw_os_error(libc::EINVAL));
+                },
+            (_, true) =>
+                if self.truncate && !self.create_new {
+                    return Err(Error::from_raw_os_error(libc::EINVAL));
+                },
+        }
+
+        Ok(match (self.create, self.truncate, self.create_new) {
+                (false, false, false) => 0,
+                (true,  false, false) => libc::O_CREAT,
+                (false, true,  false) => libc::O_TRUNC,
+                (true,  true,  false) => libc::O_CREAT | libc::O_TRUNC,
+                (_,      _,    true)  => libc::O_CREAT | libc::O_EXCL,
+           })
+    }
+}
+
+impl File {
+    pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
+        let path = cstr(path)?;
+        File::open_c(&path, opts)
+    }
+
+    pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
+        let flags = libc::O_CLOEXEC |
+                opts.get_access_mode()? |
+                opts.get_creation_mode()? |
+                (opts.custom_flags as c_int & !libc::O_ACCMODE);
+        let fd = cvt_r(|| unsafe {
+            open(path.as_ptr(), flags, opts.mode as c_int)
+        })?;
+        Ok(File(FileDesc::new(fd)))
+    }
+
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        let mut stat: stat64 = unsafe { mem::zeroed() };
+        cvt(unsafe {
+            ::libc::fstat(self.0.raw(), &mut stat)
+        })?;
+        Ok(FileAttr { stat: stat })
+    }
+
+    pub fn fsync(&self) -> io::Result<()> {
+        cvt_r(|| unsafe { libc::fsync(self.0.raw()) })?;
+        Ok(())
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        cvt_r(|| unsafe { os_datasync(self.0.raw()) })?;
+        return Ok(());
+        unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) } //not supported
+    }
+
+    pub fn truncate(&self, size: u64) -> io::Result<()> {
+        return cvt_r(|| unsafe {
+            ftruncate(self.0.raw(), size as off_t)
+        }).map(|_| ());
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
+    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+        self.0.read_at(buf, offset)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
+    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+        self.0.write_at(buf, offset)
+    }
+
+    pub fn flush(&self) -> io::Result<()> { Ok(()) }
+
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        let (whence, pos) = match pos {
+            // Casting to `i64` is fine, too large values will end up as
+            // negative which will cause an error in `"lseek64"`.
+            SeekFrom::Start(off) => (libc::SEEK_SET, off as i64),
+            SeekFrom::End(off) => (libc::SEEK_END, off),
+            SeekFrom::Current(off) => (libc::SEEK_CUR, off),
+        };
+        let n = cvt(unsafe { lseek(self.0.raw(), pos, whence) })?;
+        Ok(n as u64)
+    }
+
+    pub fn duplicate(&self) -> io::Result<File> {
+        self.0.duplicate().map(File)
+    }
+
+    pub fn fd(&self) -> &FileDesc { &self.0 }
+
+    pub fn into_fd(self) -> FileDesc { self.0 }
+
+    pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
+        cvt_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?;
+        Ok(())
+    }
+
+    pub fn diverge(&self) -> ! {
+        panic!()
+    }
+}
+
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder { mode: 0o777 }
+    }
+
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        let p = cstr(p)?;
+        cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) })?;
+        Ok(())
+    }
+
+    pub fn set_mode(&mut self, mode: u32) {
+        self.mode = mode as mode_t;
+    }
+}
+
+fn cstr(path: &Path) -> io::Result<CString> {
+    use crate::sys::vxworks::ext::ffi::OsStrExt;
+    Ok(CString::new(path.as_os_str().as_bytes())?)
+}
+
+impl FromInner<c_int> for File {
+    fn from_inner(fd: c_int) -> File {
+        File(FileDesc::new(fd))
+    }
+}
+
+impl fmt::Debug for File {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fn get_path(_fd: c_int) -> Option<PathBuf> {
+            // FIXME(#:(): implement this for VxWorks
+            None
+        }
+        fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
+            // FIXME(#:(): implement this for VxWorks
+            None
+        }
+
+        let fd = self.0.raw();
+        let mut b = f.debug_struct("File");
+        b.field("fd", &fd);
+        if let Some(path) = get_path(fd) {
+            b.field("path", &path);
+        }
+        if let Some((read, write)) = get_mode(fd) {
+            b.field("read", &read).field("write", &write);
+        }
+        b.finish()
+    }
+}
+
+pub fn readdir(p: &Path) -> io::Result<ReadDir> {
+    let root = p.to_path_buf();
+    let p = cstr(p)?;
+    unsafe {
+        let ptr = libc::opendir(p.as_ptr());
+        if ptr.is_null() {
+            Err(Error::last_os_error())
+        } else {
+            let inner = InnerReadDir { dirp: Dir(ptr), root };
+            Ok(ReadDir{
+                inner: Arc::new(inner),
+                end_of_stream: false,
+            })
+        }
+    }
+}
+
+pub fn unlink(p: &Path) -> io::Result<()> {
+    let p = cstr(p)?;
+    cvt(unsafe { libc::unlink(p.as_ptr()) })?;
+    Ok(())
+}
+
+pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
+    let old = cstr(old)?;
+    let new = cstr(new)?;
+    cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) })?;
+    Ok(())
+}
+
+pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
+    let p = cstr(p)?;
+    cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) })?;
+    Ok(())
+}
+
+pub fn rmdir(p: &Path) -> io::Result<()> {
+    let p = cstr(p)?;
+    cvt(unsafe { libc::rmdir(p.as_ptr()) })?;
+    Ok(())
+}
+
+pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    let filetype = lstat(path)?.file_type();
+    if filetype.is_symlink() {
+        unlink(path)
+    } else {
+        remove_dir_all_recursive(path)
+    }
+}
+
+fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
+    for child in readdir(path)? {
+        let child = child?;
+        if child.file_type()?.is_dir() {
+            remove_dir_all_recursive(&child.path())?;
+        } else {
+            unlink(&child.path())?;
+        }
+    }
+    rmdir(path)
+}
+
+pub fn readlink(p: &Path) -> io::Result<PathBuf> {
+    let c_path = cstr(p)?;
+    let p = c_path.as_ptr();
+
+    let mut buf = Vec::with_capacity(256);
+
+    loop {
+        let buf_read = cvt(unsafe {
+            libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity())
+        })? as usize;
+
+        unsafe { buf.set_len(buf_read); }
+
+        if buf_read != buf.capacity() {
+            buf.shrink_to_fit();
+
+            return Ok(PathBuf::from(OsString::from_vec(buf)));
+        }
+
+        // Trigger the internal buffer resizing logic of `Vec` by requiring
+        // more space than the current capacity. The length is guaranteed to be
+        // the same as the capacity due to the if statement above.
+        buf.reserve(1);
+    }
+}
+
+pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
+    let src = cstr(src)?;
+    let dst = cstr(dst)?;
+    cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })?;
+    Ok(())
+}
+
+pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
+    let src = cstr(src)?;
+    let dst = cstr(dst)?;
+    cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?;
+    Ok(())
+}
+
+pub fn stat(p: &Path) -> io::Result<FileAttr> {
+    let p = cstr(p)?;
+    let mut stat: stat64 = unsafe { mem::zeroed() };
+    cvt(unsafe {
+        libc::lstat(p.as_ptr(), &mut stat as *mut _ as *mut _)
+    })?;
+    Ok(FileAttr { stat })
+}
+
+pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+    let p = cstr(p)?;
+    let mut stat: stat64 = unsafe { mem::zeroed() };
+    cvt(unsafe {
+        ::libc::lstat(p.as_ptr(), &mut stat as *mut _ as *mut _)
+    })?;
+    Ok(FileAttr { stat })
+}
+
+pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
+    use crate::sys::vxworks::ext::ffi::OsStrExt;
+    let path = CString::new(p.as_os_str().as_bytes())?;
+    let buf;
+    unsafe {
+        let r = libc::realpath(path.as_ptr(), ptr::null_mut());
+        if r.is_null() {
+            return Err(io::Error::last_os_error())
+        }
+        buf = CStr::from_ptr(r).to_bytes().to_vec();
+        libc::free(r as *mut _);
+    }
+    Ok(PathBuf::from(OsString::from_vec(buf)))
+}
+
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    use crate::fs::File;
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::InvalidInput,
+                              "the source path is not an existing regular file"))
+    }
+
+    let mut reader = File::open(from)?;
+    let mut writer = File::create(to)?;
+    let perm = reader.metadata()?.permissions();
+
+    let ret = io::copy(&mut reader, &mut writer)?;
+    writer.set_permissions(perm)?;
+    Ok(ret)
+}
diff --git a/src/libstd/sys/vxworks/io.rs b/src/libstd/sys/vxworks/io.rs
new file mode 100644
index 00000000000..8cd11cbf5df
--- /dev/null
+++ b/src/libstd/sys/vxworks/io.rs
@@ -0,0 +1,86 @@
+use crate::marker::PhantomData;
+use crate::slice;
+
+use libc::{iovec, c_void};
+
+#[repr(transparent)]
+pub struct IoSlice<'a> {
+    vec: iovec,
+    _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice {
+            vec: iovec {
+                iov_base: buf.as_ptr() as *mut u8 as *mut c_void,
+                iov_len: buf.len()
+            },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len)
+        }
+    }
+}
+
+pub struct IoSliceMut<'a> {
+    vec: iovec,
+    _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut {
+            vec: iovec {
+                iov_base: buf.as_mut_ptr() as *mut c_void,
+                iov_len: buf.len()
+            },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSliceMut beyond its length");
+        }
+
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len)
+        }
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [u8] {
+        unsafe {
+            slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len)
+        }
+    }
+}
diff --git a/src/libstd/sys/vxworks/memchr.rs b/src/libstd/sys/vxworks/memchr.rs
new file mode 100644
index 00000000000..b5b4e6d9c13
--- /dev/null
+++ b/src/libstd/sys/vxworks/memchr.rs
@@ -0,0 +1,24 @@
+// Original implementation taken from rust-memchr.
+// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
+
+pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+    let p = unsafe {
+        libc::memchr(
+            haystack.as_ptr() as *const libc::c_void,
+            needle as libc::c_int,
+            haystack.len())
+    };
+    if p.is_null() {
+        None
+    } else {
+        Some(p as usize - (haystack.as_ptr() as usize))
+    }
+}
+
+pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        core::slice::memchr::memrchr(needle, haystack)
+    }
+
+    memrchr_specific(needle, haystack)
+}
diff --git a/src/libstd/sys/vxworks/mod.rs b/src/libstd/sys/vxworks/mod.rs
new file mode 100644
index 00000000000..1eff4fbcd83
--- /dev/null
+++ b/src/libstd/sys/vxworks/mod.rs
@@ -0,0 +1,125 @@
+#![allow(dead_code)]
+#![allow(missing_docs, nonstandard_style)]
+
+use crate::io::ErrorKind;
+
+pub use crate::os::vxworks as platform;
+pub use self::rand::hashmap_random_keys;
+pub use libc::strlen;
+
+pub mod alloc;
+pub mod args;
+pub mod cmath;
+pub mod condvar;
+pub mod env;
+pub mod ext;
+pub mod fast_thread_local;
+pub mod fd;
+pub mod fs;
+pub mod memchr;
+pub mod io;
+pub mod mutex;
+pub mod net;
+pub mod os;
+pub mod path;
+pub mod pipe;
+pub mod process;
+pub mod rand;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod thread;
+pub mod thread_local;
+pub mod time;
+pub mod stdio;
+
+pub use crate::sys_common::os_str_bytes as os_str;
+
+#[cfg(not(test))]
+pub fn init() {
+    // By default, some platforms will send a *signal* when an EPIPE error
+    // would otherwise be delivered. This runtime doesn't install a SIGPIPE
+    // handler, causing it to kill the program, which isn't exactly what we
+    // want!
+    //
+    // Hence, we set SIGPIPE to ignore when the program starts up in order
+    // to prevent this problem.
+    unsafe {
+        reset_sigpipe();
+    }
+
+    unsafe fn reset_sigpipe() { }
+}
+
+pub use libc::signal;
+
+pub fn decode_error_kind(errno: i32) -> ErrorKind {
+    match errno as libc::c_int {
+        libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
+        libc::ECONNRESET => ErrorKind::ConnectionReset,
+        libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
+        libc::EPIPE => ErrorKind::BrokenPipe,
+        libc::ENOTCONN => ErrorKind::NotConnected,
+        libc::ECONNABORTED => ErrorKind::ConnectionAborted,
+        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
+        libc::EADDRINUSE => ErrorKind::AddrInUse,
+        libc::ENOENT => ErrorKind::NotFound,
+        libc::EINTR => ErrorKind::Interrupted,
+        libc::EINVAL => ErrorKind::InvalidInput,
+        libc::ETIMEDOUT => ErrorKind::TimedOut,
+        libc::EEXIST => ErrorKind::AlreadyExists,
+
+        // These two constants can have the same value on some systems,
+        // but different values on others, so we can't use a match
+        // clause
+        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
+            ErrorKind::WouldBlock,
+
+        _ => ErrorKind::Other,
+    }
+}
+
+#[doc(hidden)]
+pub trait IsMinusOne {
+    fn is_minus_one(&self) -> bool;
+}
+
+macro_rules! impl_is_minus_one {
+    ($($t:ident)*) => ($(impl IsMinusOne for $t {
+        fn is_minus_one(&self) -> bool {
+            *self == -1
+        }
+    })*)
+}
+
+impl_is_minus_one! { i8 i16 i32 i64 isize }
+
+pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
+    if t.is_minus_one() {
+        Err(crate::io::Error::last_os_error())
+    } else {
+        Ok(t)
+    }
+}
+
+pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
+    where T: IsMinusOne,
+          F: FnMut() -> T
+{
+    loop {
+        match cvt(f()) {
+            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+            other => return other,
+        }
+    }
+}
+
+// On Unix-like platforms, libc::abort will unregister signal handlers
+// including the SIGABRT handler, preventing the abort from being blocked, and
+// fclose streams, with the side effect of flushing them so libc bufferred
+// output will be printed.  Additionally the shell will generally print a more
+// understandable error message like "Abort trap" rather than "Illegal
+// instruction" that intrinsics::abort would cause, as intrinsics::abort is
+// implemented as an illegal instruction.
+pub unsafe fn abort_internal() -> ! {
+    libc::abort()
+}
diff --git a/src/libstd/sys/vxworks/mutex.rs b/src/libstd/sys/vxworks/mutex.rs
new file mode 100644
index 00000000000..b43af8fdcaa
--- /dev/null
+++ b/src/libstd/sys/vxworks/mutex.rs
@@ -0,0 +1,127 @@
+use crate::cell::UnsafeCell;
+use crate::mem::MaybeUninit;
+
+pub struct Mutex { inner: UnsafeCell<libc::pthread_mutex_t> }
+
+#[inline]
+pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t {
+    m.inner.get()
+}
+
+unsafe impl Send for Mutex {}
+unsafe impl Sync for Mutex {}
+
+#[allow(dead_code)] // sys isn't exported yet
+impl Mutex {
+    pub const fn new() -> Mutex {
+        // Might be moved to a different address, so it is better to avoid
+        // initialization of potentially opaque OS data before it landed.
+        // Be very careful using this newly constructed `Mutex`, reentrant
+        // locking is undefined behavior until `init` is called!
+        Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
+    }
+    #[inline]
+    pub unsafe fn init(&mut self) {
+        // Issue #33770
+        //
+        // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have
+        // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you
+        // try to re-lock it from the same thread when you already hold a lock.
+        //
+        // In practice, glibc takes advantage of this undefined behavior to
+        // implement hardware lock elision, which uses hardware transactional
+        // memory to avoid acquiring the lock. While a transaction is in
+        // progress, the lock appears to be unlocked. This isn't a problem for
+        // other threads since the transactional memory will abort if a conflict
+        // is detected, however no abort is generated if re-locking from the
+        // same thread.
+        //
+        // Since locking the same mutex twice will result in two aliasing &mut
+        // references, we instead create the mutex with type
+        // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
+        // re-lock it from the same thread, thus avoiding undefined behavior.
+        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
+        let r = libc::pthread_mutexattr_init(attr.as_mut_ptr());
+        debug_assert_eq!(r, 0);
+        let r = libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL);
+        debug_assert_eq!(r, 0);
+        let r = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
+        debug_assert_eq!(r, 0);
+        let r = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn lock(&self) {
+        let r = libc::pthread_mutex_lock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        let r = libc::pthread_mutex_unlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        libc::pthread_mutex_trylock(self.inner.get()) == 0
+    }
+    #[inline]
+    #[cfg(not(target_os = "dragonfly"))]
+    pub unsafe fn destroy(&self) {
+        let r = libc::pthread_mutex_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    #[cfg(target_os = "dragonfly")]
+    pub unsafe fn destroy(&self) {
+        let r = libc::pthread_mutex_destroy(self.inner.get());
+        // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
+        // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
+        // Once it is used (locked/unlocked) or pthread_mutex_init() is called,
+        // this behaviour no longer occurs.
+        debug_assert!(r == 0 || r == libc::EINVAL);
+    }
+}
+
+pub struct ReentrantMutex { inner: UnsafeCell<libc::pthread_mutex_t> }
+
+unsafe impl Send for ReentrantMutex {}
+unsafe impl Sync for ReentrantMutex {}
+
+impl ReentrantMutex {
+    pub unsafe fn uninitialized() -> ReentrantMutex {
+        ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
+    }
+
+    pub unsafe fn init(&mut self) {
+        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
+        let result = libc::pthread_mutexattr_init(attr.as_mut_ptr());
+        debug_assert_eq!(result, 0);
+        let result = libc::pthread_mutexattr_settype(attr.as_mut_ptr(),
+                                                    libc::PTHREAD_MUTEX_RECURSIVE);
+        debug_assert_eq!(result, 0);
+        let result = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
+        debug_assert_eq!(result, 0);
+        let result = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
+        debug_assert_eq!(result, 0);
+    }
+
+    pub unsafe fn lock(&self) {
+        let result = libc::pthread_mutex_lock(self.inner.get());
+        debug_assert_eq!(result, 0);
+    }
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        libc::pthread_mutex_trylock(self.inner.get()) == 0
+    }
+
+    pub unsafe fn unlock(&self) {
+        let result = libc::pthread_mutex_unlock(self.inner.get());
+        debug_assert_eq!(result, 0);
+    }
+
+    pub unsafe fn destroy(&self) {
+        let result = libc::pthread_mutex_destroy(self.inner.get());
+        debug_assert_eq!(result, 0);
+    }
+}
diff --git a/src/libstd/sys/vxworks/net.rs b/src/libstd/sys/vxworks/net.rs
new file mode 100644
index 00000000000..56962e11dcf
--- /dev/null
+++ b/src/libstd/sys/vxworks/net.rs
@@ -0,0 +1,357 @@
+use crate::ffi::CStr;
+use crate::io;
+use crate::io::{IoSlice, IoSliceMut};
+use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
+use crate::mem;
+use crate::net::{SocketAddr, Shutdown};
+use crate::str;
+use crate::sys::fd::FileDesc;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
+use crate::time::{Duration, Instant};
+use crate::cmp;
+
+pub use crate::sys::{cvt, cvt_r};
+
+#[allow(unused_extern_crates)]
+pub extern crate libc as netc;
+
+pub type wrlen_t = size_t;
+
+
+const SOCK_CLOEXEC: c_int = 0;
+const SO_NOSIGPIPE: c_int = 0;
+
+pub struct Socket(FileDesc);
+
+pub fn init() {}
+
+pub fn cvt_gai(err: c_int) -> io::Result<()> {
+    if err == 0 {
+        return Ok(())
+    }
+
+    // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
+    on_resolver_failure();
+
+    if err == EAI_SYSTEM {
+        return Err(io::Error::last_os_error())
+    }
+
+    let detail = unsafe {
+        str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap()
+            .to_owned()
+    };
+    Err(io::Error::new(io::ErrorKind::Other,
+                       &format!("failed to lookup address information: {}",
+                                detail)[..]))
+}
+
+impl Socket {
+    pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
+        let fam = match *addr {
+            SocketAddr::V4(..) => libc::AF_INET,
+            SocketAddr::V6(..) => libc::AF_INET6,
+        };
+        Socket::new_raw(fam, ty)
+    }
+
+    pub fn new_raw(fam: c_int, ty: c_int) -> io::Result<Socket> {
+        unsafe {
+            let fd = cvt(libc::socket(fam, ty, 0))?;
+            let fd = FileDesc::new(fd);
+            fd.set_cloexec()?;
+            let socket = Socket(fd);
+            Ok(socket)
+        }
+    }
+
+    pub fn new_pair(_fam: c_int, _ty: c_int) -> io::Result<(Socket, Socket)> {
+            unimplemented!();
+    }
+
+    pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
+        self.set_nonblocking(true)?;
+        let r = unsafe {
+            let (addrp, len) = addr.into_inner();
+            cvt(libc::connect(self.0.raw(), addrp, len))
+        };
+        self.set_nonblocking(false)?;
+
+        match r {
+            Ok(_) => return Ok(()),
+            // there's no ErrorKind for EINPROGRESS :(
+            Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
+            Err(e) => return Err(e),
+        }
+
+        let mut pollfd = libc::pollfd {
+            fd: self.0.raw(),
+            events: libc::POLLOUT,
+            revents: 0,
+        };
+
+        if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                      "cannot set a 0 duration timeout"));
+        }
+
+        let start = Instant::now();
+
+        loop {
+            let elapsed = start.elapsed();
+            if elapsed >= timeout {
+                return Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out"));
+            }
+
+            let timeout = timeout - elapsed;
+            let mut timeout = timeout.as_secs()
+                .saturating_mul(1_000)
+                .saturating_add(timeout.subsec_nanos() as u64 / 1_000_000);
+            if timeout == 0 {
+                timeout = 1;
+            }
+
+            let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int;
+
+            match unsafe { libc::poll(&mut pollfd, 1, timeout) } {
+                -1 => {
+                    let err = io::Error::last_os_error();
+                    if err.kind() != io::ErrorKind::Interrupted {
+                        return Err(err);
+                    }
+                }
+                0 => {}
+                _ => {
+                    // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
+                    // for POLLHUP rather than read readiness
+                    if pollfd.revents & libc::POLLHUP != 0 {
+                        let e = self.take_error()?
+                            .unwrap_or_else(|| {
+                                io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
+                            });
+                        return Err(e);
+                    }
+
+                    return Ok(());
+                }
+            }
+        }
+    }
+
+    pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t)
+                  -> io::Result<Socket> {
+        let fd = cvt_r(|| unsafe {
+            libc::accept(self.0.raw(), storage, len)
+        })?;
+        let fd = FileDesc::new(fd);
+        fd.set_cloexec()?;
+        Ok(Socket(fd))
+    }
+
+    pub fn duplicate(&self) -> io::Result<Socket> {
+        self.0.duplicate().map(Socket)
+    }
+
+    fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::recv(self.0.raw(),
+                       buf.as_mut_ptr() as *mut c_void,
+                       buf.len(),
+                       flags)
+        })?;
+        Ok(ret as usize)
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.recv_with_flags(buf, 0)
+    }
+
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.recv_with_flags(buf, MSG_PEEK)
+    }
+
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
+    fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int)
+                            -> io::Result<(usize, SocketAddr)> {
+        let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
+        let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t;
+
+        let n = cvt(unsafe {
+            libc::recvfrom(self.0.raw(),
+                        buf.as_mut_ptr() as *mut c_void,
+                        buf.len(),
+                        flags,
+                        &mut storage as *mut _ as *mut _,
+                        &mut addrlen)
+        })?;
+        Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
+    }
+
+    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_with_flags(buf, 0)
+    }
+
+    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_with_flags(buf, MSG_PEEK)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
+    pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
+        let timeout = match dur {
+            Some(dur) => {
+                if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
+                    return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                              "cannot set a 0 duration timeout"));
+                }
+
+                let secs = if dur.as_secs() > libc::time_t::max_value() as u64 {
+                    libc::time_t::max_value()
+                } else {
+                    dur.as_secs() as libc::time_t
+                };
+                let mut timeout = libc::timeval {
+                    tv_sec: secs,
+                    tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t,
+                };
+                if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+                    timeout.tv_usec = 1;
+                }
+                timeout
+            }
+            None => {
+                libc::timeval {
+                    tv_sec: 0,
+                    tv_usec: 0,
+                }
+            }
+        };
+        setsockopt(self, libc::SOL_SOCKET, kind, timeout)
+    }
+
+    pub fn timeout(&self, kind: libc::c_int) -> io::Result<Option<Duration>> {
+        let raw: libc::timeval = getsockopt(self, libc::SOL_SOCKET, kind)?;
+        if raw.tv_sec == 0 && raw.tv_usec == 0 {
+            Ok(None)
+        } else {
+            let sec = raw.tv_sec as u64;
+            let nsec = (raw.tv_usec as u32) * 1000;
+            Ok(Some(Duration::new(sec, nsec)))
+        }
+    }
+
+    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
+        let how = match how {
+            Shutdown::Write => libc::SHUT_WR,
+            Shutdown::Read => libc::SHUT_RD,
+            Shutdown::Both => libc::SHUT_RDWR,
+        };
+        cvt(unsafe { libc::shutdown(self.0.raw(), how) })?;
+        Ok(())
+    }
+
+    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
+        setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int)
+    }
+
+    pub fn nodelay(&self) -> io::Result<bool> {
+        let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY)?;
+        Ok(raw != 0)
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        let mut nonblocking = nonblocking as libc::c_int;
+        cvt(unsafe { libc::ioctl(*self.as_inner(), libc::FIONBIO, &mut nonblocking) }).map(|_| ())
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?;
+        if raw == 0 {
+            Ok(None)
+        } else {
+            Ok(Some(io::Error::from_raw_os_error(raw as i32)))
+        }
+    }
+}
+
+impl AsInner<c_int> for Socket {
+    fn as_inner(&self) -> &c_int { self.0.as_inner() }
+}
+
+impl FromInner<c_int> for Socket {
+    fn from_inner(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) }
+}
+
+impl IntoInner<c_int> for Socket {
+    fn into_inner(self) -> c_int { self.0.into_raw() }
+}
+
+// In versions of glibc prior to 2.26, there's a bug where the DNS resolver
+// will cache the contents of /etc/resolv.conf, so changes to that file on disk
+// can be ignored by a long-running program. That can break DNS lookups on e.g.
+// laptops where the network comes and goes. See
+// https://sourceware.org/bugzilla/show_bug.cgi?id=984. Note however that some
+// distros including Debian have patched glibc to fix this for a long time.
+//
+// A workaround for this bug is to call the res_init libc function, to clear
+// the cached configs. Unfortunately, while we believe glibc's implementation
+// of res_init is thread-safe, we know that other implementations are not
+// (https://github.com/rust-lang/rust/issues/43592). Code here in libstd could
+// try to synchronize its res_init calls with a Mutex, but that wouldn't
+// protect programs that call into libc in other ways. So instead of calling
+// res_init unconditionally, we call it only when we detect we're linking
+// against glibc version < 2.26. (That is, when we both know its needed and
+// believe it's thread-safe).
+#[cfg(target_env = "gnu")]
+fn on_resolver_failure() {
+/*
+    use crate::sys;
+
+    // If the version fails to parse, we treat it the same as "not glibc".
+    if let Some(version) = sys::os::glibc_version() {
+        if version < (2, 26) {
+            unsafe { libc::res_init() };
+        }
+    }
+    */
+}
+
+#[cfg(not(target_env = "gnu"))]
+fn on_resolver_failure() {}
+
+#[cfg(all(test, taget_env = "gnu"))]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_res_init() {
+        // This mostly just tests that the weak linkage doesn't panic wildly...
+        res_init_if_glibc_before_2_26().unwrap();
+    }
+
+    #[test]
+    fn test_parse_glibc_version() {
+        let cases = [
+            ("0.0", Some((0, 0))),
+            ("01.+2", Some((1, 2))),
+            ("3.4.5.six", Some((3, 4))),
+            ("1", None),
+            ("1.-2", None),
+            ("1.foo", None),
+            ("foo.1", None),
+        ];
+        for &(version_str, parsed) in cases.iter() {
+            assert_eq!(parsed, parse_glibc_version(version_str));
+        }
+    }
+}
diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/vxworks/os.rs
index 76e43a83b73..5dc35a6176b 100644
--- a/src/libstd/sys/redox/os.rs
+++ b/src/libstd/sys/vxworks/os.rs
@@ -1,72 +1,136 @@
-//! Implementation of `std::os` functionality for unix systems
-
-#![allow(unused_imports)] // lots of cfg code here
-
-use libc::c_char;
-
-use crate::os::unix::prelude::*;
-
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CString, CStr, OsString, OsStr};
 use crate::fmt;
-use crate::io::{self, Read, Write};
+use crate::io;
 use crate::iter;
+use libc::{self, c_int, c_char /*,c_void */};
 use crate::marker::PhantomData;
 use crate::mem;
 use crate::memchr;
-use crate::path::{self, PathBuf};
+use crate::path::{self, PathBuf, Path};
 use crate::ptr;
 use crate::slice;
 use crate::str;
 use crate::sys_common::mutex::Mutex;
-use crate::sys::{cvt, cvt_libc, fd, syscall};
+use crate::sys::cvt;
+/*use sys::fd; this one is probably important */
 use crate::vec;
 
-extern {
-    #[link_name = "__errno_location"]
-    fn errno_location() -> *mut i32;
+const TMPBUF_SZ: usize = 128;
+static ENV_LOCK: Mutex = Mutex::new();
+
+
+// This is a terrible fix
+use crate::sys::os_str::Buf;
+use crate::sys_common::{FromInner, IntoInner, AsInner};
+
+pub trait OsStringExt {
+    fn from_vec(vec: Vec<u8>) -> Self;
+    fn into_vec(self) -> Vec<u8>;
 }
 
-/// Returns the platform-specific value of errno
-pub fn errno() -> i32 {
-    unsafe {
-        (*errno_location())
+impl OsStringExt for OsString {
+    fn from_vec(vec: Vec<u8>) -> OsString {
+        FromInner::from_inner(Buf { inner: vec })
     }
+    fn into_vec(self) -> Vec<u8> {
+        self.into_inner().inner
+    }
+}
+
+pub trait OsStrExt {
+    fn from_bytes(slice: &[u8]) -> &Self;
+    fn as_bytes(&self) -> &[u8];
+}
+
+impl OsStrExt for OsStr {
+    fn from_bytes(slice: &[u8]) -> &OsStr {
+        unsafe { mem::transmute(slice) }
+    }
+    fn as_bytes(&self) -> &[u8] {
+        &self.as_inner().inner
+    }
+}
+
+pub fn errno() -> i32 {
+    unsafe { libc::errnoGet() }
+}
+
+pub fn set_errno(e: i32) {
+    unsafe { libc::errnoSet(e as c_int); }
 }
 
 /// Gets a detailed string description for the given error number.
 pub fn error_string(errno: i32) -> String {
-    if let Some(string) = syscall::STR_ERROR.get(errno as usize) {
-        string.to_string()
-    } else {
-        "unknown error".to_string()
+    let mut buf = [0 as c_char; TMPBUF_SZ];
+    extern {
+        fn strerror_r(
+            errnum: c_int,
+            buf: *mut c_char,
+            buflen: libc::size_t
+        ) -> c_int;
+    }
+
+    let p = buf.as_mut_ptr();
+    unsafe {
+        if strerror_r(errno as c_int, p, buf.len()) < 0 {
+            panic!("strerror_r failure");
+        }
+        let p = p as *const _;
+        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
     }
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    let mut buf = [0; 4096];
-    let count = cvt(syscall::getcwd(&mut buf))?;
-    Ok(PathBuf::from(OsString::from_vec(buf[.. count].to_vec())))
+    let mut buf = Vec::with_capacity(512);
+    loop {
+        unsafe {
+            let ptr = buf.as_mut_ptr() as *mut libc::c_char;
+            if !libc::getcwd(ptr, buf.capacity() as libc::size_t).is_null() {
+                let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
+                buf.set_len(len);
+                buf.shrink_to_fit();
+                return Ok(PathBuf::from(OsString::from_vec(buf)));
+            } else {
+                let error = io::Error::last_os_error();
+                if error.raw_os_error() != Some(libc::ERANGE) {
+                    return Err(error);
+                }
+            }
+            // Trigger the internal buffer resizing logic of `Vec` by requiring
+            // more space than the current capacity.
+            let cap = buf.capacity();
+            buf.set_len(cap);
+            buf.reserve(1);
+        }
+    }
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
-    cvt(syscall::chdir(p.to_str().unwrap())).and(Ok(()))
+    let p: &OsStr = p.as_ref();
+    let p = CString::new(p.as_bytes())?;
+    unsafe {
+        match libc::chdir(p.as_ptr()) == (0 as c_int) {
+            true => Ok(()),
+            false => Err(io::Error::last_os_error()),
+        }
+    }
 }
 
 pub struct SplitPaths<'a> {
     iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
-                    fn(&'a [u8]) -> PathBuf>,
+            fn(&'a [u8]) -> PathBuf>,
 }
 
-pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
+pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> {
     fn bytes_to_path(b: &[u8]) -> PathBuf {
         PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
     }
-    fn is_semicolon(b: &u8) -> bool { *b == b';' }
+    fn is_colon(b: &u8) -> bool { *b == b':' }
     let unparsed = unparsed.as_bytes();
     SplitPaths {
-        iter: unparsed.split(is_semicolon as fn(&u8) -> bool)
-                      .map(bytes_to_path as fn(&[u8]) -> PathBuf)
+        iter: unparsed.split(is_colon as fn(&u8) -> bool)
+                        .map(bytes_to_path as fn(&[u8]) -> PathBuf)
     }
 }
 
@@ -83,11 +147,13 @@ pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
     where I: Iterator<Item=T>, T: AsRef<OsStr>
 {
     let mut joined = Vec::new();
-    let sep = b';';
+    let sep = b':';
 
     for (i, path) in paths.enumerate() {
         let path = path.as_ref().as_bytes();
-        if i > 0 { joined.push(sep) }
+        if i > 0 {
+            joined.push(sep)
+        }
         if path.contains(&sep) {
             return Err(JoinPathsError)
         }
@@ -97,7 +163,7 @@ pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
 }
 
 impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "path segment contains separator `:`".fmt(f)
     }
 }
@@ -107,22 +173,17 @@ impl StdError for JoinPathsError {
 }
 
 pub fn current_exe() -> io::Result<PathBuf> {
-    use crate::fs::File;
-
-    let mut file = File::open("sys:exe")?;
+    #[cfg(test)]
+    use realstd::env;
 
-    let mut path = String::new();
-    file.read_to_string(&mut path)?;
+    #[cfg(not(test))]
+    use crate::env;
 
-    if path.ends_with('\n') {
-        path.pop();
-    }
-
-    Ok(PathBuf::from(path))
+    let exe_path = env::args().next().unwrap();
+    let path = Path::new(&exe_path);
+    path.canonicalize()
 }
 
-pub static ENV_LOCK: Mutex = Mutex::new();
-
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
     _dont_send_or_sync_me: PhantomData<*mut ()>,
@@ -147,7 +208,7 @@ pub fn env() -> Env {
         let mut environ = *environ();
         if environ == ptr::null() {
             panic!("os::env() failure getting env string from OS: {}",
-                   io::Error::last_os_error());
+                io::Error::last_os_error());
         }
         let mut result = Vec::new();
         while *environ != ptr::null() {
@@ -200,7 +261,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
 
     unsafe {
         let _guard = ENV_LOCK.lock();
-        cvt_libc(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
+        cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
     }
 }
 
@@ -209,12 +270,14 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
 
     unsafe {
         let _guard = ENV_LOCK.lock();
-        cvt_libc(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
+        cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
     }
 }
 
 pub fn page_size() -> usize {
-    4096
+    unsafe {
+        libc::sysconf(libc::_SC_PAGESIZE) as usize
+    }
 }
 
 pub fn temp_dir() -> PathBuf {
@@ -224,18 +287,38 @@ pub fn temp_dir() -> PathBuf {
 }
 
 pub fn home_dir() -> Option<PathBuf> {
-    return crate::env::var_os("HOME").map(PathBuf::from);
+    return crate::env::var_os("HOME").or_else(|| unsafe {
+        fallback()
+    }).map(PathBuf::from);
+
+    unsafe fn fallback() -> Option<OsString> {
+        let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
+            n if n < 0 => 512 as usize,
+            n => n as usize,
+        };
+        let mut buf = Vec::with_capacity(amt);
+        let mut passwd: libc::passwd = mem::zeroed();
+        let mut result = ptr::null_mut();
+        match libc::getpwuid_r(libc::getuid(), &mut passwd, buf.as_mut_ptr(),
+                                buf.capacity(), &mut result) {
+            0 if !result.is_null() => {
+                let ptr = passwd.pw_dir as *const _;
+                let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
+                Some(OsStringExt::from_vec(bytes))
+            },
+            _ => None,
+        }
+    }
 }
 
 pub fn exit(code: i32) -> ! {
-    let _ = syscall::exit(code as usize);
-    unreachable!();
+    unsafe { libc::exit(code as c_int) }
 }
 
 pub fn getpid() -> u32 {
-    syscall::getpid().unwrap() as u32
+    unsafe { libc::getpid() as u32 }
 }
 
 pub fn getppid() -> u32 {
-    syscall::getppid().unwrap() as u32
+    unsafe { libc::getppid() as u32 }
 }
diff --git a/src/libstd/sys/vxworks/path.rs b/src/libstd/sys/vxworks/path.rs
new file mode 100644
index 00000000000..7a183956107
--- /dev/null
+++ b/src/libstd/sys/vxworks/path.rs
@@ -0,0 +1,19 @@
+use crate::path::Prefix;
+use crate::ffi::OsStr;
+
+#[inline]
+pub fn is_sep_byte(b: u8) -> bool {
+    b == b'/'
+}
+
+#[inline]
+pub fn is_verbatim_sep(b: u8) -> bool {
+    b == b'/'
+}
+
+pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
+    None
+}
+
+pub const MAIN_SEP_STR: &str = "/";
+pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/vxworks/pipe.rs b/src/libstd/sys/vxworks/pipe.rs
new file mode 100644
index 00000000000..e09dbe6e99b
--- /dev/null
+++ b/src/libstd/sys/vxworks/pipe.rs
@@ -0,0 +1,95 @@
+use crate::io::{self, IoSlice, IoSliceMut};
+use libc::{self /*, c_int apparently not used? */};
+use crate::mem;
+use crate::sync::atomic::{AtomicBool};
+use crate::sys::fd::FileDesc;
+use crate::sys::{cvt, cvt_r};
+
+pub struct AnonPipe(FileDesc);
+
+pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
+    static INVALID: AtomicBool = AtomicBool::new(false);
+
+    let mut fds = [0; 2];
+    cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
+
+    let fd0 = FileDesc::new(fds[0]);
+    let fd1 = FileDesc::new(fds[1]);
+    fd0.set_cloexec()?;
+    fd1.set_cloexec()?;
+    Ok((AnonPipe(fd0), AnonPipe(fd1)))
+}
+
+impl AnonPipe {
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+                self.0.read_vectored(bufs)
+        }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+        pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+                self.0.write_vectored(bufs)
+        }
+
+    pub fn fd(&self) -> &FileDesc { &self.0 }
+    pub fn into_fd(self) -> FileDesc { self.0 }
+    pub fn diverge(&self) -> ! {
+        panic!()
+     }
+}
+
+pub fn read2(p1: AnonPipe,
+             v1: &mut Vec<u8>,
+             p2: AnonPipe,
+             v2: &mut Vec<u8>) -> io::Result<()> {
+
+    // Set both pipes into nonblocking mode as we're gonna be reading from both
+    // in the `select` loop below, and we wouldn't want one to block the other!
+    let p1 = p1.into_fd();
+    let p2 = p2.into_fd();
+    p1.set_nonblocking_pipe(true)?;
+    p2.set_nonblocking_pipe(true)?;
+
+    let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
+    fds[0].fd = p1.raw();
+    fds[0].events = libc::POLLIN;
+    fds[1].fd = p2.raw();
+    fds[1].events = libc::POLLIN;
+    loop {
+        // wait for either pipe to become readable using `poll`
+        cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
+
+        if fds[0].revents != 0 && read(&p1, v1)? {
+            p2.set_nonblocking_pipe(false)?;
+            return p2.read_to_end(v2).map(|_| ());
+        }
+        if fds[1].revents != 0 && read(&p2, v2)? {
+            p1.set_nonblocking_pipe(false)?;
+            return p1.read_to_end(v1).map(|_| ());
+        }
+    }
+
+    // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
+    // EAGAIN. If we hit EOF, then this will happen because the underlying
+    // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
+    // this case we flip the other fd back into blocking mode and read
+    // whatever's leftover on that file descriptor.
+    fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
+        match fd.read_to_end(dst) {
+            Ok(_) => Ok(true),
+            Err(e) => {
+                if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
+                   e.raw_os_error() == Some(libc::EAGAIN) {
+                    Ok(false)
+                } else {
+                    Err(e)
+                }
+            }
+        }
+    }
+}
diff --git a/src/libstd/sys/vxworks/process/mod.rs b/src/libstd/sys/vxworks/process/mod.rs
new file mode 100644
index 00000000000..4dc706006f4
--- /dev/null
+++ b/src/libstd/sys/vxworks/process/mod.rs
@@ -0,0 +1,7 @@
+pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes};
+pub use self::process_inner::Process;
+
+mod process_common;
+#[path = "process_vxworks.rs"]
+mod process_inner;
+mod rtp;
diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs
new file mode 100644
index 00000000000..397200c39c2
--- /dev/null
+++ b/src/libstd/sys/vxworks/process/process_common.rs
@@ -0,0 +1,405 @@
+use crate::os::unix::prelude::*;
+
+use crate::ffi::{OsString, OsStr, CString, CStr};
+use crate::fmt;
+use crate::io;
+use crate::ptr;
+use crate::sys::fd::FileDesc;
+use crate::sys::fs::{File, OpenOptions};
+use crate::sys::pipe::{self, AnonPipe};
+use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::collections::BTreeMap;
+
+use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+    // Currently we try hard to ensure that the call to `.exec()` doesn't
+    // actually allocate any memory. While many platforms try to ensure that
+    // memory allocation works after a fork in a multithreaded process, it's
+    // been observed to be buggy and somewhat unreliable, so we do our best to
+    // just not do it at all!
+    //
+    // Along those lines, the `argv` and `envp` raw pointers here are exactly
+    // what's gonna get passed to `execvp`. The `argv` array starts with the
+    // `program` and ends with a NULL, and the `envp` pointer, if present, is
+    // also null-terminated.
+    //
+    // Right now we don't support removing arguments, so there's no much fancy
+    // support there, but we support adding and removing environment variables,
+    // so a side table is used to track where in the `envp` array each key is
+    // located. Whenever we add a key we update it in place if it's already
+    // present, and whenever we remove a key we update the locations of all
+    // other keys.
+    program: CString,
+    args: Vec<CString>,
+    argv: Argv,
+    env: CommandEnv<DefaultEnvKey>,
+
+    cwd: Option<CString>,
+    uid: Option<uid_t>,
+    gid: Option<gid_t>,
+    saw_nul: bool,
+    closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
+    stdin: Option<Stdio>,
+    stdout: Option<Stdio>,
+    stderr: Option<Stdio>,
+}
+
+// Create a new type for argv, so that we can make it `Send`
+struct Argv(Vec<*const c_char>);
+
+// It is safe to make Argv Send, because it contains pointers to memory owned by `Command.args`
+unsafe impl Send for Argv {}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+    pub stdin: Option<AnonPipe>,
+    pub stdout: Option<AnonPipe>,
+    pub stderr: Option<AnonPipe>,
+}
+
+// passed to do_exec() with configuration of what the child stdio should look
+// like
+pub struct ChildPipes {
+    pub stdin: ChildStdio,
+    pub stdout: ChildStdio,
+    pub stderr: ChildStdio,
+}
+
+pub enum ChildStdio {
+    Inherit,
+    Explicit(c_int),
+    Owned(FileDesc),
+}
+
+pub enum Stdio {
+    Inherit,
+    Null,
+    MakePipe,
+    Fd(FileDesc),
+}
+
+impl Command {
+    pub fn new(program: &OsStr) -> Command {
+        let mut saw_nul = false;
+        let program = os2c(program, &mut saw_nul);
+        Command {
+            argv: Argv(vec![program.as_ptr(), ptr::null()]),
+            program,
+            args: Vec::new(),
+            env: Default::default(),
+            cwd: None,
+            uid: None,
+            gid: None,
+            saw_nul,
+            closures: Vec::new(),
+            stdin: None,
+            stdout: None,
+            stderr: None,
+        }
+    }
+
+    pub fn arg(&mut self, arg: &OsStr) {
+        // Overwrite the trailing NULL pointer in `argv` and then add a new null
+        // pointer.
+        let arg = os2c(arg, &mut self.saw_nul);
+        self.argv.0[self.args.len() + 1] = arg.as_ptr();
+        self.argv.0.push(ptr::null());
+
+        // Also make sure we keep track of the owned value to schedule a
+        // destructor for this memory.
+        self.args.push(arg);
+    }
+
+    pub fn cwd(&mut self, dir: &OsStr) {
+        self.cwd = Some(os2c(dir, &mut self.saw_nul));
+    }
+    pub fn uid(&mut self, id: uid_t) {
+        self.uid = Some(id);
+    }
+    pub fn gid(&mut self, id: gid_t) {
+        self.gid = Some(id);
+    }
+
+    pub fn saw_nul(&self) -> bool {
+        self.saw_nul
+    }
+    pub fn get_argv(&self) -> &Vec<*const c_char> {
+        &self.argv.0
+    }
+
+    #[allow(dead_code)]
+    pub fn get_cwd(&self) -> &Option<CString> {
+        &self.cwd
+    }
+    #[allow(dead_code)]
+    pub fn get_uid(&self) -> Option<uid_t> {
+        self.uid
+    }
+    #[allow(dead_code)]
+    pub fn get_gid(&self) -> Option<gid_t> {
+        self.gid
+    }
+
+    pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> {
+        &mut self.closures
+    }
+
+    pub unsafe fn pre_exec(
+        &mut self,
+        _f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>,
+    ) {
+        // Fork() is not supported in vxWorks so no way to run the closure in the new procecss.
+        unimplemented!();;
+    }
+
+    pub fn stdin(&mut self, stdin: Stdio) {
+        self.stdin = Some(stdin);
+    }
+
+    pub fn stdout(&mut self, stdout: Stdio) {
+        self.stdout = Some(stdout);
+    }
+
+    pub fn stderr(&mut self, stderr: Stdio) {
+        self.stderr = Some(stderr);
+    }
+
+    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+        &mut self.env
+    }
+
+    pub fn capture_env(&mut self) -> Option<CStringArray> {
+        let maybe_env = self.env.capture_if_changed();
+        maybe_env.map(|env| construct_envp(env, &mut self.saw_nul))
+    }
+    #[allow(dead_code)]
+    pub fn env_saw_path(&self) -> bool {
+        self.env.have_changed_path()
+    }
+
+    pub fn setup_io(&self, default: Stdio, needs_stdin: bool)
+                -> io::Result<(StdioPipes, ChildPipes)> {
+        let null = Stdio::Null;
+        let default_stdin = if needs_stdin {&default} else {&null};
+        let stdin = self.stdin.as_ref().unwrap_or(default_stdin);
+        let stdout = self.stdout.as_ref().unwrap_or(&default);
+        let stderr = self.stderr.as_ref().unwrap_or(&default);
+        let (their_stdin, our_stdin) = stdin.to_child_stdio(true)?;
+        let (their_stdout, our_stdout) = stdout.to_child_stdio(false)?;
+        let (their_stderr, our_stderr) = stderr.to_child_stdio(false)?;
+        let ours = StdioPipes {
+            stdin: our_stdin,
+            stdout: our_stdout,
+            stderr: our_stderr,
+        };
+        let theirs = ChildPipes {
+            stdin: their_stdin,
+            stdout: their_stdout,
+            stderr: their_stderr,
+        };
+        Ok((ours, theirs))
+    }
+}
+
+fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString {
+    CString::new(s.as_bytes()).unwrap_or_else(|_e| {
+        *saw_nul = true;
+        CString::new("<string-with-nul>").unwrap()
+    })
+}
+
+// Helper type to manage ownership of the strings within a C-style array.
+pub struct CStringArray {
+    items: Vec<CString>,
+    ptrs: Vec<*const c_char>
+}
+
+impl CStringArray {
+    pub fn with_capacity(capacity: usize) -> Self {
+        let mut result = CStringArray {
+            items: Vec::with_capacity(capacity),
+            ptrs: Vec::with_capacity(capacity+1)
+        };
+        result.ptrs.push(ptr::null());
+        result
+    }
+    pub fn push(&mut self, item: CString) {
+        let l = self.ptrs.len();
+        self.ptrs[l-1] = item.as_ptr();
+        self.ptrs.push(ptr::null());
+        self.items.push(item);
+    }
+    pub fn as_ptr(&self) -> *const *const c_char {
+        self.ptrs.as_ptr()
+    }
+}
+
+fn construct_envp(env: BTreeMap<DefaultEnvKey, OsString>, saw_nul: &mut bool) -> CStringArray {
+    let mut result = CStringArray::with_capacity(env.len());
+    for (k, v) in env {
+        let mut k: OsString = k.into();
+
+        // Reserve additional space for '=' and null terminator
+        k.reserve_exact(v.len() + 2);
+        k.push("=");
+        k.push(&v);
+
+        // Add the new entry into the array
+        if let Ok(item) = CString::new(k.into_vec()) {
+            result.push(item);
+        } else {
+            *saw_nul = true;
+        }
+    }
+
+    result
+}
+
+impl Stdio {
+    pub fn to_child_stdio(&self, readable: bool)
+                      -> io::Result<(ChildStdio, Option<AnonPipe>)> {
+        match *self {
+            Stdio::Inherit => {
+                Ok((ChildStdio::Inherit, None))
+            },
+
+            // Make sure that the source descriptors are not an stdio
+            // descriptor, otherwise the order which we set the child's
+            // descriptors may blow away a descriptor which we are hoping to
+            // save. For example, suppose we want the child's stderr to be the
+            // parent's stdout, and the child's stdout to be the parent's
+            // stderr. No matter which we dup first, the second will get
+            // overwritten prematurely.
+            Stdio::Fd(ref fd) => {
+                if fd.raw() >= 0 && fd.raw() <= libc::STDERR_FILENO {
+                    Ok((ChildStdio::Owned(fd.duplicate()?), None))
+                } else {
+                    Ok((ChildStdio::Explicit(fd.raw()), None))
+                }
+            }
+
+            Stdio::MakePipe => {
+                let (reader, writer) = pipe::anon_pipe()?;
+                let (ours, theirs) = if readable {
+                    (writer, reader)
+                } else {
+                    (reader, writer)
+                };
+                Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours)))
+            }
+
+            Stdio::Null => {
+                let mut opts = OpenOptions::new();
+                opts.read(readable);
+                opts.write(!readable);
+                let path = unsafe {
+                    CStr::from_ptr("/null\0".as_ptr() as *const _)
+                };
+                let fd = File::open_c(&path, &opts)?;
+                Ok((ChildStdio::Owned(fd.into_fd()), None))
+            }
+        }
+    }
+}
+
+impl From<AnonPipe> for Stdio {
+    fn from(pipe: AnonPipe) -> Stdio {
+        Stdio::Fd(pipe.into_fd())
+    }
+}
+
+impl From<File> for Stdio {
+    fn from(file: File) -> Stdio {
+        Stdio::Fd(file.into_fd())
+    }
+}
+
+impl ChildStdio {
+    pub fn fd(&self) -> Option<c_int> {
+        match *self {
+            ChildStdio::Inherit => None,
+            ChildStdio::Explicit(fd) => Some(fd),
+            ChildStdio::Owned(ref fd) => Some(fd.raw()),
+        }
+    }
+}
+
+impl fmt::Debug for Command {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self.program)?;
+        for arg in &self.args {
+            write!(f, " {:?}", arg)?;
+        }
+        Ok(())
+    }
+}
+
+/// Unix exit statuses
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitStatus(c_int);
+
+impl ExitStatus {
+    pub fn new(status: c_int) -> ExitStatus {
+        ExitStatus(status)
+    }
+
+    fn exited(&self) -> bool {
+        /*unsafe*/ { libc::WIFEXITED(self.0) }
+    }
+
+    pub fn success(&self) -> bool {
+        self.code() == Some(0)
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        if self.exited() {
+            Some(/*unsafe*/ { libc::WEXITSTATUS(self.0) })
+        } else {
+            None
+        }
+    }
+
+    pub fn signal(&self) -> Option<i32> {
+        if !self.exited() {
+            Some(/*unsafe*/ { libc::WTERMSIG(self.0) })
+        } else {
+            None
+        }
+    }
+}
+
+impl From<c_int> for ExitStatus {
+    fn from(a: c_int) -> ExitStatus {
+        ExitStatus(a)
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if let Some(code) = self.code() {
+            write!(f, "exit code: {}", code)
+        } else {
+            let signal = self.signal().unwrap();
+            write!(f, "signal: {}", signal)
+        }
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(u8);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
+    pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
+
+    #[inline]
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs
new file mode 100644
index 00000000000..b07966fa206
--- /dev/null
+++ b/src/libstd/sys/vxworks/process/process_vxworks.rs
@@ -0,0 +1,156 @@
+use crate::io::{self, Error, ErrorKind};
+use libc::{self, c_int, c_char};
+use libc::{RTP_ID};
+use crate::sys;
+use crate::sys::cvt;
+use crate::sys::process::rtp;
+use crate::sys::process::process_common::*;
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+impl Command {
+    pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
+                 -> io::Result<(Process, StdioPipes)> {
+        use crate::sys::{cvt_r};
+        const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+
+        if self.saw_nul() {
+            return Err(io::Error::new(ErrorKind::InvalidInput,
+                                      "nul byte found in provided data"));
+        }
+        let (ours, theirs) = self.setup_io(default, needs_stdin)?;
+        let mut p = Process { pid: 0, status: None };
+
+        unsafe {
+            macro_rules! t {
+                ($e:expr) => (match $e {
+                    Ok(e) => e,
+                    Err(e) => return Err(e.into()),
+                })
+            }
+
+            let mut orig_stdin = libc::STDIN_FILENO;
+            let mut orig_stdout = libc::STDOUT_FILENO;
+            let mut orig_stderr = libc::STDERR_FILENO;
+
+            if let Some(fd) = theirs.stdin.fd() {
+                orig_stdin = t!(cvt_r(|| libc::dup(libc::STDIN_FILENO)));
+                t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO)));
+            }
+            if let Some(fd) = theirs.stdout.fd() {
+                orig_stdout = t!(cvt_r(|| libc::dup(libc::STDOUT_FILENO)));
+                t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO)));
+            }
+            if let Some(fd) = theirs.stderr.fd() {
+                orig_stderr = t!(cvt_r(|| libc::dup(libc::STDERR_FILENO)));
+                t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO)));
+            }
+
+            if let Some(ref cwd) = *self.get_cwd() {
+                t!(cvt(libc::chdir(cwd.as_ptr())));
+            }
+
+            let ret = rtp::rtpSpawn(
+                self.get_argv()[0],                   // executing program
+                self.get_argv().as_ptr() as *const _, // argv
+                *sys::os::environ() as *const *const c_char,
+                100 as c_int,                         // initial priority
+                0x16000,                                    // initial stack size. 0 defaults
+                                                      // to 0x4000 in 32 bit and 0x8000 in 64 bit
+                0,                                    // options
+                0                                     // task options
+            );
+
+            // Because FileDesc was not used, each duplicated file descriptor
+            // needs to be closed manually
+            if orig_stdin != libc::STDIN_FILENO {
+                t!(cvt_r(|| libc::dup2(orig_stdin, libc::STDIN_FILENO)));
+                libc::close(orig_stdin);
+            }
+            if orig_stdout != libc::STDOUT_FILENO {
+                t!(cvt_r(|| libc::dup2(orig_stdout, libc::STDOUT_FILENO)));
+                libc::close(orig_stdout);
+            }
+            if orig_stderr != libc::STDERR_FILENO {
+                t!(cvt_r(|| libc::dup2(orig_stderr, libc::STDERR_FILENO)));
+                libc::close(orig_stderr);
+            }
+
+            if ret != rtp::RTP_ID_ERROR {
+                p.pid = ret;
+                Ok((p, ours))
+            } else {
+                Err(io::Error::last_os_error())
+            }
+        }
+    }
+
+    pub fn exec(&mut self, default: Stdio) -> io::Error {
+        let ret = Command::spawn(self, default, false);
+        match ret {
+            Ok(t) => unsafe {
+                let mut status = 0 as c_int;
+                libc::waitpid(t.0.pid, &mut status, 0);
+                libc::exit(0);
+            },
+            Err(e) => e,
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Processes
+////////////////////////////////////////////////////////////////////////////////
+
+/// The unique id of the process (this should never be negative).
+pub struct Process {
+    pid: RTP_ID,
+    status: Option<ExitStatus>,
+}
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        self.pid as u32
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        // If we've already waited on this process then the pid can be recycled
+        // and used for another process, and we probably shouldn't be killing
+        // random processes, so just return an error.
+        if self.status.is_some() {
+            Err(Error::new(ErrorKind::InvalidInput,
+                           "invalid argument: can't kill an exited process"))
+        } else {
+            cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ())
+        }
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        use crate::sys::cvt_r;
+        if let Some(status) = self.status {
+            return Ok(status)
+        }
+        let mut status = 0 as c_int;
+        cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
+        self.status = Some(ExitStatus::new(status));
+        Ok(ExitStatus::new(status))
+    }
+
+    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+        if let Some(status) = self.status {
+            return Ok(Some(status))
+        }
+        let mut status = 0 as c_int;
+        let pid = cvt(unsafe {
+            libc::waitpid(self.pid, &mut status, libc::WNOHANG)
+        })?;
+        if pid == 0 {
+            Ok(None)
+        } else {
+            self.status = Some(ExitStatus::new(status));
+            Ok(Some(ExitStatus::new(status)))
+        }
+    }
+}
diff --git a/src/libstd/sys/vxworks/process/rtp.rs b/src/libstd/sys/vxworks/process/rtp.rs
new file mode 100644
index 00000000000..3e6e0017abc
--- /dev/null
+++ b/src/libstd/sys/vxworks/process/rtp.rs
@@ -0,0 +1,298 @@
+#![allow(non_camel_case_types, unused)]
+
+use libc::{self, c_int, size_t, c_char, BOOL, RTP_DESC, RTP_ID, TASK_ID};
+
+
+// Copied directly from rtpLibCommon.h, rtpLib.h, signal.h and taskLibCommon.h (for task options)
+
+// ****     definitions for rtpLibCommon.h    ****
+
+pub const RTP_GLOBAL_SYMBOLS     : c_int = 0x01; // register global symbols for RTP
+pub const RTP_LOCAL_SYMBOLS      : c_int = 0x02; // idem for local symbols
+pub const RTP_ALL_SYMBOLS        : c_int = (RTP_GLOBAL_SYMBOLS | RTP_LOCAL_SYMBOLS);
+pub const RTP_DEBUG              : c_int = 0x10; // set RTP in debug mode when created
+pub const RTP_BUFFER_VAL_OFF     : c_int = 0x20; // disable buffer validation for all
+                                                 // system calls issued from the RTP
+pub const RTP_LOADED_WAIT        : c_int = 0x40; // Wait until the RTP is loaded
+pub const RTP_CPU_AFFINITY_NONE  : c_int = 0x80; // Remove any CPU affinity (SMP)
+
+// Error Status codes
+
+pub const M_rtpLib : c_int = 178 << 16;
+
+pub const S_rtpLib_INVALID_FILE                   : c_int = (M_rtpLib | 1);
+pub const S_rtpLib_INVALID_OPTION                 : c_int = (M_rtpLib | 2);
+pub const S_rtpLib_ACCESS_DENIED                  : c_int = (M_rtpLib | 3);
+pub const S_rtpLib_INVALID_RTP_ID                 : c_int = (M_rtpLib | 4);
+pub const S_rtpLib_NO_SYMBOL_TABLE                : c_int = (M_rtpLib | 5);
+pub const S_rtpLib_INVALID_SEGMENT_START_ADDRESS  : c_int = (M_rtpLib | 6);
+pub const S_rtpLib_INVALID_SYMBOL_REGISTR_POLICY  : c_int = (M_rtpLib | 7);
+pub const S_rtpLib_INSTANTIATE_FAILED             : c_int = (M_rtpLib | 8);
+pub const S_rtpLib_INVALID_TASK_OPTION            : c_int = (M_rtpLib | 9);
+pub const S_rtpLib_RTP_NAME_LENGTH_EXCEEDED       : c_int = (M_rtpLib | 10);    // rtpInfoGet
+
+pub const VX_RTP_NAME_LENGTH                      : c_int  = 255;    // max name length for diplay
+
+
+// The 'status' field (32 bit integer) of a RTP holds the RTP state and status.
+//
+// NOTE: RTP_STATE_GET()    : read the RTP state(s)
+//       RTP_STATE_PUT()    : write the RTP state(s)
+//       RTP_STATE_SET()    : set a RTP state
+//       RTP_STATE_UNSET()  : unset a RTP state
+//
+//       RTP_STATUS_GET()   : read the RTP status
+//       RTP_STATUS_PUT()   : write the RTP status
+//       RTP_STATUS_SET()   : set a RTP status
+//       RTP_STATUS_UNSET() : unset a RTP status
+//
+// The PUT/SET/UNSET macros are available only in the kernel headers.
+
+
+// RTP states
+
+pub const RTP_STATE_CREATE           : c_int  = 0x0001; // RrtpStructTP is under construction
+pub const RTP_STATE_NORMAL           : c_int  = 0x0002; // RrtpStructTP is ready
+pub const RTP_STATE_DELETE           : c_int  = 0x0004; // RrtpStructTP is being deleted
+
+pub const RTP_STATUS_STOP            : c_int  = 0x0100; // RTP hrtpStructas recieved stopped signal
+pub const RTP_STATUS_ELECTED_DELETER : c_int  = 0x0200; // RTP drtpStructelete has started
+
+pub const RTP_STATE_MASK             : c_int  = (RTP_STATE_CREATE | RTP_STATE_NORMAL |
+                                                 RTP_STATE_DELETE);
+pub const RTP_STATUS_MASK            : c_int  = (RTP_STATUS_STOP | RTP_STATUS_ELECTED_DELETER);
+
+pub fn RTP_STATE_GET  (value : c_int) -> c_int {
+    value & RTP_STATE_MASK
+}
+pub fn RTP_STATUS_GET (value : c_int) -> c_int {
+    value & RTP_STATUS_MASK
+}
+
+// Indicates that the RTP_ID returned is not valid.
+
+// RTP_ID_ERROR is supposed to be set to -1, but you can't set
+// an unsigned value to a negative without casting, and you
+// can't cast unless the size of the integer types are the same,
+// but the size of RTP_ID may differ between kernel and user space.
+// Bitwise or-ing min and max should get the same result.
+pub const RTP_ID_ERROR : RTP_ID = RTP_ID::min_value() | RTP_ID::max_value();
+
+// IS_RTP_ C macros
+
+pub fn IS_RTP_STATE_NORMAL           (value : c_int) -> bool {
+    (RTP_STATE_GET(value)  & RTP_STATE_NORMAL) == RTP_STATE_NORMAL
+}
+pub fn IS_RTP_STATE_CREATE           (value : c_int) -> bool {
+    (RTP_STATE_GET(value)  & RTP_STATE_CREATE) == RTP_STATE_CREATE
+}
+pub fn IS_RTP_STATE_DELETE           (value : c_int) -> bool {
+    (RTP_STATE_GET(value)  & RTP_STATE_DELETE) == RTP_STATE_DELETE
+}
+pub fn IS_RTP_STATUS_STOP            (value : c_int) -> bool {
+    (RTP_STATUS_GET(value) & RTP_STATUS_STOP ) == RTP_STATUS_STOP
+}
+pub fn IS_RTP_STATUS_ELECTED_DELETER (value : c_int) -> bool {
+    (RTP_STATUS_GET(value) &  RTP_STATUS_ELECTED_DELETER) == RTP_STATUS_ELECTED_DELETER
+}
+
+// **** end of definitions for rtpLibCommon.h ****
+
+
+
+
+// ****    definitions for rtpLib.h     ****
+
+pub fn rtpExit(exitCode : c_int) -> ! {
+    unsafe{ libc::exit (exitCode) }
+}
+
+/* rtpLib.h in the kernel
+pub const RTP_DEL_VIA_TASK_DELETE : c_int  = 0x1;          // rtpDelete() via taskDestroy()
+pub const RTP_DEL_FORCE           : c_int  = 0x2;          // Forceful  rtpDelete()
+pub const RTP_ID_ANY              : RTP_ID = 0;            // used for when a kernel task
+                                                           // wants to wait for the next
+                                                           // RTP to finish
+
+
+// Function pointers
+
+pub type RTP_PRE_CREATE_HOOK    = size_t;
+pub type RTP_POST_CREATE_HOOK   = size_t;
+pub type RTP_INIT_COMPLETE_HOOK = size_t;
+pub type RTP_DELETE_HOOK        = size_t;
+*/
+
+// **** end of definitions for rtpLib.h ****
+
+
+
+
+
+// ****     definitions for signal.h    ****
+pub fn rtpKill(rtpId : RTP_ID, signo : c_int) -> c_int {
+    unsafe{ libc::kill(rtpId as c_int, signo) }
+}
+
+pub fn rtpSigqueue(rtpId : RTP_ID, signo : c_int, value : size_t) -> c_int {
+    unsafe{ libc::sigqueue(rtpId as c_int, signo, value) }
+}
+
+pub fn _rtpSigqueue(rtpId : RTP_ID, signo : c_int, value : *mut size_t, code : c_int) -> c_int {
+    unsafe{ libc::_sigqueue(rtpId, signo, value, code) }
+}
+
+pub fn taskRaise(signo : c_int) -> c_int {
+    unsafe{ libc::taskKill(libc::taskIdSelf(), signo) }
+}
+pub fn rtpRaise(signo : c_int) -> c_int {
+    unsafe{ libc::raise(signo) }
+}
+
+// **** end of definitions for signal.h ****
+
+
+
+// ****     definitions for taskLibCommon.h    ****
+pub const VX_PRIVATE_ENV      : c_int = 0x0080;  // 1 = private environment variables
+pub const VX_NO_STACK_FILL    : c_int = 0x0100;  // 1 = avoid stack fill of 0xee
+pub const VX_PRIVATE_UMASK    : c_int = 0x0400;  // 1 = private file creation mode mask
+pub const VX_TASK_NOACTIVATE  : c_int = 0x2000;  // taskOpen() does not taskActivate()
+pub const VX_NO_STACK_PROTECT : c_int = 0x4000;  // no over/underflow stack protection,
+                                                 // stack space remains executable
+
+// define for all valid user task options
+
+pub const VX_USR_TASK_OPTIONS_BASE: c_int = (VX_PRIVATE_ENV      |
+                                             VX_NO_STACK_FILL    |
+                                             VX_TASK_NOACTIVATE  |
+                                             VX_NO_STACK_PROTECT |
+                                             VX_PRIVATE_UMASK);
+
+// **** end of definitions for taskLibCommon.h ****
+
+
+
+extern "C" {
+// functions in rtpLibCommon.h
+
+// forward declarations
+    pub fn rtpSpawn (
+        pubrtpFileName : *const c_char,
+        argv           : *const *const c_char,
+        envp           : *const *const c_char,
+        priority       : c_int,
+        uStackSize     : size_t,
+        options        : c_int,
+        taskOptions    : c_int,
+    ) -> RTP_ID;
+
+    pub fn rtpInfoGet (
+        rtpId     : RTP_ID,
+        rtpStruct : *mut RTP_DESC,
+    ) -> c_int;
+
+/* functions in rtpLib.h for kernel
+
+
+    // function declarations
+
+    pub fn rtpDelete (
+        id      : RTP_ID,
+        options : c_int,
+        status  : c_int,
+    ) -> c_int;
+
+    pub fn rtpDeleteForce (
+        rtpId : RTP_ID
+    ) -> c_int;
+
+    pub fn rtpShow (
+        rtpNameOrId : *mut c_char,
+        level       : c_int,
+    ) -> BOOL;
+
+    // RTP signals are always present when RTPs are included.  The public RTP
+    // signal APIs are declared here.
+
+
+    pub fn rtpKill (
+        rtpId : RTP_ID,
+        signo : c_int,
+    ) -> c_int;
+
+    pub fn rtpSigqueue (
+        rtpId : RTP_ID,
+        signo : c_int,
+        value : size_t, // Actual type is const union sigval value,
+                        // which is a union of int and void *
+    ) -> c_int;
+
+    pub fn rtpTaskKill (
+        tid   : TASK_ID,
+        signo : c_int,
+    ) -> c_int;
+
+    pub fn rtpTaskSigqueue (
+        tid   : TASK_ID,
+        signo : c_int,
+        value : const size_t, // Actual type is const union sigval,
+                        // which is a union of int and void *
+    ) -> c_int;
+
+    pub fn rtpWait (
+        rtpWaitId : RTP_ID,
+        timeout   : libc::alloc_jemalloc_Vx_ticks_t,
+        pRtpId    : *mut RTP_ID,
+        pStatus   : *mut c_int,
+    ) -> c_int;
+
+                             // Other public functions
+
+
+    pub fn rtpPreCreateHookAdd     (
+        hook      : RTP_PRE_CREATE_HOOK,
+        addToHead : BOOL,
+    ) -> c_int;
+
+    pub fn rtpPreCreateHookDelete  (
+        hook      : RTP_POST_CREATE_HOOK,
+    ) -> c_int;
+
+    pub fn rtpPostCreateHookAdd    (
+        hook      : RTP_POST_CREATE_HOOK,
+        addToHead : BOOL,
+    ) -> c_int;
+
+    pub fn rtpPostCreateHookDelete (
+        hook      : RTP_POST_CREATE_HOOK,
+    ) -> c_int;
+
+    pub fn rtpInitCompleteHookAdd  (
+        hook      : RTP_INIT_COMPLETE_HOOK,
+        addToHead : BOOL,
+    ) -> c_int;
+
+    pub fn rtpInitCompleteHookDelete (
+        hook      : RTP_INIT_COMPLETE_HOOK,
+    ) -> c_int;
+
+    pub fn rtpDeleteHookAdd        (
+        hook      : RTP_DELETE_HOOK,
+        addToHead : BOOL,
+    ) -> c_int;
+
+    pub fn rtpDeleteHookDelete     (
+        hook      : RTP_DELETE_HOOK,
+    ) -> c_int;
+
+    pub fn rtpMemShow              (
+        rtpNameOrId : *mut c_char,
+        level       : c_int,
+    ) -> c_int;
+
+    pub fn rtpHookShow             (
+
+    );
+*/
+}
diff --git a/src/libstd/sys/vxworks/rand.rs b/src/libstd/sys/vxworks/rand.rs
new file mode 100644
index 00000000000..1ec0cbe4dcf
--- /dev/null
+++ b/src/libstd/sys/vxworks/rand.rs
@@ -0,0 +1,31 @@
+use crate::mem;
+use crate::slice;
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+    let mut v = (0, 0);
+    unsafe {
+        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8,
+                                             mem::size_of_val(&v));
+        imp::fill_bytes(view);
+    }
+    return v
+}
+
+mod imp {
+    use libc;
+    use crate::io;
+
+    extern "C" {
+        fn randBytes (randBuf: *mut libc::c_uchar,
+                      numOfBytes: libc::c_int) -> libc::c_int;
+    }
+
+    pub fn fill_bytes(v: &mut [u8]) {
+        let ret = unsafe {
+            randBytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
+        };
+        if ret == -1 {
+            panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
+        }
+    }
+}
diff --git a/src/libstd/sys/vxworks/rwlock.rs b/src/libstd/sys/vxworks/rwlock.rs
new file mode 100644
index 00000000000..718f422ed11
--- /dev/null
+++ b/src/libstd/sys/vxworks/rwlock.rs
@@ -0,0 +1,113 @@
+use libc;
+use crate::cell::UnsafeCell;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+
+pub struct RWLock {
+    inner: UnsafeCell<libc::pthread_rwlock_t>,
+    write_locked: UnsafeCell<bool>,
+    num_readers: AtomicUsize,
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
+impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock {
+            inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER),
+            write_locked: UnsafeCell::new(false),
+            num_readers: AtomicUsize::new(0),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn read(&self) {
+        let r = libc::pthread_rwlock_rdlock(self.inner.get());
+        if r == libc::EAGAIN {
+            panic!("rwlock maximum reader count exceeded");
+        } else if r == libc::EDEADLK || *self.write_locked.get() {
+            if r == 0 {
+                self.raw_unlock();
+            }
+        panic!("rwlock read lock would result in deadlock");
+        } else {
+            debug_assert_eq!(r, 0);
+            self.num_readers.fetch_add(1, Ordering::Relaxed);
+        }
+    }
+
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        let r = libc::pthread_rwlock_tryrdlock(self.inner.get());
+        if r == 0 {
+            if *self.write_locked.get() {
+                self.raw_unlock();
+                false
+            } else {
+                self.num_readers.fetch_add(1, Ordering::Relaxed);
+                true
+            }
+        } else {
+            false
+        }
+    }
+
+    #[inline]
+    pub unsafe fn write(&self) {
+        let r = libc::pthread_rwlock_wrlock(self.inner.get());
+        // See comments above for why we check for EDEADLK and write_locked. We
+        // also need to check that num_readers is 0.
+        if r == libc::EDEADLK || *self.write_locked.get() ||
+            self.num_readers.load(Ordering::Relaxed) != 0 {
+            if r == 0 {
+                self.raw_unlock();
+            }
+        panic!("rwlock write lock would result in deadlock");
+        } else {
+            debug_assert_eq!(r, 0);
+        }
+        *self.write_locked.get() = true;
+    }
+
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        let r = libc::pthread_rwlock_trywrlock(self.inner.get());
+        if r == 0 {
+            if *self.write_locked.get() || self.num_readers.load(Ordering::Relaxed) != 0 {
+                self.raw_unlock();
+                false
+            } else {
+                *self.write_locked.get() = true;
+                true
+            }
+            } else {
+                false
+        }
+    }
+
+    #[inline]
+    unsafe fn raw_unlock(&self) {
+        let r = libc::pthread_rwlock_unlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        debug_assert!(!*self.write_locked.get());
+        self.num_readers.fetch_sub(1, Ordering::Relaxed);
+        self.raw_unlock();
+    }
+
+     #[inline]
+    pub unsafe fn write_unlock(&self) {
+        debug_assert_eq!(self.num_readers.load(Ordering::Relaxed), 0);
+        debug_assert!(*self.write_locked.get());
+        *self.write_locked.get() = false;
+        self.raw_unlock();
+    }
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = libc::pthread_rwlock_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/vxworks/stack_overflow.rs b/src/libstd/sys/vxworks/stack_overflow.rs
new file mode 100644
index 00000000000..08e7b310ca1
--- /dev/null
+++ b/src/libstd/sys/vxworks/stack_overflow.rs
@@ -0,0 +1,41 @@
+#![cfg_attr(test, allow(dead_code))]
+
+use self::imp::{make_handler, drop_handler};
+
+pub use self::imp::cleanup;
+pub use self::imp::init;
+
+pub struct Handler {
+    _data: *mut libc::c_void
+}
+
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        make_handler()
+    }
+}
+
+impl Drop for Handler {
+    fn drop(&mut self) {
+        unsafe {
+            drop_handler(self);
+        }
+    }
+}
+
+mod imp {
+    use crate::ptr;
+
+    pub unsafe fn init() {
+    }
+
+    pub unsafe fn cleanup() {
+    }
+
+    pub unsafe fn make_handler() -> super::Handler {
+        super::Handler { _data: ptr::null_mut() }
+    }
+
+    pub unsafe fn drop_handler(_handler: &mut super::Handler) {
+    }
+}
diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/vxworks/stdio.rs
index 33f5bdbb5d3..35f163bbdb1 100644
--- a/src/libstd/sys/redox/stdio.rs
+++ b/src/libstd/sys/vxworks/stdio.rs
@@ -1,5 +1,4 @@
 use crate::io;
-use crate::sys::{cvt, syscall};
 use crate::sys::fd::FileDesc;
 
 pub struct Stdin(());
@@ -12,9 +11,9 @@ impl Stdin {
 
 impl io::Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(0);
+        let fd = FileDesc::new(libc::STDIN_FILENO);
         let ret = fd.read(buf);
-        fd.into_raw();
+        fd.into_raw(); // do not close this FD
         ret
     }
 }
@@ -25,14 +24,14 @@ impl Stdout {
 
 impl io::Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(1);
+        let fd = FileDesc::new(libc::STDOUT_FILENO);
         let ret = fd.write(buf);
-        fd.into_raw();
+        fd.into_raw(); // do not close this FD
         ret
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        cvt(syscall::fsync(1)).and(Ok(()))
+        Ok(())
     }
 }
 
@@ -42,19 +41,19 @@ impl Stderr {
 
 impl io::Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(2);
+        let fd = FileDesc::new(libc::STDERR_FILENO);
         let ret = fd.write(buf);
-        fd.into_raw();
+        fd.into_raw(); // do not close this FD
         ret
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        cvt(syscall::fsync(2)).and(Ok(()))
+        Ok(())
     }
 }
 
 pub fn is_ebadf(err: &io::Error) -> bool {
-    err.raw_os_error() == Some(crate::sys::syscall::EBADF as i32)
+    err.raw_os_error() == Some(libc::EBADF as i32)
 }
 
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs
new file mode 100644
index 00000000000..58af8cbe48e
--- /dev/null
+++ b/src/libstd/sys/vxworks/thread.rs
@@ -0,0 +1,143 @@
+use crate::cmp;
+use crate::ffi::CStr;
+use crate::io;
+use crate::mem;
+use crate::ptr;
+use crate::sys::os;
+use crate::time::Duration;
+
+use crate::sys_common::thread::*;
+
+pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
+
+pub struct Thread {
+    id: libc::pthread_t,
+}
+
+// Some platforms may have pthread_t as a pointer in which case we still want
+// a thread to be Send/Sync
+unsafe impl Send for Thread {}
+unsafe impl Sync for Thread {}
+
+// The pthread_attr_setstacksize symbol doesn't exist in the emscripten libc,
+// so we have to not link to it to satisfy emcc's ERROR_ON_UNDEFINED_SYMBOLS.
+unsafe fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
+                                    stack_size: libc::size_t) -> libc::c_int {
+    libc::pthread_attr_setstacksize(attr, stack_size)
+}
+
+impl Thread {
+    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
+    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>)
+                          -> io::Result<Thread> {
+        let p = box p;
+        let mut native: libc::pthread_t = mem::zeroed();
+        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+
+        let stack_size = cmp::max(stack, min_stack_size(&attr));
+
+        match pthread_attr_setstacksize(&mut attr,
+                                        stack_size) {
+            0 => {}
+            n => {
+                assert_eq!(n, libc::EINVAL);
+                // EINVAL means |stack_size| is either too small or not a
+                // multiple of the system page size.  Because it's definitely
+                // >= PTHREAD_STACK_MIN, it must be an alignment issue.
+                // Round up to the nearest page and try again.
+                let page_size = os::page_size();
+                let stack_size = (stack_size + page_size - 1) &
+                                 (-(page_size as isize - 1) as usize - 1);
+                assert_eq!(libc::pthread_attr_setstacksize(&mut attr,
+                                                           stack_size), 0);
+            }
+        };
+
+        let ret = libc::pthread_create(&mut native, &attr, thread_start,
+                                       &*p as *const _ as *mut _);
+        assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+
+        return if ret != 0 {
+            Err(io::Error::from_raw_os_error(ret))
+        } else {
+            mem::forget(p); // ownership passed to pthread_create
+            Ok(Thread { id: native })
+        };
+
+        extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
+            unsafe { start_thread(main as *mut u8); }
+            ptr::null_mut()
+        }
+    }
+
+    pub fn yield_now() {
+        let ret = unsafe { libc::sched_yield() };
+        debug_assert_eq!(ret, 0);
+    }
+
+    pub fn set_name(_name: &CStr) {
+        assert!(false, "FIXME: set_name");
+    }
+
+    pub fn sleep(dur: Duration) {
+        let mut secs = dur.as_secs();
+        let mut nsecs = dur.subsec_nanos() as _;
+
+        // If we're awoken with a signal then the return value will be -1 and
+        // nanosleep will fill in `ts` with the remaining time.
+        unsafe {
+            while secs > 0 || nsecs > 0 {
+                let mut ts = libc::timespec {
+                    tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
+                    tv_nsec: nsecs,
+                };
+                secs -= ts.tv_sec as u64;
+                if libc::nanosleep(&ts, &mut ts) == -1 {
+                    assert_eq!(os::errno(), libc::EINTR);
+                    secs += ts.tv_sec as u64;
+                    nsecs = ts.tv_nsec;
+                } else {
+                    nsecs = 0;
+                }
+            }
+        }
+    }
+
+    pub fn join(self) {
+        unsafe {
+            let ret = libc::pthread_join(self.id, ptr::null_mut());
+            mem::forget(self);
+            assert!(ret == 0,
+                    "failed to join thread: {}", io::Error::from_raw_os_error(ret));
+        }
+    }
+
+    pub fn id(&self) -> libc::pthread_t { self.id }
+
+    pub fn into_id(self) -> libc::pthread_t {
+        let id = self.id;
+        mem::forget(self);
+        id
+    }
+}
+
+impl Drop for Thread {
+    fn drop(&mut self) {
+        let ret = unsafe { libc::pthread_detach(self.id) };
+        debug_assert_eq!(ret, 0);
+    }
+}
+
+#[cfg_attr(test, allow(dead_code))]
+pub mod guard {
+    use crate::ops::Range;
+    pub type Guard = Range<usize>;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
+    pub unsafe fn deinit() {}
+}
+
+fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
+    libc::PTHREAD_STACK_MIN
+}
diff --git a/src/libstd/sys/vxworks/thread_local.rs b/src/libstd/sys/vxworks/thread_local.rs
new file mode 100644
index 00000000000..ac615b76b36
--- /dev/null
+++ b/src/libstd/sys/vxworks/thread_local.rs
@@ -0,0 +1,34 @@
+#![allow(dead_code)] // not used on all platforms
+
+use crate::mem;
+
+pub type Key = libc::pthread_key_t;
+
+#[inline]
+pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    let mut key = 0;
+    assert_eq!(libc::pthread_key_create(&mut key, mem::transmute(dtor)), 0);
+    key
+}
+
+#[inline]
+pub unsafe fn set(key: Key, value: *mut u8) {
+    let r = libc::pthread_setspecific(key, value as *mut _);
+    debug_assert_eq!(r, 0);
+}
+
+#[inline]
+pub unsafe fn get(key: Key) -> *mut u8 {
+    libc::pthread_getspecific(key) as *mut u8
+}
+
+#[inline]
+pub unsafe fn destroy(key: Key) {
+    let r = libc::pthread_key_delete(key);
+    debug_assert_eq!(r, 0);
+}
+
+#[inline]
+pub fn requires_synchronized_create() -> bool {
+    false
+}
diff --git a/src/libstd/sys/vxworks/time.rs b/src/libstd/sys/vxworks/time.rs
new file mode 100644
index 00000000000..cb3a4241ea6
--- /dev/null
+++ b/src/libstd/sys/vxworks/time.rs
@@ -0,0 +1,224 @@
+use crate::cmp::Ordering;
+use libc;
+use crate::time::Duration;
+use ::core::hash::{Hash, Hasher};
+
+pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
+use crate::convert::TryInto;
+
+const NSEC_PER_SEC: u64 = 1_000_000_000;
+
+#[derive(Copy, Clone)]
+struct Timespec {
+    t: libc::timespec,
+}
+
+impl Timespec {
+    const fn zero() -> Timespec {
+        Timespec {
+            t: libc::timespec { tv_sec: 0, tv_nsec: 0 },
+        }
+    }
+    fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
+        if self >= other {
+            Ok(if self.t.tv_nsec >= other.t.tv_nsec {
+                Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
+                                (self.t.tv_nsec - other.t.tv_nsec) as u32)
+                } else {
+                    Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
+                        self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
+                        other.t.tv_nsec as u32)
+                })
+        } else {
+            match other.sub_timespec(self) {
+                Ok(d) => Err(d),
+                Err(d) => Ok(d),
+            }
+        }
+    }
+
+    fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
+        let mut secs = other
+            .as_secs()
+            .try_into() // <- target type would be `libc::time_t`
+            .ok()
+            .and_then(|secs| self.t.tv_sec.checked_add(secs))?;
+
+        // Nano calculations can't overflow because nanos are <1B which fit
+        // in a u32.
+        let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
+        if nsec >= NSEC_PER_SEC as u32 {
+            nsec -= NSEC_PER_SEC as u32;
+            secs = secs.checked_add(1)?;
+        }
+        Some(Timespec {
+            t: libc::timespec {
+                tv_sec: secs,
+                tv_nsec: nsec as _,
+            },
+        })
+    }
+
+    fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
+        let mut secs = other
+            .as_secs()
+            .try_into() // <- target type would be `libc::time_t`
+            .ok()
+            .and_then(|secs| self.t.tv_sec.checked_sub(secs))?;
+
+        // Similar to above, nanos can't overflow.
+        let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
+        if nsec < 0 {
+            nsec += NSEC_PER_SEC as i32;
+            secs = secs.checked_sub(1)?;
+        }
+        Some(Timespec {
+            t: libc::timespec {
+                tv_sec: secs,
+                tv_nsec: nsec as _,
+            },
+        })
+    }
+}
+
+impl PartialEq for Timespec {
+    fn eq(&self, other: &Timespec) -> bool {
+        self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
+    }
+}
+
+impl Eq for Timespec {}
+
+impl PartialOrd for Timespec {
+    fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Timespec {
+    fn cmp(&self, other: &Timespec) -> Ordering {
+        let me = (self.t.tv_sec, self.t.tv_nsec);
+        let other = (other.t.tv_sec, other.t.tv_nsec);
+        me.cmp(&other)
+    }
+}
+
+impl Hash for Timespec {
+    fn hash<H : Hasher>(&self, state: &mut H) {
+        self.t.tv_sec.hash(state);
+        self.t.tv_nsec.hash(state);
+    }
+}
+mod inner {
+    use crate::fmt;
+    use libc;
+    use crate::sys::cvt;
+    use crate::time::Duration;
+
+    use super::Timespec;
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+    pub struct Instant {
+        t: Timespec,
+    }
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+    pub struct SystemTime {
+        t: Timespec,
+    }
+
+    pub const UNIX_EPOCH: SystemTime = SystemTime {
+        t: Timespec {
+            t: libc::timespec {
+                tv_sec: 0,
+                tv_nsec: 0,
+            },
+        },
+    };
+
+    impl Instant {
+        pub fn now() -> Instant {
+            Instant { t: now(libc::CLOCK_MONOTONIC) }
+        }
+
+        pub const fn zero() -> Instant {
+            Instant {
+                t: Timespec::zero(),
+            }
+        }
+
+        pub fn actually_monotonic() -> bool {
+            true
+        }
+
+        pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+            self.t.sub_timespec(&other.t).ok()
+        }
+
+        pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+            Some(Instant { t: self.t.checked_add_duration(other)? })
+        }
+
+        pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
+            Some(Instant { t: self.t.checked_sub_duration(other)? })
+        }
+    }
+
+    impl fmt::Debug for Instant {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            f.debug_struct("Instant")
+             .field("tv_sec", &self.t.t.tv_sec)
+             .field("tv_nsec", &self.t.t.tv_nsec)
+             .finish()
+        }
+    }
+
+    impl SystemTime {
+        pub fn now() -> SystemTime {
+            SystemTime { t: now(libc::CLOCK_REALTIME) }
+        }
+
+        pub fn sub_time(&self, other: &SystemTime)
+                        -> Result<Duration, Duration> {
+            self.t.sub_timespec(&other.t)
+        }
+
+        pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+            Some(SystemTime { t: self.t.checked_add_duration(other)? })
+        }
+
+        pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+            Some(SystemTime { t: self.t.checked_sub_duration(other)? })
+        }
+    }
+
+    impl From<libc::timespec> for SystemTime {
+        fn from(t: libc::timespec) -> SystemTime {
+            SystemTime { t: Timespec { t: t } }
+        }
+    }
+
+    impl fmt::Debug for SystemTime {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            f.debug_struct("SystemTime")
+             .field("tv_sec", &self.t.t.tv_sec)
+             .field("tv_nsec", &self.t.t.tv_nsec)
+             .finish()
+        }
+    }
+
+    pub type clock_t = libc::c_int;
+
+    fn now(clock: clock_t) -> Timespec {
+        let mut t = Timespec {
+            t: libc::timespec {
+                tv_sec: 0,
+                tv_nsec: 0,
+            }
+        };
+        cvt(unsafe {
+            libc::clock_gettime(clock, &mut t.t)
+        }).unwrap();
+        t
+    }
+}
diff --git a/src/libstd/sys/vxworks/weak.rs b/src/libstd/sys/vxworks/weak.rs
new file mode 100644
index 00000000000..284f2116423
--- /dev/null
+++ b/src/libstd/sys/vxworks/weak.rs
@@ -0,0 +1,60 @@
+//! Support for "weak linkage" to symbols on Unix
+//!
+//! Some I/O operations we do in libstd require newer versions of OSes but we
+//! need to maintain binary compatibility with older releases for now. In order
+//! to use the new functionality when available we use this module for
+//! detection.
+//!
+//! One option to use here is weak linkage, but that is unfortunately only
+//! really workable on Linux. Hence, use dlsym to get the symbol value at
+//! runtime. This is also done for compatibility with older versions of glibc,
+//! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
+//! we've been dynamically linked to the library the symbol comes from, but that
+//! is currently always the case for things like libpthread/libc.
+//!
+//! A long time ago this used weak linkage for the __pthread_get_minstack
+//! symbol, but that caused Debian to detect an unnecessarily strict versioned
+//! dependency on libc6 (#23628).
+
+use crate::ffi::CStr;
+use crate::marker;
+use crate::mem;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+
+pub struct Weak<F> {
+    name: &'static str,
+    addr: AtomicUsize,
+    _marker: marker::PhantomData<F>,
+}
+
+impl<F> Weak<F> {
+    pub const fn new(name: &'static str) -> Weak<F> {
+        Weak {
+            name,
+            addr: AtomicUsize::new(1),
+            _marker: marker::PhantomData,
+        }
+    }
+
+    pub fn get(&self) -> Option<F> {
+        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+        unsafe {
+            if self.addr.load(Ordering::SeqCst) == 1 {
+                self.addr.store(fetch(self.name), Ordering::SeqCst);
+            }
+            match self.addr.load(Ordering::SeqCst) {
+                0 => None,
+                addr => Some(mem::transmute_copy::<usize, F>(&addr)),
+            }
+        }
+    }
+}
+
+unsafe fn fetch(name: &str) -> usize {
+    let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
+        Ok(cstr) => cstr,
+        Err(..) => return 0,
+    };
+    assert!(false, "FIXME: fetch");
+   libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
+}
diff --git a/src/libstd/sys/wasi/alloc.rs b/src/libstd/sys/wasi/alloc.rs
new file mode 100644
index 00000000000..c8529937bbd
--- /dev/null
+++ b/src/libstd/sys/wasi/alloc.rs
@@ -0,0 +1,43 @@
+use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::ptr;
+use crate::sys_common::alloc::{MIN_ALIGN, realloc_fallback};
+use libc;
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+unsafe impl GlobalAlloc for System {
+    #[inline]
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+            libc::malloc(layout.size()) as *mut u8
+        } else {
+            libc::aligned_alloc(layout.size(), layout.align()) as *mut u8
+        }
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+            libc::calloc(layout.size(), 1) as *mut u8
+        } else {
+            let ptr = self.alloc(layout.clone());
+            if !ptr.is_null() {
+                ptr::write_bytes(ptr, 0, layout.size());
+            }
+            ptr
+        }
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
+        libc::free(ptr as *mut libc::c_void)
+    }
+
+    #[inline]
+    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
+            libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
+        } else {
+            realloc_fallback(self, ptr, layout, new_size)
+        }
+    }
+}
diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs
new file mode 100644
index 00000000000..8b4b354d9fc
--- /dev/null
+++ b/src/libstd/sys/wasi/args.rs
@@ -0,0 +1,76 @@
+use crate::ffi::CStr;
+use crate::io;
+use crate::sys::cvt_wasi;
+use crate::ffi::OsString;
+use crate::marker::PhantomData;
+use crate::os::wasi::ffi::OsStringExt;
+use crate::vec;
+
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+}
+
+pub unsafe fn cleanup() {
+}
+
+pub struct Args {
+    iter: vec::IntoIter<OsString>,
+    _dont_send_or_sync_me: PhantomData<*mut ()>,
+}
+
+/// Returns the command line arguments
+pub fn args() -> Args {
+    maybe_args().unwrap_or_else(|_| {
+        Args {
+            iter: Vec::new().into_iter(),
+            _dont_send_or_sync_me: PhantomData
+        }
+    })
+}
+
+fn maybe_args() -> io::Result<Args> {
+    unsafe {
+        let (mut argc, mut argv_buf_size) = (0, 0);
+        cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?;
+
+        let mut argc = vec![core::ptr::null_mut::<libc::c_char>(); argc];
+        let mut argv_buf = vec![0; argv_buf_size];
+        cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?;
+
+        let args = argc.into_iter()
+            .map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec())
+            .map(|bytes| OsString::from_vec(bytes))
+            .collect::<Vec<_>>();
+        Ok(Args {
+            iter: args.into_iter(),
+            _dont_send_or_sync_me: PhantomData,
+        })
+    }
+}
+
+impl Args {
+    pub fn inner_debug(&self) -> &[OsString] {
+        self.iter.as_slice()
+    }
+}
+
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl ExactSizeIterator for Args {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+}
+
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> {
+        self.iter.next_back()
+    }
+}
diff --git a/src/libstd/sys/wasi/env.rs b/src/libstd/sys/wasi/env.rs
new file mode 100644
index 00000000000..730e356d7fe
--- /dev/null
+++ b/src/libstd/sys/wasi/env.rs
@@ -0,0 +1,9 @@
+pub mod os {
+    pub const FAMILY: &str = "";
+    pub const OS: &str = "";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = ".wasm";
+    pub const DLL_EXTENSION: &str = "wasm";
+    pub const EXE_SUFFIX: &str = ".wasm";
+    pub const EXE_EXTENSION: &str = "wasm";
+}
diff --git a/src/libstd/sys/wasi/ext/ffi.rs b/src/libstd/sys/wasi/ext/ffi.rs
new file mode 100644
index 00000000000..f71f316d1ba
--- /dev/null
+++ b/src/libstd/sys/wasi/ext/ffi.rs
@@ -0,0 +1,6 @@
+//! WASI-specific extension to the primitives in the `std::ffi` module
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::sys_common::os_str_bytes::*;
diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs
new file mode 100644
index 00000000000..0ec4122f385
--- /dev/null
+++ b/src/libstd/sys/wasi/ext/fs.rs
@@ -0,0 +1,412 @@
+//! WASI-specific extensions to primitives in the `std::fs` module.
+
+#![unstable(feature = "wasi_ext", issue = "0")]
+
+use crate::fs::{self, File, Metadata, OpenOptions};
+use crate::io::{self, IoSlice, IoSliceMut};
+use crate::os::wasi::ffi::OsStrExt;
+use crate::path::{Path, PathBuf};
+use crate::sys_common::{AsInner, AsInnerMut, FromInner};
+
+/// WASI-specific extensions to [`File`].
+///
+/// [`File`]: ../../../../std/fs/struct.File.html
+pub trait FileExt {
+    /// Reads a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes read.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Note that similar to [`File::read_vectored`], it is not an error to
+    /// return with a short read.
+    ///
+    /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read_vectored
+    fn read_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize>;
+
+    /// Writes a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes written.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// When writing beyond the end of the file, the file is appropriately
+    /// extended and the intermediate bytes are initialized with the value 0.
+    ///
+    /// Note that similar to [`File::write_vectored`], it is not an error to return a
+    /// short write.
+    ///
+    /// [`File::write`]: ../../../../std/fs/struct.File.html#method.write_vectored
+    fn write_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize>;
+
+    /// Returns the current position within the file.
+    ///
+    /// This corresponds to the `__wasi_fd_tell` syscall and is similar to
+    /// `seek` where you offset 0 bytes from the current position.
+    fn tell(&self) -> io::Result<u64>;
+
+    /// Adjust the flags associated with this file.
+    ///
+    /// This corresponds to the `__wasi_fd_fdstat_set_flags` syscall.
+    fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>;
+
+    /// Adjust the rights associated with this file.
+    ///
+    /// This corresponds to the `__wasi_fd_fdstat_set_rights` syscall.
+    fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>;
+
+    /// Provide file advisory information on a file descriptor.
+    ///
+    /// This corresponds to the `__wasi_fd_advise` syscall.
+    fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>;
+
+    /// Force the allocation of space in a file.
+    ///
+    /// This corresponds to the `__wasi_fd_allocate` syscall.
+    fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
+
+    /// Create a directory.
+    ///
+    /// This corresponds to the `__wasi_path_create_directory` syscall.
+    fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()>;
+
+    /// Read the contents of a symbolic link.
+    ///
+    /// This corresponds to the `__wasi_path_readlink` syscall.
+    fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf>;
+
+    /// Return the attributes of a file or directory.
+    ///
+    /// This corresponds to the `__wasi_path_filestat_get` syscall.
+    fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata>;
+
+    /// Unlink a file.
+    ///
+    /// This corresponds to the `__wasi_path_unlink_file` syscall.
+    fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
+
+    /// Remove a directory.
+    ///
+    /// This corresponds to the `__wasi_path_remove_directory` syscall.
+    fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
+}
+
+// FIXME: bind __wasi_fd_fdstat_get - need to define a custom return type
+// FIXME: bind __wasi_fd_readdir - can't return `ReadDir` since we only have entry name
+// FIXME: bind __wasi_fd_filestat_set_times maybe? - on crates.io for unix
+// FIXME: bind __wasi_path_filestat_set_times maybe? - on crates.io for unix
+// FIXME: bind __wasi_poll_oneoff maybe? - probably should wait for I/O to settle
+// FIXME: bind __wasi_random_get maybe? - on crates.io for unix
+
+impl FileExt for fs::File {
+    fn read_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        self.as_inner().fd().pread(bufs, offset)
+    }
+
+    fn write_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        self.as_inner().fd().pwrite(bufs, offset)
+    }
+
+    fn tell(&self) -> io::Result<u64> {
+        self.as_inner().fd().tell()
+    }
+
+    fn fdstat_set_flags(&self, flags: u16) -> io::Result<()> {
+        self.as_inner().fd().set_flags(flags)
+    }
+
+    fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()> {
+        self.as_inner().fd().set_rights(rights, inheriting)
+    }
+
+    fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()> {
+        self.as_inner().fd().advise(offset, len, advice)
+    }
+
+    fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
+        self.as_inner().fd().allocate(offset, len)
+    }
+
+    fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()> {
+        self.as_inner()
+            .fd()
+            .create_directory(dir.as_ref().as_os_str().as_bytes())
+    }
+
+    fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
+        self.as_inner().read_link(path.as_ref())
+    }
+
+    fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata> {
+        let m = self.as_inner().metadata_at(lookup_flags, path.as_ref())?;
+        Ok(FromInner::from_inner(m))
+    }
+
+    fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+        self.as_inner()
+            .fd()
+            .unlink_file(path.as_ref().as_os_str().as_bytes())
+    }
+
+    fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+        self.as_inner()
+            .fd()
+            .remove_directory(path.as_ref().as_os_str().as_bytes())
+    }
+}
+
+/// WASI-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
+pub trait OpenOptionsExt {
+    /// Pass custom `dirflags` argument to `__wasi_path_open`.
+    ///
+    /// This option configures the `dirflags` argument to the
+    /// `__wasi_path_open` syscall which `OpenOptions` will eventually call. The
+    /// `dirflags` argument configures how the file is looked up, currently
+    /// primarily affecting whether symlinks are followed or not.
+    ///
+    /// By default this value is `__WASI_LOOKUP_SYMLINK_FOLLOW`, or symlinks are
+    /// followed. You can call this method with 0 to disable following symlinks
+    fn lookup_flags(&mut self, flags: u32) -> &mut Self;
+
+    /// Indicates whether `OpenOptions` must open a directory or not.
+    ///
+    /// This method will configure whether the `__WASI_O_DIRECTORY` flag is
+    /// passed when opening a file. When passed it will require that the opened
+    /// path is a directory.
+    ///
+    /// This option is by default `false`
+    fn directory(&mut self, dir: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_DSYNC` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn dsync(&mut self, dsync: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_NONBLOCK` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn nonblock(&mut self, nonblock: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_RSYNC` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn rsync(&mut self, rsync: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_SYNC` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn sync(&mut self, sync: bool) -> &mut Self;
+
+    /// Indicates the value that should be passed in for the `fs_rights_base`
+    /// parameter of `__wasi_path_open`.
+    ///
+    /// This option defaults based on the `read` and `write` configuration of
+    /// this `OpenOptions` builder. If this method is called, however, the
+    /// exact mask passed in will be used instead.
+    fn fs_rights_base(&mut self, rights: u64) -> &mut Self;
+
+    /// Indicates the value that should be passed in for the
+    /// `fs_rights_inheriting` parameter of `__wasi_path_open`.
+    ///
+    /// The default for this option is the same value as what will be passed
+    /// for the `fs_rights_base` parameter but if this method is called then
+    /// the specified value will be used instead.
+    fn fs_rights_inheriting(&mut self, rights: u64) -> &mut Self;
+
+    /// Open a file or directory.
+    ///
+    /// This corresponds to the `__wasi_path_open` syscall.
+    fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File>;
+}
+
+impl OpenOptionsExt for OpenOptions {
+    fn lookup_flags(&mut self, flags: u32) -> &mut OpenOptions {
+        self.as_inner_mut().lookup_flags(flags);
+        self
+    }
+
+    fn directory(&mut self, dir: bool) -> &mut OpenOptions {
+        self.as_inner_mut().directory(dir);
+        self
+    }
+
+    fn dsync(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().dsync(enabled);
+        self
+    }
+
+    fn nonblock(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().nonblock(enabled);
+        self
+    }
+
+    fn rsync(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().rsync(enabled);
+        self
+    }
+
+    fn sync(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().sync(enabled);
+        self
+    }
+
+    fn fs_rights_base(&mut self, rights: u64) -> &mut OpenOptions {
+        self.as_inner_mut().fs_rights_base(rights);
+        self
+    }
+
+    fn fs_rights_inheriting(&mut self, rights: u64) -> &mut OpenOptions {
+        self.as_inner_mut().fs_rights_inheriting(rights);
+        self
+    }
+
+    fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File> {
+        let inner = file.as_inner().open_at(path.as_ref(), self.as_inner())?;
+        Ok(File::from_inner(inner))
+    }
+}
+
+/// WASI-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
+pub trait MetadataExt {
+    /// Returns the `st_dev` field of the internal `__wasi_filestat_t`
+    fn dev(&self) -> u64;
+    /// Returns the `st_ino` field of the internal `__wasi_filestat_t`
+    fn ino(&self) -> u64;
+    /// Returns the `st_nlink` field of the internal `__wasi_filestat_t`
+    fn nlink(&self) -> u32;
+    /// Returns the `st_atim` field of the internal `__wasi_filestat_t`
+    fn atim(&self) -> u64;
+    /// Returns the `st_mtim` field of the internal `__wasi_filestat_t`
+    fn mtim(&self) -> u64;
+    /// Returns the `st_ctim` field of the internal `__wasi_filestat_t`
+    fn ctim(&self) -> u64;
+}
+
+impl MetadataExt for fs::Metadata {
+    fn dev(&self) -> u64 {
+        self.as_inner().as_wasi().st_dev
+    }
+    fn ino(&self) -> u64 {
+        self.as_inner().as_wasi().st_ino
+    }
+    fn nlink(&self) -> u32 {
+        self.as_inner().as_wasi().st_nlink
+    }
+    fn atim(&self) -> u64 {
+        self.as_inner().as_wasi().st_atim
+    }
+    fn mtim(&self) -> u64 {
+        self.as_inner().as_wasi().st_mtim
+    }
+    fn ctim(&self) -> u64 {
+        self.as_inner().as_wasi().st_ctim
+    }
+}
+
+/// WASI-specific extensions for [`FileType`].
+///
+/// Adds support for special WASI file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
+pub trait FileTypeExt {
+    /// Returns `true` if this file type is a block device.
+    fn is_block_device(&self) -> bool;
+    /// Returns `true` if this file type is a character device.
+    fn is_character_device(&self) -> bool;
+    /// Returns `true` if this file type is a socket datagram.
+    fn is_socket_dgram(&self) -> bool;
+    /// Returns `true` if this file type is a socket stream.
+    fn is_socket_stream(&self) -> bool;
+}
+
+impl FileTypeExt for fs::FileType {
+    fn is_block_device(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_BLOCK_DEVICE
+    }
+    fn is_character_device(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE
+    }
+    fn is_socket_dgram(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_DGRAM
+    }
+    fn is_socket_stream(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_STREAM
+    }
+}
+
+/// WASI-specific extension methods for [`fs::DirEntry`].
+///
+/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
+pub trait DirEntryExt {
+    /// Returns the underlying `d_ino` field of the `__wasi_dirent_t`
+    fn ino(&self) -> u64;
+}
+
+impl DirEntryExt for fs::DirEntry {
+    fn ino(&self) -> u64 {
+        self.as_inner().ino()
+    }
+}
+
+/// Create a hard link.
+///
+/// This corresponds to the `__wasi_path_link` syscall.
+pub fn link<P: AsRef<Path>, U: AsRef<Path>>(
+    old_fd: &File,
+    old_flags: u32,
+    old_path: P,
+    new_fd: &File,
+    new_path: U,
+) -> io::Result<()> {
+    old_fd.as_inner().fd().link(
+        old_flags,
+        old_path.as_ref().as_os_str().as_bytes(),
+        new_fd.as_inner().fd(),
+        new_path.as_ref().as_os_str().as_bytes(),
+    )
+}
+
+/// Rename a file or directory.
+///
+/// This corresponds to the `__wasi_path_rename` syscall.
+pub fn rename<P: AsRef<Path>, U: AsRef<Path>>(
+    old_fd: &File,
+    old_path: P,
+    new_fd: &File,
+    new_path: U,
+) -> io::Result<()> {
+    old_fd.as_inner().fd().rename(
+        old_path.as_ref().as_os_str().as_bytes(),
+        new_fd.as_inner().fd(),
+        new_path.as_ref().as_os_str().as_bytes(),
+    )
+}
+
+/// Create a symbolic link.
+///
+/// This corresponds to the `__wasi_path_symlink` syscall.
+pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
+    old_path: P,
+    fd: &File,
+    new_path: U,
+) -> io::Result<()> {
+    fd.as_inner().fd().symlink(
+        old_path.as_ref().as_os_str().as_bytes(),
+        new_path.as_ref().as_os_str().as_bytes(),
+    )
+}
diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs
new file mode 100644
index 00000000000..12afd1d42dc
--- /dev/null
+++ b/src/libstd/sys/wasi/ext/io.rs
@@ -0,0 +1,142 @@
+//! WASI-specific extensions to general I/O primitives
+
+#![unstable(feature = "wasi_ext", issue = "0")]
+
+use crate::fs;
+use crate::io;
+use crate::sys;
+use crate::net;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+
+/// Raw file descriptors.
+pub type RawFd = u32;
+
+/// A trait to extract the raw WASI file descriptor from an underlying
+/// object.
+pub trait AsRawFd {
+    /// Extracts the raw file descriptor.
+    ///
+    /// This method does **not** pass ownership of the raw file descriptor
+    /// to the caller. The descriptor is only guaranteed to be valid while
+    /// the original object has not yet been destroyed.
+    fn as_raw_fd(&self) -> RawFd;
+}
+
+/// A trait to express the ability to construct an object from a raw file
+/// descriptor.
+pub trait FromRawFd {
+    /// Constructs a new instance of `Self` from the given raw file
+    /// descriptor.
+    ///
+    /// This function **consumes ownership** of the specified file
+    /// descriptor. The returned object will take responsibility for closing
+    /// it when the object goes out of scope.
+    ///
+    /// This function is also unsafe as the primitives currently returned
+    /// have the contract that they are the sole owner of the file
+    /// descriptor they are wrapping. Usage of this function could
+    /// accidentally allow violating this contract which can cause memory
+    /// unsafety in code that relies on it being true.
+    unsafe fn from_raw_fd(fd: RawFd) -> Self;
+}
+
+/// A trait to express the ability to consume an object and acquire ownership of
+/// its raw file descriptor.
+pub trait IntoRawFd {
+    /// Consumes this object, returning the raw underlying file descriptor.
+    ///
+    /// This function **transfers ownership** of the underlying file descriptor
+    /// to the caller. Callers are then the unique owners of the file descriptor
+    /// and must close the descriptor once it's no longer needed.
+    fn into_raw_fd(self) -> RawFd;
+}
+
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        net::TcpStream::from_inner(sys::net::TcpStream::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for net::TcpStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        net::TcpListener::from_inner(sys::net::TcpListener::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for net::TcpListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for net::UdpSocket {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for net::UdpSocket {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+        net::UdpSocket::from_inner(sys::net::UdpSocket::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for net::UdpSocket {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for fs::File {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for fs::File {
+    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
+        fs::File::from_inner(sys::fs::File::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for fs::File {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for io::Stdin {
+    fn as_raw_fd(&self) -> RawFd {
+        libc::STDIN_FILENO as u32
+    }
+}
+
+impl AsRawFd for io::Stdout {
+    fn as_raw_fd(&self) -> RawFd {
+        libc::STDOUT_FILENO as u32
+    }
+}
+
+impl AsRawFd for io::Stderr {
+    fn as_raw_fd(&self) -> RawFd {
+        libc::STDERR_FILENO as u32
+    }
+}
diff --git a/src/libstd/sys/wasi/ext/mod.rs b/src/libstd/sys/wasi/ext/mod.rs
new file mode 100644
index 00000000000..1c24b244b8c
--- /dev/null
+++ b/src/libstd/sys/wasi/ext/mod.rs
@@ -0,0 +1,18 @@
+pub mod ffi;
+pub mod fs;
+pub mod io;
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod prelude {
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::sys::ext::ffi::{OsStringExt, OsStrExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::sys::ext::fs::{FileExt, DirEntryExt, MetadataExt, OpenOptionsExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::sys::ext::fs::FileTypeExt;
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::sys::ext::io::{AsRawFd, IntoRawFd, FromRawFd};
+}
diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs
new file mode 100644
index 00000000000..25692ec0868
--- /dev/null
+++ b/src/libstd/sys/wasi/fd.rs
@@ -0,0 +1,350 @@
+#![allow(dead_code)]
+
+use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
+use crate::mem;
+use crate::net::Shutdown;
+use crate::sys::cvt_wasi;
+use libc::{self, c_char, c_void};
+
+#[derive(Debug)]
+pub struct WasiFd {
+    fd: libc::__wasi_fd_t,
+}
+
+// FIXME: these should probably all be fancier structs, builders, enums, etc
+pub type LookupFlags = u32;
+pub type FdFlags = u16;
+pub type Advice = u8;
+pub type Rights = u64;
+pub type Oflags = u16;
+pub type DirCookie = u64;
+pub type Timestamp = u64;
+pub type FstFlags = u16;
+pub type RiFlags = u16;
+pub type RoFlags = u16;
+pub type SiFlags = u16;
+
+fn iovec(a: &mut [IoSliceMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) {
+    assert_eq!(
+        mem::size_of::<IoSliceMut<'_>>(),
+        mem::size_of::<libc::__wasi_iovec_t>()
+    );
+    assert_eq!(
+        mem::align_of::<IoSliceMut<'_>>(),
+        mem::align_of::<libc::__wasi_iovec_t>()
+    );
+    (a.as_ptr() as *const libc::__wasi_iovec_t, a.len())
+}
+
+fn ciovec(a: &[IoSlice<'_>]) -> (*const libc::__wasi_ciovec_t, usize) {
+    assert_eq!(
+        mem::size_of::<IoSlice<'_>>(),
+        mem::size_of::<libc::__wasi_ciovec_t>()
+    );
+    assert_eq!(
+        mem::align_of::<IoSlice<'_>>(),
+        mem::align_of::<libc::__wasi_ciovec_t>()
+    );
+    (a.as_ptr() as *const libc::__wasi_ciovec_t, a.len())
+}
+
+impl WasiFd {
+    pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd {
+        WasiFd { fd }
+    }
+
+    pub fn into_raw(self) -> libc::__wasi_fd_t {
+        let ret = self.fd;
+        mem::forget(self);
+        ret
+    }
+
+    pub fn as_raw(&self) -> libc::__wasi_fd_t {
+        self.fd
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) })
+    }
+
+    pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        let mut read = 0;
+        let (ptr, len) = iovec(bufs);
+        cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?;
+        Ok(read)
+    }
+
+    pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        let mut read = 0;
+        let (ptr, len) = ciovec(bufs);
+        cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?;
+        Ok(read)
+    }
+
+    pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        let mut read = 0;
+        let (ptr, len) = iovec(bufs);
+        cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?;
+        Ok(read)
+    }
+
+    pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let mut read = 0;
+        let (ptr, len) = ciovec(bufs);
+        cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?;
+        Ok(read)
+    }
+
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        let (whence, offset) = match pos {
+            SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64),
+            SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos),
+            SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos),
+        };
+        let mut pos = 0;
+        cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?;
+        Ok(pos)
+    }
+
+    pub fn tell(&self) -> io::Result<u64> {
+        let mut pos = 0;
+        cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?;
+        Ok(pos)
+    }
+
+    // FIXME: __wasi_fd_fdstat_get
+
+    pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) })
+    }
+
+    pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) })
+    }
+
+    pub fn sync(&self) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) })
+    }
+
+    pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) })
+    }
+
+    pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) })
+    }
+
+    pub fn create_directory(&self, path: &[u8]) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len())
+        })
+    }
+
+    pub fn link(
+        &self,
+        old_flags: LookupFlags,
+        old_path: &[u8],
+        new_fd: &WasiFd,
+        new_path: &[u8],
+    ) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_link(
+                self.fd,
+                old_flags,
+                old_path.as_ptr() as *const c_char,
+                old_path.len(),
+                new_fd.fd,
+                new_path.as_ptr() as *const c_char,
+                new_path.len(),
+            )
+        })
+    }
+
+    pub fn open(
+        &self,
+        dirflags: LookupFlags,
+        path: &[u8],
+        oflags: Oflags,
+        fs_rights_base: Rights,
+        fs_rights_inheriting: Rights,
+        fs_flags: FdFlags,
+    ) -> io::Result<WasiFd> {
+        unsafe {
+            let mut fd = 0;
+            cvt_wasi(libc::__wasi_path_open(
+                self.fd,
+                dirflags,
+                path.as_ptr() as *const c_char,
+                path.len(),
+                oflags,
+                fs_rights_base,
+                fs_rights_inheriting,
+                fs_flags,
+                &mut fd,
+            ))?;
+            Ok(WasiFd::from_raw(fd))
+        }
+    }
+
+    pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result<usize> {
+        let mut used = 0;
+        cvt_wasi(unsafe {
+            libc::__wasi_fd_readdir(
+                self.fd,
+                buf.as_mut_ptr() as *mut c_void,
+                buf.len(),
+                cookie,
+                &mut used,
+            )
+        })?;
+        Ok(used)
+    }
+
+    pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
+        let mut used = 0;
+        cvt_wasi(unsafe {
+            libc::__wasi_path_readlink(
+                self.fd,
+                path.as_ptr() as *const c_char,
+                path.len(),
+                buf.as_mut_ptr() as *mut c_char,
+                buf.len(),
+                &mut used,
+            )
+        })?;
+        Ok(used)
+    }
+
+    pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_rename(
+                self.fd,
+                old_path.as_ptr() as *const c_char,
+                old_path.len(),
+                new_fd.fd,
+                new_path.as_ptr() as *const c_char,
+                new_path.len(),
+            )
+        })
+    }
+
+    pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) })
+    }
+
+    pub fn filestat_set_times(
+        &self,
+        atim: Timestamp,
+        mtim: Timestamp,
+        fstflags: FstFlags,
+    ) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) })
+    }
+
+    pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) })
+    }
+
+    pub fn path_filestat_get(
+        &self,
+        flags: LookupFlags,
+        path: &[u8],
+        buf: *mut libc::__wasi_filestat_t,
+    ) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_filestat_get(
+                self.fd,
+                flags,
+                path.as_ptr() as *const c_char,
+                path.len(),
+                buf,
+            )
+        })
+    }
+
+    pub fn path_filestat_set_times(
+        &self,
+        flags: LookupFlags,
+        path: &[u8],
+        atim: Timestamp,
+        mtim: Timestamp,
+        fstflags: FstFlags,
+    ) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_filestat_set_times(
+                self.fd,
+                flags,
+                path.as_ptr() as *const c_char,
+                path.len(),
+                atim,
+                mtim,
+                fstflags,
+            )
+        })
+    }
+
+    pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_symlink(
+                old_path.as_ptr() as *const c_char,
+                old_path.len(),
+                self.fd,
+                new_path.as_ptr() as *const c_char,
+                new_path.len(),
+            )
+        })
+    }
+
+    pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len())
+        })
+    }
+
+    pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len())
+        })
+    }
+
+    pub fn sock_recv(
+        &self,
+        ri_data: &mut [IoSliceMut<'_>],
+        ri_flags: RiFlags,
+    ) -> io::Result<(usize, RoFlags)> {
+        let mut ro_datalen = 0;
+        let mut ro_flags = 0;
+        let (ptr, len) = iovec(ri_data);
+        cvt_wasi(unsafe {
+            libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags)
+        })?;
+        Ok((ro_datalen, ro_flags))
+    }
+
+    pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: SiFlags) -> io::Result<usize> {
+        let mut so_datalen = 0;
+        let (ptr, len) = ciovec(si_data);
+        cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?;
+        Ok(so_datalen)
+    }
+
+    pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
+        let how = match how {
+            Shutdown::Read => libc::__WASI_SHUT_RD,
+            Shutdown::Write => libc::__WASI_SHUT_WR,
+            Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD,
+        };
+        cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?;
+        Ok(())
+    }
+}
+
+impl Drop for WasiFd {
+    fn drop(&mut self) {
+        unsafe {
+            // FIXME: can we handle the return code here even though we can't on
+            // unix?
+            libc::__wasi_fd_close(self.fd);
+        }
+    }
+}
diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
new file mode 100644
index 00000000000..172c60385b3
--- /dev/null
+++ b/src/libstd/sys/wasi/fs.rs
@@ -0,0 +1,691 @@
+use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::fmt;
+use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
+use crate::iter;
+use crate::mem::{self, ManuallyDrop};
+use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
+use crate::path::{Path, PathBuf};
+use crate::ptr;
+use crate::sync::Arc;
+use crate::sys::fd::{DirCookie, WasiFd};
+use crate::sys::time::SystemTime;
+use crate::sys::unsupported;
+use crate::sys_common::FromInner;
+
+pub use crate::sys_common::fs::copy;
+pub use crate::sys_common::fs::remove_dir_all;
+
+pub struct File {
+    fd: WasiFd,
+}
+
+#[derive(Clone)]
+pub struct FileAttr {
+    meta: libc::__wasi_filestat_t,
+}
+
+pub struct ReadDir {
+    inner: Arc<ReadDirInner>,
+    cookie: Option<DirCookie>,
+    buf: Vec<u8>,
+    offset: usize,
+    cap: usize,
+}
+
+struct ReadDirInner {
+    root: PathBuf,
+    dir: File,
+}
+
+pub struct DirEntry {
+    meta: libc::__wasi_dirent_t,
+    name: Vec<u8>,
+    inner: Arc<ReadDirInner>,
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct OpenOptions {
+    read: bool,
+    write: bool,
+    dirflags: libc::__wasi_lookupflags_t,
+    fdflags: libc::__wasi_fdflags_t,
+    oflags: libc::__wasi_oflags_t,
+    rights_base: Option<libc::__wasi_rights_t>,
+    rights_inheriting: Option<libc::__wasi_rights_t>,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FilePermissions {
+    readonly: bool,
+}
+
+#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
+pub struct FileType {
+    bits: libc::__wasi_filetype_t,
+}
+
+#[derive(Debug)]
+pub struct DirBuilder {}
+
+impl FileAttr {
+    fn zero() -> FileAttr {
+        FileAttr {
+            meta: unsafe { mem::zeroed() },
+        }
+    }
+
+    pub fn size(&self) -> u64 {
+        self.meta.st_size
+    }
+
+    pub fn perm(&self) -> FilePermissions {
+        // not currently implemented in wasi yet
+        FilePermissions { readonly: false }
+    }
+
+    pub fn file_type(&self) -> FileType {
+        FileType {
+            bits: self.meta.st_filetype,
+        }
+    }
+
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from_wasi_timestamp(self.meta.st_mtim))
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from_wasi_timestamp(self.meta.st_atim))
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim))
+    }
+
+    pub fn as_wasi(&self) -> &libc::__wasi_filestat_t {
+        &self.meta
+    }
+}
+
+impl FilePermissions {
+    pub fn readonly(&self) -> bool {
+        self.readonly
+    }
+
+    pub fn set_readonly(&mut self, readonly: bool) {
+        self.readonly = readonly;
+    }
+}
+
+impl FileType {
+    pub fn is_dir(&self) -> bool {
+        self.bits == libc::__WASI_FILETYPE_DIRECTORY
+    }
+
+    pub fn is_file(&self) -> bool {
+        self.bits == libc::__WASI_FILETYPE_REGULAR_FILE
+    }
+
+    pub fn is_symlink(&self) -> bool {
+        self.bits == libc::__WASI_FILETYPE_SYMBOLIC_LINK
+    }
+
+    pub fn bits(&self) -> libc::__wasi_filetype_t {
+        self.bits
+    }
+}
+
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("ReadDir").finish()
+    }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        loop {
+            // If we've reached the capacity of our buffer then we need to read
+            // some more from the OS, otherwise we pick up at our old offset.
+            let offset = if self.offset == self.cap {
+                let cookie = self.cookie.take()?;
+                match self.inner.dir.fd.readdir(&mut self.buf, cookie) {
+                    Ok(bytes) => self.cap = bytes,
+                    Err(e) => return Some(Err(e)),
+                }
+                self.offset = 0;
+                self.cookie = Some(cookie);
+
+                // If we didn't actually read anything, this is in theory the
+                // end of the directory.
+                if self.cap == 0 {
+                    self.cookie = None;
+                    return None;
+                }
+
+                0
+            } else {
+                self.offset
+            };
+            let data = &self.buf[offset..self.cap];
+
+            // If we're not able to read a directory entry then that means it
+            // must have been truncated at the end of the buffer, so reset our
+            // offset so we can go back and reread into the buffer, picking up
+            // where we last left off.
+            let dirent_size = mem::size_of::<libc::__wasi_dirent_t>();
+            if data.len() < dirent_size {
+                assert!(self.cookie.is_some());
+                assert!(self.buf.len() >= dirent_size);
+                self.offset = self.cap;
+                continue;
+            }
+            let (dirent, data) = data.split_at(dirent_size);
+            let dirent =
+                unsafe { ptr::read_unaligned(dirent.as_ptr() as *const libc::__wasi_dirent_t) };
+
+            // If the file name was truncated, then we need to reinvoke
+            // `readdir` so we truncate our buffer to start over and reread this
+            // descriptor. Note that if our offset is 0 that means the file name
+            // is massive and we need a bigger buffer.
+            if data.len() < dirent.d_namlen as usize {
+                if offset == 0 {
+                    let amt_to_add = self.buf.capacity();
+                    self.buf.extend(iter::repeat(0).take(amt_to_add));
+                }
+                assert!(self.cookie.is_some());
+                self.offset = self.cap;
+                continue;
+            }
+            self.cookie = Some(dirent.d_next);
+            self.offset = offset + dirent_size + dirent.d_namlen as usize;
+
+            let name = &data[..(dirent.d_namlen as usize)];
+
+            // These names are skipped on all other platforms, so let's skip
+            // them here too
+            if name == b"." || name == b".." {
+                continue;
+            }
+
+            return Some(Ok(DirEntry {
+                meta: dirent,
+                name: name.to_vec(),
+                inner: self.inner.clone(),
+            }));
+        }
+    }
+}
+
+impl DirEntry {
+    pub fn path(&self) -> PathBuf {
+        let name = OsStr::from_bytes(&self.name);
+        self.inner.root.join(name)
+    }
+
+    pub fn file_name(&self) -> OsString {
+        OsString::from_vec(self.name.clone())
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        metadata_at(
+            &self.inner.dir.fd,
+            0,
+            OsStr::from_bytes(&self.name).as_ref(),
+        )
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        Ok(FileType {
+            bits: self.meta.d_type,
+        })
+    }
+
+    pub fn ino(&self) -> libc::__wasi_inode_t {
+        self.meta.d_ino
+    }
+}
+
+impl OpenOptions {
+    pub fn new() -> OpenOptions {
+        let mut base = OpenOptions::default();
+        base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW;
+        return base;
+    }
+
+    pub fn read(&mut self, read: bool) {
+        self.read = read;
+    }
+
+    pub fn write(&mut self, write: bool) {
+        self.write = write;
+    }
+
+    pub fn truncate(&mut self, truncate: bool) {
+        self.oflag(libc::__WASI_O_TRUNC, truncate);
+    }
+
+    pub fn create(&mut self, create: bool) {
+        self.oflag(libc::__WASI_O_CREAT, create);
+    }
+
+    pub fn create_new(&mut self, create_new: bool) {
+        self.oflag(libc::__WASI_O_EXCL, create_new);
+        self.oflag(libc::__WASI_O_CREAT, create_new);
+    }
+
+    pub fn directory(&mut self, directory: bool) {
+        self.oflag(libc::__WASI_O_DIRECTORY, directory);
+    }
+
+    fn oflag(&mut self, bit: libc::__wasi_oflags_t, set: bool) {
+        if set {
+            self.oflags |= bit;
+        } else {
+            self.oflags &= !bit;
+        }
+    }
+
+    pub fn append(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_APPEND, set);
+    }
+
+    pub fn dsync(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_DSYNC, set);
+    }
+
+    pub fn nonblock(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_NONBLOCK, set);
+    }
+
+    pub fn rsync(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_RSYNC, set);
+    }
+
+    pub fn sync(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_SYNC, set);
+    }
+
+    fn fdflag(&mut self, bit: libc::__wasi_fdflags_t, set: bool) {
+        if set {
+            self.fdflags |= bit;
+        } else {
+            self.fdflags &= !bit;
+        }
+    }
+
+    pub fn fs_rights_base(&mut self, rights: libc::__wasi_rights_t) {
+        self.rights_base = Some(rights);
+    }
+
+    pub fn fs_rights_inheriting(&mut self, rights: libc::__wasi_rights_t) {
+        self.rights_inheriting = Some(rights);
+    }
+
+    fn rights_base(&self) -> libc::__wasi_rights_t {
+        if let Some(rights) = self.rights_base {
+            return rights;
+        }
+
+        // If rights haven't otherwise been specified try to pick a reasonable
+        // set. This can always be overridden by users via extension traits, and
+        // implementations may give us fewer rights silently than we ask for. So
+        // given that, just look at `read` and `write` and bucket permissions
+        // based on that.
+        let mut base = 0;
+        if self.read {
+            base |= libc::__WASI_RIGHT_FD_READ;
+            base |= libc::__WASI_RIGHT_FD_READDIR;
+        }
+        if self.write {
+            base |= libc::__WASI_RIGHT_FD_WRITE;
+            base |= libc::__WASI_RIGHT_FD_DATASYNC;
+            base |= libc::__WASI_RIGHT_FD_ALLOCATE;
+            base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE;
+        }
+
+        // FIXME: some of these should probably be read-only or write-only...
+        base |= libc::__WASI_RIGHT_FD_ADVISE;
+        base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS;
+        base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES;
+        base |= libc::__WASI_RIGHT_FD_SEEK;
+        base |= libc::__WASI_RIGHT_FD_SYNC;
+        base |= libc::__WASI_RIGHT_FD_TELL;
+        base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY;
+        base |= libc::__WASI_RIGHT_PATH_CREATE_FILE;
+        base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET;
+        base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE;
+        base |= libc::__WASI_RIGHT_PATH_LINK_TARGET;
+        base |= libc::__WASI_RIGHT_PATH_OPEN;
+        base |= libc::__WASI_RIGHT_PATH_READLINK;
+        base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY;
+        base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE;
+        base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET;
+        base |= libc::__WASI_RIGHT_PATH_SYMLINK;
+        base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE;
+        base |= libc::__WASI_RIGHT_POLL_FD_READWRITE;
+
+        return base;
+    }
+
+    fn rights_inheriting(&self) -> libc::__wasi_rights_t {
+        self.rights_inheriting.unwrap_or_else(|| self.rights_base())
+    }
+
+    pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) {
+        self.dirflags = flags;
+    }
+}
+
+impl File {
+    pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
+        let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?;
+        open_at(&dir, &file, opts)
+    }
+
+    pub fn open_at(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
+        open_at(&self.fd, path, opts)
+    }
+
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        let mut ret = FileAttr::zero();
+        self.fd.filestat_get(&mut ret.meta)?;
+        Ok(ret)
+    }
+
+    pub fn metadata_at(
+        &self,
+        flags: libc::__wasi_lookupflags_t,
+        path: &Path,
+    ) -> io::Result<FileAttr> {
+        metadata_at(&self.fd, flags, path)
+    }
+
+    pub fn fsync(&self) -> io::Result<()> {
+        self.fd.sync()
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        self.fd.datasync()
+    }
+
+    pub fn truncate(&self, size: u64) -> io::Result<()> {
+        self.fd.filestat_set_size(size)
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.read_vectored(&mut [IoSliceMut::new(buf)])
+    }
+
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.fd.read(bufs)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.write_vectored(&[IoSlice::new(buf)])
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.fd.write(bufs)
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        self.fd.seek(pos)
+    }
+
+    pub fn duplicate(&self) -> io::Result<File> {
+        // https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-rationale.md#why-no-dup
+        unsupported()
+    }
+
+    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
+        // Permissions haven't been fully figured out in wasi yet, so this is
+        // likely temporary
+        unsupported()
+    }
+
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
+    }
+
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
+    }
+
+    pub fn read_link(&self, file: &Path) -> io::Result<PathBuf> {
+        read_link(&self.fd, file)
+    }
+}
+
+impl FromInner<u32> for File {
+    fn from_inner(fd: u32) -> File {
+        unsafe {
+            File {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
+    }
+}
+
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder {}
+    }
+
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?;
+        dir.create_directory(file.as_os_str().as_bytes())
+    }
+}
+
+impl fmt::Debug for File {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("File")
+            .field("fd", &self.fd.as_raw())
+            .finish()
+    }
+}
+
+pub fn readdir(p: &Path) -> io::Result<ReadDir> {
+    let mut opts = OpenOptions::new();
+    opts.directory(true);
+    opts.read(true);
+    let dir = File::open(p, &opts)?;
+    Ok(ReadDir {
+        cookie: Some(0),
+        buf: vec![0; 128],
+        offset: 0,
+        cap: 0,
+        inner: Arc::new(ReadDirInner {
+            dir,
+            root: p.to_path_buf(),
+        }),
+    })
+}
+
+pub fn unlink(p: &Path) -> io::Result<()> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?;
+    dir.unlink_file(file.as_os_str().as_bytes())
+}
+
+pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
+    let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?;
+    let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?;
+    old.rename(
+        old_file.as_os_str().as_bytes(),
+        &new,
+        new_file.as_os_str().as_bytes(),
+    )
+}
+
+pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+    // Permissions haven't been fully figured out in wasi yet, so this is
+    // likely temporary
+    unsupported()
+}
+
+pub fn rmdir(p: &Path) -> io::Result<()> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?;
+    dir.remove_directory(file.as_os_str().as_bytes())
+}
+
+pub fn readlink(p: &Path) -> io::Result<PathBuf> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?;
+    read_link(&dir, &file)
+}
+
+fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
+    // Try to get a best effort initial capacity for the vector we're going to
+    // fill. Note that if it's not a symlink we don't use a file to avoid
+    // allocating gigabytes if you read_link a huge movie file by accident.
+    // Additionally we add 1 to the initial size so if it doesn't change until
+    // when we call `readlink` the returned length will be less than the
+    // capacity, guaranteeing that we got all the data.
+    let meta = metadata_at(fd, 0, file)?;
+    let initial_size = if meta.file_type().is_symlink() {
+        (meta.size() as usize).saturating_add(1)
+    } else {
+        1 // this'll fail in just a moment
+    };
+
+    // Now that we have an initial guess of how big to make our buffer, call
+    // `readlink` in a loop until it fails or reports it filled fewer bytes than
+    // we asked for, indicating we got everything.
+    let file = file.as_os_str().as_bytes();
+    let mut destination = vec![0u8; initial_size];
+    loop {
+        let len = fd.readlink(file, &mut destination)?;
+        if len < destination.len() {
+            destination.truncate(len);
+            destination.shrink_to_fit();
+            return Ok(PathBuf::from(OsString::from_vec(destination)));
+        }
+        let amt_to_add = destination.len();
+        destination.extend(iter::repeat(0).take(amt_to_add));
+    }
+}
+
+pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
+    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?;
+    dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes())
+}
+
+pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
+    let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?;
+    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?;
+    src.link(
+        libc::__WASI_LOOKUP_SYMLINK_FOLLOW,
+        src_file.as_os_str().as_bytes(),
+        &dst,
+        dst_file.as_os_str().as_bytes(),
+    )
+}
+
+pub fn stat(p: &Path) -> io::Result<FileAttr> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
+    metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file)
+}
+
+pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
+    metadata_at(&dir, 0, &file)
+}
+
+fn metadata_at(
+    fd: &WasiFd,
+    flags: libc::__wasi_lookupflags_t,
+    path: &Path,
+) -> io::Result<FileAttr> {
+    let mut ret = FileAttr::zero();
+    fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?;
+    Ok(ret)
+}
+
+pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+    // This seems to not be in wasi's API yet, and we may need to end up
+    // emulating it ourselves. For now just return an error.
+    unsupported()
+}
+
+fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
+    let fd = fd.open(
+        opts.dirflags,
+        path.as_os_str().as_bytes(),
+        opts.oflags,
+        opts.rights_base(),
+        opts.rights_inheriting(),
+        opts.fdflags,
+    )?;
+    Ok(File { fd })
+}
+
+/// Attempts to open a bare path `p`.
+///
+/// WASI has no fundamental capability to do this. All syscalls and operations
+/// are relative to already-open file descriptors. The C library, however,
+/// manages a map of preopened file descriptors to their path, and then the C
+/// library provides an API to look at this. In other words, when you want to
+/// open a path `p`, you have to find a previously opened file descriptor in a
+/// global table and then see if `p` is relative to that file descriptor.
+///
+/// This function, if successful, will return two items:
+///
+/// * The first is a `ManuallyDrop<WasiFd>`. This represents a preopened file
+///   descriptor which we don't have ownership of, but we can use. You shouldn't
+///   actually drop the `fd`.
+///
+/// * The second is a path that should be a part of `p` and represents a
+///   relative traversal from the file descriptor specified to the desired
+///   location `p`.
+///
+/// If successful you can use the returned file descriptor to perform
+/// file-descriptor-relative operations on the path returned as well. The
+/// `rights` argument indicates what operations are desired on the returned file
+/// descriptor, and if successful the returned file descriptor should have the
+/// appropriate rights for performing `rights` actions.
+///
+/// Note that this can fail if `p` doesn't look like it can be opened relative
+/// to any preopened file descriptor.
+fn open_parent(
+    p: &Path,
+    rights: libc::__wasi_rights_t,
+) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
+    let p = CString::new(p.as_os_str().as_bytes())?;
+    unsafe {
+        let mut ret = ptr::null();
+        let fd = __wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret);
+        if fd == -1 {
+            let msg = format!(
+                "failed to find a preopened file descriptor \
+                 through which {:?} could be opened",
+                p
+            );
+            return Err(io::Error::new(io::ErrorKind::Other, msg));
+        }
+        let path = Path::new(OsStr::from_bytes(CStr::from_ptr(ret).to_bytes()));
+
+        // FIXME: right now `path` is a pointer into `p`, the `CString` above.
+        // When we return `p` is deallocated and we can't use it, so we need to
+        // currently separately allocate `path`. If this becomes an issue though
+        // we should probably turn this into a closure-taking interface or take
+        // `&CString` and then pass off `&Path` tied to the same lifetime.
+        let path = path.to_path_buf();
+
+        return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
+    }
+
+    // FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API
+    // there is published
+    extern "C" {
+        pub fn __wasilibc_find_relpath(
+            path: *const libc::c_char,
+            rights_base: libc::__wasi_rights_t,
+            rights_inheriting: libc::__wasi_rights_t,
+            relative_path: *mut *const libc::c_char,
+        ) -> libc::c_int;
+    }
+}
diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs
new file mode 100644
index 00000000000..ffecca5d1b6
--- /dev/null
+++ b/src/libstd/sys/wasi/io.rs
@@ -0,0 +1,87 @@
+use crate::marker::PhantomData;
+use crate::slice;
+
+use libc::{__wasi_ciovec_t, __wasi_iovec_t, c_void};
+
+#[repr(transparent)]
+pub struct IoSlice<'a> {
+    vec: __wasi_ciovec_t,
+    _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice {
+            vec: __wasi_ciovec_t {
+                buf: buf.as_ptr() as *const c_void,
+                buf_len: buf.len(),
+            },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.buf_len < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        unsafe {
+            self.vec.buf_len -= n;
+            self.vec.buf = self.vec.buf.add(n);
+        }
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self.vec.buf as *const u8, self.vec.buf_len)
+        }
+    }
+}
+
+#[repr(transparent)]
+pub struct IoSliceMut<'a> {
+    vec: __wasi_iovec_t,
+    _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut {
+            vec: __wasi_iovec_t {
+                buf: buf.as_mut_ptr() as *mut c_void,
+                buf_len: buf.len()
+            },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.buf_len < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        unsafe {
+            self.vec.buf_len -= n;
+            self.vec.buf = self.vec.buf.add(n);
+        }
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self.vec.buf as *const u8, self.vec.buf_len)
+        }
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [u8] {
+        unsafe {
+            slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.buf_len)
+        }
+    }
+}
diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs
new file mode 100644
index 00000000000..f842869e08e
--- /dev/null
+++ b/src/libstd/sys/wasi/mod.rs
@@ -0,0 +1,128 @@
+//! System bindings for the wasm/web platform
+//!
+//! This module contains the facade (aka platform-specific) implementations of
+//! OS level functionality for wasm. Note that this wasm is *not* the emscripten
+//! wasm, so we have no runtime here.
+//!
+//! This is all super highly experimental and not actually intended for
+//! wide/production use yet, it's still all in the experimental category. This
+//! will likely change over time.
+//!
+//! Currently all functions here are basically stubs that immediately return
+//! errors. The hope is that with a portability lint we can turn actually just
+//! remove all this and just omit parts of the standard library if we're
+//! compiling for wasm. That way it's a compile time error for something that's
+//! guaranteed to be a runtime error!
+
+use libc;
+use crate::io::{Error, ErrorKind};
+use crate::mem;
+use crate::os::raw::c_char;
+
+pub mod alloc;
+pub mod args;
+#[path = "../wasm/cmath.rs"]
+pub mod cmath;
+#[path = "../wasm/condvar.rs"]
+pub mod condvar;
+pub mod env;
+pub mod fd;
+pub mod fs;
+#[path = "../wasm/memchr.rs"]
+pub mod memchr;
+#[path = "../wasm/mutex.rs"]
+pub mod mutex;
+pub mod net;
+pub mod io;
+pub mod os;
+pub use crate::sys_common::os_str_bytes as os_str;
+pub mod path;
+pub mod pipe;
+pub mod process;
+#[path = "../wasm/rwlock.rs"]
+pub mod rwlock;
+#[path = "../wasm/stack_overflow.rs"]
+pub mod stack_overflow;
+pub mod stdio;
+pub mod thread;
+#[path = "../wasm/thread_local.rs"]
+pub mod thread_local;
+#[path = "../wasm/fast_thread_local.rs"]
+pub mod fast_thread_local;
+pub mod time;
+pub mod ext;
+
+#[cfg(not(test))]
+pub fn init() {
+}
+
+pub fn unsupported<T>() -> crate::io::Result<T> {
+    Err(unsupported_err())
+}
+
+pub fn unsupported_err() -> Error {
+    Error::new(ErrorKind::Other, "operation not supported on wasm yet")
+}
+
+pub fn decode_error_kind(_code: i32) -> ErrorKind {
+    ErrorKind::Other
+}
+
+// This enum is used as the storage for a bunch of types which can't actually
+// exist.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub enum Void {}
+
+pub unsafe fn strlen(mut s: *const c_char) -> usize {
+    let mut n = 0;
+    while *s != 0 {
+        n += 1;
+        s = s.offset(1);
+    }
+    return n
+}
+
+pub unsafe fn abort_internal() -> ! {
+    libc::abort()
+}
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+    let mut ret = (0u64, 0u64);
+    unsafe {
+        let base = &mut ret as *mut (u64, u64) as *mut libc::c_void;
+        let len = mem::size_of_val(&ret);
+        cvt_wasi(libc::__wasi_random_get(base, len)).unwrap();
+    }
+    return ret
+}
+
+#[doc(hidden)]
+pub trait IsMinusOne {
+    fn is_minus_one(&self) -> bool;
+}
+
+macro_rules! impl_is_minus_one {
+    ($($t:ident)*) => ($(impl IsMinusOne for $t {
+        fn is_minus_one(&self) -> bool {
+            *self == -1
+        }
+    })*)
+}
+
+impl_is_minus_one! { i8 i16 i32 i64 isize }
+
+pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
+    if t.is_minus_one() {
+        Err(Error::last_os_error())
+    } else {
+        Ok(t)
+    }
+}
+
+pub fn cvt_wasi(r: u16) -> crate::io::Result<()> {
+    if r != libc::__WASI_ESUCCESS {
+        Err(Error::from_raw_os_error(r as i32))
+    } else {
+        Ok(())
+    }
+}
diff --git a/src/libstd/sys/wasi/net.rs b/src/libstd/sys/wasi/net.rs
new file mode 100644
index 00000000000..80f633a8e1f
--- /dev/null
+++ b/src/libstd/sys/wasi/net.rs
@@ -0,0 +1,426 @@
+use crate::fmt;
+use crate::io::{self, IoSlice, IoSliceMut};
+use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
+use crate::time::Duration;
+use crate::sys::{unsupported, Void};
+use crate::convert::TryFrom;
+use crate::sys::fd::{WasiFd};
+use crate::sys_common::FromInner;
+
+pub struct TcpStream {
+    fd: WasiFd,
+}
+
+impl TcpStream {
+    pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
+        unsupported()
+    }
+
+    pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+        unsupported()
+    }
+
+    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        unsupported()
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        unsupported()
+    }
+
+    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        unsupported()
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        unsupported()
+    }
+
+    pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpStream> {
+        unsupported()
+    }
+
+    pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn nodelay(&self) -> io::Result<bool> {
+        unsupported()
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        unsupported()
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        unsupported()
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
+    }
+
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
+    }
+}
+
+impl FromInner<u32> for TcpStream {
+    fn from_inner(fd: u32) -> TcpStream {
+        unsafe {
+            TcpStream {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
+    }
+}
+
+impl fmt::Debug for TcpStream {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("TcpStream")
+            .field("fd", &self.fd.as_raw())
+            .finish()
+    }
+}
+
+pub struct TcpListener {
+    fd: WasiFd
+}
+
+impl TcpListener {
+    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
+        unsupported()
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        unsupported()
+    }
+
+    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
+        unsupported()
+    }
+
+    pub fn duplicate(&self) -> io::Result<TcpListener> {
+        unsupported()
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        unsupported()
+    }
+
+    pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn only_v6(&self) -> io::Result<bool> {
+        unsupported()
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        unsupported()
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
+    }
+
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
+    }
+}
+
+impl FromInner<u32> for TcpListener {
+    fn from_inner(fd: u32) -> TcpListener {
+        unsafe {
+            TcpListener {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
+    }
+}
+
+impl fmt::Debug for TcpListener {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("TcpListener")
+            .field("fd", &self.fd.as_raw())
+            .finish()
+    }
+}
+
+pub struct UdpSocket {
+    fd: WasiFd,
+}
+
+impl UdpSocket {
+    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
+        unsupported()
+    }
+
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        unsupported()
+    }
+
+    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
+        unsupported()
+    }
+
+    pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        unsupported()
+    }
+
+    pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        unsupported()
+    }
+
+    pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn duplicate(&self) -> io::Result<UdpSocket> {
+        unsupported()
+    }
+
+    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        unsupported()
+    }
+
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        unsupported()
+    }
+
+    pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn broadcast(&self) -> io::Result<bool> {
+        unsupported()
+    }
+
+    pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
+        unsupported()
+    }
+
+    pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
+        unsupported()
+    }
+
+    pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
+        unsupported()
+    }
+
+    pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
+                         -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
+                         -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
+                          -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
+                          -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        unsupported()
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        unsupported()
+    }
+
+    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn send(&self, _: &[u8]) -> io::Result<usize> {
+        unsupported()
+    }
+
+    pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
+    }
+
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
+    }
+}
+
+impl FromInner<u32> for UdpSocket {
+    fn from_inner(fd: u32) -> UdpSocket {
+        unsafe {
+            UdpSocket {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
+    }
+}
+
+impl fmt::Debug for UdpSocket {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("UdpSocket")
+            .field("fd", &self.fd.as_raw())
+            .finish()
+    }
+}
+
+pub struct LookupHost(Void);
+
+impl LookupHost {
+    pub fn port(&self) -> u16 {
+        match self.0 {}
+    }
+}
+
+impl Iterator for LookupHost {
+    type Item = SocketAddr;
+    fn next(&mut self) -> Option<SocketAddr> {
+        match self.0 {}
+    }
+}
+
+impl<'a> TryFrom<&'a str> for LookupHost {
+    type Error = io::Error;
+
+    fn try_from(_v: &'a str) -> io::Result<LookupHost> {
+        unsupported()
+    }
+}
+
+impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
+    type Error = io::Error;
+
+    fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
+        unsupported()
+    }
+}
+
+#[allow(nonstandard_style)]
+pub mod netc {
+    pub const AF_INET: u8 = 0;
+    pub const AF_INET6: u8 = 1;
+    pub type sa_family_t = u8;
+
+    #[derive(Copy, Clone)]
+    pub struct in_addr {
+        pub s_addr: u32,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in {
+        pub sin_family: sa_family_t,
+        pub sin_port: u16,
+        pub sin_addr: in_addr,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct in6_addr {
+        pub s6_addr: [u8; 16],
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in6 {
+        pub sin6_family: sa_family_t,
+        pub sin6_port: u16,
+        pub sin6_addr: in6_addr,
+        pub sin6_flowinfo: u32,
+        pub sin6_scope_id: u32,
+    }
+
+    #[derive(Copy, Clone)]
+    pub struct sockaddr {
+    }
+
+    pub type socklen_t = usize;
+}
diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs
new file mode 100644
index 00000000000..822ea02a11b
--- /dev/null
+++ b/src/libstd/sys/wasi/os.rs
@@ -0,0 +1,184 @@
+use crate::any::Any;
+use crate::error::Error as StdError;
+use crate::ffi::{OsString, OsStr, CString, CStr};
+use crate::fmt;
+use crate::io;
+use crate::marker::PhantomData;
+use crate::os::wasi::prelude::*;
+use crate::path::{self, PathBuf};
+use crate::ptr;
+use crate::str;
+use crate::sys::memchr;
+use crate::sys::{cvt, unsupported, Void};
+use crate::vec;
+
+#[cfg(not(target_feature = "atomics"))]
+pub unsafe fn env_lock() -> impl Any {
+    // No need for a lock if we're single-threaded, but this function will need
+    // to get implemented for multi-threaded scenarios
+}
+
+pub fn errno() -> i32 {
+    extern {
+        #[thread_local]
+        static errno: libc::c_int;
+    }
+
+    unsafe { errno as i32 }
+}
+
+pub fn error_string(errno: i32) -> String {
+    extern {
+        fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char,
+                      buflen: libc::size_t) -> libc::c_int;
+    }
+
+    let mut buf = [0 as libc::c_char; 1024];
+
+    let p = buf.as_mut_ptr();
+    unsafe {
+        if strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
+            panic!("strerror_r failure");
+        }
+        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
+    }
+}
+
+pub fn getcwd() -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub fn chdir(_: &path::Path) -> io::Result<()> {
+    unsupported()
+}
+
+pub struct SplitPaths<'a>(&'a Void);
+
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
+    panic!("unsupported")
+}
+
+impl<'a> Iterator for SplitPaths<'a> {
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> {
+        match *self.0 {}
+    }
+}
+
+#[derive(Debug)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
+    where I: Iterator<Item=T>, T: AsRef<OsStr>
+{
+    Err(JoinPathsError)
+}
+
+impl fmt::Display for JoinPathsError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        "not supported on wasm yet".fmt(f)
+    }
+}
+
+impl StdError for JoinPathsError {
+    fn description(&self) -> &str {
+        "not supported on wasm yet"
+    }
+}
+
+pub fn current_exe() -> io::Result<PathBuf> {
+    unsupported()
+}
+
+pub struct Env {
+    iter: vec::IntoIter<(OsString, OsString)>,
+    _dont_send_or_sync_me: PhantomData<*mut ()>,
+}
+
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+    fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+
+pub fn env() -> Env {
+    unsafe {
+        let _guard = env_lock();
+        let mut environ = libc::environ;
+        let mut result = Vec::new();
+        while environ != ptr::null_mut() && *environ != ptr::null_mut() {
+            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
+                result.push(key_value);
+            }
+            environ = environ.offset(1);
+        }
+        return Env {
+            iter: result.into_iter(),
+            _dont_send_or_sync_me: PhantomData,
+        }
+    }
+
+    // See src/libstd/sys/unix/os.rs, same as that
+    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
+        if input.is_empty() {
+            return None;
+        }
+        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
+        pos.map(|p| (
+            OsStringExt::from_vec(input[..p].to_vec()),
+            OsStringExt::from_vec(input[p+1..].to_vec()),
+        ))
+    }
+}
+
+pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
+    let k = CString::new(k.as_bytes())?;
+    unsafe {
+        let _guard = env_lock();
+        let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
+        let ret = if s.is_null() {
+            None
+        } else {
+            Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
+        };
+        Ok(ret)
+    }
+}
+
+pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    let k = CString::new(k.as_bytes())?;
+    let v = CString::new(v.as_bytes())?;
+
+    unsafe {
+        let _guard = env_lock();
+        cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
+    }
+}
+
+pub fn unsetenv(n: &OsStr) -> io::Result<()> {
+    let nbuf = CString::new(n.as_bytes())?;
+
+    unsafe {
+        let _guard = env_lock();
+        cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
+    }
+}
+
+pub fn temp_dir() -> PathBuf {
+    panic!("no filesystem on wasm")
+}
+
+pub fn home_dir() -> Option<PathBuf> {
+    None
+}
+
+pub fn exit(code: i32) -> ! {
+    unsafe {
+        libc::exit(code)
+    }
+}
+
+pub fn getpid() -> u32 {
+    panic!("unsupported");
+}
diff --git a/src/libstd/sys/wasi/path.rs b/src/libstd/sys/wasi/path.rs
new file mode 100644
index 00000000000..7a183956107
--- /dev/null
+++ b/src/libstd/sys/wasi/path.rs
@@ -0,0 +1,19 @@
+use crate::path::Prefix;
+use crate::ffi::OsStr;
+
+#[inline]
+pub fn is_sep_byte(b: u8) -> bool {
+    b == b'/'
+}
+
+#[inline]
+pub fn is_verbatim_sep(b: u8) -> bool {
+    b == b'/'
+}
+
+pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
+    None
+}
+
+pub const MAIN_SEP_STR: &str = "/";
+pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/wasi/pipe.rs b/src/libstd/sys/wasi/pipe.rs
new file mode 100644
index 00000000000..9f07f054362
--- /dev/null
+++ b/src/libstd/sys/wasi/pipe.rs
@@ -0,0 +1,33 @@
+use crate::io::{self, IoSlice, IoSliceMut};
+use crate::sys::Void;
+
+pub struct AnonPipe(Void);
+
+impl AnonPipe {
+    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn diverge(&self) -> ! {
+        match self.0 {}
+    }
+}
+
+pub fn read2(p1: AnonPipe,
+             _v1: &mut Vec<u8>,
+             _p2: AnonPipe,
+             _v2: &mut Vec<u8>) -> io::Result<()> {
+    match p1.0 {}
+}
diff --git a/src/libstd/sys/wasi/process.rs b/src/libstd/sys/wasi/process.rs
new file mode 100644
index 00000000000..788b829f4ba
--- /dev/null
+++ b/src/libstd/sys/wasi/process.rs
@@ -0,0 +1,152 @@
+use crate::ffi::OsStr;
+use crate::fmt;
+use crate::io;
+use crate::sys::fs::File;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::{unsupported, Void};
+use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+    env: CommandEnv<DefaultEnvKey>
+}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+    pub stdin: Option<AnonPipe>,
+    pub stdout: Option<AnonPipe>,
+    pub stderr: Option<AnonPipe>,
+}
+
+pub enum Stdio {
+    Inherit,
+    Null,
+    MakePipe,
+}
+
+impl Command {
+    pub fn new(_program: &OsStr) -> Command {
+        Command {
+            env: Default::default()
+        }
+    }
+
+    pub fn arg(&mut self, _arg: &OsStr) {
+    }
+
+    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+        &mut self.env
+    }
+
+    pub fn cwd(&mut self, _dir: &OsStr) {
+    }
+
+    pub fn stdin(&mut self, _stdin: Stdio) {
+    }
+
+    pub fn stdout(&mut self, _stdout: Stdio) {
+    }
+
+    pub fn stderr(&mut self, _stderr: Stdio) {
+    }
+
+    pub fn spawn(&mut self, _default: Stdio, _needs_stdin: bool)
+        -> io::Result<(Process, StdioPipes)> {
+        unsupported()
+    }
+}
+
+impl From<AnonPipe> for Stdio {
+    fn from(pipe: AnonPipe) -> Stdio {
+        pipe.diverge()
+    }
+}
+
+impl From<File> for Stdio {
+    fn from(_file: File) -> Stdio {
+        panic!("unsupported")
+    }
+}
+
+impl fmt::Debug for Command {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        Ok(())
+    }
+}
+
+pub struct ExitStatus(Void);
+
+impl ExitStatus {
+    pub fn success(&self) -> bool {
+        match self.0 {}
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        match self.0 {}
+    }
+}
+
+impl Clone for ExitStatus {
+    fn clone(&self) -> ExitStatus {
+        match self.0 {}
+    }
+}
+
+impl Copy for ExitStatus {}
+
+impl PartialEq for ExitStatus {
+    fn eq(&self, _other: &ExitStatus) -> bool {
+        match self.0 {}
+    }
+}
+
+impl Eq for ExitStatus {
+}
+
+impl fmt::Debug for ExitStatus {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.0 {}
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(bool);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(false);
+    pub const FAILURE: ExitCode = ExitCode(true);
+
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
+pub struct Process(Void);
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        match self.0 {}
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        match self.0 {}
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        match self.0 {}
+    }
+
+    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+        match self.0 {}
+    }
+}
diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs
new file mode 100644
index 00000000000..2bf8d803c01
--- /dev/null
+++ b/src/libstd/sys/wasi/stdio.rs
@@ -0,0 +1,81 @@
+use crate::io::{self, IoSlice, IoSliceMut};
+use crate::libc;
+use crate::mem::ManuallyDrop;
+use crate::sys::fd::WasiFd;
+
+pub struct Stdin;
+pub struct Stdout;
+pub struct Stderr;
+
+impl Stdin {
+    pub fn new() -> io::Result<Stdin> {
+        Ok(Stdin)
+    }
+
+    pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
+        self.read_vectored(&mut [IoSliceMut::new(data)])
+    }
+
+    pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) })
+            .read(data)
+    }
+}
+
+impl Stdout {
+    pub fn new() -> io::Result<Stdout> {
+        Ok(Stdout)
+    }
+
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        self.write_vectored(&[IoSlice::new(data)])
+    }
+
+    pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) })
+            .write(data)
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub fn new() -> io::Result<Stderr> {
+        Ok(Stderr)
+    }
+
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        self.write_vectored(&[IoSlice::new(data)])
+    }
+
+    pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) })
+            .write(data)
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl io::Write for Stderr {
+    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+        (&*self).write(data)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        (&*self).flush()
+    }
+}
+
+pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
+
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(libc::__WASI_EBADF as i32)
+}
+
+pub fn panic_output() -> Option<impl io::Write> {
+    Stderr::new().ok()
+}
diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs
new file mode 100644
index 00000000000..5e69e4d948f
--- /dev/null
+++ b/src/libstd/sys/wasi/thread.rs
@@ -0,0 +1,56 @@
+use crate::cmp;
+use crate::ffi::CStr;
+use crate::io;
+use crate::sys::cvt;
+use crate::sys::{unsupported, Void};
+use crate::time::Duration;
+use libc;
+
+pub struct Thread(Void);
+
+pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+
+impl Thread {
+    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
+    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
+        -> io::Result<Thread>
+    {
+        unsupported()
+    }
+
+    pub fn yield_now() {
+        let ret = unsafe { libc::__wasi_sched_yield() };
+        debug_assert_eq!(ret, 0);
+    }
+
+    pub fn set_name(_name: &CStr) {
+        // nope
+    }
+
+    pub fn sleep(dur: Duration) {
+        let mut secs = dur.as_secs();
+        let mut nsecs = dur.subsec_nanos() as i32;
+
+        unsafe {
+            while secs > 0 || nsecs > 0 {
+                let mut ts = libc::timespec {
+                    tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
+                    tv_nsec: nsecs,
+                };
+                secs -= ts.tv_sec as u64;
+                cvt(libc::nanosleep(&ts, &mut ts)).unwrap();
+                nsecs = 0;
+            }
+        }
+    }
+
+    pub fn join(self) {
+        match self.0 {}
+    }
+}
+
+pub mod guard {
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
+}
diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs
new file mode 100644
index 00000000000..3f14c80928c
--- /dev/null
+++ b/src/libstd/sys/wasi/time.rs
@@ -0,0 +1,76 @@
+use crate::time::Duration;
+use crate::mem;
+use crate::sys::cvt_wasi;
+use libc;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct Instant(Duration);
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct SystemTime(Duration);
+
+pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
+
+fn current_time(clock: u32) -> Duration {
+    unsafe {
+        let mut ts = mem::zeroed();
+        cvt_wasi(libc::__wasi_clock_time_get(
+            clock,
+            1, // precision... seems ignored though?
+            &mut ts,
+        )).unwrap();
+        Duration::new(
+            (ts / 1_000_000_000) as u64,
+            (ts % 1_000_000_000) as u32,
+        )
+    }
+}
+
+impl Instant {
+    pub fn now() -> Instant {
+        Instant(current_time(libc::__WASI_CLOCK_MONOTONIC))
+    }
+
+    pub const fn zero() -> Instant {
+        Instant(Duration::from_secs(0))
+    }
+
+    pub fn actually_monotonic() -> bool {
+        true
+    }
+
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        self.0.checked_sub(other.0)
+    }
+
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+        Some(Instant(self.0.checked_add(*other)?))
+    }
+
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
+        Some(Instant(self.0.checked_sub(*other)?))
+    }
+}
+
+impl SystemTime {
+    pub fn now() -> SystemTime {
+        SystemTime(current_time(libc::__WASI_CLOCK_REALTIME))
+    }
+
+    pub fn from_wasi_timestamp(ts: libc::__wasi_timestamp_t) -> SystemTime {
+        SystemTime(Duration::from_nanos(ts))
+    }
+
+    pub fn sub_time(&self, other: &SystemTime)
+                    -> Result<Duration, Duration> {
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
+    }
+
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+        Some(SystemTime(self.0.checked_add(*other)?))
+    }
+
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
+        Some(SystemTime(self.0.checked_sub(*other)?))
+    }
+}
diff --git a/src/libstd/sys/wasm/alloc.rs b/src/libstd/sys/wasm/alloc.rs
index b9098548b9c..c1af6ec1262 100644
--- a/src/libstd/sys/wasm/alloc.rs
+++ b/src/libstd/sys/wasm/alloc.rs
@@ -49,7 +49,6 @@ unsafe impl GlobalAlloc for System {
 
 #[cfg(target_feature = "atomics")]
 mod lock {
-    use crate::arch::wasm32;
     use crate::sync::atomic::{AtomicI32, Ordering::SeqCst};
 
     static LOCKED: AtomicI32 = AtomicI32::new(0);
@@ -61,14 +60,76 @@ mod lock {
             if LOCKED.swap(1, SeqCst) == 0 {
                 return DropLock
             }
-            unsafe {
-                let r = wasm32::i32_atomic_wait(
-                    &LOCKED as *const AtomicI32 as *mut i32,
-                    1,  // expected value
-                    -1, // timeout
-                );
-                debug_assert!(r == 0 || r == 1);
-            }
+            // Ok so here's where things get a little depressing. At this point
+            // in time we need to synchronously acquire a lock, but we're
+            // contending with some other thread. Typically we'd execute some
+            // form of `i32.atomic.wait` like so:
+            //
+            //     unsafe {
+            //         let r = core::arch::wasm32::i32_atomic_wait(
+            //             &LOCKED as *const AtomicI32 as *mut i32,
+            //             1,  //     expected value
+            //             -1, //     timeout
+            //         );
+            //         debug_assert!(r == 0 || r == 1);
+            //     }
+            //
+            // Unfortunately though in doing so we would cause issues for the
+            // main thread. The main thread in a web browser *cannot ever
+            // block*, no exceptions. This means that the main thread can't
+            // actually execute the `i32.atomic.wait` instruction.
+            //
+            // As a result if we want to work within the context of browsers we
+            // need to figure out some sort of allocation scheme for the main
+            // thread where when there's contention on the global malloc lock we
+            // do... something.
+            //
+            // Possible ideas include:
+            //
+            // 1. Attempt to acquire the global lock. If it fails, fall back to
+            //    memory allocation via `memory.grow`. Later just ... somehow
+            //    ... inject this raw page back into the main allocator as it
+            //    gets sliced up over time. This strategy has the downside of
+            //    forcing allocation of a page to happen whenever the main
+            //    thread contents with other threads, which is unfortunate.
+            //
+            // 2. Maintain a form of "two level" allocator scheme where the main
+            //    thread has its own allocator. Somehow this allocator would
+            //    also be balanced with a global allocator, not only to have
+            //    allocations cross between threads but also to ensure that the
+            //    two allocators stay "balanced" in terms of free'd memory and
+            //    such. This, however, seems significantly complicated.
+            //
+            // Out of a lack of other ideas, the current strategy implemented
+            // here is to simply spin. Typical spin loop algorithms have some
+            // form of "hint" here to the CPU that it's what we're doing to
+            // ensure that the CPU doesn't get too hot, but wasm doesn't have
+            // such an instruction.
+            //
+            // To be clear, spinning here is not a great solution.
+            // Another thread with the lock may take quite a long time to wake
+            // up. For example it could be in `memory.grow` or it could be
+            // evicted from the CPU for a timeslice like 10ms. For these periods
+            // of time our thread will "helpfully" sit here and eat CPU time
+            // until it itself is evicted or the lock holder finishes. This
+            // means we're just burning and wasting CPU time to no one's
+            // benefit.
+            //
+            // Spinning does have the nice properties, though, of being
+            // semantically correct, being fair to all threads for memory
+            // allocation, and being simple enough to implement.
+            //
+            // This will surely (hopefully) be replaced in the future with a
+            // real memory allocator that can handle the restriction of the main
+            // thread.
+            //
+            //
+            // FIXME: We can also possibly add an optimization here to detect
+            // when a thread is the main thread or not and block on all
+            // non-main-thread threads. Currently, however, we have no way
+            // of knowing which wasm thread is on the browser main thread, but
+            // if we could figure out we could at least somewhat mitigate the
+            // cost of this spinning.
         }
     }
 
@@ -76,12 +137,16 @@ mod lock {
         fn drop(&mut self) {
             let r = LOCKED.swap(0, SeqCst);
             debug_assert_eq!(r, 1);
-            unsafe {
-                wasm32::atomic_notify(
-                    &LOCKED as *const AtomicI32 as *mut i32,
-                    1, // only one thread
-                );
-            }
+
+            // Note that due to the above logic we don't actually need to wake
+            // anyone up, but if we did it'd likely look something like this:
+            //
+            //     unsafe {
+            //         core::arch::wasm32::atomic_notify(
+            //             &LOCKED as *const AtomicI32 as *mut i32,
+            //             1, //     only one thread
+            //         );
+            //     }
         }
     }
 }
diff --git a/src/libstd/sys/wasm/backtrace.rs b/src/libstd/sys/wasm/backtrace.rs
deleted file mode 100644
index 7d56b298997..00000000000
--- a/src/libstd/sys/wasm/backtrace.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use crate::io;
-use crate::sys::unsupported;
-use crate::sys_common::backtrace::Frame;
-
-pub struct BacktraceContext;
-
-pub fn unwind_backtrace(_frames: &mut [Frame])
-    -> io::Result<(usize, BacktraceContext)>
-{
-    unsupported()
-}
-
-pub fn resolve_symname<F>(_frame: Frame,
-                          _callback: F,
-                          _: &BacktraceContext) -> io::Result<()>
-    where F: FnOnce(Option<&str>) -> io::Result<()>
-{
-    unsupported()
-}
-
-pub fn foreach_symbol_fileline<F>(_: Frame,
-                                  _: F,
-                                  _: &BacktraceContext) -> io::Result<bool>
-    where F: FnMut(&[u8], u32) -> io::Result<()>
-{
-    unsupported()
-}
diff --git a/src/libstd/sys/wasm/fast_thread_local.rs b/src/libstd/sys/wasm/fast_thread_local.rs
new file mode 100644
index 00000000000..ff2198175f0
--- /dev/null
+++ b/src/libstd/sys/wasm/fast_thread_local.rs
@@ -0,0 +1,9 @@
+#![unstable(feature = "thread_local_internals", issue = "0")]
+
+pub unsafe fn register_dtor(_t: *mut u8, _dtor: unsafe extern fn(*mut u8)) {
+    // FIXME: right now there is no concept of "thread exit", but this is likely
+    // going to show up at some point in the form of an exported symbol that the
+    // wasm runtime is oging to be expected to call. For now we basically just
+    // ignore the arguments, but if such a function starts to exist it will
+    // likely look like the OSX implementation in `unix/fast_thread_local.rs`
+}
diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/wasm/fs.rs
index 485d2c87fbd..e9095b375fe 100644
--- a/src/libstd/sys/wasm/fs.rs
+++ b/src/libstd/sys/wasm/fs.rs
@@ -1,7 +1,7 @@
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::io::{self, SeekFrom};
+use crate::io::{self, SeekFrom, IoSlice, IoSliceMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::{unsupported, Void};
@@ -82,7 +82,7 @@ impl Eq for FilePermissions {
 }
 
 impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -125,13 +125,13 @@ impl Hash for FileType {
 }
 
 impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
 
 impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -200,10 +200,18 @@ impl File {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
@@ -236,7 +244,7 @@ impl DirBuilder {
 }
 
 impl fmt::Debug for File {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/wasm/io.rs b/src/libstd/sys/wasm/io.rs
index 8b02d3fd19d..976e122463d 100644
--- a/src/libstd/sys/wasm/io.rs
+++ b/src/libstd/sys/wasm/io.rs
@@ -1,9 +1,16 @@
-pub struct IoVec<'a>(&'a [u8]);
+use crate::mem;
+
+pub struct IoSlice<'a>(&'a [u8]);
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice(buf)
+    }
 
-impl<'a> IoVec<'a> {
     #[inline]
-    pub fn new(buf: &'a [u8]) -> IoVec<'a> {
-        IoVec(buf)
+    pub fn advance(&mut self, n: usize) {
+        self.0 = &self.0[n..]
     }
 
     #[inline]
@@ -12,12 +19,19 @@ impl<'a> IoVec<'a> {
     }
 }
 
-pub struct IoVecMut<'a>(&'a mut [u8]);
+pub struct IoSliceMut<'a>(&'a mut [u8]);
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut(buf)
+    }
 
-impl<'a> IoVecMut<'a> {
     #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoVecMut<'a> {
-        IoVecMut(buf)
+    pub fn advance(&mut self, n: usize) {
+        let slice = mem::replace(&mut self.0, &mut []);
+        let (_, remaining) = slice.split_at_mut(n);
+        self.0 = remaining;
     }
 
     #[inline]
diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs
index 1828cce4e52..56cbafcfdb8 100644
--- a/src/libstd/sys/wasm/mod.rs
+++ b/src/libstd/sys/wasm/mod.rs
@@ -23,8 +23,6 @@ use crate::time::Duration;
 
 pub mod alloc;
 pub mod args;
-#[cfg(feature = "backtrace")]
-pub mod backtrace;
 pub mod cmath;
 pub mod env;
 pub mod fs;
@@ -32,7 +30,6 @@ pub mod io;
 pub mod memchr;
 pub mod net;
 pub mod os;
-pub mod os_str;
 pub mod path;
 pub mod pipe;
 pub mod process;
@@ -40,8 +37,12 @@ pub mod stack_overflow;
 pub mod thread;
 pub mod time;
 pub mod stdio;
+pub mod thread_local;
+pub mod fast_thread_local;
 
-cfg_if! {
+pub use crate::sys_common::os_str_bytes as os_str;
+
+cfg_if::cfg_if! {
     if #[cfg(target_feature = "atomics")] {
         #[path = "condvar_atomics.rs"]
         pub mod condvar;
@@ -49,13 +50,10 @@ cfg_if! {
         pub mod mutex;
         #[path = "rwlock_atomics.rs"]
         pub mod rwlock;
-        #[path = "thread_local_atomics.rs"]
-        pub mod thread_local;
     } else {
         pub mod condvar;
         pub mod mutex;
         pub mod rwlock;
-        pub mod thread_local;
     }
 }
 
diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs
index a2ea2dfbbc0..d50f989d2bb 100644
--- a/src/libstd/sys/wasm/net.rs
+++ b/src/libstd/sys/wasm/net.rs
@@ -1,5 +1,5 @@
 use crate::fmt;
-use crate::io::{self, IoVec, IoVecMut};
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
 use crate::time::Duration;
 use crate::sys::{unsupported, Void};
@@ -40,7 +40,7 @@ impl TcpStream {
         match self.0 {}
     }
 
-    pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         match self.0 {}
     }
 
@@ -48,7 +48,7 @@ impl TcpStream {
         match self.0 {}
     }
 
-    pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
+    pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
         match self.0 {}
     }
 
@@ -94,7 +94,7 @@ impl TcpStream {
 }
 
 impl fmt::Debug for TcpStream {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -144,7 +144,7 @@ impl TcpListener {
 }
 
 impl fmt::Debug for TcpListener {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
@@ -156,6 +156,10 @@ impl UdpSocket {
         unsupported()
     }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        match self.0 {}
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
@@ -278,7 +282,7 @@ impl UdpSocket {
 }
 
 impl fmt::Debug for UdpSocket {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs
index 145f9ccd73a..5d21999a991 100644
--- a/src/libstd/sys/wasm/os.rs
+++ b/src/libstd/sys/wasm/os.rs
@@ -24,7 +24,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> {
 
 pub struct SplitPaths<'a>(&'a Void);
 
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
+pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
     panic!("unsupported")
 }
 
@@ -45,7 +45,7 @@ pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
 }
 
 impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "not supported on wasm yet".fmt(f)
     }
 }
diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs
deleted file mode 100644
index 79b43458d00..00000000000
--- a/src/libstd/sys/wasm/os_str.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-/// The underlying OsString/OsStr implementation on Unix systems: just
-/// a `Vec<u8>`/`[u8]`.
-
-use crate::borrow::Cow;
-use crate::fmt;
-use crate::str;
-use crate::mem;
-use crate::rc::Rc;
-use crate::sync::Arc;
-use crate::sys_common::{AsInner, IntoInner};
-use crate::sys_common::bytestring::debug_fmt_bytestring;
-
-use core::str::lossy::Utf8Lossy;
-
-#[derive(Clone, Hash)]
-pub struct Buf {
-    pub inner: Vec<u8>
-}
-
-pub struct Slice {
-    pub inner: [u8]
-}
-
-impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        debug_fmt_bytestring(&self.inner, formatter)
-    }
-}
-
-impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
-    }
-}
-
-impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl IntoInner<Vec<u8>> for Buf {
-    fn into_inner(self) -> Vec<u8> {
-        self.inner
-    }
-}
-
-impl AsInner<[u8]> for Buf {
-    fn as_inner(&self) -> &[u8] {
-        &self.inner
-    }
-}
-
-
-impl Buf {
-    pub fn from_string(s: String) -> Buf {
-        Buf { inner: s.into_bytes() }
-    }
-
-    #[inline]
-    pub fn with_capacity(capacity: usize) -> Buf {
-        Buf {
-            inner: Vec::with_capacity(capacity)
-        }
-    }
-
-    #[inline]
-    pub fn clear(&mut self) {
-        self.inner.clear()
-    }
-
-    #[inline]
-    pub fn capacity(&self) -> usize {
-        self.inner.capacity()
-    }
-
-    #[inline]
-    pub fn reserve(&mut self, additional: usize) {
-        self.inner.reserve(additional)
-    }
-
-    #[inline]
-    pub fn reserve_exact(&mut self, additional: usize) {
-        self.inner.reserve_exact(additional)
-    }
-
-    #[inline]
-    pub fn shrink_to_fit(&mut self) {
-        self.inner.shrink_to_fit()
-    }
-
-    #[inline]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        self.inner.shrink_to(min_capacity)
-    }
-
-    pub fn as_slice(&self) -> &Slice {
-        unsafe { mem::transmute(&*self.inner) }
-    }
-
-    pub fn into_string(self) -> Result<String, Buf> {
-        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
-    }
-
-    pub fn push_slice(&mut self, s: &Slice) {
-        self.inner.extend_from_slice(&s.inner)
-    }
-
-    #[inline]
-    pub fn into_box(self) -> Box<Slice> {
-        unsafe { mem::transmute(self.inner.into_boxed_slice()) }
-    }
-
-    #[inline]
-    pub fn from_box(boxed: Box<Slice>) -> Buf {
-        let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
-        Buf { inner: inner.into_vec() }
-    }
-
-    #[inline]
-    pub fn into_arc(&self) -> Arc<Slice> {
-        self.as_slice().into_arc()
-    }
-
-    #[inline]
-    pub fn into_rc(&self) -> Rc<Slice> {
-        self.as_slice().into_rc()
-    }
-}
-
-impl Slice {
-    fn from_u8_slice(s: &[u8]) -> &Slice {
-        unsafe { mem::transmute(s) }
-    }
-
-    pub fn from_str(s: &str) -> &Slice {
-        Slice::from_u8_slice(s.as_bytes())
-    }
-
-    pub fn to_str(&self) -> Option<&str> {
-        str::from_utf8(&self.inner).ok()
-    }
-
-    pub fn to_string_lossy(&self) -> Cow<str> {
-        String::from_utf8_lossy(&self.inner)
-    }
-
-    pub fn to_owned(&self) -> Buf {
-        Buf { inner: self.inner.to_vec() }
-    }
-
-    #[inline]
-    pub fn into_box(&self) -> Box<Slice> {
-        let boxed: Box<[u8]> = self.inner.into();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    pub fn empty_box() -> Box<Slice> {
-        let boxed: Box<[u8]> = Default::default();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    #[inline]
-    pub fn into_arc(&self) -> Arc<Slice> {
-        let arc: Arc<[u8]> = Arc::from(&self.inner);
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
-    }
-
-    #[inline]
-    pub fn into_rc(&self) -> Rc<Slice> {
-        let rc: Rc<[u8]> = Rc::from(&self.inner);
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
-    }
-}
diff --git a/src/libstd/sys/wasm/path.rs b/src/libstd/sys/wasm/path.rs
index 5c062e7c97c..7a183956107 100644
--- a/src/libstd/sys/wasm/path.rs
+++ b/src/libstd/sys/wasm/path.rs
@@ -11,7 +11,7 @@ pub fn is_verbatim_sep(b: u8) -> bool {
     b == b'/'
 }
 
-pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
+pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
     None
 }
 
diff --git a/src/libstd/sys/wasm/pipe.rs b/src/libstd/sys/wasm/pipe.rs
index 2582b993b60..9f07f054362 100644
--- a/src/libstd/sys/wasm/pipe.rs
+++ b/src/libstd/sys/wasm/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::sys::Void;
 
 pub struct AnonPipe(Void);
@@ -8,10 +8,18 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs
index c49daaa1632..a02e009d953 100644
--- a/src/libstd/sys/wasm/process.rs
+++ b/src/libstd/sys/wasm/process.rs
@@ -73,7 +73,7 @@ impl From<File> for Stdio {
 }
 
 impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         Ok(())
     }
 }
@@ -108,13 +108,13 @@ impl Eq for ExitStatus {
 }
 
 impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
 
 impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {}
     }
 }
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
index a65c413119f..d06965f3278 100644
--- a/src/libstd/sys/wasm/thread.rs
+++ b/src/libstd/sys/wasm/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::ffi::CStr;
 use crate::io;
 use crate::sys::{unsupported, Void};
@@ -10,7 +9,7 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, _p: Box<dyn FnBox()>)
+    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
         -> io::Result<Thread>
     {
         unsupported()
@@ -60,48 +59,40 @@ pub mod guard {
     pub unsafe fn init() -> Option<Guard> { None }
 }
 
-cfg_if! {
-    if #[cfg(all(target_feature = "atomics", feature = "wasm-bindgen-threads"))] {
-        #[link(wasm_import_module = "__wbindgen_thread_xform__")]
-        extern {
-            fn __wbindgen_current_id() -> u32;
-            fn __wbindgen_tcb_get() -> u32;
-            fn __wbindgen_tcb_set(ptr: u32);
+// This is only used by atomics primitives when the `atomics` feature is
+// enabled. In that mode we currently just use our own thread-local to store our
+// current thread's ID, and then we lazily initialize it to something allocated
+// from a global counter.
+#[cfg(target_feature = "atomics")]
+pub fn my_id() -> u32 {
+    use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};
+
+    static NEXT_ID: AtomicU32 = AtomicU32::new(0);
+
+    #[thread_local]
+    static mut MY_ID: u32 = 0;
+
+    unsafe {
+        // If our thread ID isn't set yet then we need to allocate one. Do so
+        // with with a simple "atomically add to a global counter" strategy.
+        // This strategy doesn't handled what happens when the counter
+        // overflows, however, so just abort everything once the counter
+        // overflows and eventually we could have some sort of recycling scheme
+        // (or maybe this is all totally irrelevant by that point!). In any case
+        // though we're using a CAS loop instead of a `fetch_add` to ensure that
+        // the global counter never overflows.
+        if MY_ID == 0 {
+            let mut cur = NEXT_ID.load(SeqCst);
+            MY_ID = loop {
+                let next = cur.checked_add(1).unwrap_or_else(|| {
+                    crate::arch::wasm32::unreachable()
+                });
+                match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
+                    Ok(_) => break next,
+                    Err(i) => cur = i,
+                }
+            };
         }
-        pub fn my_id() -> u32 {
-            unsafe { __wbindgen_current_id() }
-        }
-
-        // These are currently only ever used in `thread_local_atomics.rs`, if
-        // you'd like to use them be sure to update that and make sure everyone
-        // agrees what's what.
-        pub fn tcb_get() -> *mut u8 {
-            use crate::mem;
-            assert_eq!(mem::size_of::<*mut u8>(), mem::size_of::<u32>());
-            unsafe { __wbindgen_tcb_get() as *mut u8 }
-        }
-
-        pub fn tcb_set(ptr: *mut u8) {
-            unsafe { __wbindgen_tcb_set(ptr as u32); }
-        }
-
-        // FIXME: still need something for hooking exiting a thread to free
-        // data...
-
-    } else if #[cfg(target_feature = "atomics")] {
-        pub fn my_id() -> u32 {
-            panic!("thread ids not implemented on wasm with atomics yet")
-        }
-
-        pub fn tcb_get() -> *mut u8 {
-            panic!("thread local data not implemented on wasm with atomics yet")
-        }
-
-        pub fn tcb_set(_ptr: *mut u8) {
-            panic!("thread local data not implemented on wasm with atomics yet")
-        }
-    } else {
-        // stubbed out because no functions actually access these intrinsics
-        // unless atomics are enabled
+        MY_ID
     }
 }
diff --git a/src/libstd/sys/wasm/thread_local.rs b/src/libstd/sys/wasm/thread_local.rs
index 29e9854bcfc..8a0ca6f3d25 100644
--- a/src/libstd/sys/wasm/thread_local.rs
+++ b/src/libstd/sys/wasm/thread_local.rs
@@ -1,40 +1,26 @@
-use crate::boxed::Box;
-use crate::ptr;
-
 pub type Key = usize;
 
-struct Allocated {
-    value: *mut u8,
-    dtor: Option<unsafe extern fn(*mut u8)>,
-}
-
 #[inline]
-pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
-    Box::into_raw(Box::new(Allocated {
-        value: ptr::null_mut(),
-        dtor,
-    })) as usize
+pub unsafe fn create(_dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
-pub unsafe fn set(key: Key, value: *mut u8) {
-    (*(key as *mut Allocated)).value = value;
+pub unsafe fn set(_key: Key, _value: *mut u8) {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
-pub unsafe fn get(key: Key) -> *mut u8 {
-    (*(key as *mut Allocated)).value
+pub unsafe fn get(_key: Key) -> *mut u8 {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
-pub unsafe fn destroy(key: Key) {
-    let key = Box::from_raw(key as *mut Allocated);
-    if let Some(f) = key.dtor {
-        f(key.value);
-    }
+pub unsafe fn destroy(_key: Key) {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
 pub fn requires_synchronized_create() -> bool {
-    false
+    panic!("should not be used on the wasm target");
 }
diff --git a/src/libstd/sys/wasm/thread_local_atomics.rs b/src/libstd/sys/wasm/thread_local_atomics.rs
deleted file mode 100644
index b408ad0d5c1..00000000000
--- a/src/libstd/sys/wasm/thread_local_atomics.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use crate::sys::thread;
-use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-
-const MAX_KEYS: usize = 128;
-static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
-
-struct ThreadControlBlock {
-    keys: [*mut u8; MAX_KEYS],
-}
-
-impl ThreadControlBlock {
-    fn new() -> ThreadControlBlock {
-        ThreadControlBlock {
-            keys: [0 as *mut u8; MAX_KEYS],
-        }
-    }
-
-    fn get() -> *mut ThreadControlBlock {
-        let ptr = thread::tcb_get();
-        if !ptr.is_null() {
-            return ptr as *mut ThreadControlBlock
-        }
-        let tcb = Box::into_raw(Box::new(ThreadControlBlock::new()));
-        thread::tcb_set(tcb as *mut u8);
-        tcb
-    }
-}
-
-pub type Key = usize;
-
-pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
-    drop(dtor); // FIXME: need to figure out how to hook thread exit to run this
-    let key = NEXT_KEY.fetch_add(1, SeqCst);
-    if key >= MAX_KEYS {
-        NEXT_KEY.store(MAX_KEYS, SeqCst);
-        panic!("cannot allocate space for more TLS keys");
-    }
-    // offset by 1 so we never hand out 0. This is currently required by
-    // `sys_common/thread_local.rs` where it can't cope with keys of value 0
-    // because it messes up the atomic management.
-    return key + 1
-}
-
-pub unsafe fn set(key: Key, value: *mut u8) {
-    (*ThreadControlBlock::get()).keys[key - 1] = value;
-}
-
-pub unsafe fn get(key: Key) -> *mut u8 {
-    (*ThreadControlBlock::get()).keys[key - 1]
-}
-
-pub unsafe fn destroy(_key: Key) {
-    // FIXME: should implement this somehow, this isn't typically called but it
-    // can be called if two threads race to initialize a TLS slot and one ends
-    // up not being needed.
-}
-
-#[inline]
-pub fn requires_synchronized_create() -> bool {
-    false
-}
diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs
index c1228a1b75e..3f71461eea4 100644
--- a/src/libstd/sys/wasm/time.rs
+++ b/src/libstd/sys/wasm/time.rs
@@ -22,8 +22,8 @@ impl Instant {
         false
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        self.0 - other.0
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        self.0.checked_sub(other.0)
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs
index 3f10e6e5983..b04bb484eed 100644
--- a/src/libstd/sys/windows/args.rs
+++ b/src/libstd/sys/windows/args.rs
@@ -164,13 +164,13 @@ pub struct ArgsInnerDebug<'a> {
 }
 
 impl<'a> fmt::Debug for ArgsInnerDebug<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.args.parsed_args_list.as_slice().fmt(f)
     }
 }
 
 impl Args {
-    pub fn inner_debug(&self) -> ArgsInnerDebug {
+    pub fn inner_debug(&self) -> ArgsInnerDebug<'_> {
         ArgsInnerDebug {
             args: self
         }
diff --git a/src/libstd/sys/windows/backtrace/backtrace_gnu.rs b/src/libstd/sys/windows/backtrace/backtrace_gnu.rs
deleted file mode 100644
index 7ac1f8122f7..00000000000
--- a/src/libstd/sys/windows/backtrace/backtrace_gnu.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use crate::io;
-use crate::sys::c;
-use crate::path::PathBuf;
-use crate::fs::{OpenOptions, File};
-use crate::sys::ext::fs::OpenOptionsExt;
-use crate::sys::handle::Handle;
-
-use libc::c_char;
-use super::super::{fill_utf16_buf, os2path, to_u16s, wide_char_to_multi_byte};
-
-fn query_full_process_image_name() -> io::Result<PathBuf> {
-    unsafe {
-        let process_handle = Handle::new(c::OpenProcess(c::PROCESS_QUERY_INFORMATION,
-                                                        c::FALSE,
-                                                        c::GetCurrentProcessId()));
-        fill_utf16_buf(|buf, mut sz| {
-            if c::QueryFullProcessImageNameW(process_handle.raw(), 0, buf, &mut sz) == 0 {
-                0
-            } else {
-                sz
-            }
-        }, os2path)
-    }
-}
-
-fn lock_and_get_executable_filename() -> io::Result<(PathBuf, File)> {
-    // We query the current image name, open the file without FILE_SHARE_DELETE so it
-    // can't be moved and then get the current image name again. If the names are the
-    // same than we have successfully locked the file
-    let image_name1 = query_full_process_image_name()?;
-    let file = OpenOptions::new()
-                .read(true)
-                .share_mode(c::FILE_SHARE_READ | c::FILE_SHARE_WRITE)
-                .open(&image_name1)?;
-    let image_name2 = query_full_process_image_name()?;
-
-    if image_name1 != image_name2 {
-        return Err(io::Error::new(io::ErrorKind::Other,
-                                  "executable moved while trying to lock it"));
-    }
-
-    Ok((image_name1, file))
-}
-
-// Get the executable filename for libbacktrace
-// This returns the path in the ANSI code page and a File which should remain open
-// for as long as the path should remain valid
-pub fn get_executable_filename() -> io::Result<(Vec<c_char>, File)> {
-    let (executable, file) = lock_and_get_executable_filename()?;
-    let u16_executable = to_u16s(executable.into_os_string())?;
-    Ok((wide_char_to_multi_byte(c::CP_ACP, c::WC_NO_BEST_FIT_CHARS,
-                                &u16_executable, true)?, file))
-}
diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs
deleted file mode 100644
index c5b0cc87210..00000000000
--- a/src/libstd/sys/windows/backtrace/mod.rs
+++ /dev/null
@@ -1,355 +0,0 @@
-//! As always, windows has something very different than unix, we mainly want
-//! to avoid having to depend too much on libunwind for windows.
-//!
-//! If you google around, you'll find a fair bit of references to built-in
-//! functions to get backtraces on windows. It turns out that most of these are
-//! in an external library called dbghelp. I was unable to find this library
-//! via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
-//! of it.
-//!
-//! You'll also find that there's a function called CaptureStackBackTrace
-//! mentioned frequently (which is also easy to use), but sadly I didn't have a
-//! copy of that function in my mingw install (maybe it was broken?). Instead,
-//! this takes the route of using StackWalk64 in order to walk the stack.
-
-#![allow(deprecated)] // dynamic_lib
-
-use crate::io;
-use crate::mem;
-use crate::ptr;
-use crate::sys::c;
-use crate::sys::dynamic_lib::DynamicLibrary;
-use crate::sys_common::backtrace::Frame;
-
-use libc::c_void;
-
-macro_rules! sym {
-    ($lib:expr, $e:expr, $t:ident) => (
-        $lib.symbol($e).map(|f| unsafe {
-            $crate::mem::transmute::<usize, $t>(f)
-        })
-    )
-}
-
-mod printing;
-
-#[cfg(target_env = "gnu")]
-#[path = "backtrace_gnu.rs"]
-pub mod gnu;
-
-pub use self::printing::{foreach_symbol_fileline, resolve_symname};
-use self::printing::{load_printing_fns_64, load_printing_fns_ex};
-
-pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
-    let dbghelp = DynamicLibrary::open("dbghelp.dll")?;
-
-    // Fetch the symbols necessary from dbghelp.dll
-    let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?;
-    let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?;
-
-    // StackWalkEx might not be present and we'll fall back to StackWalk64
-    let sw_var = match sym!(dbghelp, "StackWalkEx", StackWalkExFn) {
-        Ok(StackWalkEx) => {
-            StackWalkVariant::StackWalkEx(StackWalkEx, load_printing_fns_ex(&dbghelp)?)
-        }
-        Err(e) => match sym!(dbghelp, "StackWalk64", StackWalk64Fn) {
-            Ok(StackWalk64) => {
-                StackWalkVariant::StackWalk64(StackWalk64, load_printing_fns_64(&dbghelp)?)
-            }
-            Err(..) => return Err(e),
-        },
-    };
-
-    // Allocate necessary structures for doing the stack walk
-    let process = unsafe { c::GetCurrentProcess() };
-
-    let backtrace_context = BacktraceContext {
-        handle: process,
-        SymCleanup,
-        StackWalkVariant: sw_var,
-        dbghelp,
-    };
-
-    // Initialize this process's symbols
-    let ret = unsafe { SymInitialize(process, ptr::null_mut(), c::TRUE) };
-    if ret != c::TRUE {
-        return Ok((0, backtrace_context));
-    }
-
-    // And now that we're done with all the setup, do the stack walking!
-    match backtrace_context.StackWalkVariant {
-        StackWalkVariant::StackWalkEx(StackWalkEx, _) => {
-            set_frames(StackWalkEx, frames).map(|i| (i, backtrace_context))
-        }
-
-        StackWalkVariant::StackWalk64(StackWalk64, _) => {
-            set_frames(StackWalk64, frames).map(|i| (i, backtrace_context))
-        }
-    }
-}
-
-fn set_frames<W: StackWalker>(StackWalk: W, frames: &mut [Frame]) -> io::Result<usize> {
-    let process = unsafe { c::GetCurrentProcess() };
-    let thread = unsafe { c::GetCurrentProcess() };
-    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
-    unsafe { c::RtlCaptureContext(&mut context) };
-    let mut frame = W::Item::new();
-    let image = frame.init(&context);
-
-    let mut i = 0;
-    while i < frames.len()
-        && StackWalk.walk(image, process, thread, &mut frame, &mut context) == c::TRUE
-    {
-        let addr = frame.get_addr();
-        frames[i] = Frame {
-            symbol_addr: addr,
-            exact_position: addr,
-            inline_context: frame.get_inline_context(),
-        };
-
-        i += 1
-    }
-    Ok(i)
-}
-
-type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL;
-type SymCleanupFn = unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
-
-type StackWalkExFn = unsafe extern "system" fn(
-    c::DWORD,
-    c::HANDLE,
-    c::HANDLE,
-    *mut c::STACKFRAME_EX,
-    *mut c::CONTEXT,
-    *mut c_void,
-    *mut c_void,
-    *mut c_void,
-    *mut c_void,
-    c::DWORD,
-) -> c::BOOL;
-
-type StackWalk64Fn = unsafe extern "system" fn(
-    c::DWORD,
-    c::HANDLE,
-    c::HANDLE,
-    *mut c::STACKFRAME64,
-    *mut c::CONTEXT,
-    *mut c_void,
-    *mut c_void,
-    *mut c_void,
-    *mut c_void,
-) -> c::BOOL;
-
-trait StackWalker {
-    type Item: StackFrame;
-
-    fn walk(
-        &self,
-        _: c::DWORD,
-        _: c::HANDLE,
-        _: c::HANDLE,
-        _: &mut Self::Item,
-        _: &mut c::CONTEXT
-    ) -> c::BOOL;
-}
-
-impl StackWalker for StackWalkExFn {
-    type Item = c::STACKFRAME_EX;
-    fn walk(
-        &self,
-        image: c::DWORD,
-        process: c::HANDLE,
-        thread: c::HANDLE,
-        frame: &mut Self::Item,
-        context: &mut c::CONTEXT,
-    ) -> c::BOOL {
-        unsafe {
-            self(
-                image,
-                process,
-                thread,
-                frame,
-                context,
-                ptr::null_mut(),
-                ptr::null_mut(),
-                ptr::null_mut(),
-                ptr::null_mut(),
-                0,
-            )
-        }
-    }
-}
-
-impl StackWalker for StackWalk64Fn {
-    type Item = c::STACKFRAME64;
-    fn walk(
-        &self,
-        image: c::DWORD,
-        process: c::HANDLE,
-        thread: c::HANDLE,
-        frame: &mut Self::Item,
-        context: &mut c::CONTEXT,
-    ) -> c::BOOL {
-        unsafe {
-            self(
-                image,
-                process,
-                thread,
-                frame,
-                context,
-                ptr::null_mut(),
-                ptr::null_mut(),
-                ptr::null_mut(),
-                ptr::null_mut(),
-            )
-        }
-    }
-}
-
-trait StackFrame {
-    fn new() -> Self;
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD;
-    fn get_addr(&self) -> *const u8;
-    fn get_inline_context(&self) -> u32;
-}
-
-impl StackFrame for c::STACKFRAME_EX {
-    fn new() -> c::STACKFRAME_EX {
-        unsafe { mem::zeroed() }
-    }
-
-    #[cfg(target_arch = "x86")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Eip as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Esp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.Ebp as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_I386
-    }
-
-    #[cfg(target_arch = "x86_64")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Rip as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Rsp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.Rbp as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_AMD64
-    }
-
-    #[cfg(target_arch = "arm")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Pc as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Sp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.R11 as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_ARMNT
-    }
-
-    #[cfg(target_arch = "aarch64")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Pc as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Sp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.Fp as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_ARM64
-    }
-
-    fn get_addr(&self) -> *const u8 {
-        (self.AddrPC.Offset - 1) as *const u8
-    }
-
-    fn get_inline_context(&self) -> u32 {
-        self.InlineFrameContext
-    }
-}
-
-impl StackFrame for c::STACKFRAME64 {
-    fn new() -> c::STACKFRAME64 {
-        unsafe { mem::zeroed() }
-    }
-
-    #[cfg(target_arch = "x86")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Eip as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Esp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.Ebp as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_I386
-    }
-
-    #[cfg(target_arch = "x86_64")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Rip as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Rsp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.Rbp as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_AMD64
-    }
-
-    #[cfg(target_arch = "arm")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Pc as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Sp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.R11 as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_ARMNT
-    }
-
-    #[cfg(target_arch = "aarch64")]
-    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
-        self.AddrPC.Offset = ctx.Pc as u64;
-        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrStack.Offset = ctx.Sp as u64;
-        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        self.AddrFrame.Offset = ctx.Fp as u64;
-        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-        c::IMAGE_FILE_MACHINE_ARM64
-    }
-
-    fn get_addr(&self) -> *const u8 {
-        (self.AddrPC.Offset - 1) as *const u8
-    }
-
-    fn get_inline_context(&self) -> u32 {
-        0
-    }
-}
-
-enum StackWalkVariant {
-    StackWalkEx(StackWalkExFn, printing::PrintingFnsEx),
-    StackWalk64(StackWalk64Fn, printing::PrintingFns64),
-}
-
-pub struct BacktraceContext {
-    handle: c::HANDLE,
-    SymCleanup: SymCleanupFn,
-    // Only used in printing for msvc and not gnu
-    // The gnu version is effectively a ZST dummy.
-    #[allow(dead_code)]
-    StackWalkVariant: StackWalkVariant,
-    // keeping DynamycLibrary loaded until its functions no longer needed
-    #[allow(dead_code)]
-    dbghelp: DynamicLibrary,
-}
-
-impl Drop for BacktraceContext {
-    fn drop(&mut self) {
-        unsafe {
-            (self.SymCleanup)(self.handle);
-        }
-    }
-}
diff --git a/src/libstd/sys/windows/backtrace/printing/mod.rs b/src/libstd/sys/windows/backtrace/printing/mod.rs
deleted file mode 100644
index 9497d51ac17..00000000000
--- a/src/libstd/sys/windows/backtrace/printing/mod.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-#[cfg(target_env = "msvc")]
-#[path = "msvc.rs"]
-mod printing;
-
-#[cfg(target_env = "gnu")]
-mod printing {
-    pub use crate::sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
-
-    // dummy functions to mirror those present in msvc version.
-    use crate::sys::dynamic_lib::DynamicLibrary;
-    use crate::io;
-    pub struct PrintingFnsEx {}
-    pub struct PrintingFns64 {}
-    pub fn load_printing_fns_ex(_: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
-        Ok(PrintingFnsEx{})
-    }
-    pub fn load_printing_fns_64(_: &DynamicLibrary) -> io::Result<PrintingFns64> {
-        Ok(PrintingFns64{})
-    }
-}
-
-pub use self::printing::{foreach_symbol_fileline, resolve_symname};
-pub use self::printing::{load_printing_fns_ex, load_printing_fns_64,
-                         PrintingFnsEx, PrintingFns64};
diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs
deleted file mode 100644
index 13a1512d0eb..00000000000
--- a/src/libstd/sys/windows/backtrace/printing/msvc.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-use crate::ffi::CStr;
-use crate::io;
-use crate::mem;
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys::backtrace::StackWalkVariant;
-use crate::sys::c;
-use crate::sys::dynamic_lib::DynamicLibrary;
-use crate::sys_common::backtrace::Frame;
-
-use libc::{c_char, c_ulong};
-
-// Structs holding printing functions and loaders for them
-// Two versions depending on whether dbghelp.dll has StackWalkEx or not
-// (the former being in newer Windows versions, the older being in Win7 and before)
-pub struct PrintingFnsEx {
-    resolve_symname: SymFromInlineContextFn,
-    sym_get_line: SymGetLineFromInlineContextFn,
-}
-pub struct PrintingFns64 {
-    resolve_symname: SymFromAddrFn,
-    sym_get_line: SymGetLineFromAddr64Fn,
-}
-
-pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
-    Ok(PrintingFnsEx {
-        resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?,
-        sym_get_line: sym!(
-            dbghelp,
-            "SymGetLineFromInlineContext",
-            SymGetLineFromInlineContextFn
-        )?,
-    })
-}
-pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result<PrintingFns64> {
-    Ok(PrintingFns64 {
-        resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
-        sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?,
-    })
-}
-
-type SymFromAddrFn =
-    unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
-type SymFromInlineContextFn =
-    unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
-
-type SymGetLineFromAddr64Fn =
-    unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
-type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
-    c::HANDLE,
-    u64,
-    c::ULONG,
-    u64,
-    *mut c::DWORD,
-    *mut c::IMAGEHLP_LINE64,
-) -> c::BOOL;
-
-/// Converts a pointer to symbol to its string value.
-pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
-where
-    F: FnOnce(Option<&str>) -> io::Result<()>,
-{
-    match context.StackWalkVariant {
-        StackWalkVariant::StackWalkEx(_, ref fns) => resolve_symname_internal(
-            |process: c::HANDLE,
-             symbol_address: u64,
-             inline_context: c::ULONG,
-             info: *mut c::SYMBOL_INFO| unsafe {
-                let mut displacement = 0u64;
-                (fns.resolve_symname)(
-                    process,
-                    symbol_address,
-                    inline_context,
-                    &mut displacement,
-                    info,
-                )
-            },
-            frame,
-            callback,
-            context,
-        ),
-        StackWalkVariant::StackWalk64(_, ref fns) => resolve_symname_internal(
-            |process: c::HANDLE,
-             symbol_address: u64,
-             _inline_context: c::ULONG,
-             info: *mut c::SYMBOL_INFO| unsafe {
-                let mut displacement = 0u64;
-                (fns.resolve_symname)(process, symbol_address, &mut displacement, info)
-            },
-            frame,
-            callback,
-            context,
-        ),
-    }
-}
-
-fn resolve_symname_internal<F, R>(
-    mut symbol_resolver: R,
-    frame: Frame,
-    callback: F,
-    context: &BacktraceContext,
-) -> io::Result<()>
-where
-    F: FnOnce(Option<&str>) -> io::Result<()>,
-    R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL,
-{
-    unsafe {
-        let mut info: c::SYMBOL_INFO = mem::zeroed();
-        info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
-        // the struct size in C.  the value is different to
-        // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
-        // due to struct alignment.
-        info.SizeOfStruct = 88;
-
-        let ret = symbol_resolver(
-            context.handle,
-            frame.symbol_addr as u64,
-            frame.inline_context,
-            &mut info,
-        );
-        let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
-            if info.Size != 0 {
-                (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
-            } else {
-                true
-            }
-        } else {
-            false
-        };
-        let symname = if valid_range {
-            let ptr = info.Name.as_ptr() as *const c_char;
-            CStr::from_ptr(ptr).to_str().ok()
-        } else {
-            None
-        };
-        callback(symname)
-    }
-}
-
-pub fn foreach_symbol_fileline<F>(
-    frame: Frame,
-    callback: F,
-    context: &BacktraceContext,
-) -> io::Result<bool>
-where
-    F: FnMut(&[u8], u32) -> io::Result<()>,
-{
-    match context.StackWalkVariant {
-        StackWalkVariant::StackWalkEx(_, ref fns) => foreach_symbol_fileline_iternal(
-            |process: c::HANDLE,
-             frame_address: u64,
-             inline_context: c::ULONG,
-             line: *mut c::IMAGEHLP_LINE64| unsafe {
-                let mut displacement = 0u32;
-                (fns.sym_get_line)(
-                    process,
-                    frame_address,
-                    inline_context,
-                    0,
-                    &mut displacement,
-                    line,
-                )
-            },
-            frame,
-            callback,
-            context,
-        ),
-        StackWalkVariant::StackWalk64(_, ref fns) => foreach_symbol_fileline_iternal(
-            |process: c::HANDLE,
-             frame_address: u64,
-             _inline_context: c::ULONG,
-             line: *mut c::IMAGEHLP_LINE64| unsafe {
-                let mut displacement = 0u32;
-                (fns.sym_get_line)(process, frame_address, &mut displacement, line)
-            },
-            frame,
-            callback,
-            context,
-        ),
-    }
-}
-
-fn foreach_symbol_fileline_iternal<F, G>(
-    mut line_getter: G,
-    frame: Frame,
-    mut callback: F,
-    context: &BacktraceContext,
-) -> io::Result<bool>
-where
-    F: FnMut(&[u8], u32) -> io::Result<()>,
-    G: FnMut(c::HANDLE, u64, c::ULONG, *mut c::IMAGEHLP_LINE64) -> c::BOOL,
-{
-    unsafe {
-        let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
-        line.SizeOfStruct = mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
-
-        let ret = line_getter(
-            context.handle,
-            frame.exact_position as u64,
-            frame.inline_context,
-            &mut line,
-        );
-        if ret == c::TRUE {
-            let name = CStr::from_ptr(line.Filename).to_bytes();
-            callback(name, line.LineNumber as u32)?;
-        }
-        Ok(false)
-    }
-}
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 518eccf754c..f706709c9cc 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -5,8 +5,6 @@
 #![unstable(issue = "0", feature = "windows_c")]
 
 use crate::os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort, c_char};
-#[cfg(target_arch = "x86_64")]
-use crate::os::raw::c_ulonglong;
 use crate::ptr;
 
 use libc::{wchar_t, size_t, c_void};
@@ -33,16 +31,10 @@ pub type WORD = u16;
 pub type CHAR = c_char;
 pub type ULONG_PTR = usize;
 pub type ULONG = c_ulong;
-#[cfg(target_arch = "x86_64")]
-pub type ULONGLONG = u64;
-#[cfg(target_arch = "x86_64")]
-pub type DWORDLONG = ULONGLONG;
 
 pub type LPBOOL = *mut BOOL;
 pub type LPBYTE = *mut BYTE;
-pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
 pub type LPCSTR = *const CHAR;
-pub type LPCVOID = *const c_void;
 pub type LPCWSTR = *const WCHAR;
 pub type LPDWORD = *mut DWORD;
 pub type LPHANDLE = *mut HANDLE;
@@ -108,11 +100,6 @@ pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
 
 pub const FIONBIO: c_ulong = 0x8004667e;
 
-#[cfg(target_arch = "arm")]
-const ARM_MAX_BREAKPOINTS: usize = 8;
-#[cfg(target_arch = "arm")]
-const ARM_MAX_WATCHPOINTS: usize = 1;
-
 #[repr(C)]
 #[derive(Copy)]
 pub struct WIN32_FIND_DATAW {
@@ -132,6 +119,7 @@ impl Clone for WIN32_FIND_DATAW {
 }
 
 pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
+pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80;
 
 pub const WSADESCRIPTION_LEN: usize = 256;
 pub const WSASYS_STATUS_LEN: usize = 128;
@@ -141,6 +129,7 @@ pub const INVALID_SOCKET: SOCKET = !0;
 pub const WSAEACCES: c_int = 10013;
 pub const WSAEINVAL: c_int = 10022;
 pub const WSAEWOULDBLOCK: c_int = 10035;
+pub const WSAEPROTOTYPE: c_int = 10041;
 pub const WSAEADDRINUSE: c_int = 10048;
 pub const WSAEADDRNOTAVAIL: c_int = 10049;
 pub const WSAECONNABORTED: c_int = 10053;
@@ -152,7 +141,6 @@ pub const WSAECONNREFUSED: c_int = 10061;
 
 pub const MAX_PROTOCOL_CHAIN: DWORD = 7;
 
-pub const TOKEN_READ: DWORD = 0x20008;
 pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
 pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
 pub const IO_REPARSE_TAG_SYMLINK: DWORD = 0xa000000c;
@@ -168,8 +156,6 @@ pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
 pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
 pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
 
-pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
-
 pub const PROGRESS_CONTINUE: DWORD = 0;
 
 pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
@@ -270,26 +256,6 @@ pub const WAIT_OBJECT_0: DWORD = 0x00000000;
 pub const WAIT_TIMEOUT: DWORD = 258;
 pub const WAIT_FAILED: DWORD = 0xFFFFFFFF;
 
-#[cfg(target_env = "msvc")]
-#[cfg(feature = "backtrace")]
-pub const MAX_SYM_NAME: usize = 2000;
-#[cfg(target_arch = "x86")]
-#[cfg(feature = "backtrace")]
-pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
-#[cfg(target_arch = "x86_64")]
-#[cfg(feature = "backtrace")]
-pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
-#[cfg(target_arch = "aarch64")]
-#[cfg(feature = "backtrace")]
-pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
-#[cfg(target_arch = "arm")]
-#[cfg(feature = "backtrace")]
-pub const IMAGE_FILE_MACHINE_ARMNT: DWORD = 0x01c4;
-
-pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
-pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
-pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
-
 pub const PIPE_ACCESS_INBOUND: DWORD = 0x00000001;
 pub const PIPE_ACCESS_OUTBOUND: DWORD = 0x00000002;
 pub const FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD = 0x00080000;
@@ -370,20 +336,6 @@ pub struct WIN32_FILE_ATTRIBUTE_DATA {
 }
 
 #[repr(C)]
-pub struct BY_HANDLE_FILE_INFORMATION {
-    pub dwFileAttributes: DWORD,
-    pub ftCreationTime: FILETIME,
-    pub ftLastAccessTime: FILETIME,
-    pub ftLastWriteTime: FILETIME,
-    pub dwVolumeSerialNumber: DWORD,
-    pub nFileSizeHigh: DWORD,
-    pub nFileSizeLow: DWORD,
-    pub nNumberOfLinks: DWORD,
-    pub nFileIndexHigh: DWORD,
-    pub nFileIndexLow: DWORD,
-}
-
-#[repr(C)]
 #[allow(dead_code)] // we only use some variants
 pub enum FILE_INFO_BY_HANDLE_CLASS {
     FileBasicInfo                   = 0,
@@ -489,25 +441,6 @@ pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
 }
 
 #[repr(C)]
-pub struct EXCEPTION_RECORD {
-    pub ExceptionCode: DWORD,
-    pub ExceptionFlags: DWORD,
-    pub ExceptionRecord: *mut EXCEPTION_RECORD,
-    pub ExceptionAddress: LPVOID,
-    pub NumberParameters: DWORD,
-    pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS]
-}
-
-#[repr(C)]
-pub struct EXCEPTION_POINTERS {
-    pub ExceptionRecord: *mut EXCEPTION_RECORD,
-    pub ContextRecord: *mut CONTEXT,
-}
-
-pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
-        fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
-
-#[repr(C)]
 pub struct GUID {
     pub Data1: DWORD,
     pub Data2: WORD,
@@ -581,41 +514,6 @@ pub struct OVERLAPPED {
 }
 
 #[repr(C)]
-#[cfg(target_env = "msvc")]
-#[cfg(feature = "backtrace")]
-pub struct SYMBOL_INFO {
-    pub SizeOfStruct: c_ulong,
-    pub TypeIndex: c_ulong,
-    pub Reserved: [u64; 2],
-    pub Index: c_ulong,
-    pub Size: c_ulong,
-    pub ModBase: u64,
-    pub Flags: c_ulong,
-    pub Value: u64,
-    pub Address: u64,
-    pub Register: c_ulong,
-    pub Scope: c_ulong,
-    pub Tag: c_ulong,
-    pub NameLen: c_ulong,
-    pub MaxNameLen: c_ulong,
-    // note that windows has this as 1, but it basically just means that
-    // the name is inline at the end of the struct. For us, we just bump
-    // the struct size up to MAX_SYM_NAME.
-    pub Name: [c_char; MAX_SYM_NAME],
-}
-
-#[repr(C)]
-#[cfg(target_env = "msvc")]
-#[cfg(feature = "backtrace")]
-pub struct IMAGEHLP_LINE64 {
-    pub SizeOfStruct: u32,
-    pub Key: *const c_void,
-    pub LineNumber: u32,
-    pub Filename: *const c_char,
-    pub Address: u64,
-}
-
-#[repr(C)]
 #[allow(dead_code)] // we only use some variants
 pub enum ADDRESS_MODE {
     AddrMode1616,
@@ -625,280 +523,6 @@ pub enum ADDRESS_MODE {
 }
 
 #[repr(C)]
-#[cfg(feature = "backtrace")]
-pub struct ADDRESS64 {
-    pub Offset: u64,
-    pub Segment: u16,
-    pub Mode: ADDRESS_MODE,
-}
-
-#[repr(C)]
-#[cfg(feature = "backtrace")]
-pub struct STACKFRAME_EX {
-    pub AddrPC: ADDRESS64,
-    pub AddrReturn: ADDRESS64,
-    pub AddrFrame: ADDRESS64,
-    pub AddrStack: ADDRESS64,
-    pub AddrBStore: ADDRESS64,
-    pub FuncTableEntry: *mut c_void,
-    pub Params: [u64; 4],
-    pub Far: BOOL,
-    pub Virtual: BOOL,
-    pub Reserved: [u64; 3],
-    pub KdHelp: KDHELP64,
-    pub StackFrameSize: DWORD,
-    pub InlineFrameContext: DWORD,
-}
-
-#[repr(C)]
-#[cfg(feature = "backtrace")]
-pub struct STACKFRAME64 {
-    pub AddrPC: ADDRESS64,
-    pub AddrReturn: ADDRESS64,
-    pub AddrFrame: ADDRESS64,
-    pub AddrStack: ADDRESS64,
-    pub AddrBStore: ADDRESS64,
-    pub FuncTableEntry: *mut c_void,
-    pub Params: [u64; 4],
-    pub Far: BOOL,
-    pub Virtual: BOOL,
-    pub Reserved: [u64; 3],
-    pub KdHelp: KDHELP64,
-}
-
-#[repr(C)]
-#[cfg(feature = "backtrace")]
-pub struct KDHELP64 {
-    pub Thread: u64,
-    pub ThCallbackStack: DWORD,
-    pub ThCallbackBStore: DWORD,
-    pub NextCallback: DWORD,
-    pub FramePointer: DWORD,
-    pub KiCallUserMode: u64,
-    pub KeUserCallbackDispatcher: u64,
-    pub SystemRangeStart: u64,
-    pub KiUserExceptionDispatcher: u64,
-    pub StackBase: u64,
-    pub StackLimit: u64,
-    pub Reserved: [u64; 5],
-}
-
-#[cfg(target_arch = "x86")]
-#[repr(C)]
-pub struct CONTEXT {
-    pub ContextFlags: DWORD,
-    pub Dr0: DWORD,
-    pub Dr1: DWORD,
-    pub Dr2: DWORD,
-    pub Dr3: DWORD,
-    pub Dr6: DWORD,
-    pub Dr7: DWORD,
-    pub FloatSave: FLOATING_SAVE_AREA,
-    pub SegGs: DWORD,
-    pub SegFs: DWORD,
-    pub SegEs: DWORD,
-    pub SegDs: DWORD,
-    pub Edi: DWORD,
-    pub Esi: DWORD,
-    pub Ebx: DWORD,
-    pub Edx: DWORD,
-    pub Ecx: DWORD,
-    pub Eax: DWORD,
-    pub Ebp: DWORD,
-    pub Eip: DWORD,
-    pub SegCs: DWORD,
-    pub EFlags: DWORD,
-    pub Esp: DWORD,
-    pub SegSs: DWORD,
-    pub ExtendedRegisters: [u8; 512],
-}
-
-#[cfg(target_arch = "x86")]
-#[repr(C)]
-pub struct FLOATING_SAVE_AREA {
-    pub ControlWord: DWORD,
-    pub StatusWord: DWORD,
-    pub TagWord: DWORD,
-    pub ErrorOffset: DWORD,
-    pub ErrorSelector: DWORD,
-    pub DataOffset: DWORD,
-    pub DataSelector: DWORD,
-    pub RegisterArea: [u8; 80],
-    pub Cr0NpxState: DWORD,
-}
-
-#[cfg(target_arch = "x86_64")]
-#[repr(C, align(16))]
-pub struct CONTEXT {
-    pub P1Home: DWORDLONG,
-    pub P2Home: DWORDLONG,
-    pub P3Home: DWORDLONG,
-    pub P4Home: DWORDLONG,
-    pub P5Home: DWORDLONG,
-    pub P6Home: DWORDLONG,
-
-    pub ContextFlags: DWORD,
-    pub MxCsr: DWORD,
-
-    pub SegCs: WORD,
-    pub SegDs: WORD,
-    pub SegEs: WORD,
-    pub SegFs: WORD,
-    pub SegGs: WORD,
-    pub SegSs: WORD,
-    pub EFlags: DWORD,
-
-    pub Dr0: DWORDLONG,
-    pub Dr1: DWORDLONG,
-    pub Dr2: DWORDLONG,
-    pub Dr3: DWORDLONG,
-    pub Dr6: DWORDLONG,
-    pub Dr7: DWORDLONG,
-
-    pub Rax: DWORDLONG,
-    pub Rcx: DWORDLONG,
-    pub Rdx: DWORDLONG,
-    pub Rbx: DWORDLONG,
-    pub Rsp: DWORDLONG,
-    pub Rbp: DWORDLONG,
-    pub Rsi: DWORDLONG,
-    pub Rdi: DWORDLONG,
-    pub R8:  DWORDLONG,
-    pub R9:  DWORDLONG,
-    pub R10: DWORDLONG,
-    pub R11: DWORDLONG,
-    pub R12: DWORDLONG,
-    pub R13: DWORDLONG,
-    pub R14: DWORDLONG,
-    pub R15: DWORDLONG,
-
-    pub Rip: DWORDLONG,
-
-    pub FltSave: FLOATING_SAVE_AREA,
-
-    pub VectorRegister: [M128A; 26],
-    pub VectorControl: DWORDLONG,
-
-    pub DebugControl: DWORDLONG,
-    pub LastBranchToRip: DWORDLONG,
-    pub LastBranchFromRip: DWORDLONG,
-    pub LastExceptionToRip: DWORDLONG,
-    pub LastExceptionFromRip: DWORDLONG,
-}
-
-#[cfg(target_arch = "x86_64")]
-#[repr(C, align(16))]
-pub struct M128A {
-    pub Low:  c_ulonglong,
-    pub High: c_longlong
-}
-
-#[cfg(target_arch = "x86_64")]
-#[repr(C, align(16))]
-pub struct FLOATING_SAVE_AREA {
-    _Dummy: [u8; 512] // FIXME: Fill this out
-}
-
-#[cfg(target_arch = "arm")]
-#[repr(C)]
-pub struct CONTEXT {
-    pub ContextFlags: ULONG,
-    pub R0: ULONG,
-    pub R1: ULONG,
-    pub R2: ULONG,
-    pub R3: ULONG,
-    pub R4: ULONG,
-    pub R5: ULONG,
-    pub R6: ULONG,
-    pub R7: ULONG,
-    pub R8: ULONG,
-    pub R9: ULONG,
-    pub R10: ULONG,
-    pub R11: ULONG,
-    pub R12: ULONG,
-    pub Sp: ULONG,
-    pub Lr: ULONG,
-    pub Pc: ULONG,
-    pub Cpsr: ULONG,
-    pub Fpscr: ULONG,
-    pub Padding: ULONG,
-    pub D: [u64; 32],
-    pub Bvr: [ULONG; ARM_MAX_BREAKPOINTS],
-    pub Bcr: [ULONG; ARM_MAX_BREAKPOINTS],
-    pub Wvr: [ULONG; ARM_MAX_WATCHPOINTS],
-    pub Wcr: [ULONG; ARM_MAX_WATCHPOINTS],
-    pub Padding2: [ULONG; 2]
-}
-
-// FIXME(#43348): This structure is used for backtrace only, and a fake
-// definition is provided here only to allow rustdoc to pass type-check. This
-// will not appear in the final documentation. This should be also defined for
-// other architectures supported by Windows such as ARM, and for historical
-// interest, maybe MIPS and PowerPC as well.
-#[cfg(all(rustdoc, not(any(target_arch = "x86_64", target_arch = "x86",
-      target_arch = "aarch64", target_arch = "arm"))))]
-pub enum CONTEXT {}
-
-#[cfg(target_arch = "aarch64")]
-pub const ARM64_MAX_BREAKPOINTS: usize = 8;
-
-#[cfg(target_arch = "aarch64")]
-pub const ARM64_MAX_WATCHPOINTS: usize = 2;
-
-#[cfg(target_arch = "aarch64")]
-#[repr(C)]
-pub struct ARM64_NT_NEON128 {
-    pub D: [f64; 2],
-}
-
-#[cfg(target_arch = "aarch64")]
-#[repr(C, align(16))]
-pub struct CONTEXT {
-    pub ContextFlags: DWORD,
-    pub Cpsr: DWORD,
-    pub X0: u64,
-    pub X1: u64,
-    pub X2: u64,
-    pub X3: u64,
-    pub X4: u64,
-    pub X5: u64,
-    pub X6: u64,
-    pub X7: u64,
-    pub X8: u64,
-    pub X9: u64,
-    pub X10: u64,
-    pub X11: u64,
-    pub X12: u64,
-    pub X13: u64,
-    pub X14: u64,
-    pub X15: u64,
-    pub X16: u64,
-    pub X17: u64,
-    pub X18: u64,
-    pub X19: u64,
-    pub X20: u64,
-    pub X21: u64,
-    pub X22: u64,
-    pub X23: u64,
-    pub X24: u64,
-    pub X25: u64,
-    pub X26: u64,
-    pub X27: u64,
-    pub X28: u64,
-    pub Fp: u64,
-    pub Lr: u64,
-    pub Sp: u64,
-    pub Pc: u64,
-    pub V: [ARM64_NT_NEON128; 32],
-    pub Fpcr: DWORD,
-    pub Fpsr: DWORD,
-    pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
-    pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
-    pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
-    pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
-}
-
-#[repr(C)]
 pub struct SOCKADDR_STORAGE_LH {
     pub ss_family: ADDRESS_FAMILY,
     pub __ss_pad1: [CHAR; 6],
@@ -960,16 +584,6 @@ pub enum EXCEPTION_DISPOSITION {
 }
 
 #[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CONSOLE_READCONSOLE_CONTROL {
-    pub nLength: ULONG,
-    pub nInitialChars: ULONG,
-    pub dwCtrlWakeupMask: ULONG,
-    pub dwControlKeyState: ULONG,
-}
-pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
-
-#[repr(C)]
 #[derive(Copy)]
 pub struct fd_set {
     pub fd_count: c_uint,
@@ -989,6 +603,134 @@ pub struct timeval {
     pub tv_usec: c_long,
 }
 
+// Functions forbidden when targeting UWP
+cfg_if::cfg_if! {
+if #[cfg(not(target_vendor = "uwp"))] {
+    pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
+    pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
+    pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
+
+    #[repr(C)]
+    pub struct EXCEPTION_RECORD {
+        pub ExceptionCode: DWORD,
+        pub ExceptionFlags: DWORD,
+        pub ExceptionRecord: *mut EXCEPTION_RECORD,
+        pub ExceptionAddress: LPVOID,
+        pub NumberParameters: DWORD,
+        pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS]
+    }
+
+    pub enum CONTEXT {}
+
+    #[repr(C)]
+    pub struct EXCEPTION_POINTERS {
+        pub ExceptionRecord: *mut EXCEPTION_RECORD,
+        pub ContextRecord: *mut CONTEXT,
+    }
+
+    pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
+            fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
+
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    pub struct CONSOLE_READCONSOLE_CONTROL {
+        pub nLength: ULONG,
+        pub nInitialChars: ULONG,
+        pub dwCtrlWakeupMask: ULONG,
+        pub dwControlKeyState: ULONG,
+    }
+
+    pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
+
+    #[repr(C)]
+    pub struct BY_HANDLE_FILE_INFORMATION {
+        pub dwFileAttributes: DWORD,
+        pub ftCreationTime: FILETIME,
+        pub ftLastAccessTime: FILETIME,
+        pub ftLastWriteTime: FILETIME,
+        pub dwVolumeSerialNumber: DWORD,
+        pub nFileSizeHigh: DWORD,
+        pub nFileSizeLow: DWORD,
+        pub nNumberOfLinks: DWORD,
+        pub nFileIndexHigh: DWORD,
+        pub nFileIndexLow: DWORD,
+    }
+
+    pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
+    pub type LPCVOID = *const c_void;
+
+    pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
+
+    pub const TOKEN_READ: DWORD = 0x20008;
+
+    extern "system" {
+        #[link_name = "SystemFunction036"]
+        pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
+
+        pub fn ReadConsoleW(hConsoleInput: HANDLE,
+                            lpBuffer: LPVOID,
+                            nNumberOfCharsToRead: DWORD,
+                            lpNumberOfCharsRead: LPDWORD,
+                            pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL;
+
+        pub fn WriteConsoleW(hConsoleOutput: HANDLE,
+                             lpBuffer: LPCVOID,
+                             nNumberOfCharsToWrite: DWORD,
+                             lpNumberOfCharsWritten: LPDWORD,
+                             lpReserved: LPVOID) -> BOOL;
+
+        pub fn GetConsoleMode(hConsoleHandle: HANDLE,
+                              lpMode: LPDWORD) -> BOOL;
+        // Allowed but unused by UWP
+        pub fn OpenProcessToken(ProcessHandle: HANDLE,
+                                DesiredAccess: DWORD,
+                                TokenHandle: *mut HANDLE) -> BOOL;
+        pub fn GetUserProfileDirectoryW(hToken: HANDLE,
+                                        lpProfileDir: LPWSTR,
+                                        lpcchSize: *mut DWORD) -> BOOL;
+        pub fn GetFileInformationByHandle(hFile: HANDLE,
+                            lpFileInformation: LPBY_HANDLE_FILE_INFORMATION)
+                            -> BOOL;
+        pub fn SetHandleInformation(hObject: HANDLE,
+                                    dwMask: DWORD,
+                                    dwFlags: DWORD) -> BOOL;
+        pub fn AddVectoredExceptionHandler(FirstHandler: ULONG,
+                                           VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
+                                           -> LPVOID;
+        pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR,
+                               lpTargetFileName: LPCWSTR,
+                               lpSecurityAttributes: LPSECURITY_ATTRIBUTES)
+                               -> BOOL;
+    }
+}
+}
+
+// UWP specific functions & types
+cfg_if::cfg_if! {
+if #[cfg(target_vendor = "uwp")] {
+    pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
+
+    #[repr(C)]
+    pub struct FILE_STANDARD_INFO {
+        pub AllocationSize: LARGE_INTEGER,
+        pub EndOfFile: LARGE_INTEGER,
+        pub NumberOfLink: DWORD,
+        pub DeletePending: BOOLEAN,
+        pub Directory: BOOLEAN,
+    }
+
+    extern "system" {
+        pub fn GetFileInformationByHandleEx(hFile: HANDLE,
+                                            fileInfoClass: FILE_INFO_BY_HANDLE_CLASS,
+                                            lpFileInformation: LPVOID,
+                                            dwBufferSize: DWORD) -> BOOL;
+        pub fn BCryptGenRandom(hAlgorithm: LPVOID, pBuffer: *mut u8,
+                               cbBuffer: ULONG, dwFlags: ULONG) -> LONG;
+    }
+}
+}
+
+// Shared between Desktop & UWP
 extern "system" {
     pub fn WSAStartup(wVersionRequested: WORD,
                       lpWSAData: LPWSADATA) -> c_int;
@@ -1028,34 +770,13 @@ extern "system" {
     pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
     pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
 
-    pub fn ReadConsoleW(hConsoleInput: HANDLE,
-                        lpBuffer: LPVOID,
-                        nNumberOfCharsToRead: DWORD,
-                        lpNumberOfCharsRead: LPDWORD,
-                        pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL;
-
-    pub fn WriteConsoleW(hConsoleOutput: HANDLE,
-                         lpBuffer: LPCVOID,
-                         nNumberOfCharsToWrite: DWORD,
-                         lpNumberOfCharsWritten: LPDWORD,
-                         lpReserved: LPVOID) -> BOOL;
-
-    pub fn GetConsoleMode(hConsoleHandle: HANDLE,
-                          lpMode: LPDWORD) -> BOOL;
     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
     pub fn SetFileAttributesW(lpFileName: LPCWSTR,
                               dwFileAttributes: DWORD) -> BOOL;
-    pub fn GetFileInformationByHandle(hFile: HANDLE,
-                            lpFileInformation: LPBY_HANDLE_FILE_INFORMATION)
-                            -> BOOL;
-
     pub fn SetLastError(dwErrCode: DWORD);
     pub fn GetCommandLineW() -> *mut LPCWSTR;
     pub fn GetTempPathW(nBufferLength: DWORD,
                         lpBuffer: LPCWSTR) -> DWORD;
-    pub fn OpenProcessToken(ProcessHandle: HANDLE,
-                            DesiredAccess: DWORD,
-                            TokenHandle: *mut HANDLE) -> BOOL;
     pub fn GetCurrentProcess() -> HANDLE;
     pub fn GetCurrentThread() -> HANDLE;
     pub fn GetStdHandle(which: DWORD) -> HANDLE;
@@ -1080,21 +801,12 @@ extern "system" {
     pub fn SwitchToThread() -> BOOL;
     pub fn Sleep(dwMilliseconds: DWORD);
     pub fn GetProcessId(handle: HANDLE) -> DWORD;
-    pub fn GetUserProfileDirectoryW(hToken: HANDLE,
-                                    lpProfileDir: LPWSTR,
-                                    lpcchSize: *mut DWORD) -> BOOL;
-    pub fn SetHandleInformation(hObject: HANDLE,
-                                dwMask: DWORD,
-                                dwFlags: DWORD) -> BOOL;
     pub fn CopyFileExW(lpExistingFileName: LPCWSTR,
                        lpNewFileName: LPCWSTR,
                        lpProgressRoutine: LPPROGRESS_ROUTINE,
                        lpData: LPVOID,
                        pbCancel: LPBOOL,
                        dwCopyFlags: DWORD) -> BOOL;
-    pub fn AddVectoredExceptionHandler(FirstHandler: ULONG,
-                                       VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
-                                       -> LPVOID;
     pub fn FormatMessageW(flags: DWORD,
                           lpSrc: LPVOID,
                           msgId: DWORD,
@@ -1191,10 +903,6 @@ extern "system" {
                      lpOverlapped: LPOVERLAPPED)
                      -> BOOL;
     pub fn CloseHandle(hObject: HANDLE) -> BOOL;
-    pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR,
-                           lpTargetFileName: LPCWSTR,
-                           lpSecurityAttributes: LPSECURITY_ATTRIBUTES)
-                           -> BOOL;
     pub fn MoveFileExW(lpExistingFileName: LPCWSTR,
                        lpNewFileName: LPCWSTR,
                        dwFlags: DWORD)
@@ -1220,8 +928,6 @@ extern "system" {
     pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW)
                          -> BOOL;
     pub fn FindClose(findFile: HANDLE) -> BOOL;
-    #[cfg(feature = "backtrace")]
-    pub fn RtlCaptureContext(ctx: *mut CONTEXT);
     pub fn getsockopt(s: SOCKET,
                       level: c_int,
                       optname: c_int,
@@ -1252,10 +958,6 @@ extern "system" {
                        res: *mut *mut ADDRINFOA) -> c_int;
     pub fn freeaddrinfo(res: *mut ADDRINFOA);
 
-    #[cfg(feature = "backtrace")]
-    pub fn LoadLibraryW(name: LPCWSTR) -> HMODULE;
-    #[cfg(feature = "backtrace")]
-    pub fn FreeLibrary(handle: HMODULE) -> BOOL;
     pub fn GetProcAddress(handle: HMODULE,
                           name: LPCSTR) -> *mut c_void;
     pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
@@ -1290,8 +992,6 @@ extern "system" {
                   exceptfds: *mut fd_set,
                   timeout: *const timeval) -> c_int;
 
-    #[link_name = "SystemFunction036"]
-    pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
 
     pub fn GetProcessHeap() -> HANDLE;
     pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
@@ -1315,6 +1015,7 @@ compat_fn! {
                                      _dwFlags: DWORD) -> DWORD {
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
     }
+    #[cfg(not(target_vendor = "uwp"))]
     pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
     }
@@ -1361,34 +1062,3 @@ compat_fn! {
         panic!("rwlocks not available")
     }
 }
-
-#[cfg(all(target_env = "gnu", feature = "backtrace"))]
-mod gnu {
-    use super::*;
-
-    pub const PROCESS_QUERY_INFORMATION: DWORD = 0x0400;
-
-    pub const CP_ACP: UINT = 0;
-
-    pub const WC_NO_BEST_FIT_CHARS: DWORD = 0x00000400;
-
-    extern "system" {
-        pub fn OpenProcess(dwDesiredAccess: DWORD,
-                           bInheritHandle: BOOL,
-                           dwProcessId: DWORD) -> HANDLE;
-    }
-
-    compat_fn! {
-        kernel32:
-
-        pub fn QueryFullProcessImageNameW(_hProcess: HANDLE,
-                                          _dwFlags: DWORD,
-                                          _lpExeName: LPWSTR,
-                                          _lpdwSize: LPDWORD) -> BOOL {
-            SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
-        }
-    }
-}
-
-#[cfg(all(target_env = "gnu", feature = "backtrace"))]
-pub use self::gnu::*;
diff --git a/src/libstd/sys/windows/compat.rs b/src/libstd/sys/windows/compat.rs
index 748c1616d1d..544b2087f92 100644
--- a/src/libstd/sys/windows/compat.rs
+++ b/src/libstd/sys/windows/compat.rs
@@ -37,12 +37,14 @@ pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
 
 macro_rules! compat_fn {
     ($module:ident: $(
+        $(#[$meta:meta])*
         pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
                                   -> $rettype:ty {
             $($body:expr);*
         }
     )*) => ($(
         #[allow(unused_variables)]
+        $(#[$meta])*
         pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
             use crate::sync::atomic::{AtomicUsize, Ordering};
             use crate::mem;
diff --git a/src/libstd/sys/windows/dynamic_lib.rs b/src/libstd/sys/windows/dynamic_lib.rs
deleted file mode 100644
index b9d5105cb73..00000000000
--- a/src/libstd/sys/windows/dynamic_lib.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use crate::os::windows::prelude::*;
-
-use crate::ffi::{CString, OsStr};
-use crate::io;
-use crate::sys::c;
-
-pub struct DynamicLibrary {
-    handle: c::HMODULE,
-}
-
-impl DynamicLibrary {
-    pub fn open(filename: &str) -> io::Result<DynamicLibrary> {
-        let filename = OsStr::new(filename)
-                             .encode_wide()
-                             .chain(Some(0))
-                             .collect::<Vec<_>>();
-        let result = unsafe {
-            c::LoadLibraryW(filename.as_ptr())
-        };
-        if result.is_null() {
-            Err(io::Error::last_os_error())
-        } else {
-            Ok(DynamicLibrary { handle: result })
-        }
-    }
-
-    pub fn symbol(&self, symbol: &str) -> io::Result<usize> {
-        let symbol = CString::new(symbol)?;
-        unsafe {
-            match c::GetProcAddress(self.handle, symbol.as_ptr()) as usize {
-                0 => Err(io::Error::last_os_error()),
-                n => Ok(n),
-            }
-        }
-    }
-}
-
-impl Drop for DynamicLibrary {
-    fn drop(&mut self) {
-        unsafe {
-            c::FreeLibrary(self.handle);
-        }
-    }
-}
diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs
index 547b1ef796b..1381825806f 100644
--- a/src/libstd/sys/windows/ext/ffi.rs
+++ b/src/libstd/sys/windows/ext/ffi.rs
@@ -131,12 +131,12 @@ pub trait OsStrExt {
     ///
     /// [`OsString::from_wide`]: ./trait.OsStringExt.html#tymethod.from_wide
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn encode_wide(&self) -> EncodeWide;
+    fn encode_wide(&self) -> EncodeWide<'_>;
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl OsStrExt for OsStr {
-    fn encode_wide(&self) -> EncodeWide {
+    fn encode_wide(&self) -> EncodeWide<'_> {
         self.as_inner().inner.encode_wide()
     }
 }
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
index 268a14ff0aa..23964dc5bd5 100644
--- a/src/libstd/sys/windows/ext/fs.rs
+++ b/src/libstd/sys/windows/ext/fs.rs
@@ -437,6 +437,33 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn file_size(&self) -> u64;
+
+    /// Returns the value of the `dwVolumeSerialNumber` field of this
+    /// metadata.
+    ///
+    /// This will return `None` if the `Metadata` instance was created from a
+    /// call to `DirEntry::metadata`. If this `Metadata` was created by using
+    /// `fs::metadata` or `File::metadata`, then this will return `Some`.
+    #[unstable(feature = "windows_by_handle", issue = "63010")]
+    fn volume_serial_number(&self) -> Option<u32>;
+
+    /// Returns the value of the `nNumberOfLinks` field of this
+    /// metadata.
+    ///
+    /// This will return `None` if the `Metadata` instance was created from a
+    /// call to `DirEntry::metadata`. If this `Metadata` was created by using
+    /// `fs::metadata` or `File::metadata`, then this will return `Some`.
+    #[unstable(feature = "windows_by_handle", issue = "63010")]
+    fn number_of_links(&self) -> Option<u32>;
+
+    /// Returns the value of the `nFileIndex{Low,High}` fields of this
+    /// metadata.
+    ///
+    /// This will return `None` if the `Metadata` instance was created from a
+    /// call to `DirEntry::metadata`. If this `Metadata` was created by using
+    /// `fs::metadata` or `File::metadata`, then this will return `Some`.
+    #[unstable(feature = "windows_by_handle", issue = "63010")]
+    fn file_index(&self) -> Option<u64>;
 }
 
 #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -446,6 +473,9 @@ impl MetadataExt for Metadata {
     fn last_access_time(&self) -> u64 { self.as_inner().accessed_u64() }
     fn last_write_time(&self) -> u64 { self.as_inner().modified_u64() }
     fn file_size(&self) -> u64 { self.as_inner().size() }
+    fn volume_serial_number(&self) -> Option<u32> { self.as_inner().volume_serial_number() }
+    fn number_of_links(&self) -> Option<u32> { self.as_inner().number_of_links() }
+    fn file_index(&self) -> Option<u64> { self.as_inner().file_index() }
 }
 
 /// Windows-specific extensions to [`FileType`].
diff --git a/src/libstd/sys/windows/ext/io.rs b/src/libstd/sys/windows/ext/io.rs
index 1a7d734b89e..ec47c2e9d5a 100644
--- a/src/libstd/sys/windows/ext/io.rs
+++ b/src/libstd/sys/windows/ext/io.rs
@@ -83,6 +83,27 @@ impl AsRawHandle for io::Stderr {
     }
 }
 
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawHandle for io::StdinLock<'a> {
+    fn as_raw_handle(&self) -> RawHandle {
+        unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle }
+    }
+}
+
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawHandle for io::StdoutLock<'a> {
+    fn as_raw_handle(&self) -> RawHandle {
+        unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle }
+    }
+}
+
+#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
+impl<'a> AsRawHandle for io::StderrLock<'a> {
+    fn as_raw_handle(&self) -> RawHandle {
+        unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle }
+    }
+}
+
 #[stable(feature = "from_raw_os", since = "1.1.0")]
 impl FromRawHandle for fs::File {
     unsafe fn from_raw_handle(handle: RawHandle) -> fs::File {
diff --git a/src/libstd/sys/windows/fast_thread_local.rs b/src/libstd/sys/windows/fast_thread_local.rs
index 0ccc67e3fd5..31d0bd1e72e 100644
--- a/src/libstd/sys/windows/fast_thread_local.rs
+++ b/src/libstd/sys/windows/fast_thread_local.rs
@@ -2,7 +2,3 @@
 #![cfg(target_thread_local)]
 
 pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor;
-
-pub fn requires_move_before_drop() -> bool {
-    false
-}
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index daf8aae24dd..5bae6ba4749 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -2,7 +2,7 @@ use crate::os::windows::prelude::*;
 
 use crate::ffi::OsString;
 use crate::fmt;
-use crate::io::{self, Error, SeekFrom};
+use crate::io::{self, Error, SeekFrom, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::path::{Path, PathBuf};
 use crate::ptr;
@@ -25,6 +25,9 @@ pub struct FileAttr {
     last_write_time: c::FILETIME,
     file_size: u64,
     reparse_tag: c::DWORD,
+    volume_serial_number: Option<u32>,
+    number_of_links: Option<u32>,
+    file_index: Option<u64>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -74,7 +77,7 @@ pub struct FilePermissions { attrs: c::DWORD }
 pub struct DirBuilder;
 
 impl fmt::Debug for ReadDir {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
         // Thus the result will be e g 'ReadDir("C:\")'
         fmt::Debug::fmt(&*self.root, f)
@@ -156,6 +159,9 @@ impl DirEntry {
                 } else {
                     0
                 },
+            volume_serial_number: None,
+            number_of_links: None,
+            file_index: None,
         })
     }
 }
@@ -287,19 +293,70 @@ impl File {
         Ok(())
     }
 
+    #[cfg(not(target_vendor = "uwp"))]
     pub fn file_attr(&self) -> io::Result<FileAttr> {
         unsafe {
             let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed();
-            cvt(c::GetFileInformationByHandle(self.handle.raw(),
-                                              &mut info))?;
-            let mut attr = FileAttr {
+            cvt(c::GetFileInformationByHandle(self.handle.raw(), &mut info))?;
+            let mut reparse_tag = 0;
+            if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+                let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+                if let Ok((_, buf)) = self.reparse_point(&mut b) {
+                    reparse_tag = buf.ReparseTag;
+                }
+            }
+            Ok(FileAttr {
                 attributes: info.dwFileAttributes,
                 creation_time: info.ftCreationTime,
                 last_access_time: info.ftLastAccessTime,
                 last_write_time: info.ftLastWriteTime,
-                file_size: ((info.nFileSizeHigh as u64) << 32) | (info.nFileSizeLow as u64),
+                file_size: (info.nFileSizeLow as u64) | ((info.nFileSizeHigh as u64) << 32),
+                reparse_tag,
+                volume_serial_number: Some(info.dwVolumeSerialNumber),
+                number_of_links: Some(info.nNumberOfLinks),
+                file_index: Some((info.nFileIndexLow as u64) |
+                                 ((info.nFileIndexHigh as u64) << 32)),
+            })
+        }
+    }
+
+    #[cfg(target_vendor = "uwp")]
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        unsafe {
+            let mut info: c::FILE_BASIC_INFO = mem::zeroed();
+            let size = mem::size_of_val(&info);
+            cvt(c::GetFileInformationByHandleEx(self.handle.raw(),
+                                              c::FileBasicInfo,
+                                              &mut info as *mut _ as *mut libc::c_void,
+                                              size as c::DWORD))?;
+            let mut attr = FileAttr {
+                attributes: info.FileAttributes,
+                creation_time: c::FILETIME {
+                    dwLowDateTime: info.CreationTime as c::DWORD,
+                    dwHighDateTime: (info.CreationTime >> 32) as c::DWORD,
+                },
+                last_access_time: c::FILETIME {
+                    dwLowDateTime: info.LastAccessTime as c::DWORD,
+                    dwHighDateTime: (info.LastAccessTime >> 32) as c::DWORD,
+                },
+                last_write_time: c::FILETIME {
+                    dwLowDateTime: info.LastWriteTime as c::DWORD,
+                    dwHighDateTime: (info.LastWriteTime >> 32) as c::DWORD,
+                },
+                file_size: 0,
                 reparse_tag: 0,
+                volume_serial_number: None,
+                number_of_links: None,
+                file_index: None,
             };
+            let mut info: c::FILE_STANDARD_INFO = mem::zeroed();
+            let size = mem::size_of_val(&info);
+            cvt(c::GetFileInformationByHandleEx(self.handle.raw(),
+                                                c::FileStandardInfo,
+                                                &mut info as *mut _ as *mut libc::c_void,
+                                                size as c::DWORD))?;
+            attr.file_size = info.AllocationSize as u64;
+            attr.number_of_links = Some(info.NumberOfLinks);
             if attr.is_reparse_point() {
                 let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
                 if let Ok((_, buf)) = self.reparse_point(&mut b) {
@@ -314,6 +371,10 @@ impl File {
         self.handle.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.handle.read_vectored(bufs)
+    }
+
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.handle.read_at(buf, offset)
     }
@@ -322,6 +383,10 @@ impl File {
         self.handle.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.handle.write_vectored(bufs)
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.handle.write_at(buf, offset)
     }
@@ -435,7 +500,7 @@ impl FromInner<c::HANDLE> for File {
 }
 
 impl fmt::Debug for File {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // FIXME(#24570): add more info here (e.g., mode)
         let mut b = f.debug_struct("File");
         b.field("handle", &self.handle.raw());
@@ -455,7 +520,9 @@ impl FileAttr {
         FilePermissions { attrs: self.attributes }
     }
 
-    pub fn attrs(&self) -> u32 { self.attributes as u32 }
+    pub fn attrs(&self) -> u32 {
+        self.attributes
+    }
 
     pub fn file_type(&self) -> FileType {
         FileType::new(self.attributes, self.reparse_tag)
@@ -485,8 +552,16 @@ impl FileAttr {
         to_u64(&self.creation_time)
     }
 
-    fn is_reparse_point(&self) -> bool {
-        self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0
+    pub fn volume_serial_number(&self) -> Option<u32> {
+        self.volume_serial_number
+    }
+
+    pub fn number_of_links(&self) -> Option<u32> {
+        self.number_of_links
+    }
+
+    pub fn file_index(&self) -> Option<u64> {
+        self.file_index
     }
 }
 
@@ -662,6 +737,7 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
     Ok(())
 }
 
+#[cfg(not(target_vendor = "uwp"))]
 pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
     let src = to_u16s(src)?;
     let dst = to_u16s(dst)?;
@@ -671,6 +747,12 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
     Ok(())
 }
 
+#[cfg(target_vendor = "uwp")]
+pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+    return Err(io::Error::new(io::ErrorKind::Other,
+                            "hard link are not supported on UWP"));
+}
+
 pub fn stat(path: &Path) -> io::Result<FileAttr> {
     let mut opts = OpenOptions::new();
     // No read or write permissions are necessary
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index 02549088c87..3e5aa693354 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -1,7 +1,7 @@
 #![unstable(issue = "0", feature = "windows_handle")]
 
 use crate::cmp;
-use crate::io::{self, ErrorKind, Read};
+use crate::io::{self, ErrorKind, Read, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::ops::Deref;
 use crate::ptr;
@@ -89,6 +89,10 @@ impl RawHandle {
         }
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        crate::io::default_read_vectored(|buf| self.read(buf), bufs)
+    }
+
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         let mut read = 0;
         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
@@ -169,6 +173,10 @@ impl RawHandle {
         Ok(amt as usize)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        crate::io::default_write_vectored(|buf| self.write(buf), bufs)
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         let mut written = 0;
         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
@@ -199,4 +207,8 @@ impl<'a> Read for &'a RawHandle {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         (**self).read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        (**self).read_vectored(bufs)
+    }
 }
diff --git a/src/libstd/sys/windows/io.rs b/src/libstd/sys/windows/io.rs
index 54dd271c9d6..e44dcbe164d 100644
--- a/src/libstd/sys/windows/io.rs
+++ b/src/libstd/sys/windows/io.rs
@@ -3,16 +3,16 @@ use crate::slice;
 use crate::sys::c;
 
 #[repr(transparent)]
-pub struct IoVec<'a> {
+pub struct IoSlice<'a> {
     vec: c::WSABUF,
     _p: PhantomData<&'a [u8]>,
 }
 
-impl<'a> IoVec<'a> {
+impl<'a> IoSlice<'a> {
     #[inline]
-    pub fn new(buf: &'a [u8]) -> IoVec<'a> {
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
         assert!(buf.len() <= c::ULONG::max_value() as usize);
-        IoVec {
+        IoSlice {
             vec: c::WSABUF {
                 len: buf.len() as c::ULONG,
                 buf: buf.as_ptr() as *mut u8 as *mut c::CHAR,
@@ -22,6 +22,18 @@ impl<'a> IoVec<'a> {
     }
 
     #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if (self.vec.len as usize) < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        unsafe {
+            self.vec.len -= n as c::ULONG;
+            self.vec.buf = self.vec.buf.add(n);
+        }
+    }
+
+    #[inline]
     pub fn as_slice(&self) -> &[u8] {
         unsafe {
             slice::from_raw_parts(self.vec.buf as *mut u8, self.vec.len as usize)
@@ -29,16 +41,17 @@ impl<'a> IoVec<'a> {
     }
 }
 
-pub struct IoVecMut<'a> {
+#[repr(transparent)]
+pub struct IoSliceMut<'a> {
     vec: c::WSABUF,
     _p: PhantomData<&'a mut [u8]>,
 }
 
-impl<'a> IoVecMut<'a> {
+impl<'a> IoSliceMut<'a> {
     #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoVecMut<'a> {
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
         assert!(buf.len() <= c::ULONG::max_value() as usize);
-        IoVecMut {
+        IoSliceMut {
             vec: c::WSABUF {
                 len: buf.len() as c::ULONG,
                 buf: buf.as_mut_ptr() as *mut c::CHAR,
@@ -48,6 +61,18 @@ impl<'a> IoVecMut<'a> {
     }
 
     #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if (self.vec.len as usize) < n {
+            panic!("advancing IoSliceMut beyond its length");
+        }
+
+        unsafe {
+            self.vec.len -= n as c::ULONG;
+            self.vec.buf = self.vec.buf.add(n);
+        }
+    }
+
+    #[inline]
     pub fn as_slice(&self) -> &[u8] {
         unsafe {
             slice::from_raw_parts(self.vec.buf as *mut u8, self.vec.len as usize)
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 1425254a2e1..d59ac5959a6 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -14,13 +14,9 @@ pub use self::rand::hashmap_random_keys;
 
 pub mod alloc;
 pub mod args;
-#[cfg(feature = "backtrace")]
-pub mod backtrace;
 pub mod c;
 pub mod cmath;
 pub mod condvar;
-#[cfg(feature = "backtrace")]
-pub mod dynamic_lib;
 pub mod env;
 pub mod ext;
 pub mod fast_thread_local;
@@ -37,11 +33,20 @@ pub mod pipe;
 pub mod process;
 pub mod rand;
 pub mod rwlock;
-pub mod stack_overflow;
 pub mod thread;
 pub mod thread_local;
 pub mod time;
-pub mod stdio;
+cfg_if::cfg_if! {
+    if #[cfg(not(target_vendor = "uwp"))] {
+        pub mod stdio;
+        pub mod stack_overflow;
+    } else {
+        pub mod stdio_uwp;
+        pub mod stack_overflow_uwp;
+        pub use self::stdio_uwp as stdio;
+        pub use self::stack_overflow_uwp as stack_overflow;
+    }
+}
 
 #[cfg(not(test))]
 pub fn init() {
@@ -199,7 +204,7 @@ fn wide_char_to_multi_byte(code_page: u32,
     }
 }
 
-pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
+pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
     match v.iter().position(|c| *c == 0) {
         // don't include the 0
         Some(i) => &v[..i],
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 1aa910f05c9..37cbdcefced 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -154,7 +154,7 @@ unsafe impl Sync for ReentrantMutex {}
 
 impl ReentrantMutex {
     pub fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninitialized()) }
+        ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) }
     }
 
     pub unsafe fn init(&mut self) {
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index 1231fd55e25..32f4011fb32 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -1,7 +1,7 @@
 #![unstable(issue = "0", feature = "windows_net")]
 
 use crate::cmp;
-use crate::io::{self, Read, IoVec, IoVecMut};
+use crate::io::{self, Read, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::net::{SocketAddr, Shutdown};
 use crate::ptr;
@@ -97,12 +97,26 @@ impl Socket {
         };
         let socket = unsafe {
             match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
-                                c::WSA_FLAG_OVERLAPPED) {
-                c::INVALID_SOCKET => Err(last_error()),
+                                c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
+                c::INVALID_SOCKET => {
+                    match c::WSAGetLastError() {
+                        c::WSAEPROTOTYPE => {
+                            match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
+                                                c::WSA_FLAG_OVERLAPPED) {
+                                c::INVALID_SOCKET => Err(last_error()),
+                                n => {
+                                    let s = Socket(n);
+                                    s.set_no_inherit()?;
+                                    Ok(s)
+                                },
+                            }
+                        },
+                        n => Err(io::Error::from_raw_os_error(n)),
+                    }
+                },
                 n => Ok(Socket(n)),
             }
         }?;
-        socket.set_no_inherit()?;
         Ok(socket)
     }
 
@@ -168,7 +182,6 @@ impl Socket {
                 n => Ok(Socket(n)),
             }
         }?;
-        socket.set_no_inherit()?;
         Ok(socket)
     }
 
@@ -178,16 +191,34 @@ impl Socket {
             cvt(c::WSADuplicateSocketW(self.0,
                                             c::GetCurrentProcessId(),
                                             &mut info))?;
+
             match c::WSASocketW(info.iAddressFamily,
                                 info.iSocketType,
                                 info.iProtocol,
                                 &mut info, 0,
-                                c::WSA_FLAG_OVERLAPPED) {
-                c::INVALID_SOCKET => Err(last_error()),
+                                c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
+                c::INVALID_SOCKET => {
+                    match c::WSAGetLastError() {
+                        c::WSAEPROTOTYPE => {
+                            match c::WSASocketW(info.iAddressFamily,
+                                                info.iSocketType,
+                                                info.iProtocol,
+                                                &mut info, 0,
+                                                c::WSA_FLAG_OVERLAPPED) {
+                                c::INVALID_SOCKET => Err(last_error()),
+                                n => {
+                                    let s = Socket(n);
+                                    s.set_no_inherit()?;
+                                    Ok(s)
+                                },
+                            }
+                        },
+                        n => Err(io::Error::from_raw_os_error(n)),
+                    }
+                },
                 n => Ok(Socket(n)),
             }
         }?;
-        socket.set_no_inherit()?;
         Ok(socket)
     }
 
@@ -208,7 +239,7 @@ impl Socket {
         self.recv_with_flags(buf, 0)
     }
 
-    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
         let len = cmp::min(bufs.len(), c::DWORD::max_value() as usize) as c::DWORD;
@@ -268,7 +299,7 @@ impl Socket {
         self.recv_from_with_flags(buf, c::MSG_PEEK)
     }
 
-    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let len = cmp::min(bufs.len(), c::DWORD::max_value() as usize) as c::DWORD;
         let mut nwritten = 0;
         unsafe {
@@ -312,6 +343,7 @@ impl Socket {
         }
     }
 
+    #[cfg(not(target_vendor = "uwp"))]
     fn set_no_inherit(&self) -> io::Result<()> {
         sys::cvt(unsafe {
             c::SetHandleInformation(self.0 as c::HANDLE,
@@ -319,6 +351,11 @@ impl Socket {
         }).map(|_| ())
     }
 
+    #[cfg(target_vendor = "uwp")]
+    fn set_no_inherit(&self) -> io::Result<()> {
+        Err(io::Error::new(io::ErrorKind::Other, "Unavailable on UWP"))
+    }
+
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
         let how = match how {
             Shutdown::Write => c::SD_SEND,
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index 5b433ddfb4a..7c400dce686 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -13,7 +13,6 @@ use crate::path::{self, PathBuf};
 use crate::ptr;
 use crate::slice;
 use crate::sys::{c, cvt};
-use crate::sys::handle::Handle;
 
 use super::to_u16s;
 
@@ -136,7 +135,7 @@ pub struct SplitPaths<'a> {
     must_yield: bool,
 }
 
-pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
+pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> {
     SplitPaths {
         data: unparsed.encode_wide(),
         must_yield: true,
@@ -212,7 +211,7 @@ pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
 }
 
 impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "path segment contains `\"`".fmt(f)
     }
 }
@@ -284,10 +283,11 @@ pub fn temp_dir() -> PathBuf {
     }, super::os2path).unwrap()
 }
 
-pub fn home_dir() -> Option<PathBuf> {
-    crate::env::var_os("HOME").or_else(|| {
-        crate::env::var_os("USERPROFILE")
-    }).map(PathBuf::from).or_else(|| unsafe {
+#[cfg(not(target_vendor = "uwp"))]
+fn home_dir_crt() -> Option<PathBuf> {
+    unsafe {
+        use crate::sys::handle::Handle;
+
         let me = c::GetCurrentProcess();
         let mut token = ptr::null_mut();
         if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
@@ -301,7 +301,18 @@ pub fn home_dir() -> Option<PathBuf> {
                 _ => sz - 1, // sz includes the null terminator
             }
         }, super::os2path).ok()
-    })
+    }
+}
+
+#[cfg(target_vendor = "uwp")]
+fn home_dir_crt() -> Option<PathBuf> {
+    None
+}
+
+pub fn home_dir() -> Option<PathBuf> {
+    crate::env::var_os("HOME").or_else(|| {
+        crate::env::var_os("USERPROFILE")
+    }).map(PathBuf::from).or_else(|| home_dir_crt())
 }
 
 pub fn exit(code: i32) -> ! {
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index 8befa66ecdc..c7a82e09252 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -33,13 +33,13 @@ impl AsInner<Wtf8> for Buf {
 }
 
 impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(self.as_slice(), formatter)
     }
 }
 
 impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self.as_slice(), formatter)
     }
 }
@@ -49,13 +49,13 @@ pub struct Slice {
 }
 
 impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.inner, formatter)
     }
 }
 
 impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(&self.inner, formatter)
     }
 }
@@ -139,7 +139,7 @@ impl Slice {
         self.inner.as_str()
     }
 
-    pub fn to_string_lossy(&self) -> Cow<str> {
+    pub fn to_string_lossy(&self) -> Cow<'_, str> {
         self.inner.to_string_lossy()
     }
 
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
index b8532ca9b0d..7eae28cb14f 100644
--- a/src/libstd/sys/windows/path.rs
+++ b/src/libstd/sys/windows/path.rs
@@ -19,7 +19,7 @@ pub fn is_verbatim_sep(b: u8) -> bool {
     b == b'\\'
 }
 
-pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
+pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
     use crate::path::Prefix::*;
     unsafe {
         // The unsafety here stems from converting between &OsStr and &[u8]
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index 07f4f5f0e58..041d5385eb6 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -1,7 +1,7 @@
 use crate::os::windows::prelude::*;
 
 use crate::ffi::OsStr;
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::path::Path;
 use crate::ptr;
@@ -37,15 +37,15 @@ pub struct Pipes {
 ///
 /// The ours/theirs pipes are *not* specifically readable or writable. Each
 /// one only supports a read or a write, but which is which depends on the
-/// boolean flag given. If `ours_readable` is true then `ours` is readable where
-/// `theirs` is writable. Conversely if `ours_readable` is false then `ours` is
-/// writable where `theirs` is readable.
+/// boolean flag given. If `ours_readable` is `true`, then `ours` is readable and
+/// `theirs` is writable. Conversely, if `ours_readable` is `false`, then `ours`
+/// is writable and `theirs` is readable.
 ///
 /// Also note that the `ours` pipe is always a handle opened up in overlapped
 /// mode. This means that technically speaking it should only ever be used
 /// with `OVERLAPPED` instances, but also works out ok if it's only ever used
 /// once at a time (which we do indeed guarantee).
-pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
+pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
     // Note that we specifically do *not* use `CreatePipe` here because
     // unfortunately the anonymous pipes returned do not support overlapped
     // operations. Instead, we create a "hopefully unique" name and create a
@@ -137,6 +137,13 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
         opts.write(ours_readable);
         opts.read(!ours_readable);
         opts.share_mode(0);
+        let size = mem::size_of::<c::SECURITY_ATTRIBUTES>();
+        let mut sa = c::SECURITY_ATTRIBUTES {
+            nLength: size as c::DWORD,
+            lpSecurityDescriptor: ptr::null_mut(),
+            bInheritHandle: their_handle_inheritable as i32,
+        };
+        opts.security_attributes(&mut sa);
         let theirs = File::open(Path::new(&name), &opts)?;
         let theirs = AnonPipe { inner: theirs.into_handle() };
 
@@ -166,9 +173,17 @@ impl AnonPipe {
         self.inner.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
 }
 
 pub fn read2(p1: AnonPipe,
@@ -334,7 +349,7 @@ impl<'a> Drop for AsyncPipe<'a> {
         // If anything here fails, there's not really much we can do, so we leak
         // the buffer/OVERLAPPED pointers to ensure we're at least memory safe.
         if self.pipe.cancel_io().is_err() || self.result().is_err() {
-            let buf = mem::replace(self.dst, Vec::new());
+            let buf = mem::take(self.dst);
             let overlapped = Box::new(unsafe { mem::zeroed() });
             let overlapped = mem::replace(&mut self.overlapped, overlapped);
             mem::forget((buf, overlapped));
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 95f061d22bd..05e0ca67064 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -219,7 +219,7 @@ impl Command {
 }
 
 impl fmt::Debug for Command {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self.program)?;
         for arg in &self.args {
             write!(f, " {:?}", arg)?;
@@ -267,13 +267,8 @@ impl Stdio {
 
             Stdio::MakePipe => {
                 let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
-                let pipes = pipe::anon_pipe(ours_readable)?;
+                let pipes = pipe::anon_pipe(ours_readable, true)?;
                 *pipe = Some(pipes.ours);
-                cvt(unsafe {
-                    c::SetHandleInformation(pipes.theirs.handle().raw(),
-                                            c::HANDLE_FLAG_INHERIT,
-                                            c::HANDLE_FLAG_INHERIT)
-                })?;
                 Ok(pipes.theirs.into_handle())
             }
 
@@ -393,7 +388,7 @@ impl From<c::DWORD> for ExitStatus {
 }
 
 impl fmt::Display for ExitStatus {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Windows exit codes with the high bit set typically mean some form of
         // unhandled exception or warning. In this scenario printing the exit
         // code in decimal doesn't always make sense because it's a very large
diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs
index 0193f4defa1..c9bcb5d7415 100644
--- a/src/libstd/sys/windows/rand.rs
+++ b/src/libstd/sys/windows/rand.rs
@@ -2,6 +2,7 @@ use crate::io;
 use crate::mem;
 use crate::sys::c;
 
+#[cfg(not(target_vendor = "uwp"))]
 pub fn hashmap_random_keys() -> (u64, u64) {
     let mut v = (0, 0);
     let ret = unsafe {
@@ -14,3 +15,20 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     }
     return v
 }
+
+#[cfg(target_vendor = "uwp")]
+pub fn hashmap_random_keys() -> (u64, u64) {
+    use crate::ptr;
+
+    let mut v = (0, 0);
+    let ret = unsafe {
+        c::BCryptGenRandom(ptr::null_mut(), &mut v as *mut _ as *mut u8,
+                           mem::size_of_val(&v) as c::ULONG,
+                           c::BCRYPT_USE_SYSTEM_PREFERRED_RNG)
+    };
+    if ret != 0 {
+        panic!("couldn't generate random bytes: {}",
+               io::Error::last_os_error());
+    }
+    return v
+}
diff --git a/src/libstd/sys/redox/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow_uwp.rs
index cf01d323d45..e7236cf359c 100644
--- a/src/libstd/sys/redox/stack_overflow.rs
+++ b/src/libstd/sys/windows/stack_overflow_uwp.rs
@@ -3,15 +3,11 @@
 pub struct Handler;
 
 impl Handler {
-    pub unsafe fn new() -> Handler {
+    pub fn new() -> Handler {
         Handler
     }
 }
 
-pub unsafe fn init() {
+pub unsafe fn init() {}
 
-}
-
-pub unsafe fn cleanup() {
-
-}
+pub unsafe fn cleanup() {}
diff --git a/src/libstd/sys/windows/stdio_uwp.rs b/src/libstd/sys/windows/stdio_uwp.rs
new file mode 100644
index 00000000000..489d3df2860
--- /dev/null
+++ b/src/libstd/sys/windows/stdio_uwp.rs
@@ -0,0 +1,85 @@
+#![unstable(issue = "0", feature = "windows_stdio")]
+
+use crate::io;
+use crate::sys::c;
+use crate::sys::handle::Handle;
+use crate::mem::ManuallyDrop;
+
+pub struct Stdin {
+}
+pub struct Stdout;
+pub struct Stderr;
+
+const MAX_BUFFER_SIZE: usize = 8192;
+pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3;
+
+pub fn get_handle(handle_id: c::DWORD) -> io::Result<c::HANDLE> {
+    let handle = unsafe { c::GetStdHandle(handle_id) };
+    if handle == c::INVALID_HANDLE_VALUE {
+        Err(io::Error::last_os_error())
+    } else if handle.is_null() {
+        Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
+    } else {
+        Ok(handle)
+    }
+}
+
+fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
+    let handle = get_handle(handle_id)?;
+    let handle = Handle::new(handle);
+    ManuallyDrop::new(handle).write(data)
+}
+
+impl Stdin {
+    pub fn new() -> io::Result<Stdin> {
+        Ok(Stdin { })
+    }
+}
+
+impl io::Read for Stdin {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let handle = get_handle(c::STD_INPUT_HANDLE)?;
+        let handle = Handle::new(handle);
+        ManuallyDrop::new(handle).read(buf)
+    }
+}
+
+impl Stdout {
+    pub fn new() -> io::Result<Stdout> {
+        Ok(Stdout)
+    }
+}
+
+impl io::Write for Stdout {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        write(c::STD_OUTPUT_HANDLE, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub fn new() -> io::Result<Stderr> {
+        Ok(Stderr)
+    }
+}
+
+impl io::Write for Stderr {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        write(c::STD_ERROR_HANDLE, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
+}
+
+pub fn panic_output() -> Option<impl io::Write> {
+    Stderr::new().ok()
+}
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 1b0a811f13b..ebdf3612e06 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::io;
 use crate::ffi::CStr;
 use crate::mem;
@@ -20,7 +19,7 @@ pub struct Thread {
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnBox()>)
+    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>)
                           -> io::Result<Thread> {
         let p = box p;
 
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index 2c99bca7009..e0f0e3a1a45 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -49,17 +49,17 @@ impl Instant {
         Instant { t: Duration::from_secs(0) }
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
         // On windows there's a threshold below which we consider two timestamps
         // equivalent due to measurement error. For more details + doc link,
         // check the docs on epsilon.
         let epsilon =
             perf_counter::PerformanceCounterInstant::epsilon();
         if other.t > self.t && other.t - self.t <= epsilon {
-            return Duration::new(0, 0)
+            Some(Duration::new(0, 0))
+        } else {
+            self.t.checked_sub(other.t)
         }
-        self.t.checked_sub(other.t)
-              .expect("specified instant was later than self")
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
@@ -139,7 +139,7 @@ impl Ord for SystemTime {
 }
 
 impl fmt::Debug for SystemTime {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("SystemTime")
          .field("intervals", &self.intervals())
          .finish()
@@ -173,7 +173,7 @@ fn intervals2dur(intervals: u64) -> Duration {
 
 mod perf_counter {
     use super::{NANOS_PER_SEC};
-    use crate::sync::Once;
+    use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
     use crate::sys_common::mul_div_u64;
     use crate::sys::c;
     use crate::sys::cvt;
@@ -210,13 +210,25 @@ mod perf_counter {
 
     fn frequency() -> c::LARGE_INTEGER {
         static mut FREQUENCY: c::LARGE_INTEGER = 0;
-        static ONCE: Once = Once::new();
+        static STATE: AtomicUsize = AtomicUsize::new(0);
 
         unsafe {
-            ONCE.call_once(|| {
-                cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
-            });
-            FREQUENCY
+            // If a previous thread has filled in this global state, use that.
+            if STATE.load(SeqCst) == 2 {
+                return FREQUENCY;
+            }
+
+            // ... otherwise learn for ourselves ...
+            let mut frequency = 0;
+            cvt(c::QueryPerformanceFrequency(&mut frequency)).unwrap();
+
+            // ... and attempt to be the one thread that stores it globally for
+            // all other threads
+            if STATE.compare_exchange(0, 1, SeqCst, SeqCst).is_ok() {
+                FREQUENCY = frequency;
+                STATE.store(2, SeqCst);
+            }
+            return frequency;
         }
     }
 
diff --git a/src/libstd/sys_common/alloc.rs b/src/libstd/sys_common/alloc.rs
index 978a70bee09..1cfc7ed17f2 100644
--- a/src/libstd/sys_common/alloc.rs
+++ b/src/libstd/sys_common/alloc.rs
@@ -12,7 +12,8 @@ use crate::ptr;
               target_arch = "powerpc",
               target_arch = "powerpc64",
               target_arch = "asmjs",
-              target_arch = "wasm32")))]
+              target_arch = "wasm32",
+              target_arch = "hexagon")))]
 pub const MIN_ALIGN: usize = 8;
 #[cfg(all(any(target_arch = "x86_64",
               target_arch = "aarch64",
diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs
index 1181b861611..cdb72ee872e 100644
--- a/src/libstd/sys_common/at_exit_imp.rs
+++ b/src/libstd/sys_common/at_exit_imp.rs
@@ -2,12 +2,11 @@
 //!
 //! Documentation can be found on the `rt::at_exit` function.
 
-use crate::boxed::FnBox;
 use crate::ptr;
 use crate::mem;
 use crate::sys_common::mutex::Mutex;
 
-type Queue = Vec<Box<dyn FnBox()>>;
+type Queue = Vec<Box<dyn FnOnce()>>;
 
 // NB these are specifically not types from `std::sync` as they currently rely
 // on poisoning and this module needs to operate at a lower level than requiring
@@ -61,7 +60,7 @@ pub fn cleanup() {
     }
 }
 
-pub fn push(f: Box<dyn FnBox()>) -> bool {
+pub fn push(f: Box<dyn FnOnce()>) -> bool {
     unsafe {
         let _guard = LOCK.lock();
         if init() {
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 1a80908779e..bf37ff7ddbd 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -2,40 +2,17 @@
 /// supported platforms.
 
 use crate::env;
-use crate::io::prelude::*;
 use crate::io;
+use crate::io::prelude::*;
+use crate::mem;
 use crate::path::{self, Path};
 use crate::ptr;
-use crate::str;
 use crate::sync::atomic::{self, Ordering};
 use crate::sys::mutex::Mutex;
 
-use rustc_demangle::demangle;
-
-pub use crate::sys::backtrace::{
-    unwind_backtrace,
-    resolve_symname,
-    foreach_symbol_fileline,
-    BacktraceContext
-};
-
-#[cfg(target_pointer_width = "64")]
-pub const HEX_WIDTH: usize = 18;
-
-#[cfg(target_pointer_width = "32")]
-pub const HEX_WIDTH: usize = 10;
-
-/// Represents an item in the backtrace list. See `unwind_backtrace` for how
-/// it is created.
-#[derive(Debug, Copy, Clone)]
-pub struct Frame {
-    /// Exact address of the call that failed.
-    pub exact_position: *const u8,
-    /// Address of the enclosing function.
-    pub symbol_addr: *const u8,
-    /// Which inlined function is this frame referring to
-    pub inline_context: u32,
-}
+use backtrace::{BytesOrWideString, Frame, Symbol};
+
+pub const HEX_WIDTH: usize = 2 + 2 * mem::size_of::<usize>();
 
 /// Max number of frames to print.
 const MAX_NB_FRAMES: usize = 100;
@@ -49,7 +26,7 @@ pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
     // test mode immediately return here to optimize away any references to the
     // libbacktrace symbols
     if cfg!(test) {
-        return Ok(())
+        return Ok(());
     }
 
     // Use a lock to prevent mixed output in multithreading context.
@@ -63,75 +40,39 @@ pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
 }
 
 fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
-    let mut frames = [Frame {
-        exact_position: ptr::null(),
-        symbol_addr: ptr::null(),
-        inline_context: 0,
-    }; MAX_NB_FRAMES];
-    let (nb_frames, context) = unwind_backtrace(&mut frames)?;
-    let (skipped_before, skipped_after) =
-        filter_frames(&frames[..nb_frames], format, &context);
-    if skipped_before + skipped_after > 0 {
-        writeln!(w, "note: Some details are omitted, \
-                     run with `RUST_BACKTRACE=full` for a verbose backtrace.")?;
-    }
     writeln!(w, "stack backtrace:")?;
 
-    let filtered_frames = &frames[..nb_frames - skipped_after];
-    for (index, frame) in filtered_frames.iter().skip(skipped_before).enumerate() {
-        resolve_symname(*frame, |symname| {
-            output(w, index, *frame, symname, format)
-        }, &context)?;
-        let has_more_filenames = foreach_symbol_fileline(*frame, |file, line| {
-            output_fileline(w, file, line, format)
-        }, &context)?;
-        if has_more_filenames {
-            w.write_all(b" <... and possibly more>")?;
-        }
-    }
-
-    Ok(())
-}
-
-/// Returns a number of frames to remove at the beginning and at the end of the
-/// backtrace, according to the backtrace format.
-fn filter_frames(frames: &[Frame],
-                 format: PrintFormat,
-                 context: &BacktraceContext) -> (usize, usize)
-{
-    if format == PrintFormat::Full {
-        return (0, 0);
-    }
-
-    let skipped_before = 0;
-
-    let skipped_after = frames.len() - frames.iter().position(|frame| {
-        let mut is_marker = false;
-        let _ = resolve_symname(*frame, |symname| {
-            if let Some(mangled_symbol_name) = symname {
-                // Use grep to find the concerned functions
-                if mangled_symbol_name.contains("__rust_begin_short_backtrace") {
-                    is_marker = true;
-                }
+    let mut printer = Printer::new(format, w);
+    unsafe {
+        backtrace::trace_unsynchronized(|frame| {
+            let mut hit = false;
+            backtrace::resolve_frame_unsynchronized(frame, |symbol| {
+                hit = true;
+                printer.output(frame, Some(symbol));
+            });
+            if !hit {
+                printer.output(frame, None);
             }
-            Ok(())
-        }, context);
-        is_marker
-    }).unwrap_or(frames.len());
-
-    if skipped_before + skipped_after >= frames.len() {
-        // Avoid showing completely empty backtraces
-        return (0, 0);
+            !printer.done
+        });
     }
-
-    (skipped_before, skipped_after)
+    if printer.skipped {
+        writeln!(
+            w,
+            "note: Some details are omitted, \
+             run with `RUST_BACKTRACE=full` for a verbose backtrace."
+        )?;
+    }
+    Ok(())
 }
 
-
 /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
 #[inline(never)]
 pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
-    where F: FnOnce() -> T, F: Send, T: Send
+where
+    F: FnOnce() -> T,
+    F: Send,
+    T: Send,
 {
     f()
 }
@@ -156,7 +97,7 @@ pub fn log_enabled() -> Option<PrintFormat> {
         _ => return Some(PrintFormat::Full),
     }
 
-    let val = env::var_os("RUST_BACKTRACE").and_then(|x|
+    let val = env::var_os("RUST_BACKTRACE").and_then(|x| {
         if &x == "0" {
             None
         } else if &x == "full" {
@@ -164,81 +105,141 @@ pub fn log_enabled() -> Option<PrintFormat> {
         } else {
             Some(PrintFormat::Short)
         }
+    });
+    ENABLED.store(
+        match val {
+            Some(v) => v as isize,
+            None => 1,
+        },
+        Ordering::SeqCst,
     );
-    ENABLED.store(match val {
-        Some(v) => v as isize,
-        None => 1,
-    }, Ordering::SeqCst);
     val
 }
 
-/// Prints the symbol of the backtrace frame.
-///
-/// These output functions should now be used everywhere to ensure consistency.
-/// You may want to also use `output_fileline`.
-fn output(w: &mut dyn Write, idx: usize, frame: Frame,
-              s: Option<&str>, format: PrintFormat) -> io::Result<()> {
-    // Remove the `17: 0x0 - <unknown>` line.
-    if format == PrintFormat::Short && frame.exact_position == ptr::null() {
-        return Ok(());
+struct Printer<'a, 'b> {
+    format: PrintFormat,
+    done: bool,
+    skipped: bool,
+    idx: usize,
+    out: &'a mut (dyn Write + 'b),
+}
+
+impl<'a, 'b> Printer<'a, 'b> {
+    fn new(format: PrintFormat, out: &'a mut (dyn Write + 'b)) -> Printer<'a, 'b> {
+        Printer { format, done: false, skipped: false, idx: 0, out }
     }
-    match format {
-        PrintFormat::Full => write!(w,
-                                    "  {:2}: {:2$?} - ",
-                                    idx,
-                                    frame.exact_position,
-                                    HEX_WIDTH)?,
-        PrintFormat::Short => write!(w, "  {:2}: ", idx)?,
+
+    /// Prints the symbol of the backtrace frame.
+    ///
+    /// These output functions should now be used everywhere to ensure consistency.
+    /// You may want to also use `output_fileline`.
+    fn output(&mut self, frame: &Frame, symbol: Option<&Symbol>) {
+        if self.idx > MAX_NB_FRAMES {
+            self.done = true;
+            self.skipped = true;
+            return;
+        }
+        if self._output(frame, symbol).is_err() {
+            self.done = true;
+        }
+        self.idx += 1;
     }
-    match s {
-        Some(string) => {
-            let symbol = demangle(string);
-            match format {
-                PrintFormat::Full => write!(w, "{}", symbol)?,
-                // strip the trailing hash if short mode
-                PrintFormat::Short => write!(w, "{:#}", symbol)?,
+
+    fn _output(&mut self, frame: &Frame, symbol: Option<&Symbol>) -> io::Result<()> {
+        if self.format == PrintFormat::Short {
+            if let Some(sym) = symbol.and_then(|s| s.name()).and_then(|s| s.as_str()) {
+                if sym.contains("__rust_begin_short_backtrace") {
+                    self.skipped = true;
+                    self.done = true;
+                    return Ok(());
+                }
+            }
+
+            // Remove the `17: 0x0 - <unknown>` line.
+            if self.format == PrintFormat::Short && frame.ip() == ptr::null_mut() {
+                self.skipped = true;
+                return Ok(());
             }
         }
-        None => w.write_all(b"<unknown>")?,
-    }
-    w.write_all(b"\n")
-}
 
-/// Prints the filename and line number of the backtrace frame.
-///
-/// See also `output`.
-#[allow(dead_code)]
-fn output_fileline(w: &mut dyn Write,
-                   file: &[u8],
-                   line: u32,
-                   format: PrintFormat) -> io::Result<()> {
-    // prior line: "  ##: {:2$} - func"
-    w.write_all(b"")?;
-    match format {
-        PrintFormat::Full => write!(w,
-                                    "           {:1$}",
-                                    "",
-                                    HEX_WIDTH)?,
-        PrintFormat::Short => write!(w, "           ")?,
-    }
+        match self.format {
+            PrintFormat::Full => {
+                write!(self.out, "  {:2}: {:2$?} - ", self.idx, frame.ip(), HEX_WIDTH)?
+            }
+            PrintFormat::Short => write!(self.out, "  {:2}: ", self.idx)?,
+        }
 
-    let file = str::from_utf8(file).unwrap_or("<unknown>");
-    let file_path = Path::new(file);
-    let mut already_printed = false;
-    if format == PrintFormat::Short && file_path.is_absolute() {
-        if let Ok(cwd) = env::current_dir() {
-            if let Ok(stripped) = file_path.strip_prefix(&cwd) {
-                if let Some(s) = stripped.to_str() {
-                    write!(w, "  at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?;
-                    already_printed = true;
+        match symbol.and_then(|s| s.name()) {
+            Some(symbol) => {
+                match self.format {
+                    PrintFormat::Full => write!(self.out, "{}", symbol)?,
+                    // Strip the trailing hash if short mode.
+                    PrintFormat::Short => write!(self.out, "{:#}", symbol)?,
                 }
             }
+            None => self.out.write_all(b"<unknown>")?,
         }
-    }
-    if !already_printed {
-        write!(w, "  at {}:{}", file, line)?;
+        self.out.write_all(b"\n")?;
+        if let Some(sym) = symbol {
+            self.output_fileline(sym)?;
+        }
+        Ok(())
     }
 
-    w.write_all(b"\n")
-}
+    /// Prints the filename and line number of the backtrace frame.
+    ///
+    /// See also `output`.
+    fn output_fileline(&mut self, symbol: &Symbol) -> io::Result<()> {
+        #[cfg(windows)]
+        let path_buf;
+        let file = match symbol.filename_raw() {
+            #[cfg(unix)]
+            Some(BytesOrWideString::Bytes(bytes)) => {
+                use crate::os::unix::prelude::*;
+                Path::new(crate::ffi::OsStr::from_bytes(bytes))
+            }
+            #[cfg(not(unix))]
+            Some(BytesOrWideString::Bytes(bytes)) => {
+                Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>"))
+            }
+            #[cfg(windows)]
+            Some(BytesOrWideString::Wide(wide)) => {
+                use crate::os::windows::prelude::*;
+                path_buf = crate::ffi::OsString::from_wide(wide);
+                Path::new(&path_buf)
+            }
+            #[cfg(not(windows))]
+            Some(BytesOrWideString::Wide(_wide)) => {
+                Path::new("<unknown>")
+            }
+            None => return Ok(()),
+        };
+        let line = match symbol.lineno() {
+            Some(line) => line,
+            None => return Ok(()),
+        };
+        // prior line: "  ##: {:2$} - func"
+        self.out.write_all(b"")?;
+        match self.format {
+            PrintFormat::Full => write!(self.out, "           {:1$}", "", HEX_WIDTH)?,
+            PrintFormat::Short => write!(self.out, "           ")?,
+        }
 
+        let mut already_printed = false;
+        if self.format == PrintFormat::Short && file.is_absolute() {
+            if let Ok(cwd) = env::current_dir() {
+                if let Ok(stripped) = file.strip_prefix(&cwd) {
+                    if let Some(s) = stripped.to_str() {
+                        write!(self.out, "  at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?;
+                        already_printed = true;
+                    }
+                }
+            }
+        }
+        if !already_printed {
+            write!(self.out, "  at {}:{}", file.display(), line)?;
+        }
+
+        self.out.write_all(b"\n")
+    }
+}
diff --git a/src/libstd/sys_common/bytestring.rs b/src/libstd/sys_common/bytestring.rs
index 273d586a5a0..429ecf6281b 100644
--- a/src/libstd/sys_common/bytestring.rs
+++ b/src/libstd/sys_common/bytestring.rs
@@ -3,9 +3,9 @@
 use crate::fmt::{Formatter, Result, Write};
 use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
 
-pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter) -> Result {
+pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter<'_>) -> Result {
     // Writes out a valid unicode string with the correct escape sequences
-    fn write_str_escaped(f: &mut Formatter, s: &str) -> Result {
+    fn write_str_escaped(f: &mut Formatter<'_>, s: &str) -> Result {
         for c in s.chars().flat_map(|c| c.escape_debug()) {
             f.write_char(c)?
         }
@@ -32,7 +32,7 @@ mod tests {
         struct Helper<'a>(&'a [u8]);
 
         impl Debug for Helper<'_> {
-            fn fmt(&self, f: &mut Formatter) -> Result {
+            fn fmt(&self, f: &mut Formatter<'_>) -> Result {
                 debug_fmt_bytestring(self.0, f)
             }
         }
diff --git a/src/libstd/sys_common/fs.rs b/src/libstd/sys_common/fs.rs
new file mode 100644
index 00000000000..7152fcd215c
--- /dev/null
+++ b/src/libstd/sys_common/fs.rs
@@ -0,0 +1,41 @@
+#![allow(dead_code)] // not used on all platforms
+
+use crate::path::Path;
+use crate::fs;
+use crate::io::{self, Error, ErrorKind};
+
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::InvalidInput,
+                              "the source path is not an existing regular file"))
+    }
+
+    let mut reader = fs::File::open(from)?;
+    let mut writer = fs::File::create(to)?;
+    let perm = reader.metadata()?.permissions();
+
+    let ret = io::copy(&mut reader, &mut writer)?;
+    fs::set_permissions(to, perm)?;
+    Ok(ret)
+}
+
+pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    let filetype = fs::symlink_metadata(path)?.file_type();
+    if filetype.is_symlink() {
+        fs::remove_file(path)
+    } else {
+        remove_dir_all_recursive(path)
+    }
+}
+
+fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
+    for child in fs::read_dir(path)? {
+        let child = child?;
+        if child.file_type()?.is_dir() {
+            remove_dir_all_recursive(&child.path())?;
+        } else {
+            fs::remove_file(&child.path())?;
+        }
+    }
+    fs::remove_dir(path)
+}
diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs
deleted file mode 100644
index 6cd050242dd..00000000000
--- a/src/libstd/sys_common/gnu/libbacktrace.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-use backtrace_sys::backtrace_state;
-
-use crate::ffi::CStr;
-use crate::io;
-use crate::mem;
-use crate::ptr;
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys_common::backtrace::Frame;
-
-pub fn foreach_symbol_fileline<F>(frame: Frame,
-                                  mut f: F,
-                                  _: &BacktraceContext) -> io::Result<bool>
-where F: FnMut(&[u8], u32) -> io::Result<()>
-{
-    // pcinfo may return an arbitrary number of file:line pairs,
-    // in the order of stack trace (i.e., inlined calls first).
-    // in order to avoid allocation, we stack-allocate a fixed size of entries.
-    const FILELINE_SIZE: usize = 32;
-    let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE];
-    let ret;
-    let fileline_count = {
-        let state = unsafe { init_state() };
-        if state.is_null() {
-            return Err(io::Error::new(
-                io::ErrorKind::Other,
-                "failed to allocate libbacktrace state")
-            )
-        }
-        let mut fileline_win: &mut [FileLine] = &mut fileline_buf;
-        let fileline_addr = &mut fileline_win as *mut &mut [FileLine];
-        ret = unsafe {
-            backtrace_sys::backtrace_pcinfo(
-                state,
-                frame.exact_position as libc::uintptr_t,
-                pcinfo_cb,
-                error_cb,
-                fileline_addr as *mut libc::c_void,
-            )
-        };
-        FILELINE_SIZE - fileline_win.len()
-    };
-    if ret == 0 {
-        for &(file, line) in &fileline_buf[..fileline_count] {
-            if file.is_null() { continue; } // just to be sure
-            let file = unsafe { CStr::from_ptr(file).to_bytes() };
-            f(file, line)?;
-        }
-        Ok(fileline_count == FILELINE_SIZE)
-    } else {
-        Ok(false)
-    }
-}
-
-/// Converts a pointer to symbol to its string value.
-pub fn resolve_symname<F>(frame: Frame,
-                          callback: F,
-                          _: &BacktraceContext) -> io::Result<()>
-    where F: FnOnce(Option<&str>) -> io::Result<()>
-{
-    let symname = {
-        let state = unsafe { init_state() };
-        if state.is_null() {
-            return Err(io::Error::new(
-                io::ErrorKind::Other,
-                "failed to allocate libbacktrace state")
-            )
-        }
-        let mut data: *const libc::c_char = ptr::null();
-        let data_addr = &mut data as *mut *const libc::c_char;
-        let ret = unsafe {
-            backtrace_sys::backtrace_syminfo(
-                state,
-                frame.symbol_addr as libc::uintptr_t,
-                syminfo_cb,
-                error_cb,
-                data_addr as *mut libc::c_void,
-            )
-        };
-        if ret == 0 || data.is_null() {
-            None
-        } else {
-            unsafe {
-                CStr::from_ptr(data).to_str().ok()
-            }
-        }
-    };
-    callback(symname)
-}
-
-////////////////////////////////////////////////////////////////////////
-// helper callbacks
-////////////////////////////////////////////////////////////////////////
-
-type FileLine = (*const libc::c_char, u32);
-
-extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
-                   _errnum: libc::c_int) {
-    // do nothing for now
-}
-extern fn syminfo_cb(data: *mut libc::c_void,
-                     _pc: libc::uintptr_t,
-                     symname: *const libc::c_char,
-                     _symval: libc::uintptr_t,
-                     _symsize: libc::uintptr_t) {
-    let slot = data as *mut *const libc::c_char;
-    unsafe { *slot = symname; }
-}
-extern fn pcinfo_cb(data: *mut libc::c_void,
-                    _pc: libc::uintptr_t,
-                    filename: *const libc::c_char,
-                    lineno: libc::c_int,
-                    _function: *const libc::c_char) -> libc::c_int {
-    if !filename.is_null() {
-        let slot = data as *mut &mut [FileLine];
-        let buffer = unsafe {ptr::read(slot)};
-
-        // if the buffer is not full, add file:line to the buffer
-        // and adjust the buffer for next possible calls to pcinfo_cb.
-        if !buffer.is_empty() {
-            buffer[0] = (filename, lineno as u32);
-            unsafe { ptr::write(slot, &mut buffer[1..]); }
-        }
-    }
-
-    0
-}
-
-// The libbacktrace API supports creating a state, but it does not
-// support destroying a state. I personally take this to mean that a
-// state is meant to be created and then live forever.
-//
-// I would love to register an at_exit() handler which cleans up this
-// state, but libbacktrace provides no way to do so.
-//
-// With these constraints, this function has a statically cached state
-// that is calculated the first time this is requested. Remember that
-// backtracing all happens serially (one global lock).
-//
-// Things don't work so well on not-Linux since libbacktrace can't track
-// down that executable this is. We at one point used env::current_exe but
-// it turns out that there are some serious security issues with that
-// approach.
-//
-// Specifically, on certain platforms like BSDs, a malicious actor can cause
-// an arbitrary file to be placed at the path returned by current_exe.
-// libbacktrace does not behave defensively in the presence of ill-formed
-// DWARF information, and has been demonstrated to segfault in at least one
-// case. There is no evidence at the moment to suggest that a more carefully
-// constructed file can't cause arbitrary code execution. As a result of all
-// of this, we don't hint libbacktrace with the path to the current process.
-unsafe fn init_state() -> *mut backtrace_state {
-    static mut STATE: *mut backtrace_state = ptr::null_mut();
-    if !STATE.is_null() { return STATE  }
-
-    let filename = match crate::sys::backtrace::gnu::get_executable_filename() {
-        Ok((filename, file)) => {
-            // filename is purposely leaked here since libbacktrace requires
-            // it to stay allocated permanently, file is also leaked so that
-            // the file stays locked
-            let filename_ptr = filename.as_ptr();
-            mem::forget(filename);
-            mem::forget(file);
-            filename_ptr
-        },
-        Err(_) => ptr::null(),
-    };
-
-    STATE = backtrace_sys::backtrace_create_state(
-        filename,
-        0,
-        error_cb,
-        ptr::null_mut(),
-    );
-    STATE
-}
diff --git a/src/libstd/sys_common/gnu/mod.rs b/src/libstd/sys_common/gnu/mod.rs
deleted file mode 100644
index d6959697f2a..00000000000
--- a/src/libstd/sys_common/gnu/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![allow(missing_docs)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-
-pub mod libbacktrace;
diff --git a/src/libstd/sys_common/io.rs b/src/libstd/sys_common/io.rs
index 44b0963302d..8789abe55c3 100644
--- a/src/libstd/sys_common/io.rs
+++ b/src/libstd/sys_common/io.rs
@@ -16,7 +16,7 @@ pub mod test {
             p.join(path)
         }
 
-        pub fn path<'a>(&'a self) -> &'a Path {
+        pub fn path(&self) -> &Path {
             let TempDir(ref p) = *self;
             p
         }
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 1fc32365408..9190a3b0d5f 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -28,6 +28,17 @@ macro_rules! rtassert {
     })
 }
 
+#[allow(unused_macros)] // not used on all platforms
+macro_rules! rtunwrap {
+    ($ok:ident, $e:expr) => (match $e {
+        $ok(v) => v,
+        ref err => {
+            let err = err.as_ref().map(|_|()); // map Ok/Some which might not be Debug
+            rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err)
+        },
+    })
+}
+
 pub mod alloc;
 pub mod at_exit_imp;
 #[cfg(feature = "backtrace")]
@@ -35,6 +46,13 @@ pub mod backtrace;
 pub mod condvar;
 pub mod io;
 pub mod mutex;
+#[cfg(any(rustdoc, // see `mod os`, docs are generated for multiple platforms
+          unix,
+          target_os = "redox",
+          target_os = "cloudabi",
+          target_arch = "wasm32",
+          all(target_vendor = "fortanix", target_env = "sgx")))]
+pub mod os_str_bytes;
 pub mod poison;
 pub mod remutex;
 pub mod rwlock;
@@ -45,11 +63,11 @@ pub mod util;
 pub mod wtf8;
 pub mod bytestring;
 pub mod process;
+pub mod fs;
 
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(any(target_os = "cloudabi",
                  target_os = "l4re",
-                 target_os = "redox",
                  all(target_arch = "wasm32", not(target_os = "emscripten")),
                  all(target_vendor = "fortanix", target_env = "sgx")))] {
         pub use crate::sys::net;
@@ -58,12 +76,6 @@ cfg_if! {
     }
 }
 
-#[cfg(feature = "backtrace")]
-#[cfg(any(all(unix, not(target_os = "emscripten")),
-          all(windows, target_env = "gnu"),
-          target_os = "redox"))]
-pub mod gnu;
-
 // common error constructors
 
 /// A trait for viewing representations from std types
diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs
index 4b58cac7941..28d85949ffa 100644
--- a/src/libstd/sys_common/mutex.rs
+++ b/src/libstd/sys_common/mutex.rs
@@ -38,7 +38,7 @@ impl Mutex {
     /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
     /// will be unlocked.
     #[inline]
-    pub unsafe fn lock(&self) -> MutexGuard {
+    pub unsafe fn lock(&self) -> MutexGuard<'_> {
         self.raw_lock();
         MutexGuard(&self.0)
     }
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index b9505aaa69b..391f670346f 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -1,7 +1,7 @@
 use crate::cmp;
 use crate::ffi::CString;
 use crate::fmt;
-use crate::io::{self, Error, ErrorKind, IoVec, IoVecMut};
+use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
 use crate::ptr;
@@ -37,12 +37,12 @@ use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP;
 #[cfg(any(target_os = "linux", target_os = "android",
           target_os = "dragonfly", target_os = "freebsd",
           target_os = "openbsd", target_os = "netbsd",
-          target_os = "haiku", target_os = "bitrig"))]
+          target_os = "haiku"))]
 use libc::MSG_NOSIGNAL;
 #[cfg(not(any(target_os = "linux", target_os = "android",
               target_os = "dragonfly", target_os = "freebsd",
               target_os = "openbsd", target_os = "netbsd",
-              target_os = "haiku", target_os = "bitrig")))]
+              target_os = "haiku")))]
 const MSG_NOSIGNAL: c_int = 0x0;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -256,7 +256,7 @@ impl TcpStream {
         self.inner.read(buf)
     }
 
-    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         self.inner.read_vectored(bufs)
     }
 
@@ -271,7 +271,7 @@ impl TcpStream {
         Ok(ret as usize)
     }
 
-    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         self.inner.write_vectored(bufs)
     }
 
@@ -328,7 +328,7 @@ impl FromInner<Socket> for TcpStream {
 }
 
 impl fmt::Debug for TcpStream {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut res = f.debug_struct("TcpStream");
 
         if let Ok(addr) = self.socket_addr() {
@@ -435,7 +435,7 @@ impl FromInner<Socket> for TcpListener {
 }
 
 impl fmt::Debug for TcpListener {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut res = f.debug_struct("TcpListener");
 
         if let Ok(addr) = self.socket_addr() {
@@ -472,6 +472,12 @@ impl UdpSocket {
 
     pub fn into_socket(self) -> Socket { self.inner }
 
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        sockname(|buf, len| unsafe {
+            c::getpeername(*self.inner.as_inner(), buf, len)
+        })
+    }
+
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
         sockname(|buf, len| unsafe {
             c::getsockname(*self.inner.as_inner(), buf, len)
@@ -638,7 +644,7 @@ impl FromInner<Socket> for UdpSocket {
 }
 
 impl fmt::Debug for UdpSocket {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut res = f.debug_struct("UdpSocket");
 
         if let Ok(addr) = self.socket_addr() {
diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys_common/os_str_bytes.rs
index 79b43458d00..a4961974d89 100644
--- a/src/libstd/sys/unix/os_str.rs
+++ b/src/libstd/sys_common/os_str_bytes.rs
@@ -1,46 +1,47 @@
-/// The underlying OsString/OsStr implementation on Unix systems: just
-/// a `Vec<u8>`/`[u8]`.
+//! The underlying OsString/OsStr implementation on Unix and many other
+//! systems: just a `Vec<u8>`/`[u8]`.
 
 use crate::borrow::Cow;
+use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::str;
 use crate::mem;
 use crate::rc::Rc;
 use crate::sync::Arc;
-use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::{FromInner, IntoInner, AsInner};
 use crate::sys_common::bytestring::debug_fmt_bytestring;
 
 use core::str::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
-pub struct Buf {
+pub(crate) struct Buf {
     pub inner: Vec<u8>
 }
 
-pub struct Slice {
+pub(crate) struct Slice {
     pub inner: [u8]
 }
 
 impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         debug_fmt_bytestring(&self.inner, formatter)
     }
 }
 
 impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
     }
 }
 
 impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(self.as_slice(), formatter)
     }
 }
 
 impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self.as_slice(), formatter)
     }
 }
@@ -147,7 +148,7 @@ impl Slice {
         str::from_utf8(&self.inner).ok()
     }
 
-    pub fn to_string_lossy(&self) -> Cow<str> {
+    pub fn to_string_lossy(&self) -> Cow<'_, str> {
         String::from_utf8_lossy(&self.inner)
     }
 
@@ -178,3 +179,69 @@ impl Slice {
         unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
     }
 }
+
+/// Platform-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStringExt {
+    /// Creates an [`OsString`] from a byte vector.
+    ///
+    /// See the module docmentation for an example.
+    ///
+    /// [`OsString`]: ../../../ffi/struct.OsString.html
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_vec(vec: Vec<u8>) -> Self;
+
+    /// Yields the underlying byte vector of this [`OsString`].
+    ///
+    /// See the module docmentation for an example.
+    ///
+    /// [`OsString`]: ../../../ffi/struct.OsString.html
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn into_vec(self) -> Vec<u8>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStringExt for OsString {
+    fn from_vec(vec: Vec<u8>) -> OsString {
+        FromInner::from_inner(Buf { inner: vec })
+    }
+    fn into_vec(self) -> Vec<u8> {
+        self.into_inner().inner
+    }
+}
+
+/// Platform-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStrExt {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    /// Creates an [`OsStr`] from a byte slice.
+    ///
+    /// See the module docmentation for an example.
+    ///
+    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
+    fn from_bytes(slice: &[u8]) -> &Self;
+
+    /// Gets the underlying byte view of the [`OsStr`] slice.
+    ///
+    /// See the module docmentation for an example.
+    ///
+    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_bytes(&self) -> &[u8];
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStrExt for OsStr {
+    #[inline]
+    fn from_bytes(slice: &[u8]) -> &OsStr {
+        unsafe { mem::transmute(slice) }
+    }
+    #[inline]
+    fn as_bytes(&self) -> &[u8] {
+        &self.as_inner().inner
+    }
+}
diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs
index d2294235666..adac45f2d59 100644
--- a/src/libstd/sys_common/poison.rs
+++ b/src/libstd/sys_common/poison.rs
@@ -136,14 +136,14 @@ pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for PoisonError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "PoisonError { inner: .. }".fmt(f)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for PoisonError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         "poisoned lock: another task failed inside".fmt(f)
     }
 }
@@ -214,7 +214,7 @@ impl<T> From<PoisonError<T>> for TryLockError<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for TryLockError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f),
             TryLockError::WouldBlock => "WouldBlock".fmt(f)
@@ -224,7 +224,7 @@ impl<T> fmt::Debug for TryLockError<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for TryLockError<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             TryLockError::Poisoned(..) => "poisoned lock: another task failed inside",
             TryLockError::WouldBlock => "try_lock failed because the operation would block"
diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs
index 2aec361d7a4..f08b13c4aa2 100644
--- a/src/libstd/sys_common/remutex.rs
+++ b/src/libstd/sys_common/remutex.rs
@@ -72,7 +72,7 @@ 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) -> LockResult<ReentrantMutexGuard<T>> {
+    pub fn lock(&self) -> LockResult<ReentrantMutexGuard<'_, T>> {
         unsafe { self.inner.lock() }
         ReentrantMutexGuard::new(&self)
     }
@@ -89,7 +89,7 @@ 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) -> TryLockResult<ReentrantMutexGuard<T>> {
+    pub fn try_lock(&self) -> TryLockResult<ReentrantMutexGuard<'_, T>> {
         if unsafe { self.inner.try_lock() } {
             Ok(ReentrantMutexGuard::new(&self)?)
         } else {
@@ -108,7 +108,7 @@ impl<T> Drop for ReentrantMutex<T> {
 }
 
 impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.try_lock() {
             Ok(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(),
             Err(TryLockError::Poisoned(err)) => {
@@ -117,7 +117,9 @@ impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
             Err(TryLockError::WouldBlock) => {
                 struct LockedPlaceholder;
                 impl fmt::Debug for LockedPlaceholder {
-                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") }
+                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                        f.write_str("<locked>")
+                    }
                 }
 
                 f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish()
diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs
index b2142e75308..6ab0d5cbe9c 100644
--- a/src/libstd/sys_common/thread.rs
+++ b/src/libstd/sys_common/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::env;
 use crate::sync::atomic::{self, Ordering};
 use crate::sys::stack_overflow;
@@ -11,7 +10,7 @@ pub unsafe fn start_thread(main: *mut u8) {
     let _handler = stack_overflow::Handler::new();
 
     // Finally, let's run some code.
-    Box::from_raw(main as *mut Box<dyn FnBox()>)()
+    Box::from_raw(main as *mut Box<dyn FnOnce()>)()
 }
 
 pub fn min_stack() -> usize {
diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs
index 206443a6736..7936dd35999 100644
--- a/src/libstd/sys_common/util.rs
+++ b/src/libstd/sys_common/util.rs
@@ -3,7 +3,7 @@ use crate::io::prelude::*;
 use crate::sys::stdio::panic_output;
 use crate::thread;
 
-pub fn dumb_print(args: fmt::Arguments) {
+pub fn dumb_print(args: fmt::Arguments<'_>) {
     if let Some(mut out) = panic_output() {
         let _ = out.write_fmt(args);
     }
@@ -14,7 +14,7 @@ pub fn dumb_print(args: fmt::Arguments) {
 // crate::intrinsics::abort() may be used instead.  The above implementations cover
 // all targets currently supported by libstd.
 
-pub fn abort(args: fmt::Arguments) -> ! {
+pub fn abort(args: fmt::Arguments<'_>) -> ! {
     dumb_print(format_args!("fatal runtime error: {}\n", args));
     unsafe { crate::sys::abort_internal(); }
 }
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index b15239e8d87..81e606fc165 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -46,7 +46,7 @@ pub struct CodePoint {
 /// Example: `U+1F4A9`
 impl fmt::Debug for CodePoint {
     #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(formatter, "U+{:04X}", self.value)
     }
 }
@@ -134,7 +134,7 @@ impl ops::DerefMut for Wtf8Buf {
 /// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
 impl fmt::Debug for Wtf8Buf {
     #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&**self, formatter)
     }
 }
@@ -146,10 +146,10 @@ impl Wtf8Buf {
         Wtf8Buf { bytes: Vec::new() }
     }
 
-    /// Creates a new, empty WTF-8 string with pre-allocated capacity for `n` bytes.
+    /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes.
     #[inline]
-    pub fn with_capacity(n: usize) -> Wtf8Buf {
-        Wtf8Buf { bytes: Vec::with_capacity(n) }
+    pub fn with_capacity(capacity: usize) -> Wtf8Buf {
+        Wtf8Buf { bytes: Vec::with_capacity(capacity) }
     }
 
     /// Creates a WTF-8 string from a UTF-8 `String`.
@@ -388,9 +388,7 @@ impl Extend<CodePoint> for Wtf8Buf {
         let (low, _high) = iterator.size_hint();
         // Lower bound of one byte per code point (ASCII only)
         self.bytes.reserve(low);
-        for code_point in iterator {
-            self.push(code_point);
-        }
+        iterator.for_each(move |code_point| self.push(code_point));
     }
 }
 
@@ -411,8 +409,8 @@ impl AsInner<[u8]> for Wtf8 {
 /// and surrogates as `\u` followed by four hexadecimal digits.
 /// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800]
 impl fmt::Debug for Wtf8 {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fn write_str_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
             use crate::fmt::Write;
             for c in s.chars().flat_map(|c| c.escape_debug()) {
                 f.write_char(c)?
@@ -441,7 +439,7 @@ impl fmt::Debug for Wtf8 {
 }
 
 impl fmt::Display for Wtf8 {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         let wtf8_bytes = &self.bytes;
         let mut pos = 0;
         loop {
@@ -522,7 +520,7 @@ impl Wtf8 {
 
     /// Returns an iterator for the string’s code points.
     #[inline]
-    pub fn code_points(&self) -> Wtf8CodePoints {
+    pub fn code_points(&self) -> Wtf8CodePoints<'_> {
         Wtf8CodePoints { bytes: self.bytes.iter() }
     }
 
@@ -547,7 +545,7 @@ impl Wtf8 {
     /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”).
     ///
     /// This only copies the data if necessary (if it contains any surrogate).
-    pub fn to_string_lossy(&self) -> Cow<str> {
+    pub fn to_string_lossy(&self) -> Cow<'_, str> {
         let surrogate_pos = match self.next_surrogate(0) {
             None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }),
             Some((pos, _)) => pos,
@@ -579,7 +577,7 @@ impl Wtf8 {
     /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units
     /// would always return the original WTF-8 string.
     #[inline]
-    pub fn encode_wide(&self) -> EncodeWide {
+    pub fn encode_wide(&self) -> EncodeWide<'_> {
         EncodeWide { code_points: self.code_points(), extra: 0 }
     }
 
@@ -1228,7 +1226,7 @@ mod tests {
         assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩"));
         let mut string = Wtf8Buf::from_str("aé 💩");
         string.push(CodePoint::from_u32(0xD800).unwrap());
-        let expected: Cow<str> = Cow::Owned(String::from("aé 💩�"));
+        let expected: Cow<'_, str> = Cow::Owned(String::from("aé 💩�"));
         assert_eq!(string.to_string_lossy(), expected);
     }
 
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index 7ad6b124e3a..f85b5d632f1 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -2,10 +2,8 @@
 
 #![unstable(feature = "thread_local_internals", issue = "0")]
 
-use crate::cell::UnsafeCell;
+use crate::error::Error;
 use crate::fmt;
-use crate::hint;
-use crate::mem;
 
 /// A thread local storage key which owns its contents.
 ///
@@ -92,15 +90,12 @@ pub struct LocalKey<T: 'static> {
     // trivially devirtualizable by LLVM because the value of `inner` never
     // changes and the constant should be readonly within a crate. This mainly
     // only runs into problems when TLS statics are exported across crates.
-    inner: unsafe fn() -> Option<&'static UnsafeCell<Option<T>>>,
-
-    // initialization routine to invoke to create a value
-    init: fn() -> T,
+    inner: unsafe fn() -> Option<&'static T>,
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: 'static> fmt::Debug for LocalKey<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("LocalKey { .. }")
     }
 }
@@ -159,10 +154,7 @@ macro_rules! __thread_local_inner {
             #[inline]
             fn __init() -> $t { $init }
 
-            unsafe fn __getit() -> $crate::option::Option<
-                &'static $crate::cell::UnsafeCell<
-                    $crate::option::Option<$t>>>
-            {
+            unsafe fn __getit() -> $crate::option::Option<&'static $t> {
                 #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
                     $crate::thread::__StaticLocalKeyInner::new();
@@ -182,11 +174,11 @@ macro_rules! __thread_local_inner {
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
 
-                __KEY.get()
+                __KEY.get(__init)
             }
 
             unsafe {
-                $crate::thread::LocalKey::new(__getit, __init)
+                $crate::thread::LocalKey::new(__getit)
             }
         }
     };
@@ -198,34 +190,36 @@ macro_rules! __thread_local_inner {
 
 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
+#[derive(Clone, Copy, Eq, PartialEq)]
 pub struct AccessError {
     _private: (),
 }
 
 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
 impl fmt::Debug for AccessError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("AccessError").finish()
     }
 }
 
 #[stable(feature = "thread_local_try_with", since = "1.26.0")]
 impl fmt::Display for AccessError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt("already destroyed", f)
     }
 }
 
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
+impl Error for AccessError {}
+
 impl<T: 'static> LocalKey<T> {
     #[doc(hidden)]
     #[unstable(feature = "thread_local_internals",
                reason = "recently added to create a key",
                issue = "0")]
-    pub const unsafe fn new(inner: unsafe fn() -> Option<&'static UnsafeCell<Option<T>>>,
-                            init: fn() -> T) -> LocalKey<T> {
+    pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey<T> {
         LocalKey {
             inner,
-            init,
         }
     }
 
@@ -246,37 +240,6 @@ impl<T: 'static> LocalKey<T> {
                                  after it is destroyed")
     }
 
-    unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
-        // Execute the initialization up front, *then* move it into our slot,
-        // just in case initialization fails.
-        let value = (self.init)();
-        let ptr = slot.get();
-
-        // note that this can in theory just be `*ptr = Some(value)`, but due to
-        // the compiler will currently codegen that pattern with something like:
-        //
-        //      ptr::drop_in_place(ptr)
-        //      ptr::write(ptr, Some(value))
-        //
-        // Due to this pattern it's possible for the destructor of the value in
-        // `ptr` (e.g., if this is being recursively initialized) to re-access
-        // TLS, in which case there will be a `&` and `&mut` pointer to the same
-        // value (an aliasing violation). To avoid setting the "I'm running a
-        // destructor" flag we just use `mem::replace` which should sequence the
-        // operations a little differently and make this safe to call.
-        mem::replace(&mut *ptr, Some(value));
-
-        // After storing `Some` we want to get a reference to the contents of
-        // what we just stored. While we could use `unwrap` here and it should
-        // always work it empirically doesn't seem to always get optimized away,
-        // which means that using something like `try_with` can pull in
-        // panicking code and cause a large size bloat.
-        match *ptr {
-            Some(ref x) => x,
-            None => hint::unreachable_unchecked(),
-        }
-    }
-
     /// Acquires a reference to the value in this TLS key.
     ///
     /// This will lazily initialize the value if this thread has not referenced
@@ -293,13 +256,68 @@ impl<T: 'static> LocalKey<T> {
         F: FnOnce(&T) -> R,
     {
         unsafe {
-            let slot = (self.inner)().ok_or(AccessError {
+            let thread_local = (self.inner)().ok_or(AccessError {
                 _private: (),
             })?;
-            Ok(f(match *slot.get() {
-                Some(ref inner) => inner,
-                None => self.init(slot),
-            }))
+            Ok(f(thread_local))
+        }
+    }
+}
+
+mod lazy {
+    use crate::cell::UnsafeCell;
+    use crate::mem;
+    use crate::hint;
+
+    pub struct LazyKeyInner<T> {
+        inner: UnsafeCell<Option<T>>,
+    }
+
+    impl<T> LazyKeyInner<T> {
+        pub const fn new() -> LazyKeyInner<T> {
+            LazyKeyInner {
+                inner: UnsafeCell::new(None),
+            }
+        }
+
+        pub unsafe fn get(&self) -> Option<&'static T> {
+            (*self.inner.get()).as_ref()
+        }
+
+        pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T {
+            // Execute the initialization up front, *then* move it into our slot,
+            // just in case initialization fails.
+            let value = init();
+            let ptr = self.inner.get();
+
+            // note that this can in theory just be `*ptr = Some(value)`, but due to
+            // the compiler will currently codegen that pattern with something like:
+            //
+            //      ptr::drop_in_place(ptr)
+            //      ptr::write(ptr, Some(value))
+            //
+            // Due to this pattern it's possible for the destructor of the value in
+            // `ptr` (e.g., if this is being recursively initialized) to re-access
+            // TLS, in which case there will be a `&` and `&mut` pointer to the same
+            // value (an aliasing violation). To avoid setting the "I'm running a
+            // destructor" flag we just use `mem::replace` which should sequence the
+            // operations a little differently and make this safe to call.
+            mem::replace(&mut *ptr, Some(value));
+
+            // After storing `Some` we want to get a reference to the contents of
+            // what we just stored. While we could use `unwrap` here and it should
+            // always work it empirically doesn't seem to always get optimized away,
+            // which means that using something like `try_with` can pull in
+            // panicking code and cause a large size bloat.
+            match *ptr {
+                Some(ref x) => x,
+                None => hint::unreachable_unchecked(),
+            }
+        }
+
+        #[allow(unused)]
+        pub unsafe fn take(&mut self) -> Option<T> {
+            (*self.inner.get()).take()
         }
     }
 }
@@ -309,17 +327,17 @@ impl<T: 'static> LocalKey<T> {
 #[doc(hidden)]
 #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
 pub mod statik {
-    use crate::cell::UnsafeCell;
+    use super::lazy::LazyKeyInner;
     use crate::fmt;
 
     pub struct Key<T> {
-        inner: UnsafeCell<Option<T>>,
+        inner: LazyKeyInner<T>,
     }
 
     unsafe impl<T> Sync for Key<T> { }
 
     impl<T> fmt::Debug for Key<T> {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             f.pad("Key { .. }")
         }
     }
@@ -327,12 +345,16 @@ pub mod statik {
     impl<T> Key<T> {
         pub const fn new() -> Key<T> {
             Key {
-                inner: UnsafeCell::new(None),
+                inner: LazyKeyInner::new(),
             }
         }
 
-        pub unsafe fn get(&self) -> Option<&'static UnsafeCell<Option<T>>> {
-            Some(&*(&self.inner as *const _))
+        pub unsafe fn get(&self, init: fn() -> T) -> Option<&'static T> {
+            let value = match self.inner.get() {
+                Some(ref value) => value,
+                None => self.inner.initialize(init),
+            };
+            Some(value)
         }
     }
 }
@@ -340,23 +362,42 @@ pub mod statik {
 #[doc(hidden)]
 #[cfg(target_thread_local)]
 pub mod fast {
-    use crate::cell::{Cell, UnsafeCell};
+    use super::lazy::LazyKeyInner;
+    use crate::cell::Cell;
     use crate::fmt;
     use crate::mem;
-    use crate::ptr;
-    use crate::sys::fast_thread_local::{register_dtor, requires_move_before_drop};
+    use crate::sys::fast_thread_local::register_dtor;
+
+    #[derive(Copy, Clone)]
+    enum DtorState {
+        Unregistered,
+        Registered,
+        RunningOrHasRun,
+    }
 
+    // This data structure has been carefully constructed so that the fast path
+    // only contains one branch on x86. That optimization is necessary to avoid
+    // duplicated tls lookups on OSX.
+    //
+    // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
     pub struct Key<T> {
-        inner: UnsafeCell<Option<T>>,
+        // If `LazyKeyInner::get` returns `None`, that indicates either:
+        //   * The value has never been initialized
+        //   * The value is being recursively initialized
+        //   * The value has already been destroyed or is being destroyed
+        // To determine which kind of `None`, check `dtor_state`.
+        //
+        // This is very optimizer friendly for the fast path - initialized but
+        // not yet dropped.
+        inner: LazyKeyInner<T>,
 
         // Metadata to keep track of the state of the destructor. Remember that
-        // these variables are thread-local, not global.
-        dtor_registered: Cell<bool>,
-        dtor_running: Cell<bool>,
+        // this variable is thread-local, not global.
+        dtor_state: Cell<DtorState>,
     }
 
     impl<T> fmt::Debug for Key<T> {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             f.pad("Key { .. }")
         }
     }
@@ -364,54 +405,75 @@ pub mod fast {
     impl<T> Key<T> {
         pub const fn new() -> Key<T> {
             Key {
-                inner: UnsafeCell::new(None),
-                dtor_registered: Cell::new(false),
-                dtor_running: Cell::new(false)
+                inner: LazyKeyInner::new(),
+                dtor_state: Cell::new(DtorState::Unregistered),
             }
         }
 
-        pub unsafe fn get(&self) -> Option<&'static UnsafeCell<Option<T>>> {
-            if mem::needs_drop::<T>() && self.dtor_running.get() {
-                return None
+        pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
+            match self.inner.get() {
+                Some(val) => Some(val),
+                None => self.try_initialize(init),
             }
-            self.register_dtor();
-            Some(&*(&self.inner as *const _))
         }
 
-        unsafe fn register_dtor(&self) {
-            if !mem::needs_drop::<T>() || self.dtor_registered.get() {
-                return
+        // `try_initialize` is only called once per fast thread local variable,
+        // except in corner cases where thread_local dtors reference other
+        // thread_local's, or it is being recursively initialized.
+        //
+        // Macos: Inlining this function can cause two `tlv_get_addr` calls to
+        // be performed for every call to `Key::get`. The #[cold] hint makes
+        // that less likely.
+        // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
+        #[cold]
+        unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
+            if !mem::needs_drop::<T>() || self.try_register_dtor() {
+                Some(self.inner.initialize(init))
+            } else {
+                None
             }
+        }
 
-            register_dtor(self as *const _ as *mut u8,
-                          destroy_value::<T>);
-            self.dtor_registered.set(true);
+        // `try_register_dtor` is only called once per fast thread local
+        // variable, except in corner cases where thread_local dtors reference
+        // other thread_local's, or it is being recursively initialized.
+        unsafe fn try_register_dtor(&self) -> bool {
+            match self.dtor_state.get() {
+                DtorState::Unregistered => {
+                    // dtor registration happens before initialization.
+                    register_dtor(self as *const _ as *mut u8,
+                                destroy_value::<T>);
+                    self.dtor_state.set(DtorState::Registered);
+                    true
+                }
+                DtorState::Registered => {
+                    // recursively initialized
+                    true
+                }
+                DtorState::RunningOrHasRun => {
+                    false
+                }
+            }
         }
     }
 
     unsafe extern fn destroy_value<T>(ptr: *mut u8) {
         let ptr = ptr as *mut Key<T>;
-        // Right before we run the user destructor be sure to flag the
-        // destructor as running for this thread so calls to `get` will return
-        // `None`.
-        (*ptr).dtor_running.set(true);
 
-        // Some implementations may require us to move the value before we drop
-        // it as it could get re-initialized in-place during destruction.
-        //
-        // Hence, we use `ptr::read` on those platforms (to move to a "safe"
-        // location) instead of drop_in_place.
-        if requires_move_before_drop() {
-            ptr::read((*ptr).inner.get());
-        } else {
-            ptr::drop_in_place((*ptr).inner.get());
-        }
+        // Right before we run the user destructor be sure to set the
+        // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
+        // causes future calls to `get` to run `try_initialize_drop` again,
+        // which will now fail, and return `None`.
+        let value = (*ptr).inner.take();
+        (*ptr).dtor_state.set(DtorState::RunningOrHasRun);
+        drop(value);
     }
 }
 
 #[doc(hidden)]
 pub mod os {
-    use crate::cell::{Cell, UnsafeCell};
+    use super::lazy::LazyKeyInner;
+    use crate::cell::Cell;
     use crate::fmt;
     use crate::marker;
     use crate::ptr;
@@ -424,7 +486,7 @@ pub mod os {
     }
 
     impl<T> fmt::Debug for Key<T> {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             f.pad("Key { .. }")
         }
     }
@@ -432,8 +494,8 @@ pub mod os {
     unsafe impl<T> Sync for Key<T> { }
 
     struct Value<T: 'static> {
+        inner: LazyKeyInner<T>,
         key: &'static Key<T>,
-        value: UnsafeCell<Option<T>>,
     }
 
     impl<T: 'static> Key<T> {
@@ -444,24 +506,43 @@ pub mod os {
             }
         }
 
-        pub unsafe fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
+        pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> {
             let ptr = self.os.get() as *mut Value<T>;
-            if !ptr.is_null() {
-                if ptr as usize == 1 {
-                    return None
+            if ptr as usize > 1 {
+                match (*ptr).inner.get() {
+                    Some(ref value) => return Some(value),
+                    None => {},
                 }
-                return Some(&(*ptr).value);
             }
+            self.try_initialize(init)
+        }
 
-            // If the lookup returned null, we haven't initialized our own
-            // local copy, so do that now.
-            let ptr: Box<Value<T>> = box Value {
-                key: self,
-                value: UnsafeCell::new(None),
+        // `try_initialize` is only called once per os thread local variable,
+        // except in corner cases where thread_local dtors reference other
+        // thread_local's, or it is being recursively initialized.
+        unsafe fn try_initialize(&'static self, init: fn() -> T) -> Option<&'static T> {
+            let ptr = self.os.get() as *mut Value<T>;
+            if ptr as usize == 1 {
+                // destructor is running
+                return None
+            }
+
+            let ptr = if ptr.is_null() {
+                // If the lookup returned null, we haven't initialized our own
+                // local copy, so do that now.
+                let ptr: Box<Value<T>> = box Value {
+                    inner: LazyKeyInner::new(),
+                    key: self,
+                };
+                let ptr = Box::into_raw(ptr);
+                self.os.set(ptr as *mut u8);
+                ptr
+            } else {
+                // recursive initialization
+                ptr
             };
-            let ptr = Box::into_raw(ptr);
-            self.os.set(ptr as *mut u8);
-            Some(&(*ptr).value)
+
+            Some((*ptr).inner.initialize(init))
         }
     }
 
@@ -530,7 +611,7 @@ mod tests {
 
         thread::spawn(|| {
             assert!(FOO.try_with(|_| ()).is_ok());
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -584,7 +665,7 @@ mod tests {
 
         thread::spawn(move|| {
             drop(S1);
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -600,7 +681,7 @@ mod tests {
 
         thread::spawn(move|| unsafe {
             K1.with(|s| *s.get() = Some(S1));
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     // Note that this test will deadlock if TLS destructors aren't run (this
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 08f0aa2f0d2..764041d2f42 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -157,12 +157,12 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::any::Any;
-use crate::boxed::FnBox;
 use crate::cell::UnsafeCell;
 use crate::ffi::{CStr, CString};
 use crate::fmt;
 use crate::io;
 use crate::mem;
+use crate::num::NonZeroU64;
 use crate::panic;
 use crate::panicking;
 use crate::str;
@@ -269,7 +269,7 @@ impl Builder {
     ///
     /// let builder = thread::Builder::new()
     ///                               .name("foo".into())
-    ///                               .stack_size(10);
+    ///                               .stack_size(32 * 1024);
     ///
     /// let handler = builder.spawn(|| {
     ///     // thread code
@@ -443,6 +443,7 @@ impl Builder {
     /// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
     /// [`io::Result`]: ../../std/io/type.Result.html
     /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
+    /// [`JoinHandle::join`]: ../../std/thread/struct.JoinHandle.html#method.join
     #[unstable(feature = "thread_spawn_unchecked", issue = "55132")]
     pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
         F: FnOnce() -> T, F: Send + 'a, T: Send + 'a
@@ -487,7 +488,9 @@ impl Builder {
             // returning.
             native: Some(imp::Thread::new(
                 stack_size,
-                mem::transmute::<Box<dyn FnBox() + 'a>, Box<dyn FnBox() + 'static>>(Box::new(main))
+                mem::transmute::<Box<dyn FnOnce() + 'a>, Box<dyn FnOnce() + 'static>>(Box::new(
+                    main,
+                )),
             )?),
             thread: my_thread,
             packet: Packet(my_packet),
@@ -1036,7 +1039,7 @@ pub fn park_timeout(dur: Duration) {
 /// [`Thread`]: ../../std/thread/struct.Thread.html
 #[stable(feature = "thread_id", since = "1.19.0")]
 #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
-pub struct ThreadId(u64);
+pub struct ThreadId(NonZeroU64);
 
 impl ThreadId {
     // Generate a new unique thread ID.
@@ -1044,7 +1047,7 @@ impl ThreadId {
         // We never call `GUARD.init()`, so it is UB to attempt to
         // acquire this mutex reentrantly!
         static GUARD: mutex::Mutex = mutex::Mutex::new();
-        static mut COUNTER: u64 = 0;
+        static mut COUNTER: u64 = 1;
 
         unsafe {
             let _guard = GUARD.lock();
@@ -1058,7 +1061,7 @@ impl ThreadId {
             let id = COUNTER;
             COUNTER += 1;
 
-            ThreadId(id)
+            ThreadId(NonZeroU64::new(id).unwrap())
         }
     }
 }
@@ -1255,8 +1258,11 @@ impl Thread {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Thread {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.name(), f)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Thread")
+            .field("id", &self.id())
+            .field("name", &self.name())
+            .finish()
     }
 }
 
@@ -1465,7 +1471,7 @@ impl<T> IntoInner<imp::Thread> for JoinHandle<T> {
 
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T> fmt::Debug for JoinHandle<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.pad("JoinHandle { .. }")
     }
 }
@@ -1484,9 +1490,10 @@ fn _assert_sync_and_send() {
 mod tests {
     use super::Builder;
     use crate::any::Any;
+    use crate::mem;
     use crate::sync::mpsc::{channel, Sender};
     use crate::result;
-    use crate::thread;
+    use crate::thread::{self, ThreadId};
     use crate::time::Duration;
     use crate::u32;
 
@@ -1497,7 +1504,7 @@ mod tests {
     fn test_unnamed_thread() {
         thread::spawn(move|| {
             assert!(thread::current().name().is_none());
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1691,6 +1698,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_park_timeout_unpark_not_called() {
         for _ in 0..10 {
             thread::park_timeout(Duration::from_millis(10));
@@ -1698,6 +1706,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_park_timeout_unpark_called_other_thread() {
         for _ in 0..10 {
             let th = thread::current();
@@ -1712,11 +1721,17 @@ mod tests {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn sleep_ms_smoke() {
         thread::sleep(Duration::from_millis(2));
     }
 
     #[test]
+    fn test_size_of_option_thread_id() {
+        assert_eq!(mem::size_of::<Option<ThreadId>>(), mem::size_of::<ThreadId>());
+    }
+
+    #[test]
     fn test_thread_id_equal() {
         assert!(thread::current().id() == thread::current().id());
     }
@@ -1727,6 +1742,6 @@ mod tests {
         assert!(thread::current().id() != spawned_id);
     }
 
-    // NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due
+    // NOTE: the corresponding test for stderr is in ui/thread-stderr, due
     // to the test harness apparently interfering with stderr configuration.
 }
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 6d7093ac33e..98371b9ba3d 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -212,7 +212,7 @@ impl Instant {
     /// ```
     #[stable(feature = "time2", since = "1.8.0")]
     pub fn duration_since(&self, earlier: Instant) -> Duration {
-        self.0.sub_instant(&earlier.0)
+        self.0.checked_sub_instant(&earlier.0).expect("supplied instant is later than self")
     }
 
     /// Returns the amount of time elapsed from another instant to this one,
@@ -233,11 +233,7 @@ impl Instant {
     /// ```
     #[unstable(feature = "checked_duration_since", issue = "58402")]
     pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
-        if self >= &earlier {
-            Some(self.0.sub_instant(&earlier.0))
-        } else {
-            None
-        }
+        self.0.checked_sub_instant(&earlier.0)
     }
 
     /// Returns the amount of time elapsed from another instant to this one,
@@ -353,7 +349,7 @@ impl Sub<Instant> for Instant {
 
 #[stable(feature = "time2", since = "1.8.0")]
 impl fmt::Debug for Instant {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(f)
     }
 }
@@ -400,6 +396,7 @@ impl SystemTime {
     /// This function may fail because measurements taken earlier are not
     /// guaranteed to always be before later measurements (due to anomalies such
     /// as the system clock being adjusted either forwards or backwards).
+    /// [`Instant`] can be used to measure elapsed time without this risk of failure.
     ///
     /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents
     /// the amount of time elapsed from the specified measurement to this one.
@@ -410,6 +407,7 @@ impl SystemTime {
     /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Instant`]: ../../std/time/struct.Instant.html
     ///
     /// # Examples
     ///
@@ -418,7 +416,7 @@ impl SystemTime {
     ///
     /// let sys_time = SystemTime::now();
     /// let difference = sys_time.duration_since(sys_time)
-    ///                          .expect("SystemTime::duration_since failed");
+    ///                          .expect("Clock may have gone backwards");
     /// println!("{:?}", difference);
     /// ```
     #[stable(feature = "time2", since = "1.8.0")]
@@ -427,7 +425,8 @@ impl SystemTime {
         self.0.sub_time(&earlier.0).map_err(SystemTimeError)
     }
 
-    /// Returns the amount of time elapsed since this system time was created.
+    /// Returns the difference between the clock time when this
+    /// system time was created, and the current clock time.
     ///
     /// This function may fail as the underlying system clock is susceptible to
     /// drift and updates (e.g., the system clock could go backwards), so this
@@ -435,12 +434,15 @@ impl SystemTime {
     /// returned where the duration represents the amount of time elapsed from
     /// this time measurement to the current time.
     ///
+    /// To measure elapsed time reliably, use [`Instant`] instead.
+    ///
     /// Returns an [`Err`] if `self` is later than the current system time, and
     /// the error contains how far from the current system time `self` is.
     ///
     /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Instant`]: ../../std/time/struct.Instant.html
     ///
     /// # Examples
     ///
@@ -517,7 +519,7 @@ impl SubAssign<Duration> for SystemTime {
 
 #[stable(feature = "time2", since = "1.8.0")]
 impl fmt::Debug for SystemTime {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(f)
     }
 }
@@ -585,7 +587,7 @@ impl Error for SystemTimeError {
 
 #[stable(feature = "time2", since = "1.8.0")]
 impl fmt::Display for SystemTimeError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "second time provided was later than self")
     }
 }
@@ -664,20 +666,23 @@ mod tests {
 
     #[test]
     #[should_panic]
-    fn instant_duration_panic() {
+    fn instant_duration_since_panic() {
         let a = Instant::now();
         (a - Duration::new(1, 0)).duration_since(a);
     }
 
     #[test]
-    fn checked_instant_duration_nopanic() {
-        let a = Instant::now();
-        let ret = (a - Duration::new(1, 0)).checked_duration_since(a);
-        assert_eq!(ret, None);
+    fn instant_checked_duration_since_nopanic() {
+        let now = Instant::now();
+        let earlier = now - Duration::new(1, 0);
+        let later = now + Duration::new(1, 0);
+        assert_eq!(earlier.checked_duration_since(now), None);
+        assert_eq!(later.checked_duration_since(now), Some(Duration::new(1, 0)));
+        assert_eq!(now.checked_duration_since(now), Some(Duration::new(0, 0)));
     }
 
     #[test]
-    fn saturating_instant_duration_nopanic() {
+    fn instant_saturating_duration_since_nopanic() {
         let a = Instant::now();
         let ret = (a - Duration::new(1, 0)).saturating_duration_since(a);
         assert_eq!(ret, Duration::new(0,0));
@@ -712,13 +717,6 @@ mod tests {
         assert_almost_eq!(a - second + second, a);
         assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
 
-        // A difference of 80 and 800 years cannot fit inside a 32-bit time_t
-        if !(cfg!(unix) && crate::mem::size_of::<libc::time_t>() <= 4) {
-            let eighty_years = second * 60 * 60 * 24 * 365 * 80;
-            assert_almost_eq!(a - eighty_years + eighty_years, a);
-            assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
-        }
-
         let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0);
         let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000)
             + Duration::new(0, 500_000_000);
@@ -747,8 +745,8 @@ mod tests {
     #[test]
     fn since_epoch() {
         let ts = SystemTime::now();
-        let a = ts.duration_since(UNIX_EPOCH).unwrap();
-        let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
+        let a = ts.duration_since(UNIX_EPOCH + Duration::new(1, 0)).unwrap();
+        let b = ts.duration_since(UNIX_EPOCH).unwrap();
         assert!(b > a);
         assert_eq!(b - a, Duration::new(1, 0));