为什么Rust中无法在同一行两次调用FnMut类型的闭包?
核心原因是Rust的函数调用表达式求值顺序规则
要理解这个差异,首先得明确Rust中函数调用表达式的固定求值顺序:
- 第一步:先求值函数本身(也就是调用运算符
()左侧的部分) - 第二步:再从左到右依次求值所有参数表达式
我们对应两段代码具体分析:
无法编译的f(f(2))写法
对于f(f(2))这个调用:
- 首先要求值外层调用的函数部分也就是
f:因为F实现的是FnMuttrait,调用它需要对f进行可变借用,这时候第一个可变借用就产生了,而且要一直持有到整个外层函数调用结束。 - 接下来要求值外层调用的参数
f(2):这个参数本身又是一次f的调用,同样需要对f申请可变借用,而此时外层的可变借用还没释放,就触发了Rust「同一时间不能存在多个活跃可变借用」的规则,编译报错。
可以正常编译的临时变量写法
拆分临时变量的代码执行逻辑是:
- 先执行
let tmp = f(2);:这次调用f的时候会产生可变借用,调用完成后借用就立刻释放了,tmp存下计算结果。 - 再执行
f(tmp):再次对f申请可变借用,此时没有其他活跃的借用,自然可以正常执行。
你直觉里认为的「先算内层f(2)再算外层f」的逻辑,是C、Java等大部分语言的求值顺序,但Rust为了避免更多内存安全问题,特意定义了先求值函数、再求值参数的规则,才会出现这个看起来反直觉的编译错误。
内容的提问来源于stack exchange,提问作者nalzok
相关产品推荐
相关产品推荐

