【问题标题】:Rust compiler accepts mutable where it should've been immutableRust 编译器在它应该是不可变的地方接受可变的
【发布时间】:2022-08-18 00:48:44
【问题描述】:

我有一个名为和一个save_as_ppmimpl块内的函数,函数的签名是这样的:

fn save_as_ppm(&self, filename: &str){}

但是 impl 块中的其他函数有 &mut self 参数,所以当我创建一个实例时,我必须让它可变(我不知道它是否在 Rust 中被称为实例)

let mut inputs = Layer::new(SAMPLE_SIZE as usize, SAMPLE_SIZE as usize);

但是当我调用这个 save_as_ppm 函数时:

inputs.save_as_ppm(&filepath)

它编译。我的问题是它为什么编译? Save_as_ppm 函数引用自己但我刚刚通过了一个可变的自我。编译器不应该报错吗?至少是一个警告?

  • 允许编译器自动将&mut T 转换为&T,而不是相反。
  • 遵循鸭子类型的规则,因为与不可变引用相比,可变引用具有所有功能 + 更多,我认为没有理由不应该传入可变引用,因为函数本身不会能够以任何方式改变状态
  • 需要共享引用的方法会很乐意接受可变引用,因为“降级”对共享引用的可变引用总是安全的。如果let mut v = vec![]; v.push(1); println!(\"{}\", v.len()) 不能编译确实会很烦人,因为Vec::len() 需要&self,但v 是mut。
  • @merovingian 是的,该函数将无法改变状态,因为它的签名用于不可变引用。尝试改变状态会导致编译器错误。
  • 另请注意,对可变值的引用和可变引用之间存在差异

标签: rust


【解决方案1】:

Save_as_ppm 函数引用了自我,但我刚刚传递了一个可变的自我。

这不是这里发生的事情。 method call expression 使用解析算法,使用户无需显式创建合适的接收值借用即可调用方法。如有必要,有效的借用将匹配请求的接收类型.

换句话说,代码

inputs.save_as_ppm(&filepath)

相当于fully qualified syntax 中的这个调用:

Layer::save_as_ppm(&inputs, &filepath)

请注意,直接进行了不可变借用:不同种类的借用之间没有转换,所有这些对于绑定的可变性都无关紧要(let mut inputs)。由于不可变和可变变量绑定都可以不可变地借用,因此代码符合借用检查器并编译。

作为附录,没有什么能阻止您真正传递可变引用:

Layer::save_as_ppm(&mut inputs, &filepath);

这是有效的,因为可变引用是 coerced 到具有相同生命周期的不可变引用。它是 Rust 中可用的枚举 type coercions 之一。

也可以看看:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 2010-09-13
    相关资源
    最近更新 更多