I am using the I2CDevice
trait which is defined in an external crate like this:
pub trait I2CDevice {
type Error: Error;
// members
}
Neither it nor any of its members contain any generic arguments.
I am creating a decorator for any I2CDevice
implementation which delegates to an inner/concrete I2CDevice
, adding console printing for diagnostic purposes:
struct debugDeviceDecorator<'a, T: I2CDevice<Error = LinuxI2CError> + Sized + 'a> {
device: &'a mut T,
}
impl I2CDevice__A__ for debugDeviceDecorator__B__ {
type Error = LinuxI2CError;
fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
println!("read: data: {:?}", data);
self.device.read(data)
}
// etc.
}
I can't figure out what to put in place of __A__
and __B__
.
When I use no generic arguments whatsoever, I get compiler errors: Expected 1 lifetime parameter and Expected 1 type argument.
My best guess then is to leave __A__
blank because the definition of I2CDevice
requires no generic arguments, and then to mirror the type argument used for the debugDeviceDecorator
struct itself in place of __B__
like:
impl I2CDevice for debugDeviceDecorator<'a, T: I2CDevice<Error=LinuxI2CError> + Sized + 'a> { }
I get the compilation error: error: expected one of !
, (
, +
, ,
, ::
, <
, or >
, found :
, which occurs on the colon (:
) that begins the type constraint on the generic argument T
.
Perhaps the compiler thinks that I'm trying to constrain T
in a manner which diverges from the constraint in the struct definition itself, so instead I try:
impl I2CDevice for debugDeviceDecorator<'a, T> {}
Which results in the errors undeclared lifetime for the lifetime parameter, and undefined or not in scope for the type argument itself, at which point I cannot figure out how to proceed. I would assume that the lifetime and the type argument are defined by the future, as yet nonexistent code that will some day initialize a debugDeviceDecorator
struct, values which cannot yet be known and seem to me as though should not prevent this existing code from compiling.
I can see the compiler needing some information about the type of self.device
used within the functions of the impl, but I feel like my first guess in which I mirrored the struct's expanded type definition in my impl declaration should have provided that.
You should re-read The Rust Programming Language, specifically the section on how to implement traits for generic structs. A lot of hard work has gone into that documentation so that people can get started in Rust easier.
The book will show you the proper syntax for how to define a trait for a struct:
Note:
You have to declare the two generic values (
'a
andT
) before you can use them.There's nothing special about the fact that the trait has no generics.
Types in Rust use
PascalCase
, notcamelCase
, so I've changed the name.I switched to a
where
clause because it's too hard to read the bounds when they are crammed into the generic declaration.