v[i + 1] += v[i];
を
AddAssign::add_assign(IndexMut::index_mut(&mut v, i + 1), *Index::index(&v, i));
にしたら immutable な borrow と mutable な borrow を同時にするなと言われたので、演算子の場合のみ評価順序をあれこれする系の規則でもあるのかな
NLL breaks usage of AddAssign · Issue #48129 · rust-lang/rust · GitHub
https://github.com/rust-lang/rust/issues/48129#issuecomment-365124001
これとか関係ありそう
Allow two-phase borrows of &mut self in ops by bobtwinkles · Pull Request #48197 · rust-lang/rust · GitHub
https://github.com/rust-lang/rust/pull/48197
ふーむ?
どうも演算子向けには特別に two-phase borrow (最初に引数の immutable borrow の式を処理してから親の式を処理する) が有効化されてるっぽい?
Two-phase-borrows - Guide to Rustc Development
https://rust-lang.github.io/rustc-guide/borrow_check/two_phase_borrows.html
ふーむ???
https://mastodon.cardina1.red/@lo48576/102518494447484527
https://mastodon.cardina1.red/@lo48576/102518500960486152
べつに two-phase borrow は演算子じゃなくてもいけるっぽいですね (よくわかってない顔)
std::num::Wrapping でも警告になるので、ラッパーの作りかたがマズいわけではなさそう
Dubious borrowck warning in 2018 edition · Issue #59645 · rust-lang/rust · GitHub
https://github.com/rust-lang/rust/issues/59645#issuecomment-479233265
> Overloaded compound assignment operators unfortunately evaluate their operands in the opposite order to the built in ones.
これじゃない?
組込みだと右辺の引数側を評価したあとで左辺への mutation を行うので特例でなんとかできるんだけど、ユーザ定義の AddAssign だと第一引数である左辺の &mut 参照 (つまり AddAssign の self?) が先に評価されてその後で右辺の評価が起きるので two-phase borrow がうまいこといかない、みたいな感じか
借用検査は組込の複合代入演算子に対して特殊な動作を行う - 何とは言わない天然水飲みたさ
https://blog.cardina1.red/2019/07/29/borrowck-and-builtin-compound-assign/
書いた