diff --git a/listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt b/listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt deleted file mode 100644 index 3a23426392..0000000000 --- a/listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt +++ /dev/null @@ -1,20 +0,0 @@ -$ cargo build - Compiling functions-example v0.1.0 (file:///projects/functions-example) -error[E0746]: return type cannot have an unboxed trait object - --> src/lib.rs:1:25 - | -1 | fn returns_closure() -> dyn Fn(i32) -> i32 { - | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | -help: consider returning an `impl Trait` instead of a `dyn Trait` - | -1 | fn returns_closure() -> impl Fn(i32) -> i32 { - | ~~~~ -help: alternatively, box the return type, and wrap all of the returned values in `Box::new` - | -1 ~ fn returns_closure() -> Box i32> { -2 ~ Box::new(|x| x + 1) - | - -For more information about this error, try `rustc --explain E0746`. -error: could not compile `functions-example` (lib) due to 1 previous error diff --git a/listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs b/listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs index d699ac34eb..7679cc7c0a 100644 --- a/listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs +++ b/listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs @@ -1,3 +1,3 @@ -fn returns_closure() -> dyn Fn(i32) -> i32 { +fn returns_closure() -> impl Fn(i32) -> i32 { |x| x + 1 } diff --git a/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs b/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs deleted file mode 100644 index b114077472..0000000000 --- a/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn returns_closure() -> Box i32> { - Box::new(|x| x + 1) -} diff --git a/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/main.rs b/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/main.rs new file mode 100644 index 0000000000..f033ea716c --- /dev/null +++ b/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/main.rs @@ -0,0 +1,15 @@ +fn main() { + let handlers = vec![returns_closure(), returns_initialized_closure(123)]; + for handler in handlers { + let output = handler(5); + println!("{output}"); + } +} + +fn returns_closure() -> Box i32> { + Box::new(|x| x + 1) +} + +fn returns_initialized_closure(init: i32) -> Box i32> { + Box::new(move |x| x + init) +} diff --git a/src/ch20-05-advanced-functions-and-closures.md b/src/ch20-05-advanced-functions-and-closures.md index 9f04892b0a..323e57bc96 100644 --- a/src/ch20-05-advanced-functions-and-closures.md +++ b/src/ch20-05-advanced-functions-and-closures.md @@ -95,33 +95,33 @@ function. However, you can’t do that with closures because they don’t have a concrete type that is returnable; you’re not allowed to use the function pointer `fn` as a return type, for example. -The following code tries to return a closure directly, but it won’t compile: +Instead, you will normally use the `impl Trait` syntax we learned about in +Chapter 10. You can return any function type, using `Fn`, `FnOnce` and `FnMut`. +For example, this code will work just fine: ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs}} ``` -The compiler error is as follows: - -```console -{{#include ../listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt}} -``` - -The error references the `Sized` trait again! Rust doesn’t know how much space -it will need to store the closure. We saw a solution to this problem earlier. -We can use a trait object: +However, as we noted in the [“Closure Type Inference and +Annotation”][closure-types] section in Chapter 13, each closure +is also its own distinct type. If you need to work with multiple functions that +have the same signature but different implementations, you will need to use a +trait object for them: ```rust,noplayground -{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/main.rs}} ``` -This code will compile just fine. For more about trait objects, refer to the -section [“Using Trait Objects That Allow for Values of Different -Types”][using-trait-objects-that-allow-for-values-of-different-types] in Chapter 19. +This code will compile just fine—but it wouldn’t if we had tried to stick with +`impl Fn(i32) -> i32`. For more about trait objects, refer to the section +[“Using Trait Objects That Allow for Values of Different +Types”][using-trait-objects-that-allow-for-values-of-different-types] in Chapter 19. Next, let’s look at macros! [advanced-traits]: ch20-03-advanced-traits.html#advanced-traits [enum-values]: ch06-01-defining-an-enum.html#enum-values +[closure-types]: ch13-01-closures.html#closure-type-inference-and-annotation [using-trait-objects-that-allow-for-values-of-different-types]: ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types