What is the proper way to store a reference in a struct and operate on it given this example:
// Trait that cannot be changed
pub trait FooTrait {
pub fn open(&self, client: &SomeType);
pub fn close(&self);
}
pub struct Foo {
// HOW TO STORE IT HERE???
// client: &SomeType,
}
impl FooTrait for Foo {
pub fn open(&self, client: &SomeType) {
// HOW TO SAVE IT HERE?
// NOTE that &self cannot be changed into &mut self because the trait cannot be modified
// smth like self.client = client;
}
pub fn close(&self) {
// HOW TO DELETE IT HERE?
// NOTE that &self cannot be changed into &mut self because the trait cannot be modified
}
}
Is there a design pattern that could fit to my snippet?
This is horribly complicated on its surface because of lifetime issues. Rust is designed to guarantee memory safety, but this pattern creates an untenable situation where the caller of FooTrait::open() needs some way to tell Rust that the client borrow will outlive *self. If it can't do that, Rust will disallow the method call. Actually making this work with references is probably not feasible, as Foo needs a lifetime parameter, but the code that creates the Foo may not know the appropriate lifetime parameter.
You can make this pattern work by combining a few things, but only if you can modify the trait. If you can't change the definition of the trait, then what you are asking is impossible.
You need an Option so that close can clear the value.
You need interior mutability (a Cell) to allow mutating self.client even if self is a shared reference.
You need something other than a bare reference. An owned value or a shared ownership type like Rc or Arc, for example. These types sidestep the lifetime issue entirely. You can make the code generic over Borrow<T> to support them all at once.
use std::cell::Cell;
use std::borrow::Borrow;
pub trait FooTrait {
fn open(&self, client: impl Borrow<SomeType> + 'static);
fn close(&self);
}
pub struct SomeType;
pub struct Foo {
client: Cell<Option<Box<dyn Borrow<SomeType>>>>,
}
impl FooTrait for Foo {
fn open(&self, client: impl Borrow<SomeType> + 'static) {
self.client.set(Some(Box::new(client)));
}
fn close(&self) {
self.client.set(None);
}
}
Related
I've got this code snippet (playground):
struct TeddyBear {
fluffiness: u8,
}
trait Scruffy {
fn scruff_up(self: &mut Box<Self>) -> Box<dyn Scruffy>;
}
impl Scruffy for TeddyBear {
fn scruff_up(self: &mut Box<Self>) -> Box<dyn Scruffy> {
// do something about the TeddyBear's fluffiness
}
}
It doesn't compile. The error is:
the trait Scruffy cannot be made into an object
, along with the hint:
because method scruff_up's self parameter cannot be dispatched on.
I checked the "E0038" error description, but I haven't been able to figure out which category my error falls into.
I also read the "object-safety" entry in "The Rust Reference", and I believe this matches the "All associated functions must either be dispatchable from a trait object", but I'm not sure, partly because I'm not sure what "receiver" means in that context.
Can you please clarify for me what's the problem with this code and why it doesn't work?
The problem is when you pass it in as a reference, because the inner type may not be well-sized (e.g. a trait object, like if you passed in a Box<Fluffy>) the compiler doesn't have enough information to figure out how to call methods on it. If you restrict it to sized objects (like your TeddyBear) it should compile
trait Scruffy {
fn scruff_up(self: &mut Box<Self>) -> Box<dyn Scruffy> where Self: Sized;
}
A receiver is the self (&self, &mut self, self: &mut Box<Self> and so on).
Note that the list you cited from the reference lists both Box<Self> and &mut Self, but does not list &mut Box<Self> nor it says that combinations of these types are allowed.
This is, indeed, forbidden. As for the why, it is a little more complex.
In order for a type to be a valid receiver, it needs to hold the following condition:
Given any type Self that implements Trait and the receiver type Receiver, the receiver type should implement DispatchFromDyn<dyn Trait> for itself with all Self occurrences of Self replaced with dyn Trait.
For instance:
&self (has the type &Self) has to implement DispatchFromDyn<&dyn Trait>, which it does.
Box<Self> has to implement DispatchFromDyn<Box<dyn Trait>>, which it does.
But in order for &mut Box<Self> to be an object-safe receiver, it would need to impl DispatchFromDyn<&mut Box<dyn Trait>>. What you want is kind of blanket implementation DispatchFromDyn<&mut T> for &mut U where U: DispatchFromDyn<T>.
This impl will never exist. Because it is unsound (even ignoring coherence problems).
As explained in the code in rustc that calculates this:
The only case where the receiver is not dispatchable, but is still a valid receiver type (just not object-safe), is when there is more than one level of pointer indirection. E.g., self: &&Self, self: &Rc<Self>, self: Box<Box<Self>>. In these cases, there is no way, or at least no inexpensive way, to coerce the receiver from the version where Self = dyn Trait to the version where Self = T, where T is the unknown erased type contained by the trait object, because the object that needs to be coerced is behind a pointer.
The problem is inherent to how Rust handles dyn Trait.
dyn Trait is a fat pointer: it is actually two words sized. One is a pointer to the data, and the other is a pointer to the vtable.
When you call a method on dyn Trait, the compiler looks up in the vtable, find the method for the concrete type (which is unknown at compilation time, but known at runtime), and calls it.
This all may be very abstract without an example:
trait Trait {
fn foo(&self);
}
impl Trait for () {
fn foo(&self) {}
}
fn call_foo(v: &dyn Trait) {
v.foo();
}
fn create_dyn_trait(v: &impl Trait) {
let v: &dyn Trait = v;
call_foo(v);
}
The compiler generates code like:
trait Trait {
fn foo(&self);
}
impl Trait for () {
fn foo(&self) {}
}
struct TraitVTable {
foo: fn(*const ()),
}
static TRAIT_FOR_UNIT_VTABLE: TraitVTable = TraitVTable {
foo: unsafe { std::mem::transmute(<() as Trait>::foo) },
};
type DynTraitRef = (*const (), &'static TraitVTable);
impl Trait for dyn Trait {
fn foo(self: DynTraitRef) {
(self.1.foo)(self.0)
}
}
fn call_foo(v: DynTraitRef) {
v.foo();
}
fn create_dyn_trait(v: &impl Trait) {
let v: DynTraitRef = (v as *const (), &TRAIT_FOR_UNIT_VTABLE);
call_foo(v);
}
Now suppose that the pointer to the value is behind an indirection. I'll use Box<&self> because it's simple but demonstrates the concept best, but the concept applies to &mut Box<Self> too: they have the same layout. How will we write foo() for impl Trait for dyn Trait?
trait Trait {
fn foo(self: Box<&Self>);
}
impl Trait for () {
fn foo(self: Box<&Self>) {}
}
struct TraitVTable {
foo: fn(Box<*const ()>),
}
static TRAIT_FOR_UNIT_VTABLE: TraitVTable = TraitVTable {
foo: unsafe { std::mem::transmute(<() as Trait>::foo) },
};
type DynTraitRef = (*const (), &'static TraitVTable);
impl Trait for dyn Trait {
fn foo(self: Box<DynTraitRef>) {
let concrete_foo: fn(Box<*const ()>) = self.1.foo;
let data: *const () = self.0;
concrete_foo(data) // We need to wrap `data` in `Box`! Error.
}
}
You may think "then the compiler should just insert a call to Box::new()!" But besides Box not being the only one here (what with Rc, for example?) and we will need some trait to abstract over this behavior, Rust never performs any hard work implicitly. This is a design choice, and an important one (as opposed to e.g. C++, where an innocent-looking statement like auto v1 = v; can allocate and copy 10GB by a copy constructor). Converting a type to dyn Trait and back is done implicitly: the first one by a coercion, the second one when you call a method of the trait. Thus, the only thing that Rust does for that is attaching a VTable pointer in the first case, or discarding it in the second case. Even allowing only references (&&&Self, no need to call a method, just take the address of a temporary) exceeds that. And it can have severe implications in unexpected places, e.g. register allocation.
So, what to do? You can take &mut self or self: Box<Self>. Which one to choose depends on whether you need ownership (use Box) or not (use a reference). And anyway, &mut Box<Self> is not so useful (its only advantage over &mut T is that you can replace the box and not just its contents, but when you do that that's usually a mistake).
I am looking for a way to ensure a struct outlives the parameter given to a method of that struct.
Even if the struct doesn't hold a reference to that data after leaving the method.
This is for wrapped raw pointers fed to an FFI. I want to guarantee that the struct implementing the FFI outlives the Option<&'a Any> I use to feed the Rust object to the pointer wrapper.
Context is the FFI wrapper.
Data holds different types that map to FFI types. The FFI functions copies all these types immediately before returning.
Except raw pointers.
So I add a lifetime specifier to Context just for those and use that in send_data().
But somehow this is not enough. I expected below code to not compile.
Edit: someone one the Rust Discord suggested making &self mutable in send_data(). This has the desired effect but my FFI is thread safe (and stateless) and send_data() is time critical. So I would very much like to avoid this.
use std::any::Any;
use std::marker::PhantomData;
struct IntegerArray<'a> {
data: &'a [i32],
}
struct WrappedRawPointer<'a> {
ptr: *const std::ffi::c_void,
_marker: PhantomData<&'a ()>,
}
impl<'a> WrappedRawPointer<'a> {
fn new(data: Option<&'a dyn Any>) -> Self {
Self {
ptr: data
.map(|p| p as *const _ as *const std::ffi::c_void)
.unwrap_or(std::ptr::null()),
_marker: PhantomData,
}
}
}
enum Data<'a, 'b> {
IntegerArray(IntegerArray<'a>),
WrappedRawPointer(WrappedRawPointer<'b>),
}
struct Context<'a> {
ctx: u32,
_marker: PhantomData<&'a ()>,
}
impl<'a> Context<'a> {
fn new() -> Self {
Self {
ctx: 0, // Call FFI to initialize context
_marker: PhantomData,
}
}
fn send_data(&self, data: Data<'_, 'a>) {
match data {
Data::IntegerArray(_i) => (), // Call FFI function
Data::WrappedRawPointer(_p) => (), // Call FFI function
}
}
}
fn main() {
let ctx = Context::new();
{
let some_float: f32 = 42.0;
ctx.send_data(
Data::WrappedRawPointer(
WrappedRawPointer::new(
Some(&some_float)
)
)
);
// I would like rustc to complain
// here that some_float does not
// outlive ctx
}
// Explicitly drop outside
// the previous block to
// prevent rustc from being
// clever
drop(ctx);
}
Making send_data take &mut self instead of &self works because it makes the type of the self parameter invariant with respect to the type Self. Subtyping and Variance is described in the Rustonomicon, as well as other questions here on Stack Overflow (see below).
Since you want invariance even when self is an immutable reference, that suggests that the variance of Context<'a> itself is wrong: it is covariant in 'a, but it should be invariant. You can fix this by changing the type argument to PhantomData to something that is also invariant in 'a:
struct Context<'a> {
ctx: u32,
_marker: PhantomData<*mut &'a ()>, // or Cell<&'a ()>, or fn(&'a ()) -> &'a (), etc.
}
PhantomData is not just something you add mechanically to make the compiler not yell at you. The specific form of the type argument to PhantomData tells the compiler how your struct is related to its type and lifetime parameters (when the compiler can't figure it out by itself). In this case you want to tell the compiler that a Context<'some_long_lifetime> can't be substituted for a Context<'a_much_shorter_lifetime> even though its fields would all allow that substitution.
Some more questions on variance
How can this instance seemingly outlive its own parameter lifetime?
Why does linking lifetimes matter only with mutable references?
How do I share a struct containing a phantom pointer among threads? (may be relevant if Context should be Send or Sync)
I'm trying to implement a command line server application in Rust.
I'd like to have a list (or hash table) of commands that I can iterate over for printing usage and looking up/executing commands.
My problem is that each Command needs mutable references to the thing the command uses to execute (such as inserting a user into a database or something). The borrow checker obviously doesn't like passing multiple mutable references around. Is there a way to do this? I started by having the execute method take in a reference to the things it needed but then I need a separate list for commands that need different things which sounds like it would get unwieldy.
Here's an example of the problem:
struct SomeStruct {
pub some_field: String,
}
impl SomeStruct {
pub fn new(field: String) -> SomeStruct {
let some_struct = SomeStruct {
some_field: field,
};
return some_struct;
}
pub fn change_field(&mut self) {
self.some_field = "Something else".to_string();
}
}
struct SomeCommand<'a> {
pub some_struct: &'a mut SomeStruct,
}
impl<'a> SomeCommand<'a> {
pub fn new(the_struct: &'a mut SomeStruct) -> SomeCommand {
let some_command = SomeCommand {
some_struct: the_struct,
};
return some_command;
}
pub fn execute(&mut self) {
self.some_struct.change_field();
}
}
fn main() {
let mut some_struct = SomeStruct::new("hey".to_string());
let some_command1 = SomeCommand::new(&mut some_struct);
// Compiler complains because I'm making another mutable binding to some_struct
let some_command2 = SomeCommand::new(&mut some_struct);
}
Is there a better way to do this?
I was trying to do the same in Rust, following examples in book Design Patterns. The problem here is that we need to maintain the generic interface of the Command trait, which means we should not design the trait such that it takes specific objects of certain types. The only solution we are left with is to store a mutable reference to the object itself within the concrete instance of object that implements Command trait. However, if we use &'a mut ..., Rust compiler will not like multiple mutable references to a single object, which means we can only ever have one Command instance for any given object we want to execute the command on, and we can only call execute once.
This can be achieved by using RefCell or Arc<Mutex<>>. I have implemented both and they both work very well. The difference is that RefCell is not thread-safe, so you cannot share the same Command object across threads if you choose to implement it in this way; whereas Arc<Mutex<>> is thread-safe.
Below is my implementation:
trait Command {
fn execute(&mut self); // Execute command.
fn is_reversible(&self) -> bool; // Undoable operation?
fn unexecute(&mut self); // Undo command.
}
// ------ Using RefCell ------
struct ChangeFontSizeCommand<'a> {
text: &'a RefCell<dyn Text>,
old_size: Option<usize>,
new_size: usize
}
impl<'a> Command for ChangeFontSizeCommand<'a> {
// Implementation... (many calls to .borrow() and .borrow_mut())
}
impl<'a> ChangeFontSizeCommand<'a> {
pub fn new(text: &'a RefCell<dyn Text>, new_size: usize) -> Self {
// Implementation...
}
}
// ------ Using Arc and Mutex ------
struct ChangeFontColorCommand {
text: Arc<Mutex<dyn Text>>,
old_color: Option<Color>,
new_color: Color
}
impl Command for ChangeFontColorCommand {
// Implementation... (many calls to .lock().unwrap())
}
impl ChangeFontColorCommand {
pub fn new(text: Arc<Mutex<dyn Text>>, new_color: Color) -> Self {
// Implementation...
}
}
Notice that in both examples, instance of RefCell or Arc<Mutex<>> has to be created outside of object initializer, we cannot pass in a mutable reference and create them inside of the command implementation struct, that would violate Rust's borrow checker rules.
I think passing the mutable reference as a parameter of execute() instead of storing it within SomeCommand is the way to go. Don't keep references living longer than they need to live.
But this is a fairly broad question: I can think of a dozen possible solutions -- it's hard to tell what's best in your case, since your example is pretty generic. Maybe we could be more specific after you told us a little more (maybe a small subset of features you want to implement).
Just looking at the title of your post: docopt is used by many Rust project -- AFAIK even cargo uses it. However, I suspect it doesn't help you with your main design problem.
Besides: in your new methods you can delete some code thanks to implicit returns. This:
pub fn new(field: String) -> SomeStruct {
let some_struct = SomeStruct {
some_field: field,
};
return some_struct;
}
... becomes this:
pub fn new(field: String) -> SomeStruct {
SomeStruct {
some_field: field,
}
}
I'm fighting with lifetimes again. Or actually, I kinda won the fight but I'm not sure if the outcome is the intended way to handle it.
Say I have a struct with two lifetimes: Inner<'a, 'b>. Now I want to write a trait that defines a new(inner: &Inner) -> Self method. The implementer should be free to store the reference to Inner internally and define other methods to work on it.
I came up with this (it works!) but I have a couple of questions
struct Inner<'a, 'b>{
foo: &'a str,
bar: &'b str
}
trait Worker<'data, 'a, 'b> {
fn new (inner: &'data Inner<'a, 'b>) -> Self;
fn work_with_inner () { println!("works on inner");}
}
struct SomeWorker<'inner, 'a:'inner, 'b:'inner> {
inner: &'inner Inner<'a, 'b>
}
impl<'data, 'a, 'b> Worker<'data, 'a, 'b> for SomeWorker<'data, 'a, 'b> {
fn new (inner: &'data Inner<'a, 'b>) -> Self {
SomeWorker {
inner: inner
}
}
}
fn main () {
}
Playpen: http://is.gd/A3ol4w
in terms of lifetimes, can this be simplified? In particular, I was wondering if the trait really needs to define all those lifetimes or if there's a way to only define them on the struct?
if there's no way to omit the lifetimes on the trait does that mean it's a best practice to specify all possible lifetimes on a trait to have the most flexibility for the implementer? I mean, if the SomeWorker struct would not want to store the reference to Inner, the whole thing, including the trait, could be much simpler.
See, no lifetimes at all.
struct Inner<'a, 'b>{
foo: &'a str,
bar: &'b str
}
trait Worker {
fn new (inner: &Inner) -> Self;
fn work_with_inner () { println!("works on inner");}
}
struct SomeWorker;
impl Worker for SomeWorker {
fn new (inner: &Inner) -> Self {
SomeWorker
}
}
fn main () {
}
Playpen: http://is.gd/NzigjX
This is why I'm asking myself if as a trait author I should assume that all methods that take references may end up being stored on a field by the trait implementer and therefore I need to specify all the lifetimes on the trait to make that possible for implementors.
There is no one-size-fits-all solution. As a trait author, you have to think about what you are attempting to do and what you want to achieve.
If you want the ability to correlate a values lifetime with the lifetime parameters of a struct, then you must put the lifetime on the trait. This would generally be done because your trait has multiple methods that are expected to operate on the same value with lifetimes. This might something like a getter / setter pair. In some code I have written, I'm passing in &str references that I hold onto for a while before "finalizing" them. If you need to store the reference for any reason, then you will need to have lifetimes on the trait.
In your case, you have a constructor method that needs to know of the lifetimes if the struct does. You can separate that function from the rest of the trait, if it's truly distinct. In your example, the work_with_inner method doesn't accept a self argument, so that would be very distinct. If you used self but didn't need to interact with the lifetimes from Inner, it can still help:
trait WorkerBuilder<'a, 'b> {
fn new(inner: Inner<'a, 'b>) -> Self;
}
trait Worker {
fn do_work(&self);
}
#[derive(Debug)]
struct Inner<'a, 'b>{
foo: &'a str,
bar: &'b str,
}
// This does track `Inner`
#[derive(Debug)]
struct SomeWorker<'a, 'b>(Inner<'a, 'b>);
impl<'a, 'b> WorkerBuilder<'a, 'b> for SomeWorker<'a, 'b> {
fn new(inner: Inner<'a, 'b>) -> SomeWorker<'a, 'b> {
SomeWorker(inner)
}
}
impl<'a, 'b> Worker for SomeWorker<'a, 'b> {
fn do_work(&self) { println!("Doing work, {:?}", self.0) }
}
// This doesn't track `Inner`
#[derive(Debug)]
struct DumbWorker;
impl<'a, 'b> WorkerBuilder<'a, 'b> for DumbWorker {
fn new(inner: Inner<'a, 'b>) -> DumbWorker {
DumbWorker
}
}
fn main () {}
You'll see I also applied one thing that you can do to reduce the number of lifetimes. If you have a struct that is just references (or references and other small Copy types), there is no need to pass a reference to that struct. References are copyable, and tracking the lifetime of the containing struct isn't useful.
Editorial — I don't feel like "constructor" methods are generally useful in a trait. You often want to provide a different set or parameters, which is why you have different types in the first place. Perhaps your real code is using something other than a constructor in the trait though.
I have originally asked this question here, but it was marked as duplicate, although it duplicates only a part of it in my opinion, so I have created a more specific one:
Consider the following code:
use std::rc::Rc;
trait MyTrait {
fn trait_func(&self);
}
struct MyStruct1;
impl MyStruct1 {
fn my_fn(&self) {
// do something
}
}
impl MyTrait for MyStruct1 {
fn trait_func(&self) {
// do something
}
}
fn my_trait_fn(t: Rc<dyn MyTrait>) {
t.trait_func();
}
fn main() {
let my_str: Rc<MyStruct1> = Rc::new(MyStruct1);
my_trait_fn(my_str.clone());
my_str.my_fn();
}
This code works fine. Now I want to change the definition of trait_func to accept a &mut self, but it won't work as Rc works with immutable data only. The solution I use is to wrap MyTrait into RefCell:
use std::cell::RefCell;
fn my_trait_fn(t: Rc<RefCell<Box<dyn MyTrait>>>) {
t.borrow_mut().trait_func();
}
fn main() {
let my_str: Rc<RefCell<Box<MyStruct1>>> = Rc::new(RefCell::new(Box::new(MyStruct1)));
my_trait_fn(my_str.clone());
my_str.my_fn();
}
When I compile it I get an error:
error[E0308]: mismatched types
--> src/main.rs:27:17
|
27 | my_trait_fn(my_str.clone());
| ^^^^^^^^^^^^^^ expected trait MyTrait, found struct `MyStruct1`
|
= note: expected type `std::rc::Rc<std::cell::RefCell<std::boxed::Box<dyn MyTrait + 'static>>>`
found type `std::rc::Rc<std::cell::RefCell<std::boxed::Box<MyStruct1>>>`
= help: here are some functions which might fulfill your needs:
- .into_inner()
What's the best way to go around this problem?
(An older revision of this answer essentially advised to clone the underlying struct and put it in a new Rc<RefCell<Box<MyTrait>> object; this was necessary at the time on stable Rust, but since not long after that time, Rc<RefCell<MyStruct>> will coerce to Rc<RefCell<MyTrait>> without trouble.)
Drop the Box<> wrapping, and you can coerce Rc<RefCell<MyStruct>> to Rc<RefCell<MyTrait>> freely and easily. Recalling that cloning an Rc<T> just produces another Rc<T>, increasing the refcount by one, you can do something like this:
use std::rc::Rc;
use std::cell::RefCell;
trait MyTrait {
fn trait_func(&self);
}
#[derive(Clone)]
struct MyStruct1;
impl MyStruct1 {
fn my_fn(&self) {
// do something
}
}
impl MyTrait for MyStruct1 {
fn trait_func(&self) {
// do something
}
}
fn my_trait_fn(t: Rc<RefCell<MyTrait>>) {
t.borrow_mut().trait_func();
}
fn main() {
// (The type annotation is not necessary here, but helps explain it.
// If the `my_str.borrow().my_fn()` line was missing, it would actually
// be of type Rc<RefCell<MyTrait>> instead of Rc<RefCell<MyStruct1>>,
// essentially doing the coercion one step earlier.)
let my_str: Rc<RefCell<MyStruct1>> = Rc::new(RefCell::new(MyStruct1));
my_trait_fn(my_str.clone());
my_str.borrow().my_fn();
}
As a general rule, see if you can make things take the contained value by reference, ideally even generically—fn my_trait_fn<T: MyTrait>(t: &T) and similar, which can typically be called as my_str.borrow() with automatic referencing and dereferencing taking care of the rest—rather than the whole Rc<RefCell<MyTrait>> thing.