Skip to content

Commit ddf4375

Browse files
bors[bot]Dirbaio
andauthored
Merge #363
363: async/i2c: fix lifetimes on transaction() r=ryankurte a=Dirbaio Trying to implement i2c for a shared i2c bus behind an async mutex yielded lots of cursed lifetime errors, because `&'a mut [Operation<'b>]` is invariant on `'b`, not covariant as one would expect... To fix this, the GAT future needs two lifetimes. Also counterintuitively, the future must be `+ 'a`, but NOT `+ 'b`. Then `AddressMode: 'static` is needed because Rust wants annoying `where A: 'a` bounds otherwise. The async SPI PR has the same issue, will fix later. #347 With these fixes, implementing i2c on a mutex works nicely now: ```rust struct SharedI2c<T>(tokio::sync::Mutex<T>); impl<T: ErrorType> ErrorType for SharedI2c<T> { type Error = T::Error; } impl<A: AddressMode, T: I2c<A>> I2c<A> for SharedI2c<T> { type ReadFuture<'a> where Self: 'a, = impl Future<Output = Result<(), Self::Error>> + 'a; fn read<'a>(&'a mut self, address: A, read: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { self.0.lock().await.read(address, read).await } } type WriteFuture<'a> where Self: 'a, = impl Future<Output = Result<(), Self::Error>> + 'a; fn write<'a>(&'a mut self, address: A, write: &'a [u8]) -> Self::WriteFuture<'a> { async move { self.0.lock().await.write(address, write).await } } type WriteReadFuture<'a> where Self: 'a, = impl Future<Output = Result<(), Self::Error>> + 'a; fn write_read<'a>( &'a mut self, address: A, write: &'a [u8], read: &'a mut [u8], ) -> Self::WriteReadFuture<'a> { async move { self.0.lock().await.write_read(address, write, read).await } } type TransactionFuture<'a, 'b> where Self: 'a, 'b: 'a, = impl Future<Output = Result<(), Self::Error>> + 'a; fn transaction<'a, 'b>( &'a mut self, address: A, operations: &'a mut [Operation<'b>], ) -> Self::TransactionFuture<'a, 'b> { async move { self.0.lock().await.transaction(address, operations).await } } } ``` cc `@matoushybl` Co-authored-by: Dario Nieuwenhuis <[email protected]>
2 parents 173750c + 244d383 commit ddf4375

File tree

2 files changed

+13
-11
lines changed

2 files changed

+13
-11
lines changed

embedded-hal-async/src/i2c.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
107107
) -> Self::WriteReadFuture<'a>;
108108

109109
/// Future returned by the `transaction` method.
110-
type TransactionFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
110+
type TransactionFuture<'a, 'b>: Future<Output = Result<(), Self::Error>> + 'a
111111
where
112-
Self: 'a;
112+
Self: 'a,
113+
'b: 'a;
113114

114115
/// Execute the provided operations on the I2C bus as a single transaction.
115116
///
@@ -124,11 +125,11 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
124125
/// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
125126
/// - `SR` = repeated start condition
126127
/// - `SP` = stop condition
127-
fn transaction<'a>(
128+
fn transaction<'a, 'b>(
128129
&'a mut self,
129130
address: A,
130-
operations: &mut [Operation<'a>],
131-
) -> Self::TransactionFuture<'a>;
131+
operations: &'a mut [Operation<'b>],
132+
) -> Self::TransactionFuture<'a, 'b>;
132133
}
133134

134135
impl<A: AddressMode, T: I2c<A>> I2c<A> for &mut T {
@@ -164,16 +165,17 @@ impl<A: AddressMode, T: I2c<A>> I2c<A> for &mut T {
164165
T::write_read(self, address, bytes, buffer)
165166
}
166167

167-
type TransactionFuture<'a>
168+
type TransactionFuture<'a, 'b>
168169
where
169170
Self: 'a,
170-
= T::TransactionFuture<'a>;
171+
'b: 'a,
172+
= T::TransactionFuture<'a, 'b>;
171173

172-
fn transaction<'a>(
174+
fn transaction<'a, 'b>(
173175
&'a mut self,
174176
address: A,
175-
operations: &mut [Operation<'a>],
176-
) -> Self::TransactionFuture<'a> {
177+
operations: &'a mut [Operation<'b>],
178+
) -> Self::TransactionFuture<'a, 'b> {
177179
T::transaction(self, address, operations)
178180
}
179181
}

src/i2c.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ impl<T: ErrorType> ErrorType for &mut T {
244244
/// Address mode (7-bit / 10-bit)
245245
///
246246
/// Note: This trait is sealed and should not be implemented outside of this crate.
247-
pub trait AddressMode: private::Sealed {}
247+
pub trait AddressMode: private::Sealed + 'static {}
248248

249249
/// 7-bit address mode type
250250
pub type SevenBitAddress = u8;

0 commit comments

Comments
 (0)