Lifetime of function behaves differently in function pointer assignment and initialization - functional-programming

See the below example
fn fx(x: i32) -> i32
{
x
}
fn test_Functor()
{
// case 1. Initialization
let myFunctor: &Fn(i32) -> i32 = &fx ;
// case 2. Assignment
//let myFunctor: &Fn(i32) -> i32;
//myFunctor= &fx ;
}
This can compile.
If I comment case 1 and uncomment case 2. I got an error
Compiling study_rust v0.0.1 (main.rs)
src/main.rs:45:17: 45:19 error: borrowed value does not live long enough
src/main.rs:45 myFunctor= &fx ;
^~
src/main.rs:44:36: 47:2 note: reference must be valid for the block suffix following statement 0 at 44:35...
src/main.rs:44 let myFunctor: &Fn(i32) -> i32;
src/main.rs:45 myFunctor= &fx ;
src/main.rs:46
src/main.rs:47 }
src/main.rs:45:5: 45:21 note: ...but borrowed value is only valid for the statement at 45:4
src/main.rs:45 myFunctor= &fx ;
^~~~~~~~~~~~~~~~
src/main.rs:45:5: 45:21 help: consider using a `let` binding to increase its lifetime
src/main.rs:45 myFunctor= &fx ;
^~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `study_rust`.
Why? Is it a bug?
I am using rustc 1.5.0
rustc 1.5.0 (3d7cd77e4 2015-12-04)

I think it is not a bug. Note that it is also producing the same error without function pointers.
// this compiles
let a: &i32 = &3;
vs
let a: &i32;
a = &3;
//^ error: borrowed value does not live long enough
The two pieces of code above are not equivalent. A lifetime starts at the point where you bind a variable (let a: &32), not where you assign it (a = &3). If you split the two, like in the second case, you're saying that the lifetime for the &i32 is expected to start at the let a: &i32 line, which the compiler can't guarantee in the general case.
For instance, imagine if you did:
// does not compile
let a: &i32;
{
let b = 3;
a = &b;
} // b is out of scope, so a can't still contain a live reference here
you CAN make this work, but you explicitly need to tell the compiler that b is static (the static lifetime outlives everything), like this:
let a: &i32;
static b: i32 = 3;
a = &b;
or (in your original case):
let myFunctor: &Fn(i32) -> i32;
static F: fn(i32) -> i32 = fx;
myFunctor= &F;

Can it be linked to const vs static?
static i:usize = 0usize;
fn test_Functor()
{
// case 2. Assignment
let myFunctor: &usize;
myFunctor= &i ;
}
It compiles when i is static but not when i is const.
From the book, it is said that static aren't inlined ...

Related

Does the key of a HashMap have to be a pointer in Rust?

I'm admittedly new to Rust. That being said, this doesn't make sense to me yet finding out why the behavior I'm seeing isn't what I expect seems like a good learning opportunity:
use std::iter::Enumerate;
use std::collections::HashMap;
impl Solution {
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut numToI: HashMap<i32, usize> = HashMap::new();
for (i,v) in nums.iter().enumerate() {
let num: i32 = *v;
let complement: i32 = target - num;
if numToI.contains_key(complement) {
return vec![i as i32, numToI.get(complement) as i32];
} else {
numToI.insert(complement, i);
}
}
return vec![-1,-1];
}
}
Here I'm doing the simple question twoSum. I understand that nums.iter().enumerate() will return the values i and v, which are of type usize and a pointer to the element in nums (so in this case a reference to an i32), respectively. The thing I'm having trouble with is that although I specify numToI is a HashMap<i32, usize>, not HashMap<&i32, usize>, and I dereference to get the value of v with *v and assign the value to num, when I check if the HashMap numToI contains this i32 dereferenced value as a key, I get the error: expected &i32, found i32 on the call to contains_key. Why is this? Is it because the HashMap type always requires a pointer rather than a raw value, or is it due to an intricacy of Rust I'm not aware of? Shouldn't it expect a pointer for the key instead of a i32 if I had used HashMap<&i32, i32>?
More importantly, if this is due to a difference between Rust and C that has to do with the way borrowing etc. is used in Rust, where can I learn more about the intricacies of these differences?
contains_key takes a reference. It doesn't need to take ownership of the value to test with - it just needs to look at it temporarily.
Rust is complaining that you are passing in an i32 by value instead of a reference to it. It should tell you to borrow instead: numToI.contains_key(&complement).
That's the only issue with your code, really. HashMap keys don't need to be references, and it would be really inconvenient if they did.

Rust `Vec` - cannot borrow `Vec` as immutable inside `impl` method (error[E0502])

There are a lot of answers for the questions about Rust's error[E0502], but I can't really understand one particular case. I have a struct and it's impl method that goes like this:
struct Test {
test_vec: Vec<i32>,
}
impl Test {
// other methods...
fn test(&mut self) -> i32 {
self.test_vec.swap(0, self.test_vec.len() - 1);
// other operations...
}
}
Trying to compile that immediately results in error:
error[E0502]: cannot borrow self.test_vec as immutable because it is also borrowed as mutable
self.test_vec.swap(0, self.test_vec.len() - 1);
------------- ---- ^^^^^^^^^^^^^ immutable borrow occurs here
| |
| mutable borrow later used by call
mutable borrow occurs here
Can anyone please explain why? It doesn't really look like I'm trying to borrow self.test_vec there, I'm passing the usize type result of a len() call. On the other hand:
fn test(&mut self) -> i32 {
let last_index = self.test_vec.len() - 1;
self.test_vec.swap(0, last_index);
// other operations...
}
Using temporary variable, it works as expected, makes me thinking that len() call is somehow evaluated after it gets to to the swap, and thus being borrowed? Am I not seeing something because of the syntax sugar?
You have to think of this in the way the compiler does. When you write:
self.test_vec.swap(0, self.test_vec.len() - 1);
What the compiler sees:
let temp1 = &mut self.test_vec; // Mutable borrow of self.test_vec
let temp2 = &self.test_vec; // (ERROR!) Shared borrow of self.test_vec for use on getting the length
let temp3 = Vec::len(temp2) - 1;
Vec::swap(temp1, 0, temp3);
As you can see, you are borrowing self.test_vec mutably first, and then trying to get the length, which is another borrow. Since the first borrow is mutable and still in effect, the second borrow is illegal.
When you use a temporary variable, you are effectively reordering your borrows and since self.test_vec.len() terminates the borrow before the next mutable borrow, there are no conflicts.
You can argue the compiler should be able to see that your code can be correct (if interpreted with in the right way), but the compiler is clearly not smart enough yet to do so.

How do I return a reference to a concrete type that was added to a vector of trait objects?

In this code, I take a vector, create a struct instance, and add it to the vector boxed:
trait T {}
struct X {}
impl T for X {}
fn add_inst(vec: &mut Vec<Box<T>>) -> &X {
let x = X {};
vec.push(Box::new(x));
// Ugly, unsafe hack I made
unsafe { std::mem::transmute(&**vec.last().unwrap()) }
}
Obviously, it uses mem::transmute, which makes me feel it's not the right way to do this. Is this ugly hack the only way to do it?
Additionally, while this compiles in Rust 1.32, it fails in Rust 1.34:
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> src/lib.rs:10:14
|
10 | unsafe { std::mem::transmute(&**vec.last().unwrap()) }
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `&dyn T` (128 bits)
= note: target type: `&X` (64 bits)
I think that this code is safe:
fn add_inst(vec: &mut Vec<Box<dyn T>>) -> &X {
let x = X {};
let b = Box::new(x);
let ptr = &*b as *const X;
vec.push(b);
unsafe { &*ptr }
}
The trick is to save a raw pointer to *const X before converting it to a Box<dyn T>. Then you can convert it back to a reference before returning it from the function.
It is safe because a boxed value is never moved, (unless it it moved out of the Box, of course), so ptr survives the cast of b into Box<dyn T>.
Your "ugly hack" is actually completely incorrect and unsafe. You were unlucky that Rust 1.32 doesn't report the error, but thankfully Rust 1.34 does.
When you store a boxed value, you create a thin pointer. This takes up the platform-native size of an integer (e.g. 32-bit on 32-bit x86, 64-bit on 64-bit x86, etc.):
+----------+
| pointer |
| (0x1000) |
+----------+
When you store a boxed trait object, you create a fat pointer. This contains the same pointer to the data and a reference to the vtable. This pointer is two native integers in size:
+----------+----------+
| pointer | vtable |
| (0x1000) | (0xBEEF) |
+----------+----------+
By attempting to perform a transmute from the trait object to the reference, you are losing one of those pointers, but it's not defined which one. There's no guarantee which comes first: the data pointer or the vtable.
One solution would use std::raw::TraitObject, but this is unstable because the layout of fat pointers is still up in the air.
The solution I would recommend, which requires no unsafe code, is to use Any:
use std::any::Any;
trait T: Any {}
struct X {}
impl T for X {}
fn add_inst(vec: &mut Vec<Box<dyn T>>) -> &X {
let x = X {};
vec.push(Box::new(x));
let l = vec.last().unwrap();
Any::downcast_ref(l).unwrap()
}
If you couldn't / don't want to use Any, I've been told that casting a trait object pointer to a pointer to a concrete type will only keep the data pointer. Unfortunately, I cannot find an official reference for this, which means I can't fully vouch for this code, although it empirically works:
fn add_inst(vec: &mut Vec<Box<dyn T>>) -> &X {
let x = X {};
vec.push(Box::new(x));
let last: &dyn T = &**vec.last().unwrap();
// I copied this code from Stack Overflow without reading
// it and it may not actually be safe.
unsafe {
let trait_obj_ptr = last as *const dyn T;
let value_ptr = trait_obj_ptr as *const X;
&*value_ptr
}
}
See also:
Why can comparing two seemingly equal pointers with == return false?
How to get a reference to a concrete type from a trait object?
Accessing the last element of a Vec or a slice

Dereferencing raw pointer with explicit annotation in Rust

I was writing unsafe snippet of code to emulate how C would have allocated a memory for an int. The code allocates memory for an isize type, assign 0 to the pointer variable, then infinitely increment the value at the address every second
use std::process;
use std::{thread, time};
use std::alloc::{alloc, Layout};
fn main() {
unsafe {
let layout = Layout::new::<isize>();
let p = alloc(layout);
println!("({}) address pointed to by p: {:p}", process::id(), p);
*(p as *mut isize) = 0;
loop {
thread::sleep(time::Duration::from_millis(1000));
*(p as *mut isize) += 1;
println!("({}) p: {}", process::id(), *(p as *mut isize));
}
}
}
However, for each *(p as *mut size) I could have replaced with just *p without the compiler complaining (i.e. *p = 0;), thus I assumed it was correctly inferred. I need help explaining the difference and in which case the explicit type annotation may be required.
It's not correctly inferred. alloc returns a pointer to u8, which can be set to 0 or incremented, so the compiler doesn't complain. However it will wrap at 255 instead of wrapping at 4G (or whatever if you're on a 64-bit system).

How to allocate space for a Vec<T> in Rust?

I want to create a Vec<T> and make some room for it, but I don't know how to do it, and, to my surprise, there is almost nothing in the official documentation about this basic type.
let mut v: Vec<i32> = Vec<i32>(SIZE); // How do I do this ?
for i in 0..SIZE {
v[i] = i;
}
I know I can create an empty Vec<T> and fill it with pushes, but I don't want to do that since I don't always know, when writing a value at index i, if a value was already inserted there yet. I don't want to write, for obvious performance reasons, something like :
if i >= len(v) {
v.push(x);
} else {
v[i] = x;
}
And, of course, I can't use the vec! syntax either.
While vec![elem; count] from the accepted answer is sufficient to create a vector with all elements equal to the same value, there are other convenience functions.
Vec::with_capacity() creates a vector with the given capacity but with zero length. It means that until this capacity is reached, push() calls won't reallocate the vector, making push() essentially free:
fn main() {
let mut v = Vec::with_capacity(10);
for i in 0..10 {
v.push(i);
}
println!("{:?}", v);
}
You can also easily collect() a vector from an iterator. Example:
fn main() {
let v: Vec<_> = (1..10).collect();
println!("{:?}", v);
}
And finally, sometimes your vector contains values of primitive type and is supposed to be used as a buffer (e.g. in network communication). In this case you can use Vec::with_capacity() + set_len() unsafe method:
fn main() {
let mut v = Vec::with_capacity(10);
unsafe { v.set_len(10); }
for i in 0..10 {
v[i] = i;
}
println!("{:?}", v);
}
Note that you have to be extra careful if your vector contains values with destructors or references - it's easy to get a destructor run over a uninitialized piece of memory or to get an invalid reference this way. It will also work right if you only use initialized part of the vector (you have to track it yourself now). To read about all the possible dangers of uninitialized memory, you can read the documentation of mem::uninitialized().
You can use the first syntax of the vec! macro, specifically vec![elem; count]. For example:
vec![1; 10]
will create a Vec<_> containing 10 1s (the type _ will be determined later or default to i32). The elem given to the macro must implement Clone. The count can be a variable, too.
There is the Vec::resize method:
fn resize(&mut self, new_len: usize, value: T)
This code resizes an empty vector to 1024 elements by filling with the value 7:
let mut vec: Vec<i32> = Vec::new();
vec.resize(1024, 7);

Resources