Value referencing data owned by the current function - rust

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,
}
}
}

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)
}
}

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.

macro_rules!() error: Fix for "the usage of `my_macro!` is likely invalid in impl item context"?

Playground link
I have several different structs grouped together in an enum:
pub enum Ty {
A(AStruct),
B(BStruct)
}
pub struct AStruct {
base: BaseStruct
}
impl AStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
pub struct BStruct {
base: BaseStruct
}
impl BStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
All of these types will share a base struct that is common to them all. This base struct will have a lot of methods that I don't want to duplicate for each supertype.
pub struct BaseStruct {
x: i32
}
impl BaseStruct {
pub fn new(x: i32) -> Self {
Self {
x
}
}
pub fn get_x(&self) -> i32 {
self.x
}
}
#[macro_export]
macro_rules! base_struct_passthrough_impls {
() => {
pub fn get_x(&self) -> i32 {
self.base.get_x()
};
}
}
However, trying to use this code results in the following error:
error: macro expansion ignores token `;` and any following
--> src/main.rs:37:10
|
37 | };
| ^
...
46 | base_struct_passthrough_impls!();
| --------------------------------- caused by the macro expansion here
|
= note: the usage of `base_struct_passthrough_impls!` is likely invalid in impl item context
It seems like macro_rules!() is not usable in the impl item context. Is this correct, and if so is there anyway around this restriction? Would a proc macro work here, or would doing something like this work better?
The issue isn't the macro usage, but the definition. You included a trailing semicolon after the function definition created by the macro, which is what causes the error. If you remove it, everything works fine - here's the code:
fn main() {
let types = vec![Ty::A(AStruct::new(32)), Ty::B(BStruct::new(64))];
types.iter().for_each(|item| {
dbg!(match item {
Ty::A(a_struct) => a_struct.get_x(),
Ty::B(b_struct) => b_struct.get_x(),
});
})
}
pub enum Ty {
A(AStruct),
B(BStruct)
}
pub struct BaseStruct {
x: i32
}
impl BaseStruct {
pub fn new(x: i32) -> Self {
Self {
x
}
}
pub fn get_x(&self) -> i32 {
self.x
}
}
#[macro_export]
macro_rules! base_struct_passthrough_impls {
() => {
pub fn get_x(&self) -> i32 {
self.base.get_x()
} // there was an illegal semicolon here
}
}
pub struct AStruct {
base: BaseStruct
}
impl AStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
pub struct BStruct {
base: BaseStruct
}
impl BStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}

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

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.

Struggling with interior mutability

I have a data structure like this:
struct R {
hmhs: HashMap<i64, HashSet<i64>>,
}
impl R {
fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
if let None = self.hmhs.get(&0) {
self.hmhs.insert(0, HashSet::new());
}
self.hmhs.get_mut(&0).unwrap()
}
fn iter_for_hmhs<'a>(&'a mut self) -> impl Iterator<Item = &'a i64> {
self.hs_for_hmhs().iter()
}
fn insert_for_hmhs(&mut self, i: i64) -> bool {
self.hs_for_hmhs().insert(i)
}
}
This seems to work, but all the methods require a mutable
reference to self which is unfortunate. I tried to give
interior mutability a go:
struct S {
hmhs: RefCell<HashMap<i64, HashSet<i64>>>,
}
impl S {
fn hs_for_hmhs(&self) -> &HashSet<i64> {
if let None = self.hmhs.borrow().get(&0) {
self.hmhs.borrow_mut().insert(0, HashSet::new());
}
self.hmhs.borrow_mut().get_mut(&0).unwrap()
}
fn iter_for_hmhs(&mut self) -> impl Iterator<Item = &i64> {
self.hs_for_hmhs().iter()
}
fn insert_for_hmhs(&mut self, i: i64) -> bool {
self.hs_for_hmhs().insert(i)
}
}
However, I constantly seem to hit problems. Mostly some variety of How do I return a reference to something inside a RefCell without breaking encapsulation?
I have tried lots of variants here, but I am missing something
fundamental in my understanding. Is there a way of achieving what I
want?
Complete Code:
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
struct R {
hmhs: HashMap<i64, HashSet<i64>>,
}
impl R {
fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
if let None = self.hmhs.get(&0) {
self.hmhs.insert(0, HashSet::new());
}
self.hmhs.get_mut(&0).unwrap()
}
fn iter_for_hmhs<'a>(&'a mut self) -> impl Iterator<Item = &'a i64> {
self.hs_for_hmhs().iter()
}
fn insert_for_hmhs(&mut self, i: i64) -> bool {
self.hs_for_hmhs().insert(i)
}
}
struct S {
hmhs: RefCell<HashMap<i64, HashSet<i64>>>,
}
impl S {
fn hs_for_hmhs(&self) -> &mut HashSet<i64> {
if let None = self.hmhs.borrow().get(&0) {
self.hmhs.borrow_mut().insert(0, HashSet::new());
}
self.hmhs.borrow_mut().get_mut(&0).unwrap()
}
fn iter_for_hmhs(&self) -> impl Iterator<Item = &i64> {
self.hs_for_hmhs().iter()
}
fn insert_for_hmhs(&self, i: i64) -> bool {
self.hs_for_hmhs().insert(i)
}
}
fn main() {}
Compiler Message:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:36:9
|
36 | self.hmhs.borrow_mut().get_mut(&0).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
37 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 31:5...
--> src/main.rs:31:5
|
31 | / fn hs_for_hmhs(&self) -> &mut HashSet<i64> {
32 | | if let None = self.hmhs.borrow().get(&0) {
33 | | self.hmhs.borrow_mut().insert(0, HashSet::new());
34 | | }
35 | |
36 | | self.hmhs.borrow_mut().get_mut(&0).unwrap()
37 | | }
| |_____^
I found a solution -- extract the HashMap as a raw pointer. This in turn means that I can get to the HashSet without shenanigans including returning a iterator.
I'm happy enough with this as a solution. The unsafe code is small and contained and if I understand the reason why the compiler is complaining without unsafe, it cannot occur in this code, since neither the HashMap nor the HashSet are ever removed or replaced after construction.
That was a lot of effort.
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
struct R {
hmhs: HashMap<i64, HashSet<i64>>,
}
impl R {
fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
if let None = self.hmhs.get(&0) {
self.hmhs.insert(0, HashSet::new());
}
self.hmhs.get_mut(&0).unwrap()
}
fn iter_for_hmhs<'a>(&'a mut self) -> impl Iterator<Item = &'a i64> {
self.hs_for_hmhs().iter()
}
fn insert_for_hmhs(&mut self, i: i64) -> bool {
self.hs_for_hmhs().insert(i)
}
}
struct S {
hmhs: RefCell<HashMap<i64, HashSet<i64>>>,
}
impl S {
fn hs_as_ptr(&self) -> *mut HashMap<i64, HashSet<i64>> {
self.hmhs.borrow_mut().entry(0).or_insert(HashSet::new());
self.hmhs.as_ptr()
}
fn mut_hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
unsafe { (*self.hs_as_ptr()).get_mut(&0).unwrap() }
}
fn hs_for_hmhs(&self) -> &HashSet<i64> {
unsafe { (*self.hs_as_ptr()).get(&0).unwrap() }
}
fn iter_for_hmhs<'a>(&'a self) -> impl Iterator<Item = &'a i64> + 'a {
self.hs_for_hmhs().iter()
}
fn insert_for_hmhs(&mut self, i: i64) -> bool {
self.mut_hs_for_hmhs().insert(i)
}
}
fn main() {
let mut r = R {
hmhs: HashMap::new(),
};
let mut s = S {
hmhs: RefCell::new(HashMap::new()),
};
r.insert_for_hmhs(10);
s.insert_for_hmhs(20);
println!("r next: {:?}", r.iter_for_hmhs().next());
println!("s next: {:?}", s.iter_for_hmhs().next());
}
https://play.rust-lang.org/?gist=3ed1977bdd5f9f82d144fe128f618979&version=stable&mode=debug&edition=2015

Resources