Generic: Cannot infer type

Hello,

I have two i2c devices on the same bus and therefore share the same peripheral of the microcontroller. I am writing a driver and the idea is to have only an option on the interface and whenever I wanna talk with the device, first I have to pass in the interface.

The problem is that when trying to get the interface from the option I get the compile error that E cannot be derived. But in the line below with interface.write() E should be defined.

let mut interface = self.interface.ok_or(ErrorKind::NoInterface.into())?;
   |                                            ^^^^^                        ---- type must be known at this point
   |                                            |
   |                                            cannot infer type of the type parameter `E` declared on the method `ok_or`
trait Debug {}

trait I2c {
    type Error;

    fn write(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
}

struct I2cInterface {}

pub enum ErrorKind {
    WrongDeviceId,
    I2CError,
    NotStarted, // Dummy
    NoInterface,
}

pub struct Error<E> {
    pub kind: ErrorKind,
    pub source: Option<E>,
}

struct Device<Interface> {
    interface: Option<Interface>,
}

impl<Interface, E> Device<Interface>
    where
        Interface: I2c<Error=E>,
        E: Debug,
{
    pub fn write(&mut self) -> Result<(), Error<E>> {
        let mut interface = self.interface.ok_or(ErrorKind::NoInterface.into())?;
        interface.write().map_err(|e| ErrorKind::I2CError.with(e))
    }

}

// If you use `main()`, declare it as `pub` to see it in the output:
pub fn main() {}

impl<E> From<ErrorKind> for Error<E>
where
    E: Debug,
{
    fn from(kind: ErrorKind) -> Error<E> {
        let source = None;
        Error { source, kind }
    }
}

impl ErrorKind {
    fn with<E>(self, source: E) -> Error<E> {
        let s = Some(source);
        Error {
            source: s,
            kind: self,
        }
    }
}

The ? operator already does an implicit call for type conversions, so you are doing two type conversions by also calling .into. This is the cleaned code:

pub fn write(&mut self) -> Result<(), Error<E>> {
        let mut interface = self.interface.as_mut().ok_or(ErrorKind::NoInterface)?;
        interface.write().map_err(|e| ErrorKind::I2CError.with(e))
}

the problem is the .into(), because the trait Into<T> is itself generic.

you can instead explicitly speciify the error type is Error<ErrorKind>, e.g.:

// instead of
// ErrorKind::NoInterface.into()
// use this;
Error::from(ErrorKind::NoInterface)

then you just need to add as_mut() to fix the other compile error:

    pub fn write(&mut self) -> Result<(), Error<E>> {
        let mut interface = self.interface.as_mut().ok_or(Error::from(ErrorKind::NoInterface))?;
        interface.write().map_err(|e| ErrorKind::I2CError.with(e))
    }

Thank you very much!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.