-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove old (boxed) closures from the language #14798
Labels
Milestone
Comments
pnkfelix
changed the title
Remove boxed closures from the language
Remove (old) boxed closures from the language
Jun 12, 2014
emberian
changed the title
Remove (old) boxed closures from the language
Remove old (boxed) closures from the language
Jun 12, 2014
Assigning P-backcompat-lang, 1.0. |
How would one go about this? |
@huonw and now ? :p |
This was referenced Nov 20, 2014
Merged
bors
added a commit
that referenced
this issue
Jan 5, 2015
This PR removes boxed closures from the language, the closure type syntax (`let f: |int| -> bool = /* ... */`) has been obsoleted. Move all your uses of closures to the new unboxed closure system (i.e. `Fn*` traits). [breaking-change] patterns - `lef f = || {}` This binding used to type check to a boxed closure. Now that boxed closures are gone, you need to annotate the "kind" of the unboxed closure, i.e. you need pick one of these: `|&:| {}`, `|&mut:| {}` or `|:| {}`. In the (near) future we'll have closure "kind" inference, so the compiler will infer which `Fn*` trait to use based on how the closure is used. Once this inference machinery is in place, we'll be able to remove the kind annotation from most closures. - `type Alias<'a> = |int|:'a -> bool` Use a trait object: `type Alias<'a> = Box<FnMut(int) -> bool + 'a>`. Use the `Fn*` trait that makes sense for your use case. - `fn foo(&self, f: |uint| -> bool)` In this case you can use either a trait object or an unboxed closure: ``` rust fn foo(&self, f: F) where F: FnMut(uint) -> bool; // or fn foo(&self, f: Box<FnMut(uint) -> bool>); ``` - `struct Struct<'a> { f: |uint|:'a -> bool }` Again, you can use either a trait object or an unboxed closure: ``` rust struct Struct<F> where F: FnMut(uint) -> bool { f: F } // or struct Struct<'a> { f: Box<FnMut(uint) -> bool + 'a> } ``` - Using `|x, y| f(x, y)` for closure "borrows" This comes up in recursive functions, consider the following (contrived) example: ``` rust fn foo(x: uint, f: |uint| -> bool) -> bool { //foo(x / 2, f) && f(x) // can't use this because `f` gets moved away in the `foo` call foo(x / 2, |x| f(x)) && f(x) // instead "borrow" `f` in the `foo` call } ``` If you attempt to do the same with unboxed closures you'll hit ""error: reached the recursion limit during monomorphization" (see #19596): ``` rust fn foo<F>(x: uint, mut f: F) -> bool where F: FnMut(uint) -> bool { foo(x / 2, |x| f(x)) && f(x) //~^ error: reached the recursion limit during monomorphization } ``` Instead you *should* be able to write this: ``` rust fn foo<F>(x: uint, mut f: F) -> bool where F: FnMut(uint) -> bool { foo(x / 2, &mut f) && f(x) //~^ error: the trait `FnMut` is not implemented for the type `&mut F` } ``` But as you see above `&mut F` doesn't implement the `FnMut` trait. `&mut F` *should* implement the `FnMut` and the above code *should* work, but due to a bug (see #18835) it doesn't (for now). You can work around the issue by rewriting the function to take `&mut F` instead of `F`: ``` rust fn foo<F>(x: uint, f: &mut F) -> bool where F: FnMut(uint) -> bool { foo(x / 2, f) && (*f)(x) } ``` This finally works! However writing `foo(0, &mut |x| x == 0)` is unergonomic. So you can use a private helper function to avoid this: ``` rust // public API function pub fn foo<F>(x: uint, mut f: F) -> bool where F: FnMut(uint) -> bool { foo_(x, &mut f) } // private helper function fn foo_<F>(x: uint, f: &mut F) -> bool where F: FnMut(uint) -> bool { foo_(x / 2, f) && (*f)(x) } ``` Closes #14798 --- There is more cleanup to do: like renaming functions/types from `unboxed_closure` to just `closure`, removing more dead code, simplify functions which now have unused arguments, update the documentation, etc. But that can be done in another PR. r? @nikomatsakis @aturon (You probably want to focus on the deleted/modified tests.) cc @eddyb
bors
pushed a commit
to rust-lang-ci/rust
that referenced
this issue
Aug 21, 2023
…, unused_imports, ...) fixes rust-lang#14798
bors
added a commit
to rust-lang-ci/rust
that referenced
this issue
Aug 21, 2023
add check.ignore to list cargo check diagnostics to ignore (dead_code, unused_imports, ...) fixes rust-lang#14798
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
We will want to remove (old) boxed closures from the language for 1.0, I believe. At the very least we should feature gate them.
Nominating for 1.0, P-backcompat-lang.
The text was updated successfully, but these errors were encountered: