Skip to content

Commit

Permalink
Deprecate FnBox. Box<dyn FnOnce()> can be called directly, since …
Browse files Browse the repository at this point in the history
…1.35

FCP completion: rust-lang#28796 (comment)
  • Loading branch information
SimonSapin committed May 24, 2019
1 parent a8fc09b commit 73fd349
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 31 deletions.
42 changes: 33 additions & 9 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,13 +759,14 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
}
}

/// `FnBox` is deprecated and will be removed.
/// `Box<dyn FnOnce()>` can be called directly, since Rust 1.35.0.
///
/// `FnBox` is a version of the `FnOnce` intended for use with boxed
/// closure objects. The idea is that where one would normally store a
/// `Box<dyn FnOnce()>` in a data structure, you should use
/// closure objects. The idea was that where one would normally store a
/// `Box<dyn FnOnce()>` in a data structure, you whould use
/// `Box<dyn FnBox()>`. The two traits behave essentially the same, except
/// that a `FnBox` closure can only be called if it is boxed. (Note
/// that `FnBox` may be deprecated in the future if `Box<dyn FnOnce()>`
/// closures become directly usable.)
/// that a `FnBox` closure can only be called if it is boxed.
///
/// # Examples
///
Expand All @@ -777,6 +778,7 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
///
/// ```
/// #![feature(fnbox)]
/// #![allow(deprecated)]
///
/// use std::boxed::FnBox;
/// use std::collections::HashMap;
Expand All @@ -796,16 +798,38 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
/// }
/// }
/// ```
///
/// In Rust 1.35.0 or later, use `FnOnce`, `FnMut`, or `Fn` instead:
///
/// ```
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<dyn FnOnce() -> i32>> {
/// let mut map: HashMap<i32, Box<dyn FnOnce() -> i32>> = HashMap::new();
/// map.insert(1, Box::new(|| 22));
/// map.insert(2, Box::new(|| 44));
/// map
/// }
///
/// fn main() {
/// let mut map = make_map();
/// for i in &[1, 2] {
/// let f = map.remove(&i).unwrap();
/// assert_eq!(f(), i * 22);
/// }
/// }
/// ```
#[rustc_paren_sugar]
#[unstable(feature = "fnbox",
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
#[unstable(feature = "fnbox", issue = "28796")]
#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
pub trait FnBox<A>: FnOnce<A> {
/// Performs the call operation.
fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

#[unstable(feature = "fnbox",
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
#[unstable(feature = "fnbox", issue = "28796")]
#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
#[allow(deprecated, deprecated_in_future)]
impl<A, F> FnBox<A> for F
where F: FnOnce<A>
{
Expand Down
1 change: 1 addition & 0 deletions src/test/run-pass/unsized-locals/fnbox-compat.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![feature(fnbox)]
#![allow(deprecated, deprecated_in_future)]

use std::boxed::FnBox;

Expand Down
12 changes: 4 additions & 8 deletions src/test/ui/confuse-field-and-method/issue-2392.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#![feature(core, fnbox)]

use std::boxed::FnBox;

struct FuncContainer {
f1: fn(data: u8),
f2: extern "C" fn(data: u8),
Expand All @@ -18,7 +14,7 @@ struct Obj<F> where F: FnOnce() -> u32 {
}

struct BoxedObj {
boxed_closure: Box<FnBox() -> u32>,
boxed_closure: Box<FnOnce() -> u32>,
}

struct Wrapper<F> where F: FnMut() -> u32 {
Expand All @@ -29,8 +25,8 @@ fn func() -> u32 {
0
}

fn check_expression() -> Obj<Box<FnBox() -> u32>> {
Obj { closure: Box::new(|| 42_u32) as Box<FnBox() -> u32>, not_closure: 42 }
fn check_expression() -> Obj<Box<FnOnce() -> u32>> {
Obj { closure: Box::new(|| 42_u32) as Box<FnOnce() -> u32>, not_closure: 42 }
}

fn main() {
Expand All @@ -48,7 +44,7 @@ fn main() {
let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found

let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnBox() -> u32> };
let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnOnce() -> u32> };
boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found

// test expression writing in the notes
Expand Down
28 changes: 14 additions & 14 deletions src/test/ui/confuse-field-and-method/issue-2392.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:39:36: 39:41]>` in the current scope
--> $DIR/issue-2392.rs:40:15
error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
--> $DIR/issue-2392.rs:36:15
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| -------------------------------------- method `closure` not found for this
Expand All @@ -11,8 +11,8 @@ help: to call the function stored in `closure`, surround the field access with p
LL | (o_closure.closure)();
| ^ ^

error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:39:36: 39:41]>` in the current scope
--> $DIR/issue-2392.rs:42:15
error[E0599]: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:35:36: 35:41]>` in the current scope
--> $DIR/issue-2392.rs:38:15
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| -------------------------------------- method `not_closure` not found for this
Expand All @@ -23,7 +23,7 @@ LL | o_closure.not_closure();
| field, not a method

error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
--> $DIR/issue-2392.rs:46:12
--> $DIR/issue-2392.rs:42:12
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| -------------------------------------- method `closure` not found for this
Expand All @@ -36,7 +36,7 @@ LL | (o_func.closure)();
| ^ ^

error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
--> $DIR/issue-2392.rs:49:14
--> $DIR/issue-2392.rs:45:14
|
LL | struct BoxedObj {
| --------------- method `boxed_closure` not found for this
Expand All @@ -49,7 +49,7 @@ LL | (boxed_fn.boxed_closure)();
| ^ ^

error[E0599]: no method named `boxed_closure` found for type `BoxedObj` in the current scope
--> $DIR/issue-2392.rs:52:19
--> $DIR/issue-2392.rs:48:19
|
LL | struct BoxedObj {
| --------------- method `boxed_closure` not found for this
Expand All @@ -62,7 +62,7 @@ LL | (boxed_closure.boxed_closure)();
| ^ ^

error[E0599]: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
--> $DIR/issue-2392.rs:57:12
--> $DIR/issue-2392.rs:53:12
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| -------------------------------------- method `closure` not found for this
Expand All @@ -75,7 +75,7 @@ LL | (w.wrap.closure)();
| ^ ^

error[E0599]: no method named `not_closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
--> $DIR/issue-2392.rs:59:12
--> $DIR/issue-2392.rs:55:12
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| -------------------------------------- method `not_closure` not found for this
Expand All @@ -85,8 +85,8 @@ LL | w.wrap.not_closure();
| |
| field, not a method

error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::boxed::FnBox<(), Output = u32> + 'static)>>` in the current scope
--> $DIR/issue-2392.rs:62:24
error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::ops::FnOnce() -> u32 + 'static)>>` in the current scope
--> $DIR/issue-2392.rs:58:24
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| -------------------------------------- method `closure` not found for this
Expand All @@ -99,7 +99,7 @@ LL | (check_expression().closure)();
| ^ ^

error[E0599]: no method named `f1` found for type `FuncContainer` in the current scope
--> $DIR/issue-2392.rs:68:31
--> $DIR/issue-2392.rs:64:31
|
LL | struct FuncContainer {
| -------------------- method `f1` not found for this
Expand All @@ -112,7 +112,7 @@ LL | ((*self.container).f1)(1);
| ^ ^

error[E0599]: no method named `f2` found for type `FuncContainer` in the current scope
--> $DIR/issue-2392.rs:69:31
--> $DIR/issue-2392.rs:65:31
|
LL | struct FuncContainer {
| -------------------- method `f2` not found for this
Expand All @@ -125,7 +125,7 @@ LL | ((*self.container).f2)(1);
| ^ ^

error[E0599]: no method named `f3` found for type `FuncContainer` in the current scope
--> $DIR/issue-2392.rs:70:31
--> $DIR/issue-2392.rs:66:31
|
LL | struct FuncContainer {
| -------------------- method `f3` not found for this
Expand Down

0 comments on commit 73fd349

Please sign in to comment.