Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/lib.rs:8:13
|
7 | for p in &self.preprocessors {
| -------------------
| |
| immutable borrow occurs here
| immutable borrow later used here
8 | p(self);
| ^^^^^^^ mutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
error: could not compile `playground` due to previous error
if you're committed to this design, you could consider having a no-op placeholder callback, and swapping it into the Vec in order to call each callback.
Maybe redesign things so you have a struct that holds the preprocessors and the other data in a sub-struct, and your preprocessors are FnMut(&mut SubStruct).
if you're committed to this design, you could consider having a no-op placeholder callback, and swapping it into the Vec in order to call each callback.
Thanks! I don’t understand what that means. Can you elaborate?
Here's a per-preprocessor example. I think with a little imagination, you can see how this reintroduces the possibility of iterator invalidation (albeit without UB): a preprocessor could alter the list of preprocessors, so that for example this line panics because [idx] no longer exists...
...or it changes the order and you don't actually get the no-op back out and end up losing a valid preprocessor, etc etc.
The remove-all-preprocessors version I gave actually has related problems: A preprocessor could add some stuff to the list which is later thrown out; users could come to rely on the ability to populate the list and call your function recursively, which ties your hands in terms of implementation.
A substruct redesign avoids all this by removing the ability of a preprocessor to effect the list.