Should simple enums derive Copy? Is there any difference in performance? - rust

use std::collections::HashMap;
// #[derive(Copy, Clone)]
enum SomeEnum {
Some1,
Some2,
}
struct SomeStruct {
pub some_enum: SomeEnum,
pub s: String,
}
fn proc_struct(some_struct: &SomeStruct) {
let mut map = HashMap::new();
map.insert(String::from("any"), 0);
match map.get(&some_struct.s) { // just to make a reference in SomeStruct
Some(v) => {
proc1(some_struct.some_enum);
proc2(&some_struct.some_enum);
}
None => {}
}
}
fn proc1(some: SomeEnum) {}
fn proc2(some: &SomeEnum) {}
fn main() {
let some_struct = SomeStruct { some_enum: SomeEnum::Some1, s: String::from("s") };
proc_struct(&some_struct);
}
The above code produces the following error:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:20:19
|
20 | proc1(some_struct.some_enum);
| ^^^^^^^^^^^ cannot move out of borrowed content
When I add #[derive(Copy, Clone)] to SomeEnum, it compiles fine.
Should simple enums like SomeEnum derive the Copy trait?
Is there any difference in performance between functions proc1() and proc2()?

Citing the docs:
Generally speaking, if your type can implement Copy, it should.
Since your SomeEnum has no composite variants (e.g. Vecs or Strings), I recommend making it Copyable. It appears that it is actually smaller than a reference to it:
use std::mem;
enum SomeEnum {
Some1,
Some2,
}
fn main() {
assert_eq!(1, mem::size_of::<SomeEnum>());
assert_eq!(8, mem::size_of::<&SomeEnum>());
}
Though I doubt that in this case you will be able to detect any difference in performance.

Related

Can a Rust enum use methods implemented on one of its variants?

I think I misunderstand the purpose of enums.
I am looking to implement the XML DOM for practice. DOM nodes all have a list of methods associated with them, but some nodes (such as the document node) have additional methods not available on other nodes.
I was hoping to have all the main methods set up on the enum and then the variants would have the methods specific to them, but it seems like the method variants are not callable on an enum, but continue to be callable on the parameter.
#[derive(Clone, Debug, Copy)]
enum MyEnum {
MyType(MyType),
}
impl MyEnum {
pub fn do_a_thing(&self) -> i32 {
// Some code here
return 1;
}
}
#[derive(Clone, Debug, Copy)]
pub struct MyType {}
impl MyType {
pub fn do_another_thing(self) -> i32 {
// Some more code here
return 2;
}
}
fn main() {
let x = MyEnum::MyType(MyType {});
println!("{:?}", x);
println!("I can call do_a_thing, it is {}", x.do_a_thing());
println!(
"Why can't I call do_another_thing? {}",
x.do_another_thing()
);
}
This works fine, but my gut tells me I am going the wrong way about things:
impl MyEnum {
pub fn do_a_thing(&self) -> i32 {
// Some code here
return 1;
}
pub fn do_another_thing(self) -> i32 {
match self {
MyEnum::MyType(MT) => MT.do_another_thing(),
}
}
}
How should I implement this?
You are using an enum, so it's likely you're going to add more variants at some point (otherwise, why would you use enums, right?).
When Rust sees a value whose type is an enum, at compile-time it assumes the value could be any of the enum's variants, so it won't let you call a method on any variant until you check its type.
To do that is easy, as you've already shown in your question:
match self {
MyEnum::MyType(t) => t.do_another_thing()
}
You might be interested to know there's also if let in case you only want to check a single variant:
let x = MyEnum::MyType(MyType{});
if let MyEnum::MyType(t) = x {
t.do_another_thing();
}
You might want to have methods that are callable on ALL variants as well, in which case you'll need to either implement the method directly on the enum as you've done above, or use a trait that is implemented by the enum, which perhaps makes your code look more polymorphic as in most other languages (where there would be an interface for the nodes).
That will make your code in main work.
It might look like this:
#[derive(Clone, Debug, Copy)]
enum MyEnum {
MyType(MyType)
}
impl MyEnum {
pub fn do_a_thing(&self) -> i32{
// Some code here
return 1
}
}
#[derive(Clone, Debug, Copy)]
pub struct MyType {
}
trait MyTrait {
fn do_another_thing(&self) -> i32;
}
impl MyTrait for MyEnum {
fn do_another_thing(&self) -> i32 {
// Some more code here
return 2
}
}
fn main() {
let x = MyEnum::MyType(MyType{});
println!("{:?}",x);
println!("I can call do_a_thing, it is {}", x.do_a_thing());
println!("Why can't I call do_another_thing? {}", x.do_another_thing());
}

How do I enforce immutability for public views of reference-counted types with interior mutability? [duplicate]

I have a struct that has inner mutability.
use std::cell::RefCell;
struct MutableInterior {
hide_me: i32,
vec: Vec<i32>,
}
struct Foo {
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> &Vec<i32> {
&self.interior.borrow().vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
Produces the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32> {
16 | | &self.interior.borrow().vec
17 | | }
| |_____^
The problem is that I can't have a function on Foo that returns a borrowed vec, because the borrowed vec is only valid for the lifetime of the Ref, but the Ref goes out of scope immediately.
I think the Ref must stick around because:
RefCell<T> uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can claim temporary, exclusive, mutable access to the inner value. Borrows for RefCell<T>s are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because RefCell<T> borrows are dynamic it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in task panic.
Now I could instead write a function like this that returns the entire interior:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
However this potentially exposes fields (MutableInterior.hide_me in this example) that are really private implementation details to Foo.
Ideally I just want to expose the vec itself, potentially with a guard to implement the dynamic borrowing behavior. Then callers do not have to find out about hide_me.
Instead of creating a brand new type, you can use Ref::map (since Rust 1.8). This has the same result as Levans' existing answer:
use std::cell::Ref;
impl Foo {
pub fn get_items(&self) -> Ref<'_, Vec<i32>> {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can also use new features like impl Trait to hide the Ref from the API:
use std::cell::Ref;
use std::ops::Deref;
impl Foo {
pub fn get_items(&self) -> impl Deref<Target = Vec<i32>> + '_ {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can create a new struct similar to the Ref<'a,T> guard returned by RefCell::borrow(), in order to wrap this Ref and avoid having it going out of scope, like this:
use std::cell::Ref;
struct FooGuard<'a> {
guard: Ref<'a, MutableInterior>,
}
then, you can implement the Deref trait for it, so that it can be used as if it was a &Vec<i32>:
use std::ops::Deref;
impl<'b> Deref for FooGuard<'b> {
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32> {
&self.guard.vec
}
}
after that, update your get_items() method to return a FooGuard instance:
impl Foo {
pub fn get_items(&self) -> FooGuard {
FooGuard {
guard: self.interior.borrow(),
}
}
}
and Deref does the magic:
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
let v: &Vec<i32> = &items;
}
You can wrap the Vec in an Rc.
use std::cell::RefCell;
use std::rc::Rc;
struct MutableInterior {
hide_me: i32,
vec: Rc<Vec<i32>>,
}
struct Foo {
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> Rc<Vec<i32>> {
self.interior.borrow().vec.clone() // clones the Rc, not the Vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Rc::new(Vec::new()),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
When you need to mutate the Vec, use Rc::make_mut to obtain a mutable reference to the Vec. If there are still other Rcs referring to the Vec, make_mut will dissociate the Rc from the other Rcs, clone the Vec and update itself to refer to that new Vec, then give you a mutable reference to it. This ensures that the value in the other Rcs doesn't suddenly change (because Rc by itself doesn't provide interior mutability).

closure implementing FnMut not working on place where dyn FnMut is expected

use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
fn main() {
let closure_cell = Rc::new(RefCell::new(None));
let closure_cell_clone = Rc::clone(&closure_cell);
*closure_cell.borrow_mut() = Some(Closure::wrap(Box::new(move || {
request_animation_frame(closure_cell_clone.borrow().as_ref().unwrap());
})));
}
fn request_animation_frame(f: &Closure<dyn FnMut()>) {
}
In the above code request_animation_frame expects &Closure<dyn FnMut()>and I pass a closure which implements FnMnut. But I am getting an error
expected type `std::option::Option<wasm_bindgen::closure::Closure<dyn std::ops::FnMut()>>`
found type `std::option::Option<wasm_bindgen::closure::Closure<[closure#src/lib.rs:29:62: 39:6 bucket:_, world:_, closure_cell_clone:_]>>`
Arent FnMut default implemented if a closure can implement that trait? Cant a closure which implements FnMut be sent in place of dyn FnMut ? What am I missing here?
This is actually a pretty sneaky problem. Here's why:
While you can coerce a Box<T> to a Box<dyn Trait> if T: Trait, those two are incompatible types, in that you cannot use a variable or field of the type Box<T> as a Box<dyn Trait>.
Here's an example to show why that could lead to undefined behaviour, using Cell<...>s (where that box would be a field somewhere in Cell<...>)
use std::cell::Cell;
trait SomeTrait { }
#[derive(Clone, Copy)]
pub struct A;
impl SomeTrait for A { }
#[derive(Clone, Copy)]
pub struct B;
impl SomeTrait for B { }
fn use_coerced(cell: &Cell<Box<dyn SomeTrait>>) {
cell.set(Box::new(B)); // valid, since `B` implements `SomeTrait`
}
fn main() {
// I'll put what the type inference will come up with as explicit types here
let some_cell: Cell<Box<A>> = Cell::new(Box::new(A));
use_coerced(&some_cell); // If cells would coerce, this would be valid
let value: Box<A> = some_cell.into_inner(); // But we put `Box<B>` in there. So we'd have undefined behaviour.
}
So to solve that problem, you have to tell the compiler to use the dyn FnMut() type instead of the closure type somewhere. I personally prefer explicitely unsizing it after creating the Box:
fn main() {
let closure_cell = Rc::new(RefCell::new(None));
let closure_cell_clone = Rc::clone(&closure_cell);
*closure_cell.borrow_mut() = Some(Closure::wrap(Box::new(move || {
request_animation_frame(closure_cell_clone.borrow().as_ref().unwrap());
}) as Box<dyn FnMut()>));
}
fn request_animation_frame(f: &Closure<dyn FnMut()>) { }
You can, however, also specify the type of the cell:
fn main() {
let closure_cell: Rc<RefCell<Option<Closure<dyn FnMut()>>>> = Rc::new(RefCell::new(None));
let closure_cell_clone = Rc::clone(&closure_cell);
*closure_cell.borrow_mut() = Some(Closure::wrap(Box::new(move || {
request_animation_frame(closure_cell_clone.borrow().as_ref().unwrap());
})));
}
fn request_animation_frame(f: &Closure<dyn FnMut()>) { }
But that is, as you can see, way more wordy, and unnecessarily so.

How do I pass Rc<RefCell<Box<MyStruct>>> to a function accepting Rc<RefCell<Box<dyn MyTrait>>>?

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.

How do I return a reference to something inside a RefCell without breaking encapsulation?

I have a struct that has inner mutability.
use std::cell::RefCell;
struct MutableInterior {
hide_me: i32,
vec: Vec<i32>,
}
struct Foo {
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> &Vec<i32> {
&self.interior.borrow().vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
Produces the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32> {
16 | | &self.interior.borrow().vec
17 | | }
| |_____^
The problem is that I can't have a function on Foo that returns a borrowed vec, because the borrowed vec is only valid for the lifetime of the Ref, but the Ref goes out of scope immediately.
I think the Ref must stick around because:
RefCell<T> uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can claim temporary, exclusive, mutable access to the inner value. Borrows for RefCell<T>s are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because RefCell<T> borrows are dynamic it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in task panic.
Now I could instead write a function like this that returns the entire interior:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
However this potentially exposes fields (MutableInterior.hide_me in this example) that are really private implementation details to Foo.
Ideally I just want to expose the vec itself, potentially with a guard to implement the dynamic borrowing behavior. Then callers do not have to find out about hide_me.
Instead of creating a brand new type, you can use Ref::map (since Rust 1.8). This has the same result as Levans' existing answer:
use std::cell::Ref;
impl Foo {
pub fn get_items(&self) -> Ref<'_, Vec<i32>> {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can also use new features like impl Trait to hide the Ref from the API:
use std::cell::Ref;
use std::ops::Deref;
impl Foo {
pub fn get_items(&self) -> impl Deref<Target = Vec<i32>> + '_ {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can create a new struct similar to the Ref<'a,T> guard returned by RefCell::borrow(), in order to wrap this Ref and avoid having it going out of scope, like this:
use std::cell::Ref;
struct FooGuard<'a> {
guard: Ref<'a, MutableInterior>,
}
then, you can implement the Deref trait for it, so that it can be used as if it was a &Vec<i32>:
use std::ops::Deref;
impl<'b> Deref for FooGuard<'b> {
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32> {
&self.guard.vec
}
}
after that, update your get_items() method to return a FooGuard instance:
impl Foo {
pub fn get_items(&self) -> FooGuard {
FooGuard {
guard: self.interior.borrow(),
}
}
}
and Deref does the magic:
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
let v: &Vec<i32> = &items;
}
You can wrap the Vec in an Rc.
use std::cell::RefCell;
use std::rc::Rc;
struct MutableInterior {
hide_me: i32,
vec: Rc<Vec<i32>>,
}
struct Foo {
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> Rc<Vec<i32>> {
self.interior.borrow().vec.clone() // clones the Rc, not the Vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Rc::new(Vec::new()),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
When you need to mutate the Vec, use Rc::make_mut to obtain a mutable reference to the Vec. If there are still other Rcs referring to the Vec, make_mut will dissociate the Rc from the other Rcs, clone the Vec and update itself to refer to that new Vec, then give you a mutable reference to it. This ensures that the value in the other Rcs doesn't suddenly change (because Rc by itself doesn't provide interior mutability).

Resources