12 comments

[ 3.2 ms ] story [ 38.8 ms ] thread
Cute technique, but it looks too syntactically sugary and dangerous.

For instance, if I wanted to make an immutable mutable, I'd rather be explicit:

  let x = "foo".to_string();
  let mut x = x;
Much clearer than passing ownership to a block and returning the expression.
And generally, if you are passed an owned parameter or variable x, you can usually declare it as `mut x` right from the very start. So in the examples given, rather than the identity function or anything fancy like that, you can just write:

    fn consume_the_list(mut self) {
        // self is mutable here
    }
This is generally true for any other owned parameter, with the distinction that the `mut` applies to the parameter pattern and not the type. (i.e. `mut val: String`, not `val: mut String`).
Pretty deep in the nitpicky weeds here but I don't like putting mut bindings in parameters. They only affect the body of the function but they show up in the interface, including rustdoc, which can be confusing. It's easy to think that

    fn foo(x: u32) {}
    fn foo(mut x: u32) {}
has a semantic difference to the consumer similar to

    fn foo(x: &u32) {}
    fn foo(x: &mut u32) {}
but it does not. To avoid this confusion I'd rather do

    fn foo(x: u32) { let mut x = x; }
This is effectively a rustdoc bug, the pattern is very much part of the body of the function, not the signature (and this split is explicitly represented in the compiler IRs, which rustdoc effectively undoes).

While it's not really how it works, the closest valid Rust that comes to mind is:

    const foo: fn(u32) = |mut x| {};
What rustdoc should be doing is stripping binding modes (`ref` and/or `mut`), or even whole patterns - with more complex patterns, like `(a, mut b): (T, U)`, it can be beneficial to keep `(a, b)` as a way to label the two components, but the `mut` is superfluous for documentation.
I don't think anything in the blog post is supposed to be practical, more like using it in unintended ways.
I didn't realize you could modify the mutability after the initial assignment! Just learning Rust starting a few months ago, thanks for sharing haha.
It's not technically modifying the mutability, it's creating a new mutable x, and setting it to the old x (which is still accessible on the right hand side of the assignment).
Unfortunately since this is from 2015, it does not seem everything is still accurate. For example his demo of a list walk with match: https://play.rust-lang.org/?gist=613e13fd515bfca647ca&versio...

Seems to compile just fine even with the edition set to 2015.

I think (not 100% sure though) that's probably due to NLL being now supported. I don't think they were supported back then.
NLL certainly wasn't around in 2015 because it was only added after I started paying attention to rust in... 2017? 2018? And since it is only an improvement to the parser and wouldn't break code in 2015 mode I'd assume every edition supports the update to the parser.