You can't have an iterator that returns overlapping &mut such as &mut self and &mut self.op1, because then it would be possible to .collect() them and have aliasing &mut (instant UB).
You could have a lending iterator (no trait in std for that yet), but it would have to be lazy (e.g. track state separately and serially construct and hand out &mut self, &mut self.op1, ...).
Side note: Box<&dyn Trait> and similar don't make much sense; just use &dyn Trait.
I don't understand why you are using an iterator for these types. Iterators work best for collections of arbitrary size. There are some apparent exceptions, such as impl IntoIterator for Option. But even in that case the iterator has either 0 or 1 element, so it still fits the definition of arbitrary size. For a collection of fixed size, it would be more prudent to just provide accessor methods to the fields.
Extensibility is one thing. What I'm sensing here is more along the lines of duck typing. "Everything is an iterator that yields expressions." While Rust does have some types that can help with type erasure and reflection (e.g. Any and TypeId) it's usually reserved for special cases where there is really no other option. Best to leverage the type system as intended than try to work around it.
Iterators work best for collections of arbitrary size.
This collection can have an arbitrary size (via nesting).
it's usually reserved for special cases where there is really no other option.
The actual code is a Markdown parser where people should be able to contribute new AST nodes. But you make a good point. Maybe the extensibility is not needed. An enum would make things much simpler.
Another way to think of this (nesting) is that each leaf of the tree is still a fixed size, though the tree itself may be arbitrarily constructed. Or in other words, the tree is the collection, not the individual leaves. To this end, I would say the tree is a good candidate to offer an iterator, and the leaves do not need to implement Iterator to make this happen.
Addition is not the collection you are looking for.
Concretely, the most common API design I have seen for iterating over an AST has been the visitor pattern. Which is, for instance, what serde provides for deserialization.
Visitor pattern is the way to go for these kinds of trees (e.g. ASTs). I think the syn crate implements a visitor pattern for traversing a Rust syntax tree (although the implementation is complicated). Probably the serde docs, especially those about implementing the traits manually will be most useful for you.