From 5c1cd6cc73ca3683a1d5175e2adb0dd3c45891c6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 3 Apr 2019 14:10:58 -0700 Subject: [PATCH 01/17] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 63231f438a2b5..d62dcd6af4ab4 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 63231f438a2b5b84ccf319a5de22343ee0316323 +Subproject commit d62dcd6af4ab4c43816b3d0659055f042a3d7061 From a37c33b9261f534b56434c83258ff24d24bf9351 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Thu, 4 Apr 2019 10:51:18 +0200 Subject: [PATCH 02/17] Mark unix::ffi::OsStrExt methods as inline --- src/libstd/ffi/os_str.rs | 1 + src/libstd/sys_common/os_str_bytes.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 01e7a57cd003f..13aee783750f1 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -960,6 +960,7 @@ impl IntoInner for OsString { } impl AsInner for OsStr { + #[inline] fn as_inner(&self) -> &Slice { &self.inner } diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index 7cc93477a73c7..a4961974d89ab 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -236,9 +236,11 @@ pub trait OsStrExt { #[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 } From a96492112c413f0846245eb2c579bed1da251549 Mon Sep 17 00:00:00 2001 From: hgallagher1993 Date: Thu, 4 Apr 2019 13:23:11 -0400 Subject: [PATCH 03/17] Use declare_lint_pass! and impl_lint_pass! in more places --- src/librustc/lint/internal.rs | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index d5f8876d1621f..030a9c1f93531 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -28,15 +28,7 @@ impl DefaultHashTypes { } } -impl LintPass for DefaultHashTypes { - fn get_lints(&self) -> LintArray { - lint_array!(DEFAULT_HASH_TYPES) - } - - fn name(&self) -> &'static str { - "DefaultHashTypes" - } -} +impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); impl EarlyLintPass for DefaultHashTypes { fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { @@ -68,17 +60,7 @@ declare_lint! { "Usage of `ty::TyKind` outside of the `ty::sty` module" } -pub struct TyKindUsage; - -impl LintPass for TyKindUsage { - fn get_lints(&self) -> LintArray { - lint_array!(USAGE_OF_TY_TYKIND) - } - - fn name(&self) -> &'static str { - "TyKindUsage" - } -} +declare_lint_pass!(TyKindUsage => [USAGE_OF_TY_TYKIND]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage { fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path, _: HirId) { From d6b91fe18fd4bf8e61d6b3b25d6e40cc6b42305b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 4 Apr 2019 10:39:23 -0700 Subject: [PATCH 04/17] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index d62dcd6af4ab4..6f3e9c367abb4 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit d62dcd6af4ab4c43816b3d0659055f042a3d7061 +Subproject commit 6f3e9c367abb497c64f360c3839dab5e74928d5c From 1bf04c9ad775560c80e1f2553ccc9526ff3727a0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 2 Apr 2019 13:38:51 -0700 Subject: [PATCH 05/17] std: Upgrade `compiler_builtins` to fix wasi linkage Turns out we needed to exclude a number of math functions on the `wasm32-unknown-wasi` target, and this was fixed in 0.1.9 of compiler-builtins and this is pulling in the fix to libstd's own build. --- Cargo.lock | 32 ++++++++++++++++---------------- src/libstd/Cargo.toml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76db7e1064bc2..3cc0026bf4589 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -107,7 +107,7 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -465,7 +465,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", @@ -751,7 +751,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -917,7 +917,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -1769,7 +1769,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1779,7 +1779,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", @@ -1964,7 +1964,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2479,7 +2479,7 @@ name = "rustc-demangle" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2579,7 +2579,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2806,7 +2806,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2868,7 +2868,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2989,7 +2989,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3256,7 +3256,7 @@ dependencies = [ "alloc 0.0.0", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3830,7 +3830,7 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4026,7 +4026,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "a28c3898d0c57b26fa6f92de141ba665fa5ac5179f795db06db408be84302395" +"checksum compiler_builtins 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d7de11892d9f9f1bc76d43011c8233d27d58300d629dc9dfb51b6626ef7f6077" "checksum compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "56c799b1f7142badf3b047b4c1f2074cc96b6b784fb2432f2ed9c87da0a03749" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 875483518e872..86ad334d88603 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -19,7 +19,7 @@ panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.8" } +compiler_builtins = { version = "0.1.9" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] } From 79941973af54db7f7b941582fdc9537b2ee95a00 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 28 Oct 2018 15:27:29 +0900 Subject: [PATCH 06/17] Make FnBox a subtrait of FnOnce. --- src/liballoc/boxed.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b2315c6a73907..9166f917293d1 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -735,9 +735,7 @@ impl FusedIterator for Box {} #[rustc_paren_sugar] #[unstable(feature = "fnbox", reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] -pub trait FnBox { - type Output; - +pub trait FnBox: FnOnce { fn call_box(self: Box, args: A) -> Self::Output; } @@ -746,8 +744,6 @@ pub trait FnBox { impl FnBox for F where F: FnOnce { - type Output = F::Output; - fn call_box(self: Box, args: A) -> F::Output { self.call_once(args) } From 059ec76d9b2ba33be5d7b092ffeb401590a5d39d Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 28 Oct 2018 15:28:15 +0900 Subject: [PATCH 07/17] Add Fn* blanket impls for Box. --- src/liballoc/boxed.rs | 33 +++++++++++++++++++++++++++++++++ src/liballoc/lib.rs | 1 + 2 files changed, 34 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9166f917293d1..09554a1a34da8 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -694,6 +694,37 @@ impl ExactSizeIterator for Box { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Box {} +#[cfg(not(stage0))] +#[unstable(feature = "boxed_closure_impls", + reason = "Box relies on unsized rvalues and needs to be tested more", + issue = "48055")] +impl + ?Sized> FnOnce for Box { + type Output = >::Output; + + default extern "rust-call" fn call_once(self, args: A) -> Self::Output { + >::call_once(*self, args) + } +} + +#[cfg(not(stage0))] +#[unstable(feature = "boxed_closure_impls", + reason = "Box relies on unsized rvalues and needs to be tested more", + issue = "48055")] +impl + ?Sized> FnMut for Box { + extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output { + >::call_mut(self, args) + } +} + +#[cfg(not(stage0))] +#[unstable(feature = "boxed_closure_impls", + reason = "Box relies on unsized rvalues and needs to be tested more", + issue = "48055")] +impl + ?Sized> Fn for Box { + extern "rust-call" fn call(&self, args: A) -> Self::Output { + >::call(self, args) + } +} /// `FnBox` is a version of the `FnOnce` intended for use with boxed /// closure objects. The idea is that where one would normally store a @@ -752,6 +783,7 @@ impl FnBox for F #[unstable(feature = "fnbox", reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] impl FnOnce for Box + '_> { + #[cfg(stage0)] type Output = R; extern "rust-call" fn call_once(self, args: A) -> R { @@ -762,6 +794,7 @@ impl FnOnce for Box + '_> { #[unstable(feature = "fnbox", reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] impl FnOnce for Box + Send + '_> { + #[cfg(stage0)] type Output = R; extern "rust-call" fn call_once(self, args: A) -> R { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 90ff56814fbb1..9064b4ccd6a88 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -107,6 +107,7 @@ #![feature(unboxed_closures)] #![feature(unicode_internals)] #![feature(unsize)] +#![feature(unsized_locals)] #![feature(allocator_internals)] #![feature(on_unimplemented)] #![feature(rustc_const_unstable)] From 480dcb403caa90ecd2cc717ad4801805c010d3f6 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 28 Oct 2018 15:28:47 +0900 Subject: [PATCH 08/17] Add tests for boxed_closure_impls. --- .../run-pass/unsized-locals/box-fnonce.rs | 10 +++++++ .../run-pass/unsized-locals/fnbox-compat.rs | 12 +++++++++ src/test/ui/unsized-locals/fnbox-compat.rs | 12 +++++++++ .../ui/unsized-locals/fnbox-compat.stderr | 27 +++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 src/test/run-pass/unsized-locals/box-fnonce.rs create mode 100644 src/test/run-pass/unsized-locals/fnbox-compat.rs create mode 100644 src/test/ui/unsized-locals/fnbox-compat.rs create mode 100644 src/test/ui/unsized-locals/fnbox-compat.stderr diff --git a/src/test/run-pass/unsized-locals/box-fnonce.rs b/src/test/run-pass/unsized-locals/box-fnonce.rs new file mode 100644 index 0000000000000..97007a9423917 --- /dev/null +++ b/src/test/run-pass/unsized-locals/box-fnonce.rs @@ -0,0 +1,10 @@ +#![feature(boxed_closure_impls)] + +fn call_it(f: Box T>) -> T { + f() +} + +fn main() { + let s = "hello".to_owned(); + assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); +} diff --git a/src/test/run-pass/unsized-locals/fnbox-compat.rs b/src/test/run-pass/unsized-locals/fnbox-compat.rs new file mode 100644 index 0000000000000..5ec54ada13bb0 --- /dev/null +++ b/src/test/run-pass/unsized-locals/fnbox-compat.rs @@ -0,0 +1,12 @@ +#![feature(fnbox)] + +use std::boxed::FnBox; + +fn call_it(f: Box T>) -> T { + f() +} + +fn main() { + let s = "hello".to_owned(); + assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); +} diff --git a/src/test/ui/unsized-locals/fnbox-compat.rs b/src/test/ui/unsized-locals/fnbox-compat.rs new file mode 100644 index 0000000000000..3cb9ac560a256 --- /dev/null +++ b/src/test/ui/unsized-locals/fnbox-compat.rs @@ -0,0 +1,12 @@ +#![feature(fnbox)] + +use std::boxed::FnBox; + +fn call_it(f: Box T>) -> T { + f(&42) +} + +fn main() { + let s = "hello".to_owned(); + assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); +} diff --git a/src/test/ui/unsized-locals/fnbox-compat.stderr b/src/test/ui/unsized-locals/fnbox-compat.stderr new file mode 100644 index 0000000000000..5172092fb1cd5 --- /dev/null +++ b/src/test/ui/unsized-locals/fnbox-compat.stderr @@ -0,0 +1,27 @@ +error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments + --> $DIR/fnbox-compat.rs:11:34 + | +LL | assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); + | ^^ + | | + | expected closure that takes 1 argument + | takes 0 arguments +help: consider changing the closure to take and ignore the expected argument + | +LL | assert_eq!(&call_it(Box::new(|_| s)) as &str, "hello"); + | ^^^ + +error[E0277]: the size for values of type `dyn for<'r> std::boxed::FnBox<(&'r i32,), Output=_>` cannot be known at compilation time + --> $DIR/fnbox-compat.rs:11:25 + | +LL | assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `dyn for<'r> std::boxed::FnBox<(&'r i32,), Output=_>` + = note: to learn more, visit + = note: required by `>::new` + +error: aborting due to 2 previous errors + +Some errors occurred: E0277, E0593. +For more information about an error, try `rustc --explain E0277`. From 219097ecf6026954db100fb00089a2188915615d Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 28 Oct 2018 15:36:58 +0900 Subject: [PATCH 09/17] Add unstable-book articles on fnbox and boxed_closure_impls. --- .../library-features/boxed-closure-impls.md | 98 +++++++ .../src/library-features/fnbox.md | 252 ++++++++++++++++++ 2 files changed, 350 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/boxed-closure-impls.md create mode 100644 src/doc/unstable-book/src/library-features/fnbox.md diff --git a/src/doc/unstable-book/src/library-features/boxed-closure-impls.md b/src/doc/unstable-book/src/library-features/boxed-closure-impls.md new file mode 100644 index 0000000000000..0c738d0f78e03 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/boxed-closure-impls.md @@ -0,0 +1,98 @@ +# `boxed_closure_impls` + +The tracking issue for this feature is [#48055] + +[#48055]: https://github.com/rust-lang/rust/issues/48055 + +------------------------ + +This includes the following blanket impls for closure traits: + +```rust,ignore +impl + ?Sized> FnOnce for Box { + // ... +} +impl + ?Sized> FnMut for Box { + // ... +} +impl + ?Sized> Fn for Box { + // ... +} +``` + +## Usage + +`Box` can be used almost transparently. You can even use `Box` now. + +```rust +#![feature(boxed_closure_impls)] + +fn main() { + let resource = "hello".to_owned(); + // Create a boxed once-callable closure + let f: Box = Box::new(|x| { + let s = resource; + println!("{}", x); + println!("{}", s); + }); + + // Call it + f(); +} +``` + +## The reason for instability + +This is unstable because of the first impl. + +It would have been easy if we're allowed to tighten the bound: + +```rust,ignore +impl + ?Sized> FnOnce for Box { + // ... +} +``` + +However, `Box` drops out of the modified impl. +To rescue this, we had had a temporary solution called [`fnbox`][fnbox]. + +[fnbox]: library-features/fnbox.html + +Unfortunately, due to minor coherence reasons, `fnbox` and +`FnOnce for Box` had not been able to coexist. +We had preferred `fnbox` for the time being. + +Now, as [`unsized_locals`][unsized_locals] is implemented, we can just write the +original impl: + +[unsized_locals]: language-features/unsized-locals.html + +```rust,ignore +impl + ?Sized> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + // *self is an unsized rvalue + >::call_once(*self, args) + } +} +``` + +However, since `unsized_locals` is a very young feature, we're careful about +this `FnOnce` impl now. + +There's another reason for instability: for compatibility with `fnbox`, +we currently allow specialization of the `Box` impl: + +```rust,ignore +impl + ?Sized> FnOnce for Box { + type Output = >::Output; + + // we have "default" here + default extern "rust-call" fn call_once(self, args: A) -> Self::Output { + >::call_once(*self, args) + } +} +``` + +This isn't what we desire in the long term. diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md new file mode 100644 index 0000000000000..3200601e557f6 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/fnbox.md @@ -0,0 +1,252 @@ +# `fnbox` + +The tracking issue for this feature is [#28796] + +[#28796]: https://github.com/rust-lang/rust/issues/28796 + +------------------------ + +As an analogy to `&dyn Fn()` and `&mut dyn FnMut()`, you may have expected +`Box` to work. But it hadn't until the recent improvement! +`FnBox` had been a **temporary** solution for this until we are able to pass +trait objects by value. + +See [`boxed_closure_impls`][boxed_closure_impls] for the newer approach. + +[boxed_closure_impls]: library-features/boxed-closure-impls.html + +## Usage + +If you want to box `FnOnce` closures, you can use `Box` instead of `Box`. + +```rust +#![feature(fnbox)] + +use std::boxed::FnBox; + +fn main() { + let resource = "hello".to_owned(); + // Create a boxed once-callable closure + let f: Box String> = Box::new(|| resource); + + // Call it + let s = f(); + println!("{}", s); +} +``` + +## How `Box` did not work + +**Spoiler**: [`boxed_closure_impls`][boxed_closure_impls] actually implements +`Box`! This didn't work because we lacked features like +[`unsized_locals`][unsized_locals] for a long time. Therefore, this section +just explains historical reasons for `FnBox`. + +[unsized_locals]: language-features/unsized-locals.html + +### First approach: just provide `Box` adapter impl + +The first (and natural) attempt for `Box` would look like: + +```rust,ignore +impl + ?Sized> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + >::call_once(*self, args) + } +} +``` + +However, this doesn't work. We have to relax the `Sized` bound for `F` because +we expect trait objects here, but `*self` must be `Sized` because it is passed +as a function argument. + +### The second attempt: add `FnOnce::call_box` + +One may come up with this workaround: modify `FnOnce`'s definition like this: + +```rust,ignore +pub trait FnOnce { + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; + // Add this new method + extern "rust-call" fn call_box(self: Box, args: Args) -> Self::Output; +} +``` + +...and then, modify the `impl` like this: + +```rust,ignore +impl + ?Sized> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + // We can use `call_box` here! + >::call_box(self, args) + } + // We'll have to define this in every impl of `FnOnce`. + extern "rust-call" fn call_box(self: Box, args: A) -> Self::Output { + >::call_box(*self, args) + } +} +``` + +What's wrong with this? The problem here is crates: + +- `FnOnce` is in `libcore`, as it shouldn't depend on allocations. +- `Box` is in `liballoc`, as it:s the very allocated pointer. + +It is impossible to add `FnOnce::call_box` because it is reverse-dependency. + +There's another problem: `call_box` can't have defaults. +`default impl` from the specialization RFC may resolve this problem. + +### The third attempt: add `FnBox` that contains `call_box` + +`call_box` can't reside in `FnOnce`, but how about defining a new trait in +`liballoc`? + +`FnBox` is almost a copy of `FnOnce`, but with `call_box`: + +```rust,ignore +pub trait FnBox { + type Output; + + extern "rust-call" fn call_box(self: Box, args: Args) -> Self::Output; +} +``` + +For `Sized` types (from which we coerce into `dyn FnBox`), we define +the blanket impl that proxies calls to `FnOnce`: + +```rust,ignore +impl> FnBox for F { + type Output = >::Output; + + extern "rust-call" fn call_box(self: Box, args: A) -> Self::Output { + // Here we assume `F` to be sized. + >::call_once(*self, args) + } +} +``` + +Now it looks like that we can define `FnOnce` for `Box`. + +```rust,ignore +impl + ?Sized> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + >::call_box(self, args) + } +} +``` + +## Limitations of `FnBox` + +### Interaction with HRTB + +Firstly, the actual implementation is different from the one presented above. +Instead of implementing `FnOnce` for `Box`, `liballoc` only +implements `FnOnce` for `Box`. + +```rust,ignore +impl<'a, A, R> FnOnce for Box + 'a> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + FnBox::call_box(*self, args) + } +} + +// Sendable variant +impl<'a, A, R> FnOnce for Box + Send + 'a> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + FnBox::call_box(*self, args) + } +} +``` + +The consequence is that the following example doesn't work: + +```rust,compile_fail +#![feature(fnbox)] + +use std::boxed::FnBox; + +fn main() { + let f: Box = Box::new(|x| println!("{}", x)); + f(42); +} +``` + +Note that `dyn FnBox(&i32)` desugars to +`dyn for<'r> FnBox<(&'r i32,), Output = ()>`. +It isn't covered in `dyn FnBox + 'a` or +`dyn FnBox + Send + 'a` due to HRTB. + +### Interaction with `Fn`/`FnMut` + +It would be natural to have the following impls: + +```rust,ignore +impl + ?Sized> FnMut for Box { + // ... +} +impl + ?Sized> Fn for Box { + // ... +} +``` + +However, we hadn't been able to write these in presense of `FnBox` +(until [`boxed_closure_impls`][boxed_closure_impls] lands). + +To have `FnMut` for `Box`, we should have (at least) this impl: + +```rust,ignore +// Note here we only impose `F: FnMut`. +// If we can write `F: FnOnce` here, that will resolve all problems. +impl + ?Sized> FnOnce for Box { + // ... +} +``` + +Unfortunately, the compiler complains that it **overlaps** with our +`dyn FnBox()` impls. At first glance, the overlap must not happen. +The `A` generic parameter does the trick here: due to coherence rules, +a downstream crate may define the following impl: + +```rust,ignore +struct MyStruct; +impl<'a> FnMut for dyn FnBox + 'a { + // ... +} +``` + +The trait solver doesn't know that `A` is always a tuple type, so this is +still possible. With this in mind, the compiler emits the overlap error. + +## Modification + +For compatibility with [`boxed_closure_impls`][boxed_closure_impls], +we now have a slightly modified version of `FnBox`: + +```rust,ignore +// It's now a subtrait of `FnOnce` +pub trait FnBox: FnOnce { + // now uses FnOnce::Output + // type Output; + + extern "rust-call" fn call_box(self: Box, args: Args) -> Self::Output; +} +``` + +## The future of `fnbox` + +`FnBox` has long been considered a temporary solution for `Box` +problem. Since we have [`boxed_closure_impls`][boxed_closure_impls] now, +it may be deprecated and removed in the future. From e55d82c8a3a05e433897de4a991366bb2963470d Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 28 Oct 2018 17:53:43 +0900 Subject: [PATCH 10/17] Fix expectations on some ui tests involving FnOnce. --- .../two-phase-nonrecv-autoref.ast.nll.stderr | 32 ++++++----------- .../two-phase-nonrecv-autoref.ast.stderr | 22 ++++++------ .../two-phase-nonrecv-autoref.nll.stderr | 36 ++++++------------- .../ui/borrowck/two-phase-nonrecv-autoref.rs | 16 ++++----- ...owck-call-is-borrow-issue-12224.nll.stderr | 2 +- .../borrowck-call-is-borrow-issue-12224.rs | 2 +- ...borrowck-call-is-borrow-issue-12224.stderr | 4 +-- 7 files changed, 42 insertions(+), 72 deletions(-) diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr index d026f81b7aad6..df74feb4f0564 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr @@ -7,7 +7,7 @@ LL | f(f(10)); | first mutable borrow occurs here | first borrow later used by call -error[E0382]: use of moved value: `*f` +error[E0382]: use of moved value: `f` --> $DIR/two-phase-nonrecv-autoref.rs:69:11 | LL | fn twice_ten_so i32>(f: Box) { @@ -17,7 +17,7 @@ LL | f(f(10)); | | | value moved here | - = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait + = note: move occurs because `f` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:76:11 @@ -28,19 +28,7 @@ LL | f(f(10)); | first mutable borrow occurs here | first borrow later used by call -error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined - --> $DIR/two-phase-nonrecv-autoref.rs:85:9 - | -LL | f(f(10)); - | ^ - -error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined - --> $DIR/two-phase-nonrecv-autoref.rs:85:11 - | -LL | f(f(10)); - | ^ - -error[E0382]: use of moved value: `*f` +error[E0382]: use of moved value: `f` --> $DIR/two-phase-nonrecv-autoref.rs:85:11 | LL | f(f(10)); @@ -48,10 +36,10 @@ LL | f(f(10)); | | | value moved here | - = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait + = note: move occurs because `f` has type `std::boxed::Box i32>`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:129:27 + --> $DIR/two-phase-nonrecv-autoref.rs:125:27 | LL | double_access(&mut a, &a); | ------------- ------ ^^ immutable borrow occurs here @@ -60,7 +48,7 @@ LL | double_access(&mut a, &a); | mutable borrow later used by call error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:157:7 + --> $DIR/two-phase-nonrecv-autoref.rs:153:7 | LL | i[i[3]] = 4; | --^---- @@ -70,7 +58,7 @@ LL | i[i[3]] = 4; | mutable borrow later used here error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:163:7 + --> $DIR/two-phase-nonrecv-autoref.rs:159:7 | LL | i[i[3]] = i[4]; | --^---- @@ -79,7 +67,7 @@ LL | i[i[3]] = i[4]; | mutable borrow occurs here | mutable borrow later used here -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors -Some errors occurred: E0161, E0382, E0499, E0502. -For more information about an error, try `rustc --explain E0161`. +Some errors occurred: E0382, E0499, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr index 426939f371ca5..d98b272944fdc 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr @@ -15,7 +15,7 @@ LL | f(f(10)); | | second mutable borrow occurs here | first mutable borrow occurs here -error[E0382]: use of moved value: `*f` +error[E0382]: use of moved value: `f` --> $DIR/two-phase-nonrecv-autoref.rs:69:11 | LL | f(f(10)); @@ -23,7 +23,7 @@ LL | f(f(10)); | | | value moved here | - = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait + = note: move occurs because `f` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:76:11 @@ -34,7 +34,7 @@ LL | f(f(10)); | | second mutable borrow occurs here | first mutable borrow occurs here -error[E0382]: use of moved value: `*f` +error[E0382]: use of moved value: `f` --> $DIR/two-phase-nonrecv-autoref.rs:85:11 | LL | f(f(10)); @@ -42,10 +42,10 @@ LL | f(f(10)); | | | value moved here | - = note: move occurs because `*f` has type `(dyn std::ops::FnOnce(i32) -> i32 + 'static)`, which does not implement the `Copy` trait + = note: move occurs because `f` has type `std::boxed::Box<(dyn std::ops::FnOnce(i32) -> i32 + 'static)>`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:129:28 + --> $DIR/two-phase-nonrecv-autoref.rs:125:28 | LL | double_access(&mut a, &a); | - ^- mutable borrow ends here @@ -54,7 +54,7 @@ LL | double_access(&mut a, &a); | mutable borrow occurs here error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:135:9 + --> $DIR/two-phase-nonrecv-autoref.rs:131:9 | LL | a.m(a.i(10)); | - ^ - mutable borrow ends here @@ -63,7 +63,7 @@ LL | a.m(a.i(10)); | mutable borrow occurs here error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:157:7 + --> $DIR/two-phase-nonrecv-autoref.rs:153:7 | LL | i[i[3]] = 4; | - ^ - mutable borrow ends here @@ -72,7 +72,7 @@ LL | i[i[3]] = 4; | mutable borrow occurs here error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:163:7 + --> $DIR/two-phase-nonrecv-autoref.rs:159:7 | LL | i[i[3]] = i[4]; | - ^ - mutable borrow ends here @@ -81,7 +81,7 @@ LL | i[i[3]] = i[4]; | mutable borrow occurs here error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:172:12 + --> $DIR/two-phase-nonrecv-autoref.rs:168:12 | LL | v.push(v.len()); | - ^ - mutable borrow ends here @@ -90,7 +90,7 @@ LL | v.push(v.len()); | mutable borrow occurs here error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:183:9 + --> $DIR/two-phase-nonrecv-autoref.rs:179:9 | LL | s.m(s.i(10)); | - ^ - mutable borrow ends here @@ -99,7 +99,7 @@ LL | s.m(s.i(10)); | mutable borrow occurs here error[E0502]: cannot borrow `t` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:188:9 + --> $DIR/two-phase-nonrecv-autoref.rs:184:9 | LL | t.m(t.i(10)); | - ^ - mutable borrow ends here diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr index d026f81b7aad6..223de36f0df31 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr @@ -7,17 +7,15 @@ LL | f(f(10)); | first mutable borrow occurs here | first borrow later used by call -error[E0382]: use of moved value: `*f` +error[E0382]: use of moved value: `f` --> $DIR/two-phase-nonrecv-autoref.rs:69:11 | LL | fn twice_ten_so i32>(f: Box) { - | - consider adding a `Copy` constraint to this type argument + | - move occurs because `f` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | f(f(10)); | - ^ value used here after move | | | value moved here - | - = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:76:11 @@ -28,30 +26,18 @@ LL | f(f(10)); | first mutable borrow occurs here | first borrow later used by call -error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined - --> $DIR/two-phase-nonrecv-autoref.rs:85:9 - | -LL | f(f(10)); - | ^ - -error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined - --> $DIR/two-phase-nonrecv-autoref.rs:85:11 - | -LL | f(f(10)); - | ^ - -error[E0382]: use of moved value: `*f` +error[E0382]: use of moved value: `f` --> $DIR/two-phase-nonrecv-autoref.rs:85:11 | +LL | fn twice_ten_oo(f: Box i32>) { + | - move occurs because `f` has type `std::boxed::Box i32>`, which does not implement the `Copy` trait LL | f(f(10)); | - ^ value used here after move | | | value moved here - | - = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:129:27 + --> $DIR/two-phase-nonrecv-autoref.rs:125:27 | LL | double_access(&mut a, &a); | ------------- ------ ^^ immutable borrow occurs here @@ -60,7 +46,7 @@ LL | double_access(&mut a, &a); | mutable borrow later used by call error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:157:7 + --> $DIR/two-phase-nonrecv-autoref.rs:153:7 | LL | i[i[3]] = 4; | --^---- @@ -70,7 +56,7 @@ LL | i[i[3]] = 4; | mutable borrow later used here error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable - --> $DIR/two-phase-nonrecv-autoref.rs:163:7 + --> $DIR/two-phase-nonrecv-autoref.rs:159:7 | LL | i[i[3]] = i[4]; | --^---- @@ -79,7 +65,7 @@ LL | i[i[3]] = i[4]; | mutable borrow occurs here | mutable borrow later used here -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors -Some errors occurred: E0161, E0382, E0499, E0502. -For more information about an error, try `rustc --explain E0161`. +Some errors occurred: E0382, E0499, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs index 1a14cb90f38ef..1005da052970b 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs @@ -67,9 +67,9 @@ fn overloaded_call_traits() { } fn twice_ten_so i32>(f: Box) { f(f(10)); - //[nll]~^ ERROR use of moved value: `*f` - //[g2p]~^^ ERROR use of moved value: `*f` - //[ast]~^^^ ERROR use of moved value: `*f` + //[nll]~^ ERROR use of moved value: `f` + //[g2p]~^^ ERROR use of moved value: `f` + //[ast]~^^^ ERROR use of moved value: `f` } fn twice_ten_om(f: &mut FnMut(i32) -> i32) { @@ -83,13 +83,9 @@ fn overloaded_call_traits() { } fn twice_ten_oo(f: Box i32>) { f(f(10)); - //[nll]~^ ERROR cannot move a value of type - //[nll]~^^ ERROR cannot move a value of type - //[nll]~^^^ ERROR use of moved value: `*f` - //[g2p]~^^^^ ERROR cannot move a value of type - //[g2p]~^^^^^ ERROR cannot move a value of type - //[g2p]~^^^^^^ ERROR use of moved value: `*f` - //[ast]~^^^^^^^ ERROR use of moved value: `*f` + //[nll]~^ ERROR use of moved value: `f` + //[g2p]~^^ ERROR use of moved value: `f` + //[ast]~^^^ ERROR use of moved value: `f` } twice_ten_sm(&mut |x| x + 1); diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr index 1a5ab7a7d56a0..4e2ab59f82245 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr @@ -18,7 +18,7 @@ LL | fn test2(f: &F) where F: FnMut() { LL | (*f)(); | ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable -error[E0596]: cannot borrow `*f.f` as mutable, as it is behind a `&` reference +error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5 | LL | fn test4(f: &Test) { diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs index cfebd6f700359..f246f1118bf4e 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -32,7 +32,7 @@ fn test3(f: &mut F) where F: FnMut() { fn test4(f: &Test) { f.f.call_mut(()) - //~^ ERROR: cannot borrow `Box` content `*f.f` of immutable binding as mutable + //~^ ERROR: cannot borrow field `f.f` of immutable binding as mutable } fn test5(f: &mut Test) { diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 6c8f477e31062..a61ee8334afff 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -19,13 +19,13 @@ LL | fn test2(f: &F) where F: FnMut() { LL | (*f)(); | ^^^^ cannot borrow as mutable -error[E0596]: cannot borrow `Box` content `*f.f` of immutable binding as mutable +error[E0596]: cannot borrow field `f.f` of immutable binding as mutable --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5 | LL | fn test4(f: &Test) { | ----- use `&mut Test` here to make mutable LL | f.f.call_mut(()) - | ^^^ cannot borrow as mutable + | ^^^ cannot mutably borrow field of immutable binding error[E0504]: cannot move `f` into closure because it is borrowed --> $DIR/borrowck-call-is-borrow-issue-12224.rs:56:13 From 4dcd6cc208e143309d481f0ecf4051bd9d139a18 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 3 Feb 2019 22:08:34 +0900 Subject: [PATCH 11/17] Fix failing tests. --- .../library-features/boxed-closure-impls.md | 2 +- src/test/ui/unsized-locals/fnbox-compat.rs | 3 +- .../ui/unsized-locals/fnbox-compat.stderr | 30 +++++-------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/boxed-closure-impls.md b/src/doc/unstable-book/src/library-features/boxed-closure-impls.md index 0c738d0f78e03..5ceb54ff3b96e 100644 --- a/src/doc/unstable-book/src/library-features/boxed-closure-impls.md +++ b/src/doc/unstable-book/src/library-features/boxed-closure-impls.md @@ -37,7 +37,7 @@ fn main() { }); // Call it - f(); + f(&42); } ``` diff --git a/src/test/ui/unsized-locals/fnbox-compat.rs b/src/test/ui/unsized-locals/fnbox-compat.rs index 3cb9ac560a256..c2c385e9fea56 100644 --- a/src/test/ui/unsized-locals/fnbox-compat.rs +++ b/src/test/ui/unsized-locals/fnbox-compat.rs @@ -4,9 +4,10 @@ use std::boxed::FnBox; fn call_it(f: Box T>) -> T { f(&42) + //~^ERROR implementation of `std::ops::FnOnce` is not general enough } fn main() { let s = "hello".to_owned(); - assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); + assert_eq!(&call_it(Box::new(|_| s)) as &str, "hello"); } diff --git a/src/test/ui/unsized-locals/fnbox-compat.stderr b/src/test/ui/unsized-locals/fnbox-compat.stderr index 5172092fb1cd5..c37bfaa47f7eb 100644 --- a/src/test/ui/unsized-locals/fnbox-compat.stderr +++ b/src/test/ui/unsized-locals/fnbox-compat.stderr @@ -1,27 +1,11 @@ -error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments - --> $DIR/fnbox-compat.rs:11:34 +error: implementation of `std::ops::FnOnce` is not general enough + --> $DIR/fnbox-compat.rs:6:5 | -LL | assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); - | ^^ - | | - | expected closure that takes 1 argument - | takes 0 arguments -help: consider changing the closure to take and ignore the expected argument +LL | f(&42) + | ^^^^^^ | -LL | assert_eq!(&call_it(Box::new(|_| s)) as &str, "hello"); - | ^^^ + = note: `std::ops::FnOnce<(&'0 i32,)>` would have to be implemented for the type `std::boxed::Box<(dyn for<'r> std::boxed::FnBox<(&'r i32,), Output=T> + 'static)>`, for some specific lifetime `'0` + = note: but `std::ops::FnOnce<(&'1 i32,)>` is actually implemented for the type `std::boxed::Box<(dyn std::boxed::FnBox<(&'1 i32,), Output=T> + '_)>`, for some specific lifetime `'1` -error[E0277]: the size for values of type `dyn for<'r> std::boxed::FnBox<(&'r i32,), Output=_>` cannot be known at compilation time - --> $DIR/fnbox-compat.rs:11:25 - | -LL | assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); - | ^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `std::marker::Sized` is not implemented for `dyn for<'r> std::boxed::FnBox<(&'r i32,), Output=_>` - = note: to learn more, visit - = note: required by `>::new` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0277, E0593. -For more information about an error, try `rustc --explain E0277`. From a38f29272ef4d04f0cc77e4f8d4fa5fac7ed746d Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 10 Feb 2019 19:25:56 +0900 Subject: [PATCH 12/17] We already have unsized_locals in stage0. --- src/liballoc/boxed.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 09554a1a34da8..864add1ecfe8e 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -694,7 +694,6 @@ impl ExactSizeIterator for Box { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Box {} -#[cfg(not(stage0))] #[unstable(feature = "boxed_closure_impls", reason = "Box relies on unsized rvalues and needs to be tested more", issue = "48055")] @@ -706,7 +705,6 @@ impl + ?Sized> FnOnce for Box { } } -#[cfg(not(stage0))] #[unstable(feature = "boxed_closure_impls", reason = "Box relies on unsized rvalues and needs to be tested more", issue = "48055")] @@ -716,7 +714,6 @@ impl + ?Sized> FnMut for Box { } } -#[cfg(not(stage0))] #[unstable(feature = "boxed_closure_impls", reason = "Box relies on unsized rvalues and needs to be tested more", issue = "48055")] @@ -783,9 +780,6 @@ impl FnBox for F #[unstable(feature = "fnbox", reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] impl FnOnce for Box + '_> { - #[cfg(stage0)] - type Output = R; - extern "rust-call" fn call_once(self, args: A) -> R { self.call_box(args) } @@ -794,9 +788,6 @@ impl FnOnce for Box + '_> { #[unstable(feature = "fnbox", reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] impl FnOnce for Box + Send + '_> { - #[cfg(stage0)] - type Output = R; - extern "rust-call" fn call_once(self, args: A) -> R { self.call_box(args) } From 45c0b28bcb6e383cd9d24d3845ee8accda31c889 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 11 Feb 2019 10:34:24 +0900 Subject: [PATCH 13/17] Remove FnBox specialization of impl FnOnce for Box. --- src/liballoc/boxed.rs | 18 +----------------- src/test/ui/unsized-locals/fnbox-compat.rs | 13 ------------- src/test/ui/unsized-locals/fnbox-compat.stderr | 11 ----------- 3 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 src/test/ui/unsized-locals/fnbox-compat.rs delete mode 100644 src/test/ui/unsized-locals/fnbox-compat.stderr diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 864add1ecfe8e..d4fe8be36d6f5 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -700,7 +700,7 @@ impl FusedIterator for Box {} impl + ?Sized> FnOnce for Box { type Output = >::Output; - default extern "rust-call" fn call_once(self, args: A) -> Self::Output { + extern "rust-call" fn call_once(self, args: A) -> Self::Output { >::call_once(*self, args) } } @@ -777,22 +777,6 @@ impl FnBox for F } } -#[unstable(feature = "fnbox", - reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] -impl FnOnce for Box + '_> { - extern "rust-call" fn call_once(self, args: A) -> R { - self.call_box(args) - } -} - -#[unstable(feature = "fnbox", - reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] -impl FnOnce for Box + Send + '_> { - extern "rust-call" fn call_once(self, args: A) -> R { - self.call_box(args) - } -} - #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized> for Box {} diff --git a/src/test/ui/unsized-locals/fnbox-compat.rs b/src/test/ui/unsized-locals/fnbox-compat.rs deleted file mode 100644 index c2c385e9fea56..0000000000000 --- a/src/test/ui/unsized-locals/fnbox-compat.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(fnbox)] - -use std::boxed::FnBox; - -fn call_it(f: Box T>) -> T { - f(&42) - //~^ERROR implementation of `std::ops::FnOnce` is not general enough -} - -fn main() { - let s = "hello".to_owned(); - assert_eq!(&call_it(Box::new(|_| s)) as &str, "hello"); -} diff --git a/src/test/ui/unsized-locals/fnbox-compat.stderr b/src/test/ui/unsized-locals/fnbox-compat.stderr deleted file mode 100644 index c37bfaa47f7eb..0000000000000 --- a/src/test/ui/unsized-locals/fnbox-compat.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: implementation of `std::ops::FnOnce` is not general enough - --> $DIR/fnbox-compat.rs:6:5 - | -LL | f(&42) - | ^^^^^^ - | - = note: `std::ops::FnOnce<(&'0 i32,)>` would have to be implemented for the type `std::boxed::Box<(dyn for<'r> std::boxed::FnBox<(&'r i32,), Output=T> + 'static)>`, for some specific lifetime `'0` - = note: but `std::ops::FnOnce<(&'1 i32,)>` is actually implemented for the type `std::boxed::Box<(dyn std::boxed::FnBox<(&'1 i32,), Output=T> + '_)>`, for some specific lifetime `'1` - -error: aborting due to previous error - From ecc3e89dd072ed20d9aa6d53be0ab1c44d160232 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Mon, 11 Feb 2019 11:09:26 +0900 Subject: [PATCH 14/17] Stabilize boxed_closure_impls in 1.35.0. --- .../library-features/boxed-closure-impls.md | 98 ------------------- src/liballoc/boxed.rs | 12 +-- .../run-pass/unsized-locals/box-fnonce.rs | 2 - 3 files changed, 3 insertions(+), 109 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/boxed-closure-impls.md diff --git a/src/doc/unstable-book/src/library-features/boxed-closure-impls.md b/src/doc/unstable-book/src/library-features/boxed-closure-impls.md deleted file mode 100644 index 5ceb54ff3b96e..0000000000000 --- a/src/doc/unstable-book/src/library-features/boxed-closure-impls.md +++ /dev/null @@ -1,98 +0,0 @@ -# `boxed_closure_impls` - -The tracking issue for this feature is [#48055] - -[#48055]: https://github.com/rust-lang/rust/issues/48055 - ------------------------- - -This includes the following blanket impls for closure traits: - -```rust,ignore -impl + ?Sized> FnOnce for Box { - // ... -} -impl + ?Sized> FnMut for Box { - // ... -} -impl + ?Sized> Fn for Box { - // ... -} -``` - -## Usage - -`Box` can be used almost transparently. You can even use `Box` now. - -```rust -#![feature(boxed_closure_impls)] - -fn main() { - let resource = "hello".to_owned(); - // Create a boxed once-callable closure - let f: Box = Box::new(|x| { - let s = resource; - println!("{}", x); - println!("{}", s); - }); - - // Call it - f(&42); -} -``` - -## The reason for instability - -This is unstable because of the first impl. - -It would have been easy if we're allowed to tighten the bound: - -```rust,ignore -impl + ?Sized> FnOnce for Box { - // ... -} -``` - -However, `Box` drops out of the modified impl. -To rescue this, we had had a temporary solution called [`fnbox`][fnbox]. - -[fnbox]: library-features/fnbox.html - -Unfortunately, due to minor coherence reasons, `fnbox` and -`FnOnce for Box` had not been able to coexist. -We had preferred `fnbox` for the time being. - -Now, as [`unsized_locals`][unsized_locals] is implemented, we can just write the -original impl: - -[unsized_locals]: language-features/unsized-locals.html - -```rust,ignore -impl + ?Sized> FnOnce for Box { - type Output = >::Output; - - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - // *self is an unsized rvalue - >::call_once(*self, args) - } -} -``` - -However, since `unsized_locals` is a very young feature, we're careful about -this `FnOnce` impl now. - -There's another reason for instability: for compatibility with `fnbox`, -we currently allow specialization of the `Box` impl: - -```rust,ignore -impl + ?Sized> FnOnce for Box { - type Output = >::Output; - - // we have "default" here - default extern "rust-call" fn call_once(self, args: A) -> Self::Output { - >::call_once(*self, args) - } -} -``` - -This isn't what we desire in the long term. diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index d4fe8be36d6f5..f6dee7c9eefd6 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -694,9 +694,7 @@ impl ExactSizeIterator for Box { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Box {} -#[unstable(feature = "boxed_closure_impls", - reason = "Box relies on unsized rvalues and needs to be tested more", - issue = "48055")] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl + ?Sized> FnOnce for Box { type Output = >::Output; @@ -705,18 +703,14 @@ impl + ?Sized> FnOnce for Box { } } -#[unstable(feature = "boxed_closure_impls", - reason = "Box relies on unsized rvalues and needs to be tested more", - issue = "48055")] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl + ?Sized> FnMut for Box { extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output { >::call_mut(self, args) } } -#[unstable(feature = "boxed_closure_impls", - reason = "Box relies on unsized rvalues and needs to be tested more", - issue = "48055")] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl + ?Sized> Fn for Box { extern "rust-call" fn call(&self, args: A) -> Self::Output { >::call(self, args) diff --git a/src/test/run-pass/unsized-locals/box-fnonce.rs b/src/test/run-pass/unsized-locals/box-fnonce.rs index 97007a9423917..16bdeae4fad41 100644 --- a/src/test/run-pass/unsized-locals/box-fnonce.rs +++ b/src/test/run-pass/unsized-locals/box-fnonce.rs @@ -1,5 +1,3 @@ -#![feature(boxed_closure_impls)] - fn call_it(f: Box T>) -> T { f() } From 440e873a4739e7cb8f6aec0f675ca3796c336e60 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 11 Feb 2019 11:09:41 +0900 Subject: [PATCH 15/17] Simplify fnbox docs. --- .../src/library-features/fnbox.md | 250 ++---------------- 1 file changed, 15 insertions(+), 235 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md index 3200601e557f6..16ebab3abeb50 100644 --- a/src/doc/unstable-book/src/library-features/fnbox.md +++ b/src/doc/unstable-book/src/library-features/fnbox.md @@ -6,247 +6,27 @@ The tracking issue for this feature is [#28796] ------------------------ -As an analogy to `&dyn Fn()` and `&mut dyn FnMut()`, you may have expected -`Box` to work. But it hadn't until the recent improvement! -`FnBox` had been a **temporary** solution for this until we are able to pass -trait objects by value. - -See [`boxed_closure_impls`][boxed_closure_impls] for the newer approach. - -[boxed_closure_impls]: library-features/boxed-closure-impls.html - -## Usage - -If you want to box `FnOnce` closures, you can use `Box` instead of `Box`. +This had been a temporary alternative to the following impls: ```rust -#![feature(fnbox)] - -use std::boxed::FnBox; - -fn main() { - let resource = "hello".to_owned(); - // Create a boxed once-callable closure - let f: Box String> = Box::new(|| resource); - - // Call it - let s = f(); - println!("{}", s); -} +impl FnOnce for Box where F: FnOnce + ?Sized {} +impl FnMut for Box where F: FnMut + ?Sized {} +impl Fn for Box where F: Fn + ?Sized {} ``` -## How `Box` did not work - -**Spoiler**: [`boxed_closure_impls`][boxed_closure_impls] actually implements -`Box`! This didn't work because we lacked features like -[`unsized_locals`][unsized_locals] for a long time. Therefore, this section -just explains historical reasons for `FnBox`. - -[unsized_locals]: language-features/unsized-locals.html - -### First approach: just provide `Box` adapter impl - -The first (and natural) attempt for `Box` would look like: - -```rust,ignore -impl + ?Sized> FnOnce for Box { - type Output = >::Output; - - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - >::call_once(*self, args) - } -} -``` - -However, this doesn't work. We have to relax the `Sized` bound for `F` because -we expect trait objects here, but `*self` must be `Sized` because it is passed -as a function argument. - -### The second attempt: add `FnOnce::call_box` - -One may come up with this workaround: modify `FnOnce`'s definition like this: - -```rust,ignore -pub trait FnOnce { - type Output; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; - // Add this new method - extern "rust-call" fn call_box(self: Box, args: Args) -> Self::Output; -} -``` - -...and then, modify the `impl` like this: - -```rust,ignore -impl + ?Sized> FnOnce for Box { - type Output = >::Output; - - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - // We can use `call_box` here! - >::call_box(self, args) - } - // We'll have to define this in every impl of `FnOnce`. - extern "rust-call" fn call_box(self: Box, args: A) -> Self::Output { - >::call_box(*self, args) - } -} -``` - -What's wrong with this? The problem here is crates: - -- `FnOnce` is in `libcore`, as it shouldn't depend on allocations. -- `Box` is in `liballoc`, as it:s the very allocated pointer. - -It is impossible to add `FnOnce::call_box` because it is reverse-dependency. - -There's another problem: `call_box` can't have defaults. -`default impl` from the specialization RFC may resolve this problem. - -### The third attempt: add `FnBox` that contains `call_box` - -`call_box` can't reside in `FnOnce`, but how about defining a new trait in -`liballoc`? - -`FnBox` is almost a copy of `FnOnce`, but with `call_box`: - -```rust,ignore -pub trait FnBox { - type Output; - - extern "rust-call" fn call_box(self: Box, args: Args) -> Self::Output; -} -``` - -For `Sized` types (from which we coerce into `dyn FnBox`), we define -the blanket impl that proxies calls to `FnOnce`: - -```rust,ignore -impl> FnBox for F { - type Output = >::Output; +The impls are parallel to these (relatively old) impls: - extern "rust-call" fn call_box(self: Box, args: A) -> Self::Output { - // Here we assume `F` to be sized. - >::call_once(*self, args) - } -} -``` - -Now it looks like that we can define `FnOnce` for `Box`. - -```rust,ignore -impl + ?Sized> FnOnce for Box { - type Output = >::Output; - - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - >::call_box(self, args) - } -} -``` - -## Limitations of `FnBox` - -### Interaction with HRTB - -Firstly, the actual implementation is different from the one presented above. -Instead of implementing `FnOnce` for `Box`, `liballoc` only -implements `FnOnce` for `Box`. - -```rust,ignore -impl<'a, A, R> FnOnce for Box + 'a> { - type Output = R; - - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - FnBox::call_box(*self, args) - } -} - -// Sendable variant -impl<'a, A, R> FnOnce for Box + Send + 'a> { - type Output = R; - - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - FnBox::call_box(*self, args) - } -} -``` - -The consequence is that the following example doesn't work: - -```rust,compile_fail -#![feature(fnbox)] - -use std::boxed::FnBox; - -fn main() { - let f: Box = Box::new(|x| println!("{}", x)); - f(42); -} -``` - -Note that `dyn FnBox(&i32)` desugars to -`dyn for<'r> FnBox<(&'r i32,), Output = ()>`. -It isn't covered in `dyn FnBox + 'a` or -`dyn FnBox + Send + 'a` due to HRTB. - -### Interaction with `Fn`/`FnMut` - -It would be natural to have the following impls: - -```rust,ignore -impl + ?Sized> FnMut for Box { - // ... -} -impl + ?Sized> Fn for Box { - // ... -} -``` - -However, we hadn't been able to write these in presense of `FnBox` -(until [`boxed_closure_impls`][boxed_closure_impls] lands). - -To have `FnMut` for `Box`, we should have (at least) this impl: - -```rust,ignore -// Note here we only impose `F: FnMut`. -// If we can write `F: FnOnce` here, that will resolve all problems. -impl + ?Sized> FnOnce for Box { - // ... -} -``` - -Unfortunately, the compiler complains that it **overlaps** with our -`dyn FnBox()` impls. At first glance, the overlap must not happen. -The `A` generic parameter does the trick here: due to coherence rules, -a downstream crate may define the following impl: - -```rust,ignore -struct MyStruct; -impl<'a> FnMut for dyn FnBox + 'a { - // ... -} +```rust +impl FnOnce for &mut F where F: FnMut + ?Sized {} +impl FnMut for &mut F where F: FnMut + ?Sized {} +impl Fn for &mut F where F: Fn + ?Sized {} +impl FnOnce for &F where F: Fn + ?Sized {} +impl FnMut for &F where F: Fn + ?Sized {} +impl Fn for &F where F: Fn + ?Sized {} ``` -The trait solver doesn't know that `A` is always a tuple type, so this is -still possible. With this in mind, the compiler emits the overlap error. - -## Modification - -For compatibility with [`boxed_closure_impls`][boxed_closure_impls], -we now have a slightly modified version of `FnBox`: +Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box` at that time. -```rust,ignore -// It's now a subtrait of `FnOnce` -pub trait FnBox: FnOnce { - // now uses FnOnce::Output - // type Output; - - extern "rust-call" fn call_box(self: Box, args: Args) -> Self::Output; -} -``` - -## The future of `fnbox` +[unsized_locals]: language-features/unsized-locals.html -`FnBox` has long been considered a temporary solution for `Box` -problem. Since we have [`boxed_closure_impls`][boxed_closure_impls] now, -it may be deprecated and removed in the future. +`FnBox()` is an alternative approach to `Box` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box` working, the `fnbox` feature is going to be removed. From 7a63c7f01050cd612787372f7a2ca7a8ec2105bc Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 11 Feb 2019 16:32:42 +0900 Subject: [PATCH 16/17] Add ignore to doc code --- src/doc/unstable-book/src/library-features/fnbox.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md index 16ebab3abeb50..cb3386b715211 100644 --- a/src/doc/unstable-book/src/library-features/fnbox.md +++ b/src/doc/unstable-book/src/library-features/fnbox.md @@ -8,7 +8,7 @@ The tracking issue for this feature is [#28796] This had been a temporary alternative to the following impls: -```rust +```rust,ignore impl FnOnce for Box where F: FnOnce + ?Sized {} impl FnMut for Box where F: FnMut + ?Sized {} impl Fn for Box where F: Fn + ?Sized {} @@ -16,7 +16,7 @@ impl Fn for Box where F: Fn + ?Sized {} The impls are parallel to these (relatively old) impls: -```rust +```rust,ignore impl FnOnce for &mut F where F: FnMut + ?Sized {} impl FnMut for &mut F where F: FnMut + ?Sized {} impl Fn for &mut F where F: Fn + ?Sized {} From 471db2b84bbeafb128bae8a8a9cf7fed13d2df4f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 4 Apr 2019 13:23:42 -0700 Subject: [PATCH 17/17] wasm32: Default to a "static" relocation model LLVM 9 is adding support for a "pic" relocation model for wasm code, which is quite different than the current model. In order to preserve the mode of compilation that we have today default to "static" to ensure that we don't accidentally start creating experimental relocatable binaries. --- src/librustc_target/spec/wasm32_base.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs index c7e75b4fa0903..edaf902c130d8 100644 --- a/src/librustc_target/spec/wasm32_base.rs +++ b/src/librustc_target/spec/wasm32_base.rs @@ -118,6 +118,15 @@ pub fn options() -> TargetOptions { pre_link_args, + // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when + // PIC code is implemented this has quite a drastric effect if it stays + // at the default, `pic`. In an effort to keep wasm binaries as minimal + // as possible we're defaulting to `static` for now, but the hope is + // that eventually we can ship a `pic`-compatible standard library which + // works with `static` as well (or works with some method of generating + // non-relative calls and such later on). + relocation_model: "static".to_string(), + .. Default::default() } }