为什么Rust中增加一层间接调用可以省略函数参数的mut修饰符?
问题核心解释
你遇到的差异本质是对 Rust 中参数前mut关键字的语义理解偏差:mut放在参数名前仅修饰变量绑定的可变性,既不会改变参数的类型,也不会对传入的实参有额外要求,它的作用仅仅是允许你在当前函数内修改这个绑定的变量、或者对它做可变借用。
两个函数的差异分析
- 对于
write1:它的逻辑仅为把收到的out参数直接移动给write2,整个过程不需要修改out的值,也不需要对out做可变借用,因此完全不需要把out声明为可变绑定。多余的mut会被编译器识别为无用代码,触发「变量不需要可变」的警告。 - 对于
write2:内部调用的writeln!宏展开后,会触发Writetrait的write_fmt方法调用,该方法签名要求接收&mut self,也就是需要对out做可变借用。只有当out本身是可变绑定时,才能合法生成它的可变引用,因此这里必须给参数加mut修饰。
补充:容易混淆的点
很多开发者会把参数前的mut和类型中的&mut混淆:如果你把write2的签名改为fn write2(out: &mut impl Write),就算参数前不加mut也能正常编译——此时out本身的类型就是可变引用,不可变绑定的可变引用本身就允许修改它指向的对象,不需要额外的mut修饰。而原代码中write2的参数是impl Write泛型,会匹配所有实现了Write的类型(包括值类型,比如Vec<u8>),必须通过mut声明可变绑定才能生成可变借用调用 trait 方法。
内容的提问来源于stack exchange,提问作者Max Heiber
相关产品推荐
相关产品推荐

