Work with feature objects requiring size

I would like to have a LinkedList wrapper structure on an object. Internal is the stream type for the Ssl or Non-Ssl stream. My hope was to convey the shell of the structure around, and as long as the inside matches the same attribute, everything will be fine, regardless of the type of internal flow used.

A simple example:

 use std::sync::{Arc, Mutex}; use std::collections::LinkedList; use std::os::unix::io::{RawFd, AsRawFd}; pub trait HRecv {} pub trait HSend {} pub trait HStream: HRecv + HSend + AsRawFd + Clone {} pub struct Stream<T: HStream> { pub inner: T } pub type StreamList = Arc<Mutex<LinkedList<Stream<HStream>>>>; fn main() { let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new())); } 

It produces the following error:

 error: the trait 'core::marker::Sized' is not implemented for the type 'HStream' [E0277] let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new())); ^~~~~~~~~~~~~~~ 

I tried to add + Sized to the HStream definition, and also make inner a Box<T> , both of them create the same error.

Is it possible to do this with Rust? If so, what will be the syntax?

+3
source share
2 answers

Well, there are a few issues here. Processing the list of compiler errors:

 <anon>:15:53: 15:68 error: the trait `core::marker::Sized` is not implemented for the type `HStream` [E0277] <anon>:15 let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new())); ^~~~~~~~~~~~~~~ <anon>:15:53: 15:68 help: see the detailed explanation for E0277 <anon>:15:53: 15:68 note: `HStream` does not have a constant size known at compile-time <anon>:15:53: 15:68 note: required by `Stream` 

Since the HStream does not have a computable compile-time size, it cannot be replaced by a parameter of type T All type parameters implicitly require the replaced type to be compile time. If you want to allow types with dynamic size, you need to explicitly discard this implicit border by saying something like:

 <T: ?Sized + HStream> <anon>:15:53: 15:68 error: the trait `HStream` is not implemented for the type `HStream` [E0277] <anon>:15 let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new())); ^~~~~~~~~~~~~~~ <anon>:15:53: 15:68 help: see the detailed explanation for E0277 <anon>:15:53: 15:68 note: required by `Stream` 

The characteristic does not realize itself. You request a type that implements HStream , but HStream does not implement itself (how would it be?)

You must specify the type that does.

 <anon>:15:53: 15:68 error: the trait `HStream` cannot be made into an object [E0038] <anon>:15 let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new())); ^~~~~~~~~~~~~~~ <anon>:15:53: 15:68 help: see the detailed explanation for E0038 <anon>:15:53: 15:68 note: the trait cannot require that `Self : Sized` 

And here is the KO problem: HStream cannot be used with dynamic sending, period. It is not safe. This is most likely due to the Clone requirement.

The “fix” for all of the above is to reverse engineer your types so that the problem does not exist. What entails cannot be known because there is not enough context to tell what you are trying to do.

With a blind hit, however, here is what it might look like without generics (which you don't seem to be using, anyway):

 use std::sync::{Arc, Mutex}; use std::collections::LinkedList; use std::os::unix::io::{RawFd, AsRawFd}; pub trait HRecv {} pub trait HSend {} pub trait HStream: HRecv + HSend + AsRawFd + CloneHStream {} pub trait CloneHStream { fn clone_h_stream(&self) -> Box<HStream>; } impl<T> CloneHStream for T where T: 'static + Clone + HStream { fn clone_h_stream(&self) -> Box<HStream> { Box::new(self.clone()) } } pub struct Stream { pub inner: Box<HStream> } pub type StreamList = Arc<Mutex<LinkedList<Stream>>>; fn main() { let mut list = Arc::new(Mutex::new(LinkedList::<Stream>::new())); } 
+4
source

You cannot use the HStream type directly; he does not represent anything. It is used only for constructing types of derived pointers such as &HStream and Box<HStream> .

The simplest solution would be to have a LinkedList of Stream<Box<HStream>> .

 fn main() { let mut list = Arc::new(Mutex::new(LinkedList::<Stream<Box<HStream>>>::new())); } 

Then we just need to implement HStream for Box<HStream> .

 impl<'a> HRecv for Box<HStream + 'a> {} impl<'a> HSend for Box<HStream + 'a> {} impl<'a> AsRawFd for Box<HStream + 'a> { fn as_raw_fd(&self) -> RawFd { (&**self).as_raw_fd() } } impl<'a> HStream for Box<HStream + 'a> {} 

Please note that this is not a sign of ... Clone .

Clone not object-safe, which means that it is impossible to create feature object types for this characteristic, for example &Clone or Box<Clone> . Clone not object-safe because its Clone method returns Self , which represents a particular type of developer. If you used this method through an attribute object, the compiler would not be able to know the type of result in advance (it could be any of the Clone constructors!).

Since HStream is a subtone of Clone , HStream also not object-safe. The consequence of this is that we cannot implement Clone , and types of type Box<HStream> are not legal to use.

However, we can get around this by creating our own, object-safe attribute. We can even automatically implement it for types that implement the standard Clone trait.

 pub trait BoxedHStreamClone { fn boxed_clone(&self) -> Box<HStream>; } // Implementation for all types that implement HStream and Clone and don't hold any borrows impl<T: HStream + Clone + 'static> BoxedHStreamClone for T { fn boxed_clone(&self) -> Box<HStream> { Box::new(self.clone()) as Box<HStream> } } // Implementation for Box<HStream + 'a>, which cannot implement Clone impl<'a> BoxedHStreamClone for Box<HStream + 'a> { fn boxed_clone(&self) -> Box<HStream> { Box::new((&**self).boxed_clone()) as Box<HStream> } } 

Replace the Clone binding on the HStream with BoxedHStreamClone and you will be fine!

 pub trait HStream: HRecv + HSend + AsRawFd + BoxedHStreamClone {} 

Here's the last code:

 use std::sync::{Arc, Mutex}; use std::collections::LinkedList; use std::os::unix::io::{RawFd, AsRawFd}; pub trait BoxedHStreamClone { fn boxed_clone(&self) -> Box<HStream>; } impl<T: HStream + Clone + 'static> BoxedHStreamClone for T { fn boxed_clone(&self) -> Box<HStream> { Box::new(self.clone()) as Box<HStream> } } pub trait HRecv {} pub trait HSend {} pub trait HStream: HRecv + HSend + AsRawFd + BoxedHStreamClone {} pub struct Stream<T: HStream> { pub inner: T } pub type StreamList = Arc<Mutex<LinkedList<Stream<Box<HStream>>>>>; impl<'a> HRecv for Box<HStream + 'a> {} impl<'a> HSend for Box<HStream + 'a> {} impl<'a> AsRawFd for Box<HStream + 'a> { fn as_raw_fd(&self) -> RawFd { (&**self).as_raw_fd() } } impl<'a> BoxedHStreamClone for Box<HStream + 'a> { fn boxed_clone(&self) -> Box<HStream> { Box::new((&**self).boxed_clone()) as Box<HStream> } } impl<'a> HStream for Box<HStream + 'a> {} fn main() { let mut list = Arc::new(Mutex::new(LinkedList::<Stream<Box<HStream>>>::new())); } 
+3
source

Source: https://habr.com/ru/post/1265078/


All Articles