Skip to content

Passing mutable references #353

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
Pyriphlegethon opened this issue Sep 28, 2015 · 18 comments
Closed

Passing mutable references #353

Pyriphlegethon opened this issue Sep 28, 2015 · 18 comments
Assignees
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. L-unnecessary Lint: Warn about unnecessary code T-MIR Type: This lint will require working with the MIR

Comments

@Pyriphlegethon
Copy link
Contributor

Pyriphlegethon commented Sep 28, 2015

This issue already has a lint, only the second one still needs fixing

Passing a mutable reference to a function that takes an immutable reference:

fn takes_an_immutable_reference(a: &i32) -> bool {
    *a > 10
}

fn main() {
    let mut five = 5;
    println!("{}", takes_an_immutable_reference(&mut five));
}

If I'd find this code in somebody's code base I'd think that the function will mutate the argument and I'd have to make a copy if I want to preserve the original value. This lint should only be applied if the argument is actually passed as &mut, the following code should be ok:

fn takes_an_immutable_reference(a: &i32) -> bool {
    *a > 10
}

fn main() {
    let mut five = 5;
    let five_ref = &mut five;
    println!("{}", takes_an_immutable_reference(five_ref));
}

Taking a mutable reference and not mutating it:

fn takes_a_mutable_reference(a: &mut i32) -> bool {
     *a > 10
}

The rust compiler will complain whenever it sees a mutable binding that is not mutated. Strangely enough, it won't complain about mutable arguments that are never mutated. I guess this might be a hard problem?

Thanks for rust-clippy! It's an awesome tool!

@Manishearth Manishearth added good-first-issue These issues are a good way to get started with Clippy T-middle Type: Probably requires verifiying types A-lint Area: New lints labels Sep 28, 2015
@Manishearth
Copy link
Member

I like this idea. Though I'm surprised the compiler doesn't complain here.

If I'd find this code in somebody's code base I'd think that the function will mutate the argument and I'd have to make a copy if I want to preserve the original value.

It's stuff like this which makes me love Rust. 😄

Thanks for rust-clippy! It's an awesome tool!

You're welcome! Glad you enjoyed it!

@llogiq
Copy link
Contributor

llogiq commented Sep 28, 2015

We should tread carefully here. The mut is part of the interface, so implementing a trait may well require it. Also there may be situations in which we want to rule out other aliases despite not mutating an instance.

The former can be detected, the latter probably not, short of a mind-reading extension to clippy.

@Manishearth

This comment has been minimized.

@birkenfeld
Copy link
Contributor

The other lint is about taking a mutable reference and not mutating it:

This may be problematic though, as @llogiq says. At least trait impls should be excluded, and for pub items the public API would change. (Although IIUC taking &T instead of &mut T wouldn't lead to compile errors, but only clippy warnings 😄)

@Manishearth

This comment has been minimized.

@Pyriphlegethon
Copy link
Contributor Author

Yeah, didn't know that a trait impl couldn't strengthen the constraints for its arguments. That really seems like it should be allowed.
The easy fix would be to not check any trait impls like @birkenfeld said.

@birkenfeld

This comment has been minimized.

@Pyriphlegethon

This comment has been minimized.

@birkenfeld

This comment has been minimized.

@Pyriphlegethon

This comment has been minimized.

@Manishearth

This comment has been minimized.

@Pyriphlegethon

This comment has been minimized.

@oli-obk
Copy link
Contributor

oli-obk commented Feb 22, 2017

I'm gonna take this lint. I just spend 15 minutes chasing 5 functions in circles in miri to check why in the world they mutate an argument only to figure out that all of them could take a &T instead of a &mut T without any change in behaviour. Apparently I didn't get to this... And I ran into the same problem... again... in miri...

// increase this counter if you ran into this problem again and still didn't fix it: 3

@RalfJung
Copy link
Member

The other lint is about taking a mutable reference and not mutating it:

This may be problematic though, as @llogiq says. At least trait impls should be excluded, and for pub items the public API would change. (Although IIUC taking &T instead of &mut T wouldn't lead to compile errors, but only clippy warnings 😄)

Not just that; when there is unsafe code around, the &mut may be necessary to preserve safety of the API. The following version of as_mut_slice compiles, but is wrong:

    pub fn as_mut_slice<T>(self_: &Vec<T>) -> &mut [T] {
        unsafe {
            from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len())
        }
    }

@oli-obk

This comment has been minimized.

@RalfJung

This comment has been minimized.

@oli-obk oli-obk added E-medium Call for participation: Medium difficulty level problem and requires some initial experience. L-unnecessary Lint: Warn about unnecessary code T-MIR Type: This lint will require working with the MIR and removed T-middle Type: Probably requires verifiying types good-first-issue These issues are a good way to get started with Clippy hacktoberfest labels Nov 22, 2018
@L0uisc
Copy link

L0uisc commented Oct 17, 2019

I came here from TWIR call for participation. Isn't it better to put the second part of the issue directly into rustc?

@samueltardieu
Copy link
Contributor

Triaging.

This is implemented in the needless_pass_by_ref_mut nursery lint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. L-unnecessary Lint: Warn about unnecessary code T-MIR Type: This lint will require working with the MIR
Projects
None yet
Development

No branches or pull requests

8 participants