-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: conventions for ownership variants #199
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
- Start Date: (fill me in with today's date, 2014-08-13) | ||
- RFC PR #: (leave this empty) | ||
- Rust Issue #: (leave this empty) | ||
|
||
# Summary | ||
|
||
This is a *conventions RFC* for settling naming conventions when there | ||
are by value, by reference, and by mutable reference variants of an | ||
operation. | ||
|
||
# Motivation | ||
|
||
Currently the libraries are not terribly consistent about how to | ||
signal mut variants of functions; sometimes it is by a `mut_` prefix, | ||
sometimes a `_mut` suffix, and occasionally with `_mut_` appearing in | ||
the middle. These inconsistencies make APIs difficult to remember. | ||
|
||
While there are arguments in favor of each of the positions, we stand | ||
to gain a lot by standardizing, and to some degree we just need to | ||
make a choice. | ||
|
||
# Detailed design | ||
|
||
Functions often come in multiple variants: immutably borrowed, mutably | ||
borrowed, and owned. | ||
|
||
The canonical example is iterator methods: | ||
|
||
- `iter` works with immutably borrowed data | ||
- `mut_iter` works with mutably borrowed data | ||
- `move_iter` works with owned data | ||
|
||
For iterators, the "default" (unmarked) variant is immutably borrowed. | ||
In other cases, the default is owned. | ||
|
||
The proposed rules depend on which variant is the default, but use | ||
*suffixes* to mark variants in all cases. | ||
|
||
## The rules | ||
|
||
### Immutably borrowed by default | ||
|
||
If `foo` uses/produces an immutable borrow by default, use: | ||
|
||
* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant. | ||
* The `_move` suffix (e.g. `foo_move`) for the owned variant. | ||
|
||
A consequence is that the iterator methods become: `iter`, `iter_mut`, | ||
and `iter_move`. | ||
|
||
**NOTE**: This convention covers only the *method* names for | ||
iterators, not the names of the iterator types. That will be the | ||
subject of a follow up RFC. | ||
|
||
### Owned by default | ||
|
||
If `foo` uses/produces owned data by default, use: | ||
|
||
* The `_ref` suffix (e.g. `foo_ref`) for the immutably borrowed variant. | ||
* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant. | ||
|
||
### Exceptions | ||
|
||
For mutably borrowed variants, if the `mut` qualifier is part of a | ||
type name (e.g. `as_mut_slice`), it should appear as it would appear | ||
in the type. | ||
|
||
### References to type names | ||
|
||
Some places in the current libraries, we say things like `as_ref` and | ||
`as_mut`, and others we say `get_ref` and `get_mut_ref`. | ||
|
||
Proposal: generally standardize on `mut` as a shortening of `mut_ref`. | ||
|
||
|
||
## The rationale | ||
|
||
### Why suffixes? | ||
|
||
Using a suffix makes it easier to visually group variants together, | ||
especially when sorted alphabetically. It puts the emphasis on the | ||
functionality, rather than the qualifier. | ||
|
||
### Why `move`? | ||
|
||
Historically, Rust has used `move` as a way to signal ownership | ||
transfer and to connect to C++ terminology. The main disadvantage is | ||
that it does not emphasize ownership, which is our current narrative. | ||
On the other hand, in Rust all data is owned, so using `_owned` as a | ||
qualifier is a bit strange. | ||
|
||
The `Copy` trait poses a problem for any terminology about ownership | ||
transfer. The proposed mental model is that with `Copy` data you are | ||
"moving a copy". | ||
|
||
See Alternatives for more discussion. | ||
|
||
### Why `mut` rather then `mut_ref`? | ||
|
||
It's shorter, and pairs like `as_ref` and `as_mut` have a pleasant harmony | ||
that doesn't place emphasis on one kind of reference over the other. | ||
|
||
# Alternatives | ||
|
||
## Prefix or mixed qualifiers | ||
|
||
Using prefixes for variants is another possibility, but there seems to | ||
be little upside. | ||
|
||
It's possible to rationalize our current mix of prefixes and suffixes | ||
via | ||
[grammatical distinctions](https://github.com/rust-lang/rust/issues/13660#issuecomment-43576378), | ||
but this seems overly subtle and complex, and requires a strong | ||
command of English grammar to work well. | ||
|
||
## No suffix exception | ||
|
||
The rules here make an exception when `mut` is part of a type name, as | ||
in `as_mut_slice`, but we could instead *always* place the qualifier | ||
as a suffix: `as_slice_mut`. This would make APIs more consistent in | ||
some ways, less in others: conversion functions would no longer | ||
consistently use a transcription of their type name. | ||
|
||
This is perhaps not so bad, though, because as it is we often | ||
abbreviate type names. In any case, we need a convention (separate | ||
RFC) for how to refer to type names in methods. | ||
|
||
## `owned` instead of `move` | ||
|
||
The overall narrative about Rust has been evolving to focus on | ||
*ownership* as the essential concept, with borrowing giving various | ||
lesser forms of ownership, so `_owned` would be a reasonable | ||
alternative to `_move`. | ||
|
||
On the other hand, the `ref` variants do not say "borrowed", so in | ||
some sense this choice is inconsistent. In addition, the terminology | ||
is less familiar to those coming from C++. | ||
|
||
## `val` instead of `owned` | ||
|
||
Another option would be `val` or `value` instead of `owned`. This | ||
suggestion plays into the "by reference" and "by value" distinction, | ||
and so is even more congruent with `ref` than `move` is. On the other | ||
hand, it's less clear/evocative than either `move` or `owned`. | ||
|
||
## `into_iter` | ||
|
||
For the case of iteration, at least, it would make some sense to | ||
signal ownership transfer by treating the owned version as a | ||
conversion, `into_iter`. The main downside is that it would go against | ||
the general convention for ownership variants (and cannot be used as | ||
the general convention, because not all cases can be seen as | ||
conversions). | ||
|
||
Moreover, it's strange to see just the owning variant as a conversion | ||
-- why not `as_iter`, `as_iter_mut`, and `into_iter`? |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe ruining a joke, but I don't know what this means :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, there's an extra blank line here, so you should snip it 😄