# Parameterisation over mutability

**URL:** <https://internals.rust-lang.org/t/parameterisation-over-mutability/235>\
**Category:** ideas (deprecated)\
**Created:** [July 22, 2014, 7:50am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235 "2014-07-22T07:50:50Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![P1start](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/p1start/32/23_2.png) [@P1start](https://internals.rust-lang.org/u/P1start)\
**Post date:** [July 22, 2014, 7:50am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/1 "2014-07-22T07:50:50Z")

</div>

[A recent post on the /r/rust subreddit](http://www.reddit.com/r/rust/comments/2bbeqe/it_started_out_with_great_enthusiasm_but_ended_up/) brought to light a percieved problem with the current mutability system: [should mutability be able to be parameterised](https://github.com/crafn/rust-disappointment/blob/master/main.rs#L62-L65)? Right now the standard library is full with methods with immutable and mutable versions with the same functionality, so this could easily be seen as a useful change.

The syntax could be something like this:

```rust
impl<T> Vec<T> {
    pub fn get<<m>, 'a>(&'a <m> self, index: uint) -> &'a <m> T {
        &<m> self.as_slice::<<m>>()[index] // the ::<<m>> would probably be inferred
    }
}

```

(Yes, this syntax could do with a lot of improvement.) Traits like `Deref`/`DerefMut` could also probably be merged into a single trait with a mutability parameter. There is [a large number](http://doc.rust-lang.org/std/index.html?search=trait:mut) of such traits in the standard library, so this could be quite good for reducing the number of functions, methods, _and_ traits.

---

<div class="post-metadata">

**Author:** ![cmr](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cmr/32/5_2.png) [@cmr](https://internals.rust-lang.org/u/cmr)\
**Post date:** [July 22, 2014, 8:34am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/2 "2014-07-22T08:34:29Z")

</div>

I believe it is possible if you restrict the method to treating the mutability-parameterized reference _as if it were unique_ but not mutable (never usable directly as `&mut`). I also remember finding a problem with this approach, but I can’t remember precisely what it was… possibly nothing!

Such methods would have to be written in a very restricted manner due to the aliasing constraints. It may just be easier to re-introduce `&const`, instead of a weird parameterization system (where both `&` and `&mut` can be coerced to `&const`), but then one needs to summon the mutpocalypse again…

---

<div class="post-metadata">

**Author:** ![huon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/huon/32/3698_2.png) [@huon](https://internals.rust-lang.org/u/huon)\
**Post date:** [July 22, 2014, 9:37am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/3 "2014-07-22T09:37:14Z")

</div>

The `&const` Rust previously had doesn’t solve the problem, since you can’t use `fn find(&const self, key: uint) -> &const X` to get either a `&` out (if called on an `&` receiver) or a `&mut` (for a `&mut` receiver), you always get a `&const` out.

---

<div class="post-metadata">

**Author:** ![huon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/huon/32/3698_2.png) [@huon](https://internals.rust-lang.org/u/huon)\
**Post date:** [July 22, 2014, 9:39am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/4 "2014-07-22T09:39:16Z")

</div>

[This was discussed on reddit in some depth previously](http://www.reddit.com/r/rust/comments/2a721y/a_safe_way_to_reuse_the_same_code_for_immutable/).

---

<div class="post-metadata">

**Author:** ![P1start](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/p1start/32/23_2.png) [@P1start](https://internals.rust-lang.org/u/P1start)\
**Post date:** [July 22, 2014, 11:10am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/5 "2014-07-22T11:10:00Z")

</div>

After thinking about this some more, I came up with an alternative design that doesn’t even need the language to be extended (except maybe adding a lang item). All you really need is a `Reference<'a, T>` trait that is implemented only by `&'a T` and `&'a mut T`. It requires one method, `fn from_ref(r: &'a mut T) -> Self`. I tried setting this up [here](http://is.gd/2y8K6s), but unfortunately the UFCS explicit self syntax doesn’t seem to support generic types. (I’ve no idea if that’s intentional—a quick naïve search on Github didn’t reveal an issue about it.)

---

<div class="post-metadata">

**Author:** ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)\
**Post date:** [July 22, 2014, 11:31am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/6 "2014-07-22T11:31:22Z")

</div>

Isn’t this clearly something that can be put on the stack for things to do after 1.0?

If mut parameterization is introduced, we can deprecate `.as_mut_slice()` in favour of `.as_slice()` and so on.

---

<div class="post-metadata">

**Author:** ![huon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/huon/32/3698_2.png) [@huon](https://internals.rust-lang.org/u/huon)\
**Post date:** [July 22, 2014, 11:48am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/8 "2014-07-22T11:48:05Z")

</div>

I don’t think changing the behaviour of `as_slice` is fully backwards compatible: currently, `(&mut [T])::as_slice` returns a `&[T]`, but would return a `&mut [T]` with parameterised mutability, which could change which trait `impl`s are selected if a trait is implemented separately for both `&` and `&mut` (so, somewhat of an edge case).

That is the only way I can think of that will cause to stop compiling/change behaviour; the largest impact would be on programs that currently don’t compile (like, `foo.as_slice()[0] += 1` becoming valid), which is fine from a BC viewpoint.

---

<div class="post-metadata">

**Author:** ![Gankra](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gankra/32/6002_2.png) [@Gankra](https://internals.rust-lang.org/u/Gankra)\
**Post date:** [July 22, 2014, 1:59pm UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/9 "2014-07-22T13:59:01Z")

</div>

I’m hugely in favour of parameterized mutability.

Some pros:

- Reduced amount of physical code to maintain, less duplication of logic
- Smaller number of methods in APIs, less combinatoric explosions
- Reduced binary size (in contrast to generics in general, mutability is simply a compile time notion)
- More natural chaining of mut/immut method calls; this is harder to do with just macros

Some cons:

- more syntax and/or sigils; general increased language complexity
- potential increase in compile time from need to determine if a valid combination of mutabilities exists

Some other syntaxes to consider:

```
fn get <'a, "m> (foo: &'a"m Foo) -> &'a"m Bar;

```

Concise, matches lifetimes, sigil heavy, possibly precludes generic mutability of _values_, mutability is named so that it cascades in a predictable manner.

```
fn get <'a> (foo: &'a mut? Foo) -> &'a mut? Bar;

```

More verbose, matches mut’s use everywhere else, a bit sigily, permits generic mutability everywhere, mutability of one ref/value holds independent of others, potentially tricky.

Regardless of the precise syntax and implementation, I think the compiler should always try to infer immutable first, and then mutable if not possible. If neither is possible it should of course be a compilation error. Unnecessary generic mutability should also probably be a warning, if possible.

---

<div class="post-metadata">

**Author:** ![dobkeratops](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dobkeratops/32/4577_2.png) [@dobkeratops](https://internals.rust-lang.org/u/dobkeratops)\
**Post date:** [July 22, 2014, 4:51pm UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/10 "2014-07-22T16:51:13Z")

</div>

Is this something that could be done somehow with HKT later … generalised reference types? imagine something like…

```
fn foo<R<>, T>( x:R<T>) {.....}
fn foo<R:Ref, T>( x:R<T>) {.....} // some R<T> can be a type wrapping &T or &mut T

```

I’m not sure how that would play out, and people don’t already use template-template parameters to do it in C++ (that i know of)

would it help or hinder to use abstracted pointer types to manage lifetimes & mutability together… you’d probably need a lot of control over their coercions… maybe it is a case where more inbuilt syntax would be much saner

---

<div class="post-metadata">

**Author:** ![P1start](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/p1start/32/23_2.png) [@P1start](https://internals.rust-lang.org/u/P1start)\
**Post date:** [July 25, 2014, 8:30am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/11 "2014-07-25T08:30:42Z")

</div>

This actually would possibly be better if it were a three-way choice—by reference, by mutable reference, or by move. There are just so many traits, methods, and functions that have immutable, mutable, and move variants, and even ones that _should_ have move variants but don’t (e.g. `Deref*`, `Index*` &c.). Using a far-too-sigil’d syntax:

```rust
pub trait Deref<?m, Result> {
    fn deref<'a>(?m 'a self) -> ?m 'a Result;
}

// ?m can be const, mut, or move
impl<T> Deref<const, T> for Rc<T> { ... }
impl<?m, T> Deref<?m, T> for Box<T> { ... }

```

This could pose some problems for anything that wants to, for example, implement `Deref<const>` and `Deref<move>` but not `Deref<mut>`.

---

<div class="post-metadata">

**Author:** ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)\
**Post date:** [July 28, 2014, 9:04pm UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/12 "2014-07-28T21:04:52Z")

</div>

[Related thoughts](http://www.reddit.com/r/rust/comments/2a721y/a_safe_way_to_reuse_the_same_code_for_immutable/cj8pebl), similar to some of the ones above.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:22am UTC](https://internals.rust-lang.org/t/parameterisation-over-mutability/235/13 "2019-03-25T08:22:39Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
