Rust方法调用中借用检查行为与脱糖预期不符的问题咨询
Rust方法调用中借用检查行为与脱糖预期不符的问题咨询
我最近在研究Rust的方法调用脱糖规则和借用检查的交互时,遇到了一个和官方文档描述不一致的奇怪问题。根据Rust参考手册里的说明,方法调用会被脱糖成全限定语法的函数调用,而且函数参数是从左到右求值的,但实际测试时,某些方法调用的借用检查结果和手动脱糖后的代码完全不同,特来请教原因。
完整测试代码
struct S; impl S { fn by_ref(&self, _arg: ()) {} fn by_mut(&mut self, _arg: ()) {} } fn foo() { let mut s = S; s.by_mut(s.by_ref(())); // 能正常编译,但按脱糖规则预期会报错 s.by_mut(s.by_mut(())); // [E0499] 不能同时多次可变借用 `s` // 按照参考手册的脱糖规则,手动写出等价代码,但全部触发借用错误 S::by_mut(&mut s, S::by_ref(&s, ())); // [E0502] 不可变借用与可变借用冲突 S::by_mut(&mut s, S::by_mut(&mut s, ())); // [E0499] 多次可变借用 (&mut s).by_mut((&s).by_ref(())); // [E0502] 不可变借用与可变借用冲突 (&mut s).by_mut((&mut s).by_mut(())); // [E0499] 多次可变借用 } // 调换方法调用参数顺序的测试 fn bar() { let mut s = S; s.by_ref(s.by_mut(())); // [E0502] 可变借用与不可变借用冲突 s.by_ref(s.by_ref(())); // 正常编译 // 对应的手动脱糖代码行为与预期一致 S::by_ref(&s, S::by_mut(&mut s, ())); // [E0502] 借用冲突 S::by_ref(&s, S::by_ref(&s, ())); // 正常编译 }
额外测试的无关变量验证
我还尝试了多种调整,结果均未改变核心现象:
- 把参数类型从
()换成String,或给S派生Clone/Copy特性; - 修改
by_ref的接收方式为self而非&self; - 调整方法调用中参数的顺序;
以上操作都没有让s.by_mut(s.by_ref(()))出现报错,也没有让其他组合的行为发生变化。
核心疑问
我原本预期所有方法调用都会严格遵循文档描述的脱糖规则,借用检查逻辑会和手动写出的脱糖代码完全一致,但实际情况却存在明显差异:
s.by_mut(s.by_ref(()))能正常通过借用检查,但所有对应的手动脱糖版本(全限定函数调用、显式引用调用)都会触发E0502或E0499错误;- 而类似的组合(如
s.by_mut(s.by_mut(()))、s.by_ref(s.by_mut(())))则和脱糖代码的行为一致,都会触发预期的借用错误。
这到底是为什么?难道方法调用的脱糖规则在借用检查阶段有特殊的例外逻辑?还是我对参数求值顺序的理解存在偏差?
内容来源于stack exchange
相关产品推荐
相关产品推荐

