Search code examples
rusttraitstrait-objects

Supertrait as return traitobject doesn't have a known size at compile time


I am working with the DHT11 library where the argument gpio, based on the esp32 implementation, for new must implement InputPin and OutputPin. So I created a function that returns a traitobject of a supertrait of those two traits. But when I want to dereference it to actually call new, I get the error doesn't have a size known at compile-time.

This is the supertrait I made from the above mentioned traits:

trait InputOutputPin: InputPin<Error = EspError> + OutputPin<Error = EspError> {}
impl<T: InputPin<Error = EspError> + OutputPin<Error = EspError>> InputOutputPin for T {}

This is the function that creates an gpio based on which pin number is given:

    fn get_gpio(pin: &u8) -> Result<&dyn InputOutputPin, &'static str>{
        match pin {
            33 => Ok(&Peripherals::take().unwrap().pins.gpio33.into_input_output().unwrap()),
            32 => Ok(&Peripherals::take().unwrap().pins.gpio32.into_input_output().unwrap()),
            27 => Ok(&Peripherals::take().unwrap().pins.gpio27.into_input_output().unwrap()),
            26 => Ok(&Peripherals::take().unwrap().pins.gpio26.into_input_output().unwrap()),
            25 => Ok(&Peripherals::take().unwrap().pins.gpio25.into_input_output().unwrap()),
            _ => Err("Pin not configurable for dht")
        }
    }

And this is how I assign the result from the function:

let gpio = Self::get_gpio(pin).unwrap();
let dht = Dht11::new(*gpio);

All I want to do is create a DHT11 object based on what pin number was chosen, but the esp32 library implements every gpio as its own struct by using a makro. What am I missing or is there a obvious, much better way of doing it.


Solution

  • The ESP32 HAL has a degrade method for GPIO pins which erases the pin-specific typing so you don't need to use your dyn supertrait.

    The modified code would like more like this:

    fn get_gpio(pin: &u8) -> Result<GpioPin<InputOutput>, &'static str>{
            match pin {
                33 => Ok(&Peripherals::take().unwrap().pins.gpio33.into_input_output().unwrap().degrade()),
                32 => Ok(&Peripherals::take().unwrap().pins.gpio32.into_input_output().unwrap().degrade()),
                27 => Ok(&Peripherals::take().unwrap().pins.gpio27.into_input_output().unwrap().degrade()),
                26 => Ok(&Peripherals::take().unwrap().pins.gpio26.into_input_output().unwrap().degrade()),
                25 => Ok(&Peripherals::take().unwrap().pins.gpio25.into_input_output().unwrap().degrade()),
                _ => Err("Pin not configurable for dht")
            }
        }