|
| 1 | +- Start Date: (fill me in with today's date, 2014-08-13) |
| 2 | +- RFC PR #: (leave this empty) |
| 3 | +- Rust Issue #: (leave this empty) |
| 4 | + |
| 5 | +# Summary |
| 6 | + |
| 7 | +This is a *conventions RFC* for settling naming conventions when there |
| 8 | +are by value, by reference, and by mutable reference variants of an |
| 9 | +operation. |
| 10 | + |
| 11 | +# Motivation |
| 12 | + |
| 13 | +Currently the libraries are not terribly consistent about how to |
| 14 | +signal mut variants of functions; sometimes it is by a `mut_` prefix, |
| 15 | +sometimes a `_mut` suffix, and occasionally with `_mut_` appearing in |
| 16 | +the middle. These inconsistencies make APIs difficult to remember. |
| 17 | + |
| 18 | +While there are arguments in favor of each of the positions, we stand |
| 19 | +to gain a lot by standardizing, and to some degree we just need to |
| 20 | +make a choice. |
| 21 | + |
| 22 | +# Detailed design |
| 23 | + |
| 24 | +Functions often come in multiple variants: immutably borrowed, mutably |
| 25 | +borrowed, and owned. |
| 26 | + |
| 27 | +The canonical example is iterator methods: |
| 28 | + |
| 29 | +- `iter` works with immutably borrowed data |
| 30 | +- `mut_iter` works with mutably borrowed data |
| 31 | +- `move_iter` works with owned data |
| 32 | + |
| 33 | +For iterators, the "default" (unmarked) variant is immutably borrowed. |
| 34 | +In other cases, the default is owned. |
| 35 | + |
| 36 | +The proposed rules depend on which variant is the default, but use |
| 37 | +*suffixes* to mark variants in all cases. |
| 38 | + |
| 39 | +## The rules |
| 40 | + |
| 41 | +### Immutably borrowed by default |
| 42 | + |
| 43 | +If `foo` uses/produces an immutable borrow by default, use: |
| 44 | + |
| 45 | +* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant. |
| 46 | +* The `_move` suffix (e.g. `foo_move`) for the owned variant. |
| 47 | + |
| 48 | +A consequence is that the iterator methods become: `iter`, `iter_mut`, |
| 49 | +and `iter_move`. |
| 50 | + |
| 51 | +**NOTE**: This convention covers only the *method* names for |
| 52 | + iterators, not the names of the iterator types. That will be the |
| 53 | + subject of a follow up RFC. |
| 54 | + |
| 55 | +### Owned by default |
| 56 | + |
| 57 | +If `foo` uses/produces owned data by default, use: |
| 58 | + |
| 59 | +* The `_ref` suffix (e.g. `foo_ref`) for the immutably borrowed variant. |
| 60 | +* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant. |
| 61 | + |
| 62 | +### Exceptions |
| 63 | + |
| 64 | +For mutably borrowed variants, if the `mut` qualifier is part of a |
| 65 | +type name (e.g. `as_mut_slice`), it should appear as it would appear |
| 66 | +in the type. |
| 67 | + |
| 68 | +### References to type names |
| 69 | + |
| 70 | +Some places in the current libraries, we say things like `as_ref` and |
| 71 | +`as_mut`, and others we say `get_ref` and `get_mut_ref`. |
| 72 | + |
| 73 | +Proposal: generally standardize on `mut` as a shortening of `mut_ref`. |
| 74 | + |
| 75 | + |
| 76 | +## The rationale |
| 77 | + |
| 78 | +### Why suffixes? |
| 79 | + |
| 80 | +Using a suffix makes it easier to visually group variants together, |
| 81 | +especially when sorted alphabetically. It puts the emphasis on the |
| 82 | +functionality, rather than the qualifier. |
| 83 | + |
| 84 | +### Why `move`? |
| 85 | + |
| 86 | +Historically, Rust has used `move` as a way to signal ownership |
| 87 | +transfer and to connect to C++ terminology. The main disadvantage is |
| 88 | +that it does not emphasize ownership, which is our current narrative. |
| 89 | +On the other hand, in Rust all data is owned, so using `_owned` as a |
| 90 | +qualifier is a bit strange. |
| 91 | + |
| 92 | +The `Copy` trait poses a problem for any terminology about ownership |
| 93 | +transfer. The proposed mental model is that with `Copy` data you are |
| 94 | +"moving a copy". |
| 95 | + |
| 96 | +See Alternatives for more discussion. |
| 97 | + |
| 98 | +### Why `mut` rather then `mut_ref`? |
| 99 | + |
| 100 | +It's shorter, and pairs like `as_ref` and `as_mut` have a pleasant harmony |
| 101 | +that doesn't place emphasis on one kind of reference over the other. |
| 102 | + |
| 103 | +# Alternatives |
| 104 | + |
| 105 | +## Prefix or mixed qualifiers |
| 106 | + |
| 107 | +Using prefixes for variants is another possibility, but there seems to |
| 108 | +be little upside. |
| 109 | + |
| 110 | +It's possible to rationalize our current mix of prefixes and suffixes |
| 111 | +via |
| 112 | +[grammatical distinctions](https://github.com/rust-lang/rust/issues/13660#issuecomment-43576378), |
| 113 | +but this seems overly subtle and complex, and requires a strong |
| 114 | +command of English grammar to work well. |
| 115 | + |
| 116 | +## No suffix exception |
| 117 | + |
| 118 | +The rules here make an exception when `mut` is part of a type name, as |
| 119 | +in `as_mut_slice`, but we could instead *always* place the qualifier |
| 120 | +as a suffix: `as_slice_mut`. This would make APIs more consistent in |
| 121 | +some ways, less in others: conversion functions would no longer |
| 122 | +consistently use a transcription of their type name. |
| 123 | + |
| 124 | +This is perhaps not so bad, though, because as it is we often |
| 125 | +abbreviate type names. In any case, we need a convention (separate |
| 126 | +RFC) for how to refer to type names in methods. |
| 127 | + |
| 128 | +## `owned` instead of `move` |
| 129 | + |
| 130 | +The overall narrative about Rust has been evolving to focus on |
| 131 | +*ownership* as the essential concept, with borrowing giving various |
| 132 | +lesser forms of ownership, so `_owned` would be a reasonable |
| 133 | +alternative to `_move`. |
| 134 | + |
| 135 | +On the other hand, the `ref` variants do not say "borrowed", so in |
| 136 | +some sense this choice is inconsistent. In addition, the terminology |
| 137 | +is less familiar to those coming from C++. |
| 138 | + |
| 139 | +## `val` instead of `owned` |
| 140 | + |
| 141 | +Another option would be `val` or `value` instead of `owned`. This |
| 142 | +suggestion plays into the "by reference" and "by value" distinction, |
| 143 | +and so is even more congruent with `ref` than `move` is. On the other |
| 144 | +hand, it's less clear/evocative than either `move` or `owned`. |
| 145 | + |
| 146 | +## `into_iter` |
| 147 | + |
| 148 | +For the case of iteration, at least, it would make some sense to |
| 149 | +signal ownership transfer by treating the owned version as a |
| 150 | +conversion, `into_iter`. The main downside is that it would go against |
| 151 | +the general convention for ownership variants (and cannot be used as |
| 152 | +the general convention, because not all cases can be seen as |
| 153 | +conversions). |
| 154 | + |
| 155 | +Moreover, it's strange to see just the owning variant as a conversion |
| 156 | +-- why not `as_iter`, `as_iter_mut`, and `into_iter`? |
0 commit comments