Suppose I have a struct
that uses a generic type (BNO055 is a sensor):
pub struct BNO055<T: I2CDevice + Sized> {
pub i2cdev: T,
pub mode: BNO055OperationMode,
}
I also have another struct
that has the BNO055 as a field:
pub struct IMU {
device: bno055::BNO055
}
Attempting to compile this code results in an error, with the compiler saying:
error[E0107]: wrong number of type arguments: expected 1, found 0
--> src/modules/sensors/imu.rs:553:13
|
553 | device: bno055::BNO055
| ^^^^^^^^^^^^^^ expected 1 type argument
If I add a generic type to the struct
, like so:
pub struct IMU<D: I2CDevice + Sized>{
device: bno055::BNO055<D>
}
And then impl
a function:
impl<D: I2CDevice + Sized> IMU<D> {
pub fn init(imu_addr: u16) -> Self {
let mut i2c_dev = LinuxI2CDevice::new("/dev/i2c-1", imu_addr).unwrap();
let mut imu_dev = bno055::BNO055::new(i2c_dev).unwrap();
IMU {
device: imu_dev
}
}
}
I get this error:
error[E0308]: mismatched types
--> src/modules/sensors/imu.rs:567:21
|
567 | device: imu_dev
| ^^^^^^^ expected type parameter, found struct `modules::sensors::imu::bno055::i2cdev::linux::LinuxI2CDevice`
|
imu_dev
is of the type BNO055
, so I assume that it should properly fit the generic's constraints. How do I resolve this error?
This init()
function is supposed to create an IMU<D>
instance for any D
specified by the caller (provided D
satisfies the I2CDevice + Sized
bounds):
impl<D: I2CDevice + Sized> IMU<D> {
pub fn init(imu_addr: u16) -> Self {
...but it always tries to return an IMU<LinuxI2CDevice>
.
(edit) In my testing, the error[E0308]: mismatched types
is explained in a note that follows it, which should look like this:
note: expected type `......::BNO055<D>`
found type `......::BNO055<LinuxI2CDevice>`
(/edit)
To fix this, you could make init()
non-generic, e.g. by changing the impl to impl IMU<LinuxI2CDevice>
.
P.S. You call BNO055
a "type" and are trying to use it as a type... I'm not sure about terminology, but note that after you define a struct as being generic over some type parameter D
, the struct name alone doesn't represent a concrete type, but rather a family of related - but incompatible - types. You have to provide some type in place of D
: either another type parameter BNO055<T>
or a specific type BNO055<LinuxI2CDevice>
- to get a type.
Keep in mind the alternatives to using generics: making the I2CDevice
a enum or keeping it a trait, but using it as a trait object, e.g. pub i2cdev: Box<dyn I2CDevice>
.