Skip to content

Use 'mut' as alias for 'let mut' #65257

Closed

Description

@pbbob

The idea of shortening let mut to var has been discussed many times before, and the general consensus always ends up being that it is not a good idea. I would like to propose something a bit different, so please hear me out.

I propose that instead of aliasing var to let mut, we instead just make mut expand into let mut when in the context of a variable declaration. For example:

let mut foo = 12;
// is identical to
mut foo = 12;

This solves the problems (readability, more concise) that people have with let mut, whilst not causing the issues that people have (pattern matching and consistancy).

The most common issue people have with aliasing var to let mut is that it doesn't fit well with patterns, like let (x, mut y) = .... However, mut gets rid of this problem, because you wouldn't write let mut (x, mut y) if you were trying to pattern match, so why would someone want to write mut (x, mut y)? You wouldn't do that, and it wouldn't compile.

This would be optional, of course. let mut x = 1 would still work fine, and people would just have to option of removing the let to let it be implied.

There are a lot of other abbreviations used in rust (fn, mod, pub) that all serve the purpose of writing less. It just doesn't feel right that one of the most commonly used keywords is so long.

❤️🦀

Activity

  1. RustyYato commented on Oct 9, 2019

    @RustyYato
    Contributor

    Rust wants to make to make you think when you try and use mutation, even if only a little bit, because mutation can be difficult to reason about. Shortening let mut to mut doesn't fit this philosophy. Also, this makes mutation just as easy as no mutation. This will lead people to choose mutation because it will give them less compiler errors in the short term, and in doing so open themselves up to some weird bugs that could have been prevented with the syntactic salt that is let mut.

    tldr: var wasn't rejected because of the name var, but because it allowed easy mutation, which runs counter to Rust's philosophy.

  2. pbbob commented on Oct 9, 2019

    @pbbob
    Author

    This will lead people to choose mutation because it will give them less compiler errors in the short term, and in doing so open themselves up to some weird bugs that could have been prevented with the syntactic salt that is let mut.

    I politely disagree. In fact, it is actually the other way around. Using mut unnecessarily will cause compiler warnings, discouraging the use of unneeded mutability. The compiler doesn't warn when the use of mut is actually needed.

  3. RustyYato commented on Oct 9, 2019

    @RustyYato
    Contributor

    I politely disagree. In fact, it is actually the other way around. Using mut unnecessarily will cause compiler warnings

    The fact that people will choose mut in the face of compiler warnings has been shown in practice, across many projects. Also, the problem isn't that people may choose to put mut just for the heck of it, but that they will unintentionally mutate something that was supposed to be immutable. And because it is being mutated, there is no warning, and they used mut because it is their default, it is their default because it gets rid of compiler errors that say they were trying to mutate things that are immutable even though they weren't supposed to mutate them in the first place. They will use mut because it is just as easy as making it immutable. So the problem is a bit more subtle than you seem to think.

  4. burdges commented on Oct 10, 2019

    @burdges

    This solves the problems (readability, more concise) that people have with let mut

    Incorrect. Extreme brevity harms readability. See Perl. lol

    Readers would ignore the let vs mut distinction far more often that let vs let mut, partially due to length difference, but let mut works even better than say mutable.

    It's true boilerplate often harms readability, but boilerplate requires some complexity be repeated, not merely the let in let mut.

    It harms readability even further if mut also works for let mut, especially when you consider code readers need not actually know Rust.

    Rust syntax was designed largely to reduce cognitive load, not to reduce typing.

    We use return, continue, and default, not any shorter alternatives. And delegation RFCs have kinda given up the short syntaxes. I think Rust's omission of then is now considered a mistake, but presumably helps C programmers.

    Rust has short keywords only really for fundamental "items" used repeatedly by basically every module. It's similar cognitive load if you write fn, func, or function, but actually just writing the shorter bare f(..) { .. } increases cognitive load. I think var invokes the minor linguistic subtlety that variable means mutable binding, while let acts like a common term for binding, which makes let mut very slightly clearer.

  5. sinkuu commented on Oct 10, 2019

    @sinkuu
    Contributor

    whilst not causing the issues that people have (pattern matching and consistancy)

    The mut statement would be orthogonal to the current language in some sense though. let mut foo is not a special syntax, but is composed of let statement + mut foo pattern. It is in line with other places expects a pattern, where you can write match _ { mut x => ... }, for mut x in, or fn foobar(mut x: i32).

  6. transferred this issue fromrust-lang/rfcson Oct 10, 2019
  7. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`
    D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Oct 10, 2019
  8. Centril commented on Oct 10, 2019

    @Centril
    Contributor

    It seems unlikely to me that we would support mut $ident = $expr; as a short-hand. I'm personally opposed to it both because it adds unnecessary compiler complexity, stylistic schisms, and for the reasons outlined by @KrishnaSannasi.

    However, I've taken the liberty of reusing this issue towards improved diagnostics:

    mut x = 0;
    --- help: missing `let`
    

    The idea here is to check self.token.is_keyword(kw::Mut) && self.look_ahead(1, |t| t.is_ident()).

    var x = 0;
    --- help: to introduce a variable, write `let` instead of `var`
    
    auto x = 0;
    ---- help: to introduce a variable, write `let` instead of `auto`
    

    The idea here is to check:

    is_ident_var_or_auto && !self.look_ahead(1, |t| is_brace(t))`

    The relevant code is here:

    Ok(Some(if self.eat_keyword(kw::Let) {
    Stmt {
    id: DUMMY_NODE_ID,
    kind: StmtKind::Local(self.parse_local(attrs.into())?),
    span: lo.to(self.prev_span),
    }

    cc @estebank

  9. added
    E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
    E-help-wantedCall for participation: Help is requested to fix this issue.
    E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
    on Oct 10, 2019
  10. 5 remaining items

  11. Centril commented on Oct 10, 2019

    @Centril
    Contributor

    @Centril Although I would also guess that the initial idea is very unlikely to end up accepted, it feels premature to unilaterally hijack the thread in your very first comment and make it have a different (and in a way opposite) purpose.

    Implementing something as a diagnostic actually brings you closer to a working implementation -- I think more proposals should start out as diagnostics.

    Teams of the Rust project are designed to make decisions collectively. [...]

    I will not bother the other language team members with not-fully-formed proposals that we will not accept in either case. I converted the issue into the most actionable and productive thing it could be.
    The place for ephemeral discussions is either on Discord or on internals.

    If you want to discuss this further, I'm available at Discord (but will not respond to it further here).

    [...], but issue numbers are cheap.

    ...but wasting everyone's time with things that will go nowhere (because it won't be accepted and because it is not important enough to be raised at the team) is not.

  12. steveklabnik commented on Oct 10, 2019

    @steveklabnik
    Contributor

    IMHO, the original thing this issue was opened for should be an RFC, not an issue. I'd have closed this, pointed the OP to the RFCs repo, and opened a new issue for the diagnostic issue.

  13. nox commented on Oct 10, 2019

    @nox
    Contributor

    This issue was literally in the RFCs repo initially, @Centril transferred it from there.

  14. carols10cents commented on Oct 11, 2019

    @carols10cents
    Member

    Incorrect. Extreme brevity harms readability. See Perl. lol

    @burdges Language bashing is not welcome here

  15. fmckeogh commented on Oct 13, 2019

    @fmckeogh
    Contributor

    @steveklabnik Wait, so should I unassign here, and assign to the new issue?

  16. Centril commented on Oct 13, 2019

    @Centril
    Contributor

    @Chocol4te Nah, just use this one.

  17. pbbob commented on Oct 14, 2019

    @pbbob
    Author

    Yeah, thats fine. You can just change this issue to be for diagnostics instead.

  18. fmckeogh commented on Oct 17, 2019

    @fmckeogh
    Contributor

    I'm sorry, I've been pretty busy with coursework, and I'm still fighting my Python installation to even build the compiler, let alone make progress on this. Sorry :(

  19. removed their assignment
    on Oct 17, 2019
  20. self-assigned this
    on Oct 17, 2019
  21. Centril commented on Oct 17, 2019

    @Centril
    Contributor

    I'll assign this to myself to work on when I have time. If you want to work on it however, feel free to work-steal it from me!

  22. JesterOrNot commented on Nov 6, 2019

    @JesterOrNot

    I would like to help with this

  23. Centril commented on Nov 6, 2019

    @Centril
    Contributor

    @JesterOrNot Sorry; should have updated this issue...! There's a PR #65811 at the moment. Feel free to leave suggestions on it if you like. :)

  24. added a commit that references this issue on Dec 21, 2019
    c64eecf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-enhancementCategory: An issue proposing an enhancement or a PR with one.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.E-help-wantedCall for participation: Help is requested to fix this issue.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions