Does Rust support comparing struct instances without comparing their fields? [duplicate] - rust

For example:
struct Foo<'a> { bar: &'a str }
fn main() {
let foo_instance = Foo { bar: "bar" };
let some_vector: Vec<&Foo> = vec![&foo_instance];
assert!(*some_vector[0] == foo_instance);
}
I want to check if foo_instance references the same instance as *some_vector[0], but I can't do this ...
I don't want to know if the two instances are equal; I want to check if the variables point to the same instance in the memory
Is it possible to do that?

There is the function ptr::eq:
use std::ptr;
struct Foo<'a> {
bar: &'a str,
}
fn main() {
let foo_instance = Foo { bar: "bar" };
let some_vector: Vec<&Foo> = vec![&foo_instance];
assert!(ptr::eq(some_vector[0], &foo_instance));
}
Before this was stabilized in Rust 1.17.0, you could perform a cast to *const T:
assert!(some_vector[0] as *const Foo == &foo_instance as *const Foo);
It will check if the references point to the same place in the memory.

Related

Late type in 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.

How can we return a static reference to a variable we make in a function in rust?

struct Foo<'a>(&'a str);
impl<'a> Foo<'a> {
fn get(&self) -> &'static str {self.0}
}
fn main() {
let value: &str;
{
let foo = Foo("Test Value");
value = foo.get();
}
println!("{}", value);
}
In this test code, I need to get the value stored in foo but as str is not sized, I can't just copy it's value. I even tried cloning the str. In a real life scenario, I could just use String or make a wrapper or encapsulate it in a box and return it but is there no way I can return a static reference to a variable I create in a function? If so, how does the as_str function work in rust?
----Edit----
In this example, Neither putting 'static before str in Foo nor returning value with lifetime 'a works. What to do then?
struct Foo<'a>(&'a [i32]);
impl<'a> Foo<'a> {
fn get(&self) -> &'static [i32] {self.0}
}
fn main() {
let value: &[i32];
{
let test_value = [0, 1, 2, 3];
let foo = Foo(&test_value);
value = foo.get();
}
println!("{:?}", value);
}
You can do it like this:
struct Foo<'a>(&'a str);
impl<'a> Foo<'a> {
fn get(&self) -> &'a str {self.0}
}
fn main() {
let value: &str;
{
let foo = Foo("Test Value");
value = foo.get();
}
println!("{}", value);
}
Or like this:
struct Foo(&'static str);
impl Foo {
fn get(&self) -> &'static str {self.0}
}
fn main() {
let value: &str;
{
let foo = Foo("Test Value");
value = foo.get();
}
println!("{}", value);
}
The reason your code doesn't compile is that you're declaring you are returning a reference with a (potentially) longer lifetime. Compare the lifetime of static with that of a (self.0 has a lifetime of a).

Array initialization using default Foo struct [duplicate]

I'm having trouble initializing a fixed length array. My attempts so far all result in the same "use of possibly uninitialized variable: foo_array" error:
#[derive(Debug)]
struct Foo { a: u32, b: u32 }
impl Default for Foo {
fn default() -> Foo { Foo{a:1, b:2} }
}
pub fn main() {
let mut foo_array: [Foo; 10];
// Do something here to in-place initialize foo_array?
for f in foo_array.iter() {
println!("{:?}", f);
}
}
error[E0381]: use of possibly uninitialized variable: `foo_array`
--> src/main.rs:13:14
|
13 | for f in foo_array.iter() {
| ^^^^^^^^^ use of possibly uninitialized `foo_array`
I implemented the Default trait, but Rust does not seem to call this by default akin to a C++ constructor.
What is the proper way to initialize a fixed length array? I'd like to do an efficient in-place initialization rather than some sort of copy.
Related: Why is the Copy trait needed for default (struct valued) array initialization?
Related: Is there a way to not have to initialize arrays twice?
The safe but somewhat inefficient solution:
#[derive(Copy, Clone, Debug)]
struct Foo {
a: u32,
b: u32,
}
fn main() {
let mut foo_array = [Foo { a: 10, b: 10 }; 10];
}
Since you're specifically asking for a solution without copies:
use std::mem::MaybeUninit;
#[derive(Debug)]
struct Foo {
a: u32,
b: u32,
}
// We're just implementing Drop to prove there are no unnecessary copies.
impl Drop for Foo {
fn drop(&mut self) {
println!("Destructor running for a Foo");
}
}
pub fn main() {
let array = {
// Create an array of uninitialized values.
let mut array: [MaybeUninit<Foo>; 10] = unsafe { MaybeUninit::uninit().assume_init() };
for (i, element) in array.iter_mut().enumerate() {
let foo = Foo { a: i as u32, b: 0 };
*element = MaybeUninit::new(foo);
}
unsafe { std::mem::transmute::<_, [Foo; 10]>(array) }
};
for element in array.iter() {
println!("{:?}", element);
}
}
This is recommended by the documentation of MaybeUninit.
You can use the arrayvec crate:
Cargo.toml
[package]
name = "initialize_array"
version = "0.1.0"
edition = "2018"
[dependencies]
arrayvec = "0.7.2"
src/main.rs
use arrayvec::ArrayVec;
use std::iter;
#[derive(Clone)]
struct Foo {
a: u32,
b: u32,
}
fn main() {
let foo_array: [Foo; 10] = iter::repeat(Foo { a: 10, b: 10 })
.take(10)
.collect::<ArrayVec<_, 10>>()
.into_inner()
.unwrap_or_else(|_| unreachable!());
}
The easiest way is to derive Copy on your type and initialize the array with that, copying the element N times:
#[derive(Copy)]
struct Foo {
a: u32,
b: u32,
}
let mut foo_array = [Foo { a: 1, b: 2 }; 10];
If you want to avoid copying, there are a couple options. You can use the Default trait:
let mut foo_array: [Foo; 10] = Default::default();
However, this is limited to arrays up to 32 elements. With const generics, it is now possible for the standard library to provide Default for all arrays. However, this would be a backward incompatible change for subtle reasons that are being worked on.
For now, you can take advantage of the fact that const values are also allowed in array repetition expressions:
const FOO: Foo = Foo { a: 1, b: 2 };
let mut foo_array = [FOO; 10];
If you're on nightly, you can use array::map:
#![feature(array_map)]
let mut foo_array = [(); 10].map(|_| Foo::default())

How do I declare a "static" field in a struct in Rust?

How do I declare a "static" field in a struct in Rust, preferably with a default value:
struct MyStruct {
x: i32, // instance
y: i32, // instance
my_static: i32 = 123, // static, how?
}
fn main() {
let a = get_value();
if a == MyStruct::my_static {
//...
} else {
//...
}
}
You can declare an associated constant in an impl:
struct MyStruct {
x: i32,
y: i32,
}
impl MyStruct {
const MY_STATIC: i32 = 123;
}
fn main() {
println!("MyStruct::MY_STATIC = {}", MyStruct::MY_STATIC);
}
Rust does not support static fields in structures, so you can't do that. The closest thing you can get is an associated method:
struct MyStruct {
x: i32,
y: i32,
}
impl MyStruct {
#[inline]
pub fn my_static() -> i32 {
123
}
}
fn main() {
let a = get_value();
if a == MyStruct::my_static() {
//...
} else {
//...
}
}
You can't declare a field static in a struct.
You can declare a static variable at module scope like this :
static FOO: int = 42;
And you can't have a static variable mutable without unsafe code : to follow borrowing rules it would have to be wrapped in a container making runtime borrowing checks and being Sync, like Mutex or RWLock, but these cannot be stored in static variable as they have non-trivial constructors.

Is it possible to generate a struct with a macro?

trait Print {
fn print(&self);
}
struct Printer {
p: Box<Print>,
}
fn main() {
let i = 1i32;
let s = String::from_str("Hello");
// let mp = make_printer!(i,s);
let mp = |i: i32, s: String| {
struct Foo {
i: i32,
s: String,
}
impl Foo {
fn new(i: i32, s: String) -> Foo {
Foo { i: i, s: s }
}
}
impl Print for Foo {
fn print(&self) {
println!("{} {}", self.i, self.s);
}
}
Printer { p: box Foo::new(i, s) }
};
let printer = mp(i, s);
printer.p.print();
}
I want to create the make_printer! macro which should expand to mp if I call it with make_printer!(i,s).
Is this is possible? I think the biggest issue here is that I need something like decltype from C++ so that I can extract the type from a variable. The struct could then look like:
#![feature(macro_rules)]
macro_rules! make_printer(
($($element:ident),*) => (
struct Foo{
$($element : decltype($element),)*
}
)
)
No, it's not possible to do it with just the expression identifiers. You need explicit types, e.g.
macro_rules! make_printer {
($($element: ident: $ty: ty),*) => {
struct Foo { $($element: $ty),* }
}
}
called like make_printer!(x: i32, y: String).
This is required for two, mostly orthogonal, reasons:
macros don't have access to any type information, they are just local syntactic transformations (e.g. it's not even possible to write a macro (either macro_rules! or procedural) that can tell if a given ident refers to a local variable).
Rust doesn't have a decltype equivalent.

Resources