Playground Link: Rust Playground
I have existing code:
fn transmit<T: Into<u32> + Copy>(self, data: &[T]) -> SingleShotTxTransaction<Self, T>
where
Self: Sized,
used very roughly like
for v in data {
write((*v).into())
}
I'd like to change it to accept an iterator, so I can call it like ch.transmit(data.flat_map(...))
. The iterator can't return &T
because the iterator is generating values on the fly in the map. I can't just make the data be Into<u32>
- it isn't a 1:1 mapping.
I can change the signature to:
fn transmit<D, R, T: Into<u32> + Copy>(self, data: D) -> SingleShotTxTransaction<Self, R, T>
where
Self: Sized,
D: IntoIterator<Item = T, IntoIter = R>,
R: Iterator<Item = T>,
used like
for v in data {
write(v.into())
}
and change existing callers from channel.transmit(&buffer)
to channel.transmit(buffer.iter().copied())
(and then IntoInterator
isn't really needed)
But I'd like to do this without needing existing callers to change. (That's why I had the IntoIterator
above) I wonder if it is possible, given the constraint that my iterator can't return a reference?
I thought core::borrow:Borrow
might help, eg
fn transmit<D, I, B, T: Into<u32> + Copy>(self, data: D) -> SingleShotTxTransaction<Self, I, B, T>
where
Self: Sized,
B: Borrow<T>,
D: IntoIterator<Item = B, IntoIter = I>,
I: Iterator<Item = B>,
used like
for v in data {
write((*v.borrowed()).into())
}
And calling that with the an Iterator<u32>
works fine, but calling with &data
(eg existing code) won't compile:
Compiling esp-hal-smartled v0.12.0 (/home/ted/src/esp-hal/esp-hal-smartled)
error[E0283]: type annotations needed
--> /home/ted/src/esp-hal/esp-hal-smartled/src/lib.rs:191:23
|
191 | match channel.transmit(&self.rmt_buffer).wait() {
| ^^^^^^^^ cannot infer type of the type parameter `T` declared on the method `transmit`
|
= note: cannot satisfy `_: Into<u32>`
note: required by a bound in `transmit`
--> /home/ted/src/esp-hal/esp-hal/src/rmt.rs:1005:29
|
1005 | fn transmit<D, I, B, T: Into<u32> + Copy>(self, data: D) -> SingleShotTxTransaction<Self, I, B, T>
| ^^^^^^^^^ required by this bound in `TxChannel::transmit`
help: consider specifying the generic arguments
|
191 | match channel.transmit::<&[u32; BUFFER_SIZE], core::slice::Iter<'_, u32>, &u32, T>(&self.rmt_buffer).wait() {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Why can't it infer T calling it this way? Is there any way that would work? I'm guessing I should be expressing the types differently, but I'm not sure how.