How do I downgrade an Rc<RefCell<T>> into a Weak<T>? - rust

After adding a RefCell to the inside struct, I don't know how to have a reference to only the Rc value.
In other words, I'm creating an Rc<RefCell<T>> but I only need the Rc<T> to be able to downgrade into a Weak.
use std::{
cell::RefCell,
fmt,
rc::{Rc, Weak},
};
#[derive(Debug)]
struct Field {
i: u8,
y: u8,
}
impl Field {
pub fn new() -> Self {
Self { i: 8, y: 6 }
}
}
#[derive(Debug)]
pub struct Parent {
field_1: Field,
child: RefCell<Option<Child>>,
}
impl Parent {
pub fn new() -> Rc<RefCell<Self>> {
let n = Rc::new(RefCell::new(Self {
field_1: Field::new(),
child: RefCell::new(None),
}));
*n.borrow_mut().child.borrow_mut() = Some(Child::new(&n));
n
}
pub fn modify(&mut self) {
self.field_1.i = 9;
}
pub fn to_string(&self) -> String {
format!(
"{:?} {}",
self.field_1,
self.child.borrow().as_ref().unwrap()
)
}
}
#[derive(Debug)]
pub struct Child {
parent: Weak<Parent>,
field_2: Field,
}
impl Child {
pub fn new(parent: &Rc<Parent>) -> Self {
Self {
parent: Rc::downgrade(parent),
field_2: Field::new(),
}
}
}
impl fmt::Display for Child {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.parent.upgrade().unwrap().field_1.i == 1 {
write!(f, "set: {:?}", self.field_2)
} else {
write!(f, "not set {:?}", self.field_2)
}
}
}
fn main() {
let mut parent = Parent::new();
parent.borrow_mut().modify();
println!("{}", parent.borrow().to_string());
}
Error:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:32:62
|
32 | *n.borrow_mut().child.borrow_mut() = Some(Child::new(&n));
| ^^ expected struct `Parent`, found struct `std::cell::RefCell`
|
= note: expected reference `&std::rc::Rc<Parent>`
found reference `&std::rc::Rc<std::cell::RefCell<Parent>>`
I realize that the data structure itself might be the problem, but I currently can't think of a improvement.

Related

Cannot return reference to temporary value with RwLock and iterators

I haven't found an answer to this in other questions.
I have reduced my problem to the following:
use std::sync::RwLock;
pub fn main() {
iter_lock().for_each(|v| {
println!("{}", v);
});
}
fn get_lock<'a>() -> &'a RwLock<Vec<u32>> {
static mut lock: RwLock<Vec<u32>> = RwLock::new(Vec::new());
unsafe { &lock }
}
fn iter_lock<'a>() -> impl std::iter::Iterator<Item = &'a u32> {
get_lock().read().unwrap().iter()
}
playground
The code above will not compile and give the following error:
error[E0515]: cannot return reference to temporary value
--> src/main.rs:15:5
|
15 | get_lock().read().unwrap().iter()
| --------------------------^^^^^^^
| |
| returns a reference to data owned by the current function
| temporary value created here
|
= help: use `.collect()` to allocate the iterator
Note that the static mut is not necessary in the code above, but I need it because I need to define a variable inside of an impl block.
I need to return an iterator, not a Vec because I am trying to avoid any allocations, and this function will always be used to iterate.
How can I solve this issue? I'm not afraid of using unsafe code, so unsafe suggestions are also welcome.
You can try something like this:
use std::sync::{RwLock, RwLockReadGuard};
pub fn main() {
let data = Data::new(&[1, 2, 3]);
data.iter().for_each(|x| println!("{:?}", x));
}
struct Data {
inner: RwLock<Vec<u32>>,
}
impl Data {
fn new(vec: &[u32]) -> Self {
Self {
inner: RwLock::new(vec.to_vec()),
}
}
fn iter(&self) -> Iter<'_> {
let d = self.inner.read().unwrap();
Iter::new(d)
}
}
struct Iter<'a> {
inner: RwLockReadGuard<'a, Vec<u32>>,
current_index: usize,
}
impl<'a> Iter<'a> {
pub fn new(inner: RwLockReadGuard<'a, Vec<u32>>) -> Iter<'a> {
Self {
inner,
current_index: 0,
}
}
}
impl Iterator for Iter<'_> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.current_index >= self.inner.len() {
return None;
}
let item = &self.inner[self.current_index];
self.current_index += 1;
Some(*item)
}
}

Heterogeneous collection as a member of a class in Rust

I am new to Rust, and does not fully understand lifetime, so probably, that is why I can't solv the following issue. I need a solution in which a class has a heterogeneous HashMap containing different objects derived from the same trait.
I have to be able to extend an object with some (multiple) functionality dinamically. Other solutions are also welcome. Adding functionality to the class in compile time could also work, but adding functionality directly to the main class not.
use std::collections::HashMap;
trait DoerTrait {
fn do_something( & self, a : u8, b : u8 ) -> u8;
}
struct MyDoer<'a> {
}
impl DoerTrait for MyDoer<'a> {
fn do_something( & self, a : u8, b : u8 ) -> u8 {
return a + b;
}
}
struct MyMain<'a> {
doers : HashMap<u8,&'a dyn DoerTrait>,
}
impl<'a> MyMain<'a> {
fn new() -> Self {
Self {
doers : HashMap::new()
}
}
fn add_doer( &mut self, id : u8, doer : & dyn DoerTrait ) {
self.doers.insert( id, doer );
}
fn do_something( & self, id : u8 ) {
match self.doers.get( &id ) {
Some( doer ) => {
println!( "{}", doer(19,26) );
}
None => {
println!( "Doer not specified!" );
}
}
}
}
fn main() {
let mut mymain = MyMain::new();
let mydoer = MyDoer{};
mymain.add_doer( 42, &mydoer );
mymain.do_something( 42 );
}
Not too sure what issue you have, once MyDoer has been stripped of its incorrect (unnecessary) lifetime and the lifetime has correctly been declared on impl MyMain, the compiler directly points to the parameter of add_doer not matching (after which it points out that doer in do_something is not a function):
use std::collections::HashMap;
trait DoerTrait {
fn do_something(&self, a: u8, b: u8) -> u8;
}
struct MyDoer;
impl DoerTrait for MyDoer {
fn do_something(&self, a: u8, b: u8) -> u8 {
return a + b;
}
}
struct MyMain<'a> {
doers: HashMap<u8, &'a dyn DoerTrait>,
}
impl<'a> MyMain<'a> {
fn new() -> Self {
Self {
doers: HashMap::new(),
}
}
fn add_doer(&mut self, id: u8, doer: &'a dyn DoerTrait) {
self.doers.insert(id, doer);
}
fn do_something(&self, id: u8) {
match self.doers.get(&id) {
Some(doer) => {
println!("{}", doer.do_something(19, 26));
}
None => {
println!("Doer not specified!");
}
}
}
}
fn main() {
let mut mymain = MyMain::new();
let mydoer = MyDoer {};
mymain.add_doer(42, &mydoer);
mymain.do_something(42);
}

Value referencing data owned by the current function

Here's my code:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
impl Default for AnotherThing {
fn default() -> Self {
Self {
val: 2,
}
}
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
another: &AnotherThing::default(),
}
}
}
fn main() {
let _ = Something::new(1);
}
It doesn't compile because:
Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:24:9
|
24 | / Self {
25 | | val,
26 | | another: &AnotherThing::default(),
| | ----------------------- temporary value created here
27 | | }
| |_________^ returns a value referencing data owned by the current function
I understand the problem but I don't know how to fix it. If it's not possible to use the Default trait for this case, how can I deal with the function ownership. Below a simpler example:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
let at = AnotherThing { val : 2 };
Self {
val,
another: &at,
}
}
}
fn main() {
let _ = Something::new(1);
}
If I had another: &AnotherThing { val : 2 } instead of another: &at it would work. If I want the another attribute to be a reference and get the value from a function, how can I do it?
You can do like this
#[derive(Default)]
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
impl<'a> Default for &'a AnotherThing {
fn default() -> &'a AnotherThing {
&AnotherThing {
val: 3,
}
}
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
..Default::default()
}
}
}
Another option is to create a const item, of which you can create a reference with 'static lifetime, thus binding to any 'a:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
const ANOTHER_THING_DEFAULT: AnotherThing = AnotherThing { val: 3 };
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
another: &ANOTHER_THING_DEFAULT,
}
}
}

Return TypeId of Self from a default trait method

I am implementing my own blocking pub/sub pattern as seen below.
use std::any::{Any, TypeId};
#[derive(Clone)]
struct ModelA {
pub id: u32
}
#[derive(Clone)]
struct ModelB {
pub id: u32
}
struct ModelASubscriberOne<'a> {
pub model: &'a ModelA
}
impl<'a> Subscriber<u32> for ModelASubscriberOne<'a> {
fn get_type(&self) -> TypeId {
TypeId::of::<ModelASubscriberOne>()
}
fn execute(&self) {
println!("SubscriberOne ModelA id: {}", self.model.id);
}
fn id(&self) -> u32 {
self.model.id
}
}
struct ModelASubscriberTwo<'a> {
pub model: &'a ModelA
}
impl<'a> Subscriber<u32> for ModelASubscriberTwo<'a> {
fn get_type(&self) -> TypeId {
TypeId::of::<ModelASubscriberTwo>()
}
fn execute(&self) {
println!("SubscriberTwo ModelA id: {}", self.model.id);
}
fn id(&self) -> u32 {
self.model.id
}
}
trait Subscriber<TKey:Eq + 'static> {
fn get_type(&self) -> TypeId;
fn execute(&self);
fn id(&self) -> TKey;
fn filter(&self, other: TKey) -> bool{
self.id() == other
}
}
struct Publisher<'a> {
pub subscribers: Vec<&'a dyn Subscriber<u32>>
}
impl<'a> Publisher<'a> {
fn new() -> Publisher<'a> {
Publisher{subscribers: Vec::new()}
}
fn subscribe(&mut self, subscriber: &'a dyn Subscriber<u32>) {
self.subscribers.push(subscriber);
}
fn publish<T>(&self) where T: 'static + Subscriber<u32> {
self.subscribers.iter().filter(|x| {
TypeId::of::<T>() == x.get_type()
})
.for_each(|x| {
x.execute();
});
}
fn unsubscribe<T:Any>(&mut self, subscriber: u32) {
let position = self.subscribers.iter().position(|x| {
TypeId::of::<T>() == x.get_type() && x.filter(subscriber)
});
match position {
Some(position) => {
self.subscribers.remove(position);
},
_ => {}
}
}
}
fn main() {
let model_a = ModelA{id:0};
let mut model_a_list: Vec<ModelA> = Vec::new();
model_a_list.push(model_a);
let model_a = ModelA{id:1};
model_a_list.push(model_a);
let mut publisher = Publisher::new();
let subscriber = ModelASubscriberOne{model: &model_a_list[0]};
publisher.subscribe(&subscriber);
let subscriber = ModelASubscriberOne{model: &model_a_list[1]};
publisher.subscribe(&subscriber);
let subscriber = ModelASubscriberTwo{model: &model_a_list[1]};
publisher.subscribe(&subscriber);
println!("Subscribed");
publisher.publish::<ModelASubscriberOne>();
publisher.publish::<ModelASubscriberTwo>();
publisher.unsubscribe::<ModelASubscriberOne>(model_a_list[1].id);
println!("Unsubscribed");
publisher.publish::<ModelASubscriberOne>();
publisher.publish::<ModelASubscriberTwo>();
}
I feel like it would be helpful to be able to have a default implementation of get_type() for Subscriber that returns a TypeId for Self. Is there a way to do this?
I tried the following:
trait Subscriber<TKey:Eq + 'static> {
fn get_type(self: &Self) -> TypeId {
TypeId::of::<Self>()
}
// <...>
}
I get the following message:
error[E0310]: the parameter type `Self` may not live long enough
--> src\main.rs:51:5
|
51 | TypeId::of::<Self>()
| ^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `Self: 'static`...
= note: ...so that the type `Self` will meet its required lifetime bounds
I am not sure where to put the lifetime bound. I expect I need an Any trait bound as well but I am not sure where to put that either.
Thanks in advance.

Nested struct with reference

I have some nested structs and cannot create a back reference to the parent struct. An example:
struct Foo<'a> {
parent: &'a Bar<'a>,
}
impl<'a> Foo<'a> {
fn new(parent: &'a Bar) -> Self {
Foo { parent: parent }
}
fn hello_world(&self) -> String {
self.parent.hello().to_owned() + " world"
}
}
struct Bar<'b> {
child: Option<Foo<'b>>,
data: &'static str,
}
impl<'b> Bar<'b> {
fn new() -> Self {
Bar {
child: None,
data: "hello",
}
}
fn hello(&self) -> &str {
self.data
}
fn get_foo(&self) -> Option<&Foo> {
self.child.as_ref()
}
}
fn main() {
let bar = Bar::new();
assert_eq!("hello", bar.hello());
match bar.get_foo() {
Some(foo) => assert_eq!("hello world", foo.hello_world()),
None => (),
}
}
How can I replace None with Some<Foo> with a reference to Bar? So far I'm not sure that it is possible.
It's not exactly a drop-in solution for your example, but I believe you can create "circular references" as you specify using Arc and RwLock. The API is not exactly the same (e.g., parent is an optional field), I renamed some objects, and it is definitely more verbose, but your tests pass!
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
struct Child {
parent: Option<Arc<RwLock<Parent>>>
}
impl Child {
fn new() -> Self {
Child {
parent: None
}
}
fn hello_world(&self) -> String {
let x = self.parent.as_ref().unwrap().clone();
let y = x.read().unwrap();
y.hello().to_owned() + " world"
}
}
#[derive(Debug, Clone)]
struct Parent {
child: Option<Arc<RwLock<Child>>>,
data: &'static str
}
impl Parent {
fn new() -> Self {
Parent {
child: None,
data: "hello"
}
}
fn hello(&self) -> &str {
self.data
}
fn get_child(&self) -> Option<Arc<RwLock<Child>>> {
self.child.as_ref().map(|x| x.clone() )
}
}
fn main() {
let parent = Arc::new(RwLock::new(Parent::new()));
let child = Arc::new(RwLock::new(Child::new()));
parent.write().unwrap().child = Some(child.clone());
child.write().unwrap().parent = Some(parent.clone());
assert_eq!("hello", parent.read().unwrap().hello());
{
let x = parent.read().unwrap();
match x.get_child() {
Some(child) => { assert_eq!("hello world", child.read().unwrap().hello_world()); }
None => {},
}
}
}
I have a similar problem, and am not entirely satisfied with the proposed solutions.
If your structure is really nested (i.e. you have a notion of "parent" and "child", with a unique parent for each child), then it seems natural that the parent should own the child(ren). So using Rc/Arc (which are designed to allow for multiple owners) does not look like the right solution -- all the less so because, as #Shepmaster points out, it "encourages" (or at least allows) the creation of cyclic references.
My idea was to have each child hold a raw pointer to its parent:
pub struct Node {
parent: *mut Node,
// ...
}
Since a node is owned by its parent, it can only be borrowed (resp. mutably borrowed) while its parent is being borrowed (resp. mutably borrowed). So in that context, it should be safe to cast self.parent to a &Node (resp. &mut Node, if self is mutable).
impl Node {
pub fn get_parent(&self) -> Option<&Node> {
unsafe { self.parent.as_ref() }
}
pub fn get_mut_parent(&mut self) -> Option<&mut Node> {
unsafe { self.parent.as_mut() }
}
}
However, this requires that the address of the parent node never changes (i.e. the parent is never moved). This can be achieved by only ever handling boxed nodes.
pub struct Node {
parent: *mut Node,
children: Vec<Box<Node>>,
// ..
}
impl Node {
pub fn new(data: &str) -> Box<Node> {
Box::new(Node {
parent: std::ptr::null_mut(),
children: vec![],
// ..
})
}
pub fn append_child(&mut self, mut child: Box<Node>) -> usize {
child.parent = self;
self.children.push(child);
self.children.len() - 1
}
}
I implemented a full-fledged example in the playground.

Resources