I get why iterators that return mutable references are not possible in Rust without unsafe code, and I don't want to use unsafe code even if it looks safe. But I believe that for this particular case of mine, maybe there's a way, because I never need 2 mutable references, or one mutable + other const reference, at the same time. I just want to add 2 polynomials coefficient-wise:
pub struct Coefficients<'a, T> {
_phantom: &'a T,
}
impl<'a, T> Iterator for Coefficients<'a, T> {
type Item = &'a T;
#[inline(always)]
fn next(&mut self) -> Option<&'a T> {
unimplemented!()
}
}
pub fn coefficient_wise_add<'a, T>(
operand1: Coefficients<'a, T>,
operand2: Coefficients<'a, T>,
destination: Coefficients<'a, T>,
) {
for _tuple in operand1.zip(operand2).zip(destination) {
//can't set destination here, but wanted to do
//*tuple.2 = *tuple.0 + *tuple.1;
}
}
Is there a way to force the compiler to understand that I never use 2+ mutable references or 1 mutable + many const?
This assumption is not quite right. Iterators that return items of type &mut SomeType are often harder to implement (compared to iterators with &SomeType items), but also often still possible without unsafe code.
I’m not sure I understand your example code though, because that’s an iterator that does not return mutable references.
I don't really understand the problem you've run into.
Regarding the clone, that's a completely separate question, and how expensive it is depends on the underlying type. If it's an integer such as i32, it would not be expensive.
If your code was allowed conceptually, I could get two mutable references to the same data by calling next() twice(because you always return the same mutable reference). You need some static guarantee that this cannot happen.
Moreover, your a in Coefficients is "trapped" behind your mutable borrow in Iterator::next. You can't change the signature of next to work around the lifetime. That is, you must implement with fn next(&mut self), not fn next(&'a mut self).
You should look into having a dedicated data structure for this one-time iteration case, just like [T] has dedicated structures for mutable iteration and immutable iteration, and how Vec has a dedicated structure for consuming iteration.
If you don't want to go to all that trouble, you could just do something like this:
For returning an actual iterator, using option::IntoIter<&'a mut T> for type CoefficientsIter<'a, T> is an option as-well. Or array::IntoIter<&'a mut T, 1>. Created with Some(&mut self.a).into_iter() or [&mut self.1].into_iter(), respectively.