Skip to content
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

Improve documentation on closure types. #249

Merged
merged 4 commits into from
Feb 24, 2018
Merged

Conversation

alercah
Copy link
Contributor

@alercah alercah commented Feb 20, 2018

This PR more fully documents closure types, including the mechanics of captures and the traits implemented by them. I intend to work on closure expressions as well, either in this PR or a follow-up, but felt this was a good place to put them.

I didn't fully explain capturing here, as I feel like that's better for closure expressions. The bit about no field captures might make more sense there as well, but I think the mechanics of how captures are typed and the implications on the traits belong here.

This PR is written for a post-RFC 2132 world, where closures have Clone and Copy, and intended as part of the stabilization docs for that RFC. The tracking issue is rust-lang/rust#44490. That bit could easily be split out though.

Fixes #219, fixes #229.

Copy link
Contributor

@Havvy Havvy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First off, thank you oh so very much for working on this very complex corner of the language. I truly am grateful for this PR (and most PRs).

That said, there's some minor nits and small edits I've suggested.

And also, I am sorry it took sooo long to actually review this. Weather has been inclement where I live which lead to me getting more work hours to cover for those who couldn't get in. And then I was too tired or distracted to look at this.

src/types.md Outdated
closures*, can be coerced to function pointers (`fn`) with the matching
signature. To adopt the example from the section above:
The compiler prefers to capture a closed-over variable by immutable borrow,
followed by mutable borrow and finally by move (or copy, for [`Copy`] types). It
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might read better if the list was four long and by copy was in there before by move.

src/types.md Outdated
closures*, can be coerced to function pointers (`fn`) with the matching
signature. To adopt the example from the section above:
The compiler prefers to capture a closed-over variable by immutable borrow,
followed by mutable borrow and finally by move (or copy, for [`Copy`] types). It
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need a comma before the and.

src/types.md Outdated
closure to outlive the captured values, such as if the closure is being returned
or used to spawn a new thread.

Structs and tuples are always captured entirely, not by individual fields. It
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Composite types, such as structs or tuples, are"? Or are enums somehow different?

src/types.md Outdated

If, instead, the closure were to use `self.vec` directly, then it would attempt
to capture `self` by mutable reference. But since `self.set` is already
borrowed to iterate over, the closure would not compile.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code would not compile

src/types.md Outdated
* A closure which does not mutate or move out of any captured variables
implements `[Fn]`, indicating that it can be called by shared reference.

> Note that `move` closures may still implement `[Fn]` or `[FnMut]`, even
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note needs to have a colon after it to remain consistent with the rest of the notes in the reference.

src/types.md Outdated
@@ -400,6 +471,33 @@ let bo: Binop = add;
x = bo(5,7);
```

### Other traits

Closure types implement the following traits, if allowed to do so by the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comma is invalid.

src/types.md Outdated
@@ -400,6 +471,33 @@ let bo: Binop = add;
x = bo(5,7);
```

### Other traits

Closure types implement the following traits, if allowed to do so by the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual values captured don't matter, but the types of the variables do. I'd personally write it "Closures implement the following traits conditionally on the types of the captured variables."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a fair point. But it also doesn't necessarily depend on the type of the variable captured, but the type of the capturing variable in the closure. For instance, capturing a non-Copy type by reference is fine for Copy, since the reference is itself Copy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a way to make this work, please take a look once I push.

src/types.md Outdated
Closure types implement the following traits, if allowed to do so by the
captured values:

* `[Sized]`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels weird that we're talking about conditionally implemented traits and then the first one on the list is always implemented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it.

src/types.md Outdated
* `[Sized]`
* `[Send]`
* `[Sync]`
* `[Clone]`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given how Clone and Copy are lang items and Send and Sync aren't (I think? Maybe one of them is?), I'd rather see Clone and Copy listed first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sync is, Send isn't. I think it would look better reordered though, so I will do that.

src/types.md Outdated
* `[Clone]`
* `[Copy]`

`[Sized]` is always implemented (local variables are all sized, so all captured
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More of a meta-point, but I really don't like having parentheticals like this. They should generally just be another sentence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed that sentence anyway.

@Havvy Havvy merged commit ec079d3 into rust-lang:master Feb 24, 2018
@alercah alercah deleted the closures branch May 3, 2018 20:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Document RFC 2132 (copy-closures) Document more precisely the rules for selecting closure traits.
2 participants