Skip to content

Inconsistent "unused mut" warning on mutable references #30280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mkpankov opened this issue Dec 9, 2015 · 1 comment · Fixed by #43582
Closed

Inconsistent "unused mut" warning on mutable references #30280

mkpankov opened this issue Dec 9, 2015 · 1 comment · Fixed by #43582
Labels
A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug.

Comments

@mkpankov
Copy link
Contributor

mkpankov commented Dec 9, 2015

Consider this code (playpen):

fn main() {
    // types for clarity
    let mut x: String = "hello".to_string();
    x.push('x');
    {
        let y: &mut String = &mut x;
        // y.push('x');
        println!("{}", y);
    }
    {
        // warning: variable does not need to be mutable
        let mut z: &mut String = &mut x;
        // z.push('x'); // this line disables the warning
        println!("{}", z);
    }
}

Mutability of the reference itself isn't needed for z.push('x'). Then the behavior in two nested blocks is inconsistent: mut in let mut z is, in fact, unneeded, either when doing z.push('x') or when not doing it. Only the underlying String has to be mutable. But the compiler doesn't warn about it.

I expected the warning "variable does not need to be mutable" to be emitted even when z.push('x'); line is uncommented.

@mkpankov
Copy link
Contributor Author

Another example that seems to suffer from same problem.

@huonw huonw added the A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. label Jan 6, 2016
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 24, 2017
bors added a commit that referenced this issue Aug 10, 2017
Fixed mutable vars being marked used when they weren't

#### NB : bootstrapping is slow on my machine, even with `keep-stage` - fixes for occurances in the current codebase are <s>in the pipeline</s> done. This PR is being put up for review of the fix of the issue.

Fixes #43526, Fixes #30280, Fixes #25049

### Issue
Whenever the compiler detected a mutable deref being used mutably, it marked an associated value as being used mutably as well. In the case of derefencing local variables which were mutable references, this incorrectly marked the reference itself being used mutably, instead of its contents - with the consequence of making the following code emit no warnings
```
fn do_thing<T>(mut arg : &mut T) {
    ... // don't touch arg - just deref it to access the T
}
```

### Fix
Make dereferences not be counted as a mutable use, but only when they're on borrows on local variables.
#### Why not on things other than local variables?
  * Whenever you capture a variable in a closure, it gets turned into a hidden reference - when you use it in the closure, it gets dereferenced. If the closure uses the variable mutably, that is actually a mutable use of the thing being dereffed to, so it has to be counted.
  * If you deref a mutable `Box` to access the contents mutably, you are using the `Box` mutably - so it has to be counted.
ijanos pushed a commit to exercism/rust that referenced this issue Sep 1, 2017
`iter_mut()` and `or_insert()` yields mutable references, the variables 
they bind to does not need to be mutable. 

Previously, because of rust-lang/rust#30280
this was not considered a warning.

The fix is in rust-lang/rust#43582
This means on recently nightlies this warning is emitted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants