rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.21k stars 1.6k forks source link

False-positive: `cannot mutate immutable variable` #18322

Open LorDawid opened 1 week ago

LorDawid commented 1 week ago

rust-analyzer version: rust-analyzer version: 0.3.2137-standalone [/home/dawid/.vscode/extensions/rust-lang.rust-analyzer-0.3.2137-linux-x64/server/rust-analyzer]

rustc version: rustc 1.82.0 (f6e511eec 2024-10-15)

editor or extension: VSCode

relevant settings: None

code snippet to reproduce:

use libloading::*;

fn false_positive(
    library: &'static mut Library,
    symbol: Symbol<'static, fn(u64, u64)>,
    name: String,
) {
    unsafe {
        let sym = library.get::<*mut fn(u64, u64)>(name.as_bytes()).unwrap();
        // "cannot mutate immutable variable `sym`"
        // but if the variable is marked as mutable,
        // "variable does not need to be mutable"
        **sym = *symbol;
        // This works:
        // let sym = *sym;
        // *sym = *symbol;
    }
}

Rust-analyzer produces a false-positive cannot mutate immutable variable `sym` rust-analyzer(E0384) - the compiler does not report any issues. Marking that variable as mutable produces a warning variable does not need to be mutable.

As shown in the commented sample, manually dereferencing the variable set-by-step works.

UPDATE: This is a simplier example.

pub struct Test;

impl std::ops::Deref for Test {
    type Target = *mut fn();

    fn deref(&self) -> &Self::Target {
        todo!()
    }
}

pub fn test(ptr: &'static fn()) {
    let test = Test;
    unsafe { **test = *ptr }
}
ChayimFriedman2 commented 1 week ago

I think your code has a bug: it needs to be library.get::<fn(u64, u64)>(name.as_bytes()) (unrelated though, this is still a rust-analyzer bug).

LorDawid commented 1 week ago

@ChayimFriedman2 the variable i get from the library is a mut static: fn(u64, u64) initialized to a panicking function by default, so AFAIK this is correct