Skip to content
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5c1cd6c
Update cargo
dtolnay Apr 3, 2019
a37c33b
Mark unix::ffi::OsStrExt methods as inline
sugar700 Apr 4, 2019
a964921
Use declare_lint_pass! and impl_lint_pass! in more places
hgallagher1993 Apr 4, 2019
d6b91fe
Update cargo
dtolnay Apr 4, 2019
1bf04c9
std: Upgrade `compiler_builtins` to fix wasi linkage
alexcrichton Apr 2, 2019
7994197
Make FnBox a subtrait of FnOnce.
qnighy Oct 28, 2018
059ec76
Add Fn* blanket impls for Box.
qnighy Oct 28, 2018
480dcb4
Add tests for boxed_closure_impls.
qnighy Oct 28, 2018
219097e
Add unstable-book articles on fnbox and boxed_closure_impls.
qnighy Oct 28, 2018
e55d82c
Fix expectations on some ui tests involving FnOnce.
qnighy Oct 28, 2018
4dcd6cc
Fix failing tests.
qnighy Feb 3, 2019
a38f292
We already have unsized_locals in stage0.
qnighy Feb 10, 2019
45c0b28
Remove FnBox specialization of impl FnOnce for Box<impl FnOnce>.
qnighy Feb 11, 2019
ecc3e89
Stabilize boxed_closure_impls in 1.35.0.
crlf0710 Feb 11, 2019
440e873
Simplify fnbox docs.
qnighy Feb 11, 2019
7a63c7f
Add ignore to doc code
qnighy Feb 11, 2019
471db2b
wasm32: Default to a "static" relocation model
alexcrichton Apr 4, 2019
8c0e786
Rollup merge of #59500 - crlf0710:boxed-closure-impls, r=cramertj
Centril Apr 5, 2019
1f05de7
Rollup merge of #59643 - alexcrichton:wasi-symbols, r=sanxiyn
Centril Apr 5, 2019
bc995f4
Rollup merge of #59681 - dtolnay:cargo, r=alexcrichton
Centril Apr 5, 2019
6070d47
Rollup merge of #59690 - xfix:patch-17, r=cramertj
Centril Apr 5, 2019
3600e4d
Rollup merge of #59702 - hgallagher1993:origin, r=Centril
Centril Apr 5, 2019
c03fa7b
Rollup merge of #59712 - alexcrichton:wasm-static-not-pic, r=eddyb
Centril Apr 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/doc/unstable-book/src/library-features/fnbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# `fnbox`

The tracking issue for this feature is [#28796]

[#28796]: https://github.com/rust-lang/rust/issues/28796

------------------------

This had been a temporary alternative to the following impls:

```rust,ignore
impl<A, F> FnOnce for Box<F> where F: FnOnce<A> + ?Sized {}
impl<A, F> FnMut for Box<F> where F: FnMut<A> + ?Sized {}
impl<A, F> Fn for Box<F> where F: Fn<A> + ?Sized {}
```

The impls are parallel to these (relatively old) impls:

```rust,ignore
impl<A, F> FnOnce for &mut F where F: FnMut<A> + ?Sized {}
impl<A, F> FnMut for &mut F where F: FnMut<A> + ?Sized {}
impl<A, F> Fn for &mut F where F: Fn<A> + ?Sized {}
impl<A, F> FnOnce for &F where F: Fn<A> + ?Sized {}
impl<A, F> FnMut for &F where F: Fn<A> + ?Sized {}
impl<A, F> Fn for &F where F: Fn<A> + ?Sized {}
```

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<dyn FnOnce()>` at that time.

[unsized_locals]: language-features/unsized-locals.html

`FnBox()` is an alternative approach to `Box<dyn FnBox()>` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box<dyn FnOnce()>` working, the `fnbox` feature is going to be removed.
48 changes: 23 additions & 25 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,28 @@ impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {
#[stable(feature = "fused", since = "1.26.0")]
impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}

#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
impl<A, F: FnOnce<A> + ?Sized> FnOnce<A> for Box<F> {
type Output = <F as FnOnce<A>>::Output;

extern "rust-call" fn call_once(self, args: A) -> Self::Output {
<F as FnOnce<A>>::call_once(*self, args)
}
}

#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
impl<A, F: FnMut<A> + ?Sized> FnMut<A> for Box<F> {
extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output {
<F as FnMut<A>>::call_mut(self, args)
}
}

#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
extern "rust-call" fn call(&self, args: A) -> Self::Output {
<F as Fn<A>>::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
Expand Down Expand Up @@ -735,9 +757,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}
#[rustc_paren_sugar]
#[unstable(feature = "fnbox",
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
pub trait FnBox<A> {
type Output;

pub trait FnBox<A>: FnOnce<A> {
fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

Expand All @@ -746,33 +766,11 @@ pub trait FnBox<A> {
impl<A, F> FnBox<A> for F
where F: FnOnce<A>
{
type Output = F::Output;

fn call_box(self: Box<F>, args: A) -> F::Output {
self.call_once(args)
}
}

#[unstable(feature = "fnbox",
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
impl<A, R> FnOnce<A> for Box<dyn FnBox<A, Output = R> + '_> {
type Output = R;

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<FnOnce>` becomes usable", issue = "28796")]
impl<A, R> FnOnce<A> for Box<dyn FnBox<A, Output = R> + Send + '_> {
type Output = R;

extern "rust-call" fn call_once(self, args: A) -> R {
self.call_box(args)
}
}

#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}

Expand Down
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
8 changes: 8 additions & 0 deletions src/test/run-pass/unsized-locals/box-fnonce.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn call_it<T>(f: Box<dyn FnOnce() -> T>) -> T {
f()
}

fn main() {
let s = "hello".to_owned();
assert_eq!(&call_it(Box::new(|| s)) as &str, "hello");
}
12 changes: 12 additions & 0 deletions src/test/run-pass/unsized-locals/fnbox-compat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(fnbox)]

use std::boxed::FnBox;

fn call_it<T>(f: Box<dyn FnBox() -> T>) -> T {
f()
}

fn main() {
let s = "hello".to_owned();
assert_eq!(&call_it(Box::new(|| s)) as &str, "hello");
}
32 changes: 10 additions & 22 deletions src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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<F: FnOnce(i32) -> i32>(f: Box<F>) {
Expand All @@ -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<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
Expand All @@ -28,30 +28,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 | 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
= note: move occurs because `f` has type `std::boxed::Box<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
Expand All @@ -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;
| --^----
Expand All @@ -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];
| --^----
Expand All @@ -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`.
22 changes: 11 additions & 11 deletions src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ 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));
| - ^ value used here after move
| |
| 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<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
Expand All @@ -34,18 +34,18 @@ 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));
| - ^ value used here after move
| |
| 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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
36 changes: 11 additions & 25 deletions src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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<F: FnOnce(i32) -> i32>(f: Box<F>) {
| - consider adding a `Copy` constraint to this type argument
| - move occurs because `f` has type `std::boxed::Box<F>`, 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
Expand All @@ -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<FnOnce(i32) -> i32>) {
| - move occurs because `f` has type `std::boxed::Box<dyn std::ops::FnOnce(i32) -> 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
Expand All @@ -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;
| --^----
Expand All @@ -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];
| --^----
Expand All @@ -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`.
Loading