I have a trait defined in an external crate, and I need to return it in a method from a struct that I've defined. There's no problem to accept the trait type as an input argument, but I don't know how can I return it. The trait doesn't implement Sized and I can't change its implementation.
Here's a sample code (playground):
use std::fmt::Debug; // this code is defined in an external crate pub trait SomeTrait: Clone + Debug { fn get_name(&self) -> &str; } #[derive(Clone, Debug)] struct Implementor1(String); impl SomeTrait for Implementor1 { fn get_name(&self) -> &str { &self.0 } } #[derive(Clone, Debug)] struct Implementor2 { name: String, } impl SomeTrait for Implementor2 { fn get_name(&self) -> &str { &self.name } } // the code below is mine struct ImplementorManager<T: SomeTrait> { implementors: Vec<T>, } impl<T: SomeTrait> ImplementorManager<T> { pub fn call_get_name(implementor: T) -> String { implementor.get_name().to_string() } pub fn new_implementor(first: bool, name: &str) -> T { match first { true => Implementor1(name.to_string()), false => Implementor2 { name: name.to_string(), }, } } } fn main() { let implementor = Implementor1("first".to_string()); println!("name: {}", ImplementorManager::call_get_name(implementor)); } The error I get:
error[E0308]: mismatched types --> src/main.rs:40:21 | 33 | impl<T: SomeTrait> ImplementorManager<T> { | - this type parameter ... 38 | pub fn new_implementor(first: bool, name: &str) -> T { | - expected `T` because of return type 39 | match first { 40 | true => Implementor1(name.to_string()), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `Implementor1` | = note: expected type parameter `T` found struct `Implementor1` If I'll comment-out the new_implementor() method, the call_get_name() method works fine accepting the trait. I've tried Boxing the returned object, but it is not possible without the Sized trait.
Is there any way I can overcome it?
// Edit
I've kinda messed up with my explanation and example. Let me phrase it again.
I want to use Peripheral struct from btleplug crate in my struct. On Linux, this struct is public but inside a private module. Only the Peripheral trait is exposed in the api module.
Here's a sample code:
use btleplug::api::{BDAddr, Central, Peripheral}; use btleplug::bluez::manager::Manager; use btleplug::Error; use std::str::FromStr; // cannot import the Peripheral struct as the module is private // use btleplug::bluez::adapter::peripheral::Peripheral; struct MyStruct<PeripheralType: Peripheral> { device: PeripheralType, } impl<PeripheralType> MyStruct<PeripheralType> where PeripheralType: Peripheral, { fn get_device() -> PeripheralType { let central = Manager::new() .unwrap() .adapters() .unwrap() .into_iter() .next() .unwrap() .connect() .unwrap(); central .peripheral(BDAddr::from_str("2A:00:AA:BB:CC:DD").unwrap()) .unwrap() } pub fn new() -> Self { let device = Self::get_device(); Self { device } } } fn main() -> Result<(), Error> { let _ = MyStruct::new(); Ok(()) } The error I get:
error[E0308]: mismatched types --> src/main.rs:27:9 | 13 | impl<PeripheralType> MyStruct<PeripheralType> | -------------- this type parameter ... 17 | fn get_device() -> PeripheralType { | -------------- expected `PeripheralType` because of return type ... 27 | / central 28 | | .peripheral(BDAddr::from_str("2A:00:AA:BB:CC:DD").unwrap()) 29 | | .unwrap() | |_____________________^ expected type parameter `PeripheralType`, found struct `btleplug::bluez::adapter::peripheral::Peripheral` | = note: expected type parameter `PeripheralType` found struct `btleplug::bluez::adapter::peripheral::Peripheral` It somehow seems to work internally, but I don't understand why it doesn't work in my example...