Late type in Rust - rust

I'm working with two crates: A and B. I control both. I'd like to create a struct in A that has a field whose type is known only to B (i.e., A is independent of B, but B is dependent on A).
crate_a:
#[derive(Clone)]
pub struct Thing {
pub foo: i32,
pub bar: *const i32,
}
impl Thing {
fn new(x: i32) -> Self {
Thing { foo: x, bar: &0 }
}
}
crate_b:
struct Value {};
fn func1() {
let mut x = A::Thing::new(1);
let y = Value {};
x.bar = &y as *const Value as *const i32;
...
}
fn func2() {
...
let y = unsafe { &*(x.bar as *const Value) };
...
}
This works, but it doesn't feel very "rusty". Is there a cleaner way to do this? I thought about using a trait object, but ran into issues with Clone.
Note: My reason for splitting these out is that the dependencies in B make compilation very slow. Value above is actually from llvm_sys. I'd rather not leak that into A, which has no other dependency on llvm.

The standard way to implement something like this is with generics, which are kind of like type variables: they can be "assigned" a particular type, possibly within some constraints. This is how the standard library can provide types like Vec that work with types that you declare in your crate.
Basically, generics allow Thing to be defined in terms of "some unknown type that will become known later when this type is actually used."
Given the example in your code, it looks like Thing's bar field may or may not be set, which suggests that the built-in Option enum should be used. All you have to do is put a type parameter on Thing and pass that through to Option, like so:
pub mod A {
#[derive(Clone)]
pub struct Thing<T> {
pub foo: i32,
pub bar: Option<T>,
}
impl<T> Thing<T> {
pub fn new(x: i32) -> Self {
Thing { foo: x, bar: None }
}
}
}
pub mod B {
use crate::A;
struct Value;
fn func1() {
let mut x = A::Thing::new(1);
let y = Value;
x.bar = Some(y);
// ...
}
fn func2(x: &A::Thing<Value>) {
// ...
let y: &Value = x.bar.as_ref().unwrap();
// ...
}
}
(Playground)
Here, the x in B::func1() has the type Thing<Value>. You can see with this syntax how Value is substituted for T, which makes the bar field Option<Value>.
If Thing's bar isn't actually supposed to be optional, just write pub bar: T instead, and accept a T in Thing::new() to initialize it:
pub mod A {
#[derive(Clone)]
pub struct Thing<T> {
pub foo: i32,
pub bar: T,
}
impl<T> Thing<T> {
pub fn new(x: i32, y: T) -> Self {
Thing { foo: x, bar: y }
}
}
}
pub mod B {
use crate::A;
struct Value;
fn func1() {
let mut x = A::Thing::new(1, Value);
// ...
}
fn func2(x: &A::Thing<Value>) {
// ...
let y: &Value = &x.bar;
// ...
}
}
(Playground)
Note that the definition of Thing in both of these cases doesn't actually require that T implement Clone; however, Thing<T> will only implement Clone if T also does. #[derive(Clone)] will generate an implementation like:
impl<T> Clone for Thing<T> where T: Clone { /* ... */ }
This can allow your type to be more flexible -- it can now be used in contexts that don't require T to implement Clone, while also being cloneable when T does implement Clone. You get the best of both worlds this way.

Related

How do I create a long-lived reference into a collection that I know will no longer be modified?

I'm implementing a bytecode VM and am struggling referencing data stored in a parsed representation of the bytecode. As is the nature of (most) bytecode, it and thus its parsed representation remain unmodified once it's initialized. A separate Vm contains the mutable parts (stack etc.) along with that module. I made an MCVE with additional explanatory comments to illustrate the problem; it's at the bottom and on the playground. The parsed bytecode may look like this:
Module { struct_types: {"Bar": StructType::Named(["a", "b"])} }
The strings "Bar", "a", "b" are references into the bytecode and have lifetime 'b, so we also have lifetimes in the types Module<'b> and StructType<'b>.
After creating this, I will want to create struct instances, think let bar = Bar { a: (), b: () };. At least currently, each struct instance needs to hold a reference to its type, so that type might look like this:
pub struct Struct<'b> {
struct_type: &'b bytecode::StructType<'b>,
fields: Vec<Value<'b>>,
}
The values of a struct's fields may be constants whose value is stored in the bytecode, so the Value enum has a lifetime 'b as well, and that works. The problem is that I have a &'b bytecode::StructType<'b> in the first field: how do I get a reference that lives long enough? I think the reference would actually be valid long enough.
The part of the code that I suspect to be the critical one is here:
pub fn struct_type(&self, _name: &str) -> Option<&'b StructType<'b>> {
// self.struct_types.get(name)
todo!("fix lifetime problems")
}
With the commented out code, I can't get a 'b reference because the reference self.struct_types lives too short; to fix that I'd need to do &'b self which would spread virally through the code; also, most of the times I need to borrow the Vm mutably, which doesn't work if all those exclusive self references have to live long.
Introducing a separate lifetime 'm so that I could return a &'m StructType<'b> sounds like something that I could try as well, but that sounds just as viral and in addition introduces a separate lifetime I need to keep track of; being able to replace 'b with 'm (or at least only having on in each place) would be a bit nicer.
Finally this feels like something that pinning could be helpful with, but I don't understand that topic enough to make an educated guess on how that could be approached.
MCVE
#![allow(dead_code)]
mod bytecode {
use std::collections::BTreeMap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StructType<'b> {
/// unit struct type; doesn't have fields
Empty,
/// tuple struct type; fields are positional
Positional(usize),
/// "normal" struct type; fields are named
Named(Vec<&'b str>),
}
impl<'b> StructType<'b> {
pub fn field_count(&self) -> usize {
match self {
Self::Empty => 0,
Self::Positional(field_count) => *field_count,
Self::Named(fields) => fields.len(),
}
}
}
#[derive(Debug, Clone)]
pub struct Module<'b> {
struct_types: BTreeMap<&'b str, StructType<'b>>,
}
impl<'b> Module<'b> {
// here is the problem: I would like to return a reference with lifetime 'b.
// from the point I start executing instructions, I know that I won't modify
// the module (particularly, I won't add entries to the map), so I think that
// lifetime should be possible - pinning? `&'b self` everywhere? idk
pub fn struct_type(&self, _name: &str) -> Option<&'b StructType<'b>> {
// self.struct_types.get(name)
todo!("fix lifetime problems")
}
}
pub fn parse<'b>(bytecode: &'b str) -> Module<'b> {
// this would use nom to parse actual bytecode
assert_eq!(bytecode, "struct Bar { a, b }");
let bar = &bytecode[7..10];
let a = &bytecode[13..14];
let b = &bytecode[16..17];
let fields = vec![a, b];
let bar_struct = StructType::Named(fields);
let struct_types = BTreeMap::from_iter([
(bar, bar_struct),
]);
Module { struct_types }
}
}
mod vm {
use crate::bytecode::{self, StructType};
#[derive(Debug, Clone)]
pub enum Value<'b> {
Unit,
Struct(Struct<'b>),
}
#[derive(Debug, Clone)]
pub struct Struct<'b> {
struct_type: &'b bytecode::StructType<'b>,
fields: Vec<Value<'b>>,
}
impl<'b> Struct<'b> {
pub fn new(struct_type: &'b bytecode::StructType<'b>, fields: Vec<Value<'b>>) -> Self {
Struct { struct_type, fields }
}
}
#[derive(Debug, Clone)]
pub struct Vm<'b> {
module: bytecode::Module<'b>,
}
impl<'b> Vm<'b> {
pub fn new(module: bytecode::Module<'b>) -> Self {
Self { module }
}
pub fn create_struct(&mut self, type_name: &'b str) -> Value<'b> {
let struct_type: &'b StructType<'b> = self.module.struct_type(type_name).unwrap();
// just initialize the fields to something, we don't care
let fields = vec![Value::Unit; struct_type.field_count()];
let value = Value::Struct(Struct::new(struct_type, fields));
value
}
}
}
pub fn main() {
// the bytecode contains all constants needed at runtime;
// we're just interested in how struct types are handled
// obviously the real bytecode is not as human-readable
let bytecode = "struct Bar { a, b }";
// we parse that into a module that, among other things,
// has a map of all struct types
let module = bytecode::parse(bytecode);
println!("{:?}", module);
// we create a Vm that is capable of running commands
// that are stored in the module
let mut vm = vm::Vm::new(module);
// now we try to execute an instruction to create a struct value
// the instruction for this contains a reference to the type name
// stored in the bytecode.
// the struct value contains a reference to its type and holds its field values.
let value = {
let bar = &bytecode[7..10];
vm.create_struct(bar)
};
println!("{:?}", value);
}
&'b bytecode::StructType<'b> is a classic anti-pattern in Rust, it strongly indicates incorrectly annotated lifetimes. It doesn't make sense that an object would depend on some lifetime and borrowing it creates the same lifetime. That is very rare to happen on purpose.
So I suspect you need two lifetimes, which I will call 'm and 'b:
'b: the lifetime of the bytecode string, everything that references it will use &'b str.
'm: the lifetime of the Module object. Everything that references it or its contained StructType will use this lifetime.
If split into two lifetimes and adjusted correctly, it simply works:
#![allow(dead_code)]
mod bytecode {
use std::{collections::BTreeMap, iter::FromIterator};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StructType<'b> {
/// unit struct type; doesn't have fields
Empty,
/// tuple struct type; fields are positional
Positional(usize),
/// "normal" struct type; fields are named
Named(Vec<&'b str>),
}
impl<'b> StructType<'b> {
pub fn field_count(&self) -> usize {
match self {
Self::Empty => 0,
Self::Positional(field_count) => *field_count,
Self::Named(fields) => fields.len(),
}
}
}
#[derive(Debug, Clone)]
pub struct Module<'b> {
struct_types: BTreeMap<&'b str, StructType<'b>>,
}
impl<'b> Module<'b> {
// here is the problem: I would like to return a reference with lifetime 'b.
// from the point I start executing instructions, I know that I won't modify
// the module (particularly, I won't add entries to the map), so I think that
// lifetime should be possible - pinning? `&'b self` everywhere? idk
pub fn struct_type(&self, name: &str) -> Option<&StructType<'b>> {
self.struct_types.get(name)
}
}
pub fn parse<'b>(bytecode: &'b str) -> Module<'b> {
// this would use nom to parse actual bytecode
assert_eq!(bytecode, "struct Bar { a, b }");
let bar = &bytecode[7..10];
let a = &bytecode[13..14];
let b = &bytecode[16..17];
let fields = vec![a, b];
let bar_struct = StructType::Named(fields);
let struct_types = BTreeMap::from_iter([(bar, bar_struct)]);
Module { struct_types }
}
}
mod vm {
use crate::bytecode::{self, StructType};
#[derive(Debug, Clone)]
pub enum Value<'b, 'm> {
Unit,
Struct(Struct<'b, 'm>),
}
#[derive(Debug, Clone)]
pub struct Struct<'b, 'm> {
struct_type: &'m bytecode::StructType<'b>,
fields: Vec<Value<'b, 'm>>,
}
impl<'b, 'm> Struct<'b, 'm> {
pub fn new(struct_type: &'m bytecode::StructType<'b>, fields: Vec<Value<'b, 'm>>) -> Self {
Struct {
struct_type,
fields,
}
}
}
#[derive(Debug, Clone)]
pub struct Vm<'b> {
module: bytecode::Module<'b>,
}
impl<'b> Vm<'b> {
pub fn new(module: bytecode::Module<'b>) -> Self {
Self { module }
}
pub fn create_struct(&mut self, type_name: &str) -> Value<'b, '_> {
let struct_type: &StructType<'b> = self.module.struct_type(type_name).unwrap();
// just initialize the fields to something, we don't care
let fields = vec![Value::Unit; struct_type.field_count()];
let value = Value::Struct(Struct::new(struct_type, fields));
value
}
}
}
pub fn main() {
// the bytecode contains all constants needed at runtime;
// we're just interested in how struct types are handled
// obviously the real bytecode is not as human-readable
let bytecode = "struct Bar { a, b }";
// we parse that into a module that, among other things,
// has a map of all struct types
let module = bytecode::parse(bytecode);
println!("{:?}", module);
// we create a Vm that is capable of running commands
// that are stored in the module
let mut vm = vm::Vm::new(module);
// now we try to execute an instruction to create a struct value
// the instruction for this contains a reference to the type name
// stored in the bytecode.
// the struct value contains a reference to its type and holds its field values.
let value = {
let bar = &bytecode[7..10];
vm.create_struct(bar)
};
println!("{:?}", value);
}
Module { struct_types: {"Bar": Named(["a", "b"])} }
Struct(Struct { struct_type: Named(["a", "b"]), fields: [Unit, Unit] })
It can further be simplified, however, due to the fact that 'm is connected to 'b, and therefore everything that depends on 'm automatically also has access to 'b objects, because 'b is guaranteed to outlive 'm.
Therefore, let's introduce 'a, which we will now use inside of the vm mod to reference anything from the bytecode mod. This will further allow lifetime elysion to happen at a couple of points, simplifying the code even further:
#![allow(dead_code)]
mod bytecode {
use std::{collections::BTreeMap, iter::FromIterator};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StructType<'b> {
/// unit struct type; doesn't have fields
Empty,
/// tuple struct type; fields are positional
Positional(usize),
/// "normal" struct type; fields are named
Named(Vec<&'b str>),
}
impl<'b> StructType<'b> {
pub fn field_count(&self) -> usize {
match self {
Self::Empty => 0,
Self::Positional(field_count) => *field_count,
Self::Named(fields) => fields.len(),
}
}
}
#[derive(Debug, Clone)]
pub struct Module<'b> {
struct_types: BTreeMap<&'b str, StructType<'b>>,
}
impl<'b> Module<'b> {
// here is the problem: I would like to return a reference with lifetime 'b.
// from the point I start executing instructions, I know that I won't modify
// the module (particularly, I won't add entries to the map), so I think that
// lifetime should be possible - pinning? `&'b self` everywhere? idk
pub fn struct_type(&self, name: &str) -> Option<&StructType<'b>> {
self.struct_types.get(name)
}
}
pub fn parse<'b>(bytecode: &'b str) -> Module<'b> {
// this would use nom to parse actual bytecode
assert_eq!(bytecode, "struct Bar { a, b }");
let bar = &bytecode[7..10];
let a = &bytecode[13..14];
let b = &bytecode[16..17];
let fields = vec![a, b];
let bar_struct = StructType::Named(fields);
let struct_types = BTreeMap::from_iter([(bar, bar_struct)]);
Module { struct_types }
}
}
mod vm {
use crate::bytecode::{self, StructType};
#[derive(Debug, Clone)]
pub enum Value<'a> {
Unit,
Struct(Struct<'a>),
}
#[derive(Debug, Clone)]
pub struct Struct<'a> {
struct_type: &'a bytecode::StructType<'a>,
fields: Vec<Value<'a>>,
}
impl<'a> Struct<'a> {
pub fn new(struct_type: &'a bytecode::StructType, fields: Vec<Value<'a>>) -> Self {
Struct {
struct_type,
fields,
}
}
}
#[derive(Debug, Clone)]
pub struct Vm<'a> {
module: bytecode::Module<'a>,
}
impl<'a> Vm<'a> {
pub fn new(module: bytecode::Module<'a>) -> Self {
Self { module }
}
pub fn create_struct(&mut self, type_name: &str) -> Value {
let struct_type: &StructType = self.module.struct_type(type_name).unwrap();
// just initialize the fields to something, we don't care
let fields = vec![Value::Unit; struct_type.field_count()];
let value = Value::Struct(Struct::new(struct_type, fields));
value
}
}
}
pub fn main() {
// the bytecode contains all constants needed at runtime;
// we're just interested in how struct types are handled
// obviously the real bytecode is not as human-readable
let bytecode = "struct Bar { a, b }";
// we parse that into a module that, among other things,
// has a map of all struct types
let module = bytecode::parse(bytecode);
println!("{:?}", module);
// we create a Vm that is capable of running commands
// that are stored in the module
let mut vm = vm::Vm::new(module);
// now we try to execute an instruction to create a struct value
// the instruction for this contains a reference to the type name
// stored in the bytecode.
// the struct value contains a reference to its type and holds its field values.
let value = {
let bar = &bytecode[7..10];
vm.create_struct(bar)
};
println!("{:?}", value);
}
Module { struct_types: {"Bar": Named(["a", "b"])} }
Struct(Struct { struct_type: Named(["a", "b"]), fields: [Unit, Unit] })
Fun fact: This is now one of the rare cases where we legitimately have to use &'a bytecode::StructType<'a>, so take my opening statement with a grain of salt, and you were kind of right all along :)
The crazy thing is if we then rename 'a to 'b to be consistent with your original code, we get almost your code with only some minor differences:
#![allow(dead_code)]
mod bytecode {
use std::{collections::BTreeMap, iter::FromIterator};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StructType<'b> {
/// unit struct type; doesn't have fields
Empty,
/// tuple struct type; fields are positional
Positional(usize),
/// "normal" struct type; fields are named
Named(Vec<&'b str>),
}
impl<'b> StructType<'b> {
pub fn field_count(&self) -> usize {
match self {
Self::Empty => 0,
Self::Positional(field_count) => *field_count,
Self::Named(fields) => fields.len(),
}
}
}
#[derive(Debug, Clone)]
pub struct Module<'b> {
struct_types: BTreeMap<&'b str, StructType<'b>>,
}
impl<'b> Module<'b> {
// here is the problem: I would like to return a reference with lifetime 'b.
// from the point I start executing instructions, I know that I won't modify
// the module (particularly, I won't add entries to the map), so I think that
// lifetime should be possible - pinning? `&'b self` everywhere? idk
pub fn struct_type(&self, name: &str) -> Option<&StructType<'b>> {
self.struct_types.get(name)
}
}
pub fn parse<'b>(bytecode: &'b str) -> Module<'b> {
// this would use nom to parse actual bytecode
assert_eq!(bytecode, "struct Bar { a, b }");
let bar = &bytecode[7..10];
let a = &bytecode[13..14];
let b = &bytecode[16..17];
let fields = vec![a, b];
let bar_struct = StructType::Named(fields);
let struct_types = BTreeMap::from_iter([(bar, bar_struct)]);
Module { struct_types }
}
}
mod vm {
use crate::bytecode::{self, StructType};
#[derive(Debug, Clone)]
pub enum Value<'b> {
Unit,
Struct(Struct<'b>),
}
#[derive(Debug, Clone)]
pub struct Struct<'b> {
struct_type: &'b bytecode::StructType<'b>,
fields: Vec<Value<'b>>,
}
impl<'b> Struct<'b> {
pub fn new(struct_type: &'b bytecode::StructType, fields: Vec<Value<'b>>) -> Self {
Struct {
struct_type,
fields,
}
}
}
#[derive(Debug, Clone)]
pub struct Vm<'b> {
module: bytecode::Module<'b>,
}
impl<'b> Vm<'b> {
pub fn new(module: bytecode::Module<'b>) -> Self {
Self { module }
}
pub fn create_struct(&mut self, type_name: &str) -> Value {
let struct_type: &StructType = self.module.struct_type(type_name).unwrap();
// just initialize the fields to something, we don't care
let fields = vec![Value::Unit; struct_type.field_count()];
let value = Value::Struct(Struct::new(struct_type, fields));
value
}
}
}
pub fn main() {
// the bytecode contains all constants needed at runtime;
// we're just interested in how struct types are handled
// obviously the real bytecode is not as human-readable
let bytecode = "struct Bar { a, b }";
// we parse that into a module that, among other things,
// has a map of all struct types
let module = bytecode::parse(bytecode);
println!("{:?}", module);
// we create a Vm that is capable of running commands
// that are stored in the module
let mut vm = vm::Vm::new(module);
// now we try to execute an instruction to create a struct value
// the instruction for this contains a reference to the type name
// stored in the bytecode.
// the struct value contains a reference to its type and holds its field values.
let value = {
let bar = &bytecode[7..10];
vm.create_struct(bar)
};
println!("{:?}", value);
}
Module { struct_types: {"Bar": Named(["a", "b"])} }
Struct(Struct { struct_type: Named(["a", "b"]), fields: [Unit, Unit] })
So the actual fix for your original code is as follows:
4c4
< use std::collections::BTreeMap;
---
> use std::{collections::BTreeMap, iter::FromIterator};
36,38c36,37
< pub fn struct_type(&self, _name: &str) -> Option<&'b StructType<'b>> {
< // self.struct_types.get(name)
< todo!("fix lifetime problems")
---
> pub fn struct_type(&self, name: &str) -> Option<&StructType<'b>> {
> self.struct_types.get(name)
73c72
< pub fn new(struct_type: &'b bytecode::StructType<'b>, fields: Vec<Value<'b>>) -> Self {
---
> pub fn new(struct_type: &'b bytecode::StructType, fields: Vec<Value<'b>>) -> Self {
91,92c90,91
< pub fn create_struct(&mut self, type_name: &'b str) -> Value<'b> {
< let struct_type: &'b StructType<'b> = self.module.struct_type(type_name).unwrap();
---
> pub fn create_struct(&mut self, type_name: &str) -> Value {
> let struct_type: &StructType = self.module.struct_type(type_name).unwrap();
I hope deriving them step by step made it somewhat clear why those changes are necessary.

How can I reinterpret a RefMut<T> as a RefMut<U>

I have a collection containing elements wrapped in RefCell that I borrow. I have a wrapper struct to make the api usable like so:
pub struct RefWrapper<'a, T> {
inner: RefMut<'a, T>,
}
impl<T> Deref for RefWrapper<T> {
type Target = T;
fn deref(&self) -> &T { &self.inner }
}
impl<T> DerefMut for RefWrapper<T> {
fn deref_mut(&mut self) -> &mut T { &mut self.inner }
}
Foo and Bar have the same memory layout, so I can safely transmute between references of them, however RefMut is not repr(C) and transmuting would be unsound for other reasons, so I can't safely transmute RefWrapper<Foo> into RefWrapper<Bar>. is there any way to convert from RefWrapper<Foo> to RefWrapper<Bar>?
If you can get a &mut U from a &mut T, then you can use RefMut::map.
Here as a code example:
use std::cell::{RefCell, RefMut};
#[repr(C)]
#[derive(Debug)]
struct Foo {
a: i32,
b: i32,
}
#[repr(C)]
#[derive(Debug)]
struct Bar {
a: i32,
b: i32,
}
fn convert_foo_to_bar(foo: &mut Foo) -> &mut Bar {
unsafe { std::mem::transmute(foo) }
}
fn main() {
let foo = RefCell::new(Foo { a: 42, b: 69 });
{
let foo_ref = foo.borrow_mut();
let mut bar_ref = RefMut::map(foo_ref, convert_foo_to_bar);
println!("{:?}", bar_ref);
bar_ref.b = 420;
}
println!("{:?}", foo);
}
Bar { a: 42, b: 69 }
RefCell { value: Foo { a: 42, b: 420 } }
Be aware that his requires manually keeping the memory layout of Foo and Bar in sync. This will create very subtle and hard-to-find bugs if Foo and Bar are not 100% identical.
Of course one could generalize the concept by implementing From/Into for &mut Foo and &mut Bar instead of using convert_foo_to_bar. You can then use this trait to for your RefWrapper to convert between the two.

Trait as generic parameter to struct object intialization

I have this struct:
use sp_runtime::traits::Block;
struct Bar<T: Block> {
e1: Vec<T>,
}
impl<T: Block> Bar<T> {
pub fn new() -> Self {
Bar { e1: Vec::new() }
}
}
Where Block is from the sp_runtime crate.
In main:
fn main() {
let var_1 = Bar::<Block>::new();
}
Full Code
This code throws compilation error that trait can't be made into an object. I'm new to Rust, much of online solution haven't addressed this issue. Kindly let me know how to get around initialization of bar object.
Your confusion likely stems from the fact that the sp_runtime crate has two items called Block. One is the trait sp_runtime::traits::Block and the other is a struct, sp_runtime::generic::Block, which implements that trait.
Traits can be used as a constraint on a type parameter, but they cannot be used as a type argument.
So, in your definition of Bar<T>, you can constrain T with sp_runtime::traits::Block, but when you construct an instance of Bar<T>, T needs to be the struct instead.
use sp_runtime::traits::Block;
struct<T: Block> Bar {
e1: Vec<T>,
}
impl<T: Block> Bar<T> {
pub fn new() -> Self {
Bar {
e1: Vec::new(),
}
}
}
fn main() {
use sp_runtime::generic::Block;
let var_1 = Bar::<Block>::new();
}
However, given that this is the only implementation of the trait in the crate, you can just avoid mentioning the trait altogether and use the concrete struct type (unless you plan on implementing it yourself or depending on implementations from other crates):
use sp_runtime::generic::Block;
struct Bar{
e1 : Vec<Block>,
}
impl Bar {
pub fn new() -> Self{
Bar {
e1: Vec::new(),
}
}
}
fn main() {
let var_1 = Bar::new();
}

How can I denote a field that can be either Rc<T> or Weak<T>

I'd like to have a field in struct like this:
struct Foo<T> {
bar: Smart<T>
}
where bar could be either Rc<T or Weak<T>, depending on the "ownership relationships" between different instances of Foo. Is there any idiomatic way in Rust how to do this, other than to create a custom enum?
Is there any idiomatic way in Rust how to do this, other than to create a custom enum?
Just like most other "either this or that" choices in Rust, an enum is the idiomatic way.
An Peter's answer suggested, there is is no such abstraction in the stdlib. You can define a small enum to handle both cases:
use std::rc::{Rc, Weak};
enum MaybeStrong<T> {
Strong(Rc<T>),
Weak(Weak<T>),
}
impl<T> MaybeStrong<T> {
fn get(&self) -> Option<Rc<T>> {
match self {
MaybeStrong::Strong(t) => Some(Rc::clone(t)),
MaybeStrong::Weak(w) => w.upgrade(),
}
}
}
struct Foo<T> {
bar: MaybeStrong<T>
}
impl<T> Foo<T> {
fn from_weak(inner: Weak<T>) -> Self {
Self { bar: MaybeStrong::Weak(inner) }
}
fn from_strong(inner: Rc<T>) -> Self {
Self { bar: MaybeStrong::Strong(inner) }
}
fn say(&self) where T: std::fmt::Debug {
println!("{:?}", self.bar.get())
}
}
fn main() {
let inner = Rc::new("foo!");
Foo::from_weak(Rc::downgrade(&inner)).say();
Foo::from_strong(inner).say();
}
self.bar() will always return a Some if it was created from a strong pointer and return None in case it's a Weak and it's dangling. Notice that due to the fact that get() needs to create an owned Rc first, the method can't return a &T (including Option<&T>) because that &T could be dangling. This also means that all users of bar() will own one strong count on the inner value while processing, making it safe to use in any case.
This kind of construct is often called "Either" and there's a crate that looks like it can address some of the usual use-cases: https://docs.rs/either/1.5.3/either/
Then you could write
struct Foo<T> {
bar: Either<Weak<T>, Rc<T>>
}
Then an example function to get an Option<Rc<T>> might be:
impl <T> Foo<T> {
fn get_rc(self) -> Option<Rc<T>> {
self.bar
.map_left( |weak| weak.upgrade() )
.map_right( |v| Some(v) )
.into_inner()
}
}
Then it can be used like this:
fn main() {
let x = Rc::new(1);
let f_direct = Foo{ bar:Either::Right(x.clone()) };
println!("f_direct.get_rc() = {:?}", f_direct.get_rc());
let f_weak = Foo{ bar:Either::Left(Rc::downgrade(&x)) };
println!("f_weak.get_rc() = {:?}", f_weak.get_rc());
}
Link to complete example in the playground:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c20faaa46277550e16a3d3b24f3d1750

How do I clone a closure, so that their types are the same?

I have a struct which looks something like this:
pub struct MyStruct<F>
where
F: Fn(usize) -> f64,
{
field: usize,
mapper: F,
// fields omitted
}
How do I implement Clone for this struct?
One way I found to copy the function body is:
let mapper = |x| (mystruct.mapper)(x);
But this results in mapper having a different type than that of mystruct.mapper.
playground
As of Rust 1.26.0, closures implement both Copy and Clone if all of the captured variables do:
#[derive(Clone)]
pub struct MyStruct<F>
where
F: Fn(usize) -> f64,
{
field: usize,
mapper: F,
}
fn main() {
let f = MyStruct {
field: 34,
mapper: |x| x as f64,
};
let g = f.clone();
println!("{}", (g.mapper)(3));
}
You can't Clone closures. The only one in a position to implement Clone for a closure is the compiler... and it doesn't. So, you're kinda stuck.
There is one way around this, though: if you have a closure with no captured variables, you can force a copy via unsafe code. That said, a simpler approach at that point is to accept a fn(usize) -> f64 instead, since they don't have a captured environment (any zero-sized closure can be rewritten as a function), and are Copy.
You can use Rc (or Arc!) to get multiple handles of the same unclonable value. Works well with Fn (callable through shared references) closures.
pub struct MyStruct<F> where F: Fn(usize) -> f64 {
field: usize,
mapper: Rc<F>,
// fields omitted
}
impl<F> Clone for MyStruct<F>
where F: Fn(usize) -> f64,
{
fn clone(&self) -> Self {
MyStruct {
field: self.field,
mapper: self.mapper.clone(),
...
}
}
}
Remember that #[derive(Clone)] is a very useful recipe for Clone, but its recipe doesn't always do the right thing for the situation; this is one such case.
You can use trait objects to be able to implement Сlone for your struct:
use std::rc::Rc;
#[derive(Clone)]
pub struct MyStructRef<'f> {
field: usize,
mapper: &'f Fn(usize) -> f64,
}
#[derive(Clone)]
pub struct MyStructRc {
field: usize,
mapper: Rc<Fn(usize) -> f64>,
}
fn main() {
//ref
let closure = |x| x as f64;
let f = MyStructRef { field: 34, mapper: &closure };
let g = f.clone();
println!("{}", (f.mapper)(3));
println!("{}", (g.mapper)(3));
//Rc
let rcf = MyStructRc { field: 34, mapper: Rc::new(|x| x as f64 * 2.0) };
let rcg = rcf.clone();
println!("{}", (rcf.mapper)(3));
println!("{}", (rcg.mapper)(3));
}

Resources