diff --git a/active/0000-ownership-variants.md b/active/0000-ownership-variants.md new file mode 100644 index 00000000000..9ca7304a90f --- /dev/null +++ b/active/0000-ownership-variants.md @@ -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`?