Why can't I reuse a funtion's borrowed pointer - pointers

I don't understand why rustc gives me this error error: use of moved value: 'f' at compile time, with the following code:
fn inner(f: &fn(&mut int)) {
let mut a = ~1;
f(a);
}
fn borrow(b: &mut int, f: &fn(&mut int)) {
f(b);
f(b); // can reuse borrowed variable
inner(f); // shouldn't f be borrowed?
// Why can't I reuse the borrowed reference to a function?
// ** error: use of moved value: `f` **
//f(b);
}
fn main() {
let mut a = ~1;
print!("{}", (*a));
borrow(a, |x: &mut int| *x+=1);
print!("{}", (*a));
}
I want to reuse the closure after I pass it as argument to another function. I am not sure if it is a copyable or a stack closure, is there a way to tell?
That snippet was for rustc 0.8. I managed to compile a different version of the code with the latest rustc (master: g67aca9c), changing the &fn(&mut int) to a plain fn(&mut int) and using normal functions instead of a closure, but how can I get this to work with a closure?

The fact of the matter is that &fn is not actually a borrowed pointer in the normal sense. It's a closure type. In master, the function types have been fixed up a lot and the syntax for such things has changed to |&mut int|—if you wanted a borrowed pointer to a function, for the present you need to type it &(fn (...)) (&fn is marked obsolete syntax for now, to help people migrating away from it, because it's a completely distinct type).
But for closures, you can then go passing them around by reference: &|&mut int|.

Related

Error: Reached the recursion limit while instantiating `<std::iter::Filter<std::iter::Sk...]>::{closure#0}]>::{closure#0}]>`

I have a function with following declaration:
fn find_solutions_internal<'a, I>(&self, words: I, iterate_from: usize, chain: &mut Vec<u32>)
where I: Iterator<Item=&'a u32> + Clone;
Because the function recursively iterates over the same vector (max-depth of recursion is 5) with different filters I decided that it would be more effecient to pass the iterator as an argument.
Following part of code causes error:
let iterator = words.skip(iterate_from).filter(|&mask| mask & last_mask == 0);
let filtered_words = iterator.clone();
iterator.enumerate().for_each(|(i, &mask)| {
chain.push(mask);
self.find_solutions_internal(filtered_words.clone(), i, chain); // filtered_words.clone() is what indirectly causes the error
chain.pop();
});
The error:
error: reached the recursion limit while instantiating `<std::iter::Filter<std::iter::Sk...]>::{closure#0}]>::{closure#0}]>`
115 | self.iter.fold(init, fold)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `<std::iter::Filter<I, P> as Iterator>::fold` defined here
...
Self-contained example of the problematic code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ada8578f166ad2a34373d82cc376921f
Working example with collected iteration to vector: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4c13d2d0ac17038dac61c9e2d59bbab5
As #Jmb commented, the compiler does not try figuring out how many times the function recurses, at least not for the purpose of allowing this kind of code to compile. The compiler assumes each call to find_solutions_internal() can potentially recurse, and so the compiler gets stuck repeatedly instantiating the function, as each recursive call has a unique iterator parameter type.
We can fix this problem by passing the iterator as a trait object when making the recursive call, though the fact that we're cloning the iterator complicates things, as the Clone trait doesn't work with trait objects. We can work around that with the dyn_clone crate, at the cost of some boilerplate.
First we define a clonable iterator trait:
use dyn_clone::DynClone;
trait ClonableIterator<T>: Iterator<Item = T> + DynClone {}
impl<I, T> ClonableIterator<T> for I where I: Iterator<Item = T> + DynClone {}
dyn_clone::clone_trait_object!(<T> ClonableIterator<T>);
Then in the recursive call we construct the trait object:
self.find_solutions_internal(
Box::new(filtered_words.clone()) as Box<dyn ClonableIterator<_>>,
i,
chain,
);
While the above solution works, I think it'll likely end up slower than doing the simple thing of just collecting into a Vec. If the vector is really big, using a datastructure like Vector from the im crate, which supports O(1) cloning and O(log n) remove might be faster.

How to get a slice of references from a vector in Rust?

Somewhere in the API I use I have a function which takes &[&A] as argument but I only have a vector of A objects. When I try to use this function with
following syntax
pub struct A(pub u64);
fn test(a: &[&A]){}
fn main() {
let v = vec![A(1), A(2), A(3)];
let a = &v[..];
test(a);
}
I have a error:
<anon>:12:9: 12:10 error: mismatched types:
expected `&[&A]`,
found `&[A]`
(expected &-ptr,
found struct `A`) [E0308]
I have made some attempts but without any success:
let a = &v[&..]
and
let a = &v[&A]
How can I make &[&A] from Vec<A>?
Short answer: you can't. These types are not compatible with each other.
What you could do if this is really what the API needs is
test(&v.iter().collect::<Vec<_>>());
But this allocates a new vector. If you are the author of the API, consider changing it: &[&T] is a weird type to work with since you need different owners for the slice and the objects in it. &[T] already has a pass-by-reference semantic of the inner objects.

Why does asserting on the result of Deref::deref fail with a type mismatch?

The following is the Deref example from The Rust Programming Language except I've added another assertion.
Why does the assert_eq with the deref also equal 'a'? Why do I need a * once I've manually called deref?
use std::ops::Deref;
struct DerefExample<T> {
value: T,
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x.deref()); // this is true
// assert_eq!('a', x.deref()); // this is a compile error
assert_eq!('a', *x); // this is also true
println!("ok");
}
If I uncomment the line, I get this error:
error[E0308]: mismatched types
--> src/main.rs:18:5
|
18 | assert_eq!('a', x.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected char, found &char
|
= note: expected type `char`
found type `&char`
= help: here are some functions which might fulfill your needs:
- .to_ascii_lowercase()
- .to_ascii_uppercase()
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
First, let's spell out the generic types for your specific example: 'a' is char, so we have:
impl Deref for DerefExample<char> {
type Target = char;
fn deref(&self) -> &char {
&self.value
}
}
Notably, the return type of deref is a reference to a char. Thus it shouldn't be surprising that, when you use just x.deref(), the result is a &char rather than a char. Remember, at that point deref is just another normal method — it's just implicitly invoked as part of some language-provided special syntax. *x, for example, will call deref and dereference the result, when applicable. x.char_method() and fn_taking_char(&x) will also call deref some number of times and then do something further with the result.
Why does deref return a reference to begin with, you ask? Isn't that circular? Well, no, it isn't circular: it reduces library-defined smart pointers to the built-in type &T which the compiler already knows how to dereference. By returning a reference instead of a value, you avoid a copy/move (which may not always be possible!) and allow &*x (or &x when it's coerced) to refer to the actual char that DerefExample holds rather than a temporary copy.
See also:
Why is the return type of Deref::deref itself a reference?

Pointer-stashing generics via `mem::transmute()`

I'm attempting to write Rust bindings for a C collection library (Judy Arrays [1]) which only provides itself room to store a pointer-width value. My company has a fair amount of existing code which uses this space to directly store non-pointer values such as pointer-width integers and small structs. I'd like my Rust bindings to allow type-safe access to such collections using generics, but am having trouble getting the pointer-stashing semantics working correctly.
The mem::transmute() function seems like one potential tool for implementing the desired behavior, but attempting to use it on an instance of a parameterized type yield a confusing-to-me compilation error.
Example code:
pub struct Example<T> {
v: usize,
t: PhantomData<T>,
}
impl<T> Example<T> {
pub fn new() -> Example<T> {
Example { v: 0, t: PhantomData }
}
pub fn insert(&mut self, val: T) {
unsafe {
self.v = mem::transmute(val);
}
}
}
Resulting error:
src/lib.rs:95:22: 95:36 error: cannot transmute to or from a type that contains type parameters in its interior [E0139]
src/lib.rs:95 self.v = mem::transmute(val);
^~~~~~~~~~~~~~
Does this mean a type consisting only of a parameter "contains type parameters in its interior" and thus transmute() just won't work here? Any suggestions of the right way to do this?
(Related question, attempting to achieve the same result, but not necessarily via mem::transmute().)
[1] I'm aware of the existing rust-judy project, but it doesn't support the pointer-stashing I want, and I'm writing these new bindings largely as a learning exercise anyway.
Instead of transmuting T to usize directly, you can transmute a &T to &usize:
pub fn insert(&mut self, val: T) {
unsafe {
let usize_ref: &usize = mem::transmute(&val);
self.v = *usize_ref;
}
}
Beware that this may read from an invalid memory location if the size of T is smaller than the size of usize or if the alignment requirements differ. This could cause a segfault. You can add an assertion to prevent this:
assert_eq!(mem::size_of::<T>(), mem::size_of::<usize>());
assert!(mem::align_of::<usize>() <= mem::align_of::<T>());

Cannot move out of borrowed content when borrowing a generic type

I have a program that more or less looks like this
struct Test<T> {
vec: Vec<T>
}
impl<T> Test<T> {
fn get_first(&self) -> &T {
&self.vec[0]
}
fn do_something_with_x(&self, x: T) {
// Irrelevant
}
}
fn main() {
let t = Test { vec: vec![1i32, 2, 3] };
let x = t.get_first();
t.do_something_with_x(*x);
}
Basically, we call a method on the struct Test that borrows some value. Then we call another method on the same struct, passing the previously obtained value.
This example works perfectly fine. Now, when we make the content of main generic, it doesn't work anymore.
fn generic_main<T>(t: Test<T>) {
let x = t.get_first();
t.do_something_with_x(*x);
}
Then I get the following error:
error: cannot move out of borrowed content
src/main.rs:14 let raw_x = *x;
I'm not completely sure why this is happening. Can someone explain to me why Test<i32> isn't borrowed when calling get_first while Test<T> is?
The short answer is that i32 implements the Copy trait, but T does not. If you use fn generic_main<T: Copy>(t: Test<T>), then your immediate problem is fixed.
The longer answer is that Copy is a special trait which means values can be copied by simply copying bits. Types like i32 implement Copy. Types like String do not implement Copy because, for example, it requires a heap allocation. If you copied a String just by copying bits, you'd end up with two String values pointing to the same chunk of memory. That would not be good (it's unsafe!).
Therefore, giving your T a Copy bound is quite restrictive. A less restrictive bound would be T: Clone. The Clone trait is similar to Copy (in that it copies values), but it's usually done by more than just "copying bits." For example, the String type will implement Clone by creating a new heap allocation for the underlying memory.
This requires you to change how your generic_main is written:
fn generic_main<T: Clone>(t: Test<T>) {
let x = t.get_first();
t.do_something_with_x(x.clone());
}
Alternatively, if you don't want to have either the Clone or Copy bounds, then you could change your do_something_with_x method to take a reference to T rather than an owned T:
impl<T> Test<T> {
// other methods elided
fn do_something_with_x(&self, x: &T) {
// Irrelevant
}
}
And your generic_main stays mostly the same, except you don't dereference x:
fn generic_main<T>(t: Test<T>) {
let x = t.get_first();
t.do_something_with_x(x);
}
You can read more about Copy in the docs. There are some nice examples, including how to implement Copy for your own types.

Resources