Looking through the blurz bluetooth library for Rust.
There is a variable declared with a value equal to a reference of a temp value(?).
This value is then passed into another function by reference.
How is ownership handled for a variable set to the value of a reference in a single statement and what does it mean to then use that reference as a reference?
Example:
let bt_session = &Session::create_session(None)?;
let adapter: Adapter = Adapter::init(bt_session)?;
adapter.set_powered(true)?;
let session = DiscoverySession::create_session(
&bt_session,
adapter.get_id()
)?;
See variable bt_session.
Source code example link.
A commented example to illustrate some concepts:
use rand;
#[derive(Debug)]
struct Struct {
id: i32
}
impl Drop for Struct {
fn drop(&mut self) {
// print when struct is dropped
println!("dropped {:?}", self);
}
}
fn rand_struct() -> Struct {
Struct { id: rand::random() }
}
/*
this does not compile:
fn rand_struct_ref<'a>() -> &'a Struct {
&rand_struct()
// struct dropped here so we can't return it to caller's scope
}
*/
fn takes_struct_ref(s: &Struct) {}
fn main() {
// brings struct into scope and immediately creates ref to it
// this is okay because the struct is not dropped until end of this scope
let s = &rand_struct();
println!("holding ref to {:?}", s);
// all these work because of deref coercion
takes_struct_ref(s);
takes_struct_ref(&s);
takes_struct_ref(&&s);
// struct dropped here
}
playground
To answer your first question: You can't return a reference from a function if the underlying value is dropped at the end of the function but it's okay to immediately make a reference to a returned value since that value lives for the rest of the caller's scope. You can see this in action if you run the above example, as holding ref to Struct { id: <id> } will get printed before dropped Struct { id: <id> }.
To answer your second question: the reason you can pass an &Struct or an &&Struct or an &&&Struct and so on to function which only takes an &Struct is because of a Rust syntax sugar feature called deref coercion which automatically derefs variables when they are used as function arguments or as part of method calls. In your shared code examples it looks like a ref of a ref is being passed to the function but actually it's just passing a single ref after auto deref coercion takes place.
See also
Why is it legal to borrow a temporary?
What are Rust's exact auto-dereferencing rules?
Related
In module db.rs , while reading the value from the DataBase, i got the Error temporary value dropped while borrowed
consider using a let binding to create a longer lived value
use bytes::Bytes;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug)]
pub struct Db {
// pub entries: Arc<bool>,
pub entries: Arc<Mutex<HashMap<String, Bytes>>>,
}
impl Db {
pub fn new() -> Db {
Db {
entries: Arc::new(Mutex::new(HashMap::new())),
}
}
/// Reads data from the database
pub fn read(&mut self, arr: &[String]) -> Result<Bytes, &'static str> {
let key = &arr[1];
let query_result = self.entries.lock().unwrap().get(key);// Error in this Line.
if let Some(value) = query_result {
return Ok(Bytes::from("hello"));
} else {
return Err("no such key found");
}
}
}
but when i modify the code and trying to get the value in the next line, it didn't give any error.
let query_result = self.entries.lock().unwrap();
let result = query_result.get(key);
can anyone help me understand what's going on under the hood?
We can see why Rust thinks this is an error by checking how Mutex::lock works. If successful, it doesn't return a reference directly, it returns a MutexGuard struct that can deref into the type it wraps, a HashMap in your case.
The signature of Deref::deref<Target = T> is (with the elided lifetimes added):
fn deref<'a>(&'a self) -> &'a T
This means that the MutexGuard can only give us a reference to the HashMap inside for as long as it is itself alive (the lifetime 'a). But because you never store it anywhere, instead dereferencing it directly, Rust thinks that it gets dropped right after the call to get. But you keep the result of get around, which can only live for as long as the reference to the HashMap passed into it, which in turn only lives as long as the MutexGuard which gets dropped immediately.
If you store the MutexGuard, on the other hand, like
let guard = self.entries.lock().unwrap();
let query_result = guard.get(key);
it only gets dropped at the end of the scope, so any references it gave out are also valid until the end of the scope.
Consider the following Rust code, slightly modified from examples in The Book.
I'm trying to understand what happens to the value in the second running of function dangle() in the main() function (see comment). I would imagine that because the value isn't assigned to any owner, it gets deallocated, but I've so far failed to find information to confirm that. Otherwise, I would think that calling dangle() repeatedly would constantly allocate more memory without deallocating it. Which is it?
fn main() {
// Ownership of dangle()'s return value is passed to the variable `thingamabob`.
let thingamabob = dangle();
// No ownership specified. Is the return value deallocated here?
dangle();
println!("Ref: {}", thingamabob);
}
fn dangle() -> String {
// Ownership specified.
let s = String::from("hello");
// Ownership is passed to calling function.
s
}
When a value has no owner (is not bound to a variable) it goes out of scope. Values that go out of scope are dropped. Dropping a value frees the resources associated with that value.
Anything less would lead to memory leaks, which would be a poor idea in a programming language.
See also:
Is it possible in Rust to delete an object before the end of scope?
How does Rust know whether to run the destructor during stack unwind?
Does Rust free up the memory of overwritten variables?
In your example, the second call creates an unnamed temporary value whose lifetime ends immediately after that one line of code, so it goes out of scope (and any resources are reclaimed) immediately.
If you bind the value to a name using let, then its lifetime extends until the end of the current lexical scope (closing curly brace).
You can explore some of this yourself by implementing the Drop trait on a simple type to see when its lifetime ends. Here's a small program I made to play with this (playground):
#[derive(Debug)]
struct Thing {
val: i32,
}
impl Thing {
fn new(val: i32) -> Self {
println!("Creating Thing #{}", val);
Thing { val }
}
fn foo(self, val: i32) -> Self {
Thing::new(val)
}
}
impl Drop for Thing {
fn drop(&mut self) {
println!("Dropping {:?}", self);
}
}
pub fn main() {
let _t1 = Thing::new(1);
Thing::new(2); // dropped immediately
{
let t3 = Thing::new(3);
Thing::new(4).foo(5).foo(6); // all are dropped, in order, as the next one is created
println!("Doing something with t3: {:?}", t3);
} // t3 is dropped here
} // _t1 is dropped last
I have a function that will create one of several structs (all of which have a method of the same signature but have other, different, methods and traits); I would like to instance one of the structs in a function and return a reference to its method that can be called elsewhere.
// Pseudocode
type SizeGetter = fn()-> isize;
fn get_ref()-> &SizeGetter{
let catch = Fish{weight: 12};
&catch.get_weight()
//Fish.get_weight() is used here but it may be any struct.method() -> isize
}
fn main() {
let getit = get_ref();
println!("{}", getit());
}
In the above my goal is to define catch.getweight() in a function, return a reference to that function and then call it later to get the size.
That original attempt could not work because you cannot return a reference to something created in a function. In this case, returning something equivalent to a method to a locally created struct value requires the value to outlive the function's lifetime as well.
We can reference a method bar in a struct Foo with Foo::bar, but this one isn't bound to a receiver value. There is no syntax specifically for referencing a method call on a value. The solution instead is to create a closure that captures the value and calls the method.
let foo = Foo::new();
move || foo.bar()
Considering this Fish struct and implementation (adjusted to comply with naming conventions):
struct Fish {
weight: usize,
}
impl Fish {
fn weight(&self) -> usize {
self.weight
}
}
A function returning another self-sufficient function would be written like so:
fn fish_weight() -> impl Fn() -> usize {
let r#catch = Fish { weight: 12 };
move || r#catch.weight()
}
Using:
let get = fish_weight();
println!("Fish weight: {}", get());
Playground
How do I get over something like this:
struct Test {
foo: Option<fn()>
}
impl Test {
fn new(&mut self) {
self.foo = Option::Some(self.a);
}
fn a(&self) { /* can use Test */ }
}
I get this error:
error: attempted to take value of method `a` on type `&mut Test`
--> src/main.rs:7:36
|
7 | self.foo = Option::Some(self.a);
| ^
|
= help: maybe a `()` to call it is missing? If not, try an anonymous function
How do I pass a function pointer from a trait? Similar to what would happen in this case:
impl Test {
fn new(&mut self) {
self.foo = Option::Some(a);
}
}
fn a() { /* can't use Test */ }
What you're trying to do here is get a function pointer from a (to use Python terminology here, since Rust doesn't have a word for this) bound method. You can't.
Firstly, because Rust doesn't have a concept of "bound" methods; that is, you can't refer to a method with the invocant (the thing on the left of the .) already bound in place. If you want to construct a callable which approximates this, you'd use a closure; i.e. || self.a().
However, this still wouldn't work because closures aren't function pointers. There is no "base type" for callable things like in some other languages. Function pointers are a single, specific kind of callable; closures are completely different. Instead, there are traits which (when implemented) make a type callable. They are Fn, FnMut, and FnOnce. Because they are traits, you can't use them as types, and must instead use them from behind some layer of indirection, such as Box<FnOnce()> or &mut FnMut(i32) -> String.
Now, you could change Test to store an Option<Box<Fn()>> instead, but that still wouldn't help. That's because of the other, other problem: you're trying to store a reference to the struct inside of itself. This is not going to work well. If you manage to do this, you effectively render the Test value permanently unusable. More likely is that the compiler just won't let you get that far.
Aside: you can do it, but not without resorting to reference counting and dynamic borrow checking, which is out of scope here.
So the answer to your question as-asked is: you don't.
Let's change the question: instead of trying to crowbar a self-referential closure in, we can instead store a callable that doesn't attempt to capture the invocant at all.
struct Test {
foo: Option<Box<Fn(&Test)>>,
}
impl Test {
fn new() -> Test {
Test {
foo: Option::Some(Box::new(Self::a)),
}
}
fn a(&self) { /* can use Test */ }
fn invoke(&self) {
if let Some(f) = self.foo.as_ref() {
f(self);
}
}
}
fn main() {
let t = Test::new();
t.invoke();
}
The callable being stored is now a function that takes the invocant explicitly, side-stepping the issues with cyclic references. We can use this to store Test::a directly, by referring to it as a free function. Also note that because Test is the implementation type, I can also refer to it as Self.
Aside: I've also corrected your Test::new function. Rust doesn't have constructors, just functions that return values like any other.
If you're confident you will never want to store a closure in foo, you can replace Box<Fn(&Test)> with fn(&Test) instead. This limits you to function pointers, but avoids the extra allocation.
If you haven't already, I strongly urge you to read the Rust Book.
There are few mistakes with your code. new function (by the convention) should not take self reference, since it is expected to create Self type.
But the real issue is, Test::foo expecting a function type fn(), but Test::a's type is fn(&Test) == fn a(&self) if you change the type of foo to fn(&Test) it will work. Also you need to use function name with the trait name instead of self. Instead of assigning to self.a you should assign Test::a.
Here is the working version:
extern crate chrono;
struct Test {
foo: Option<fn(&Test)>
}
impl Test {
fn new() -> Test {
Test {
foo: Some(Test::a)
}
}
fn a(&self) {
println!("a run!");
}
}
fn main() {
let test = Test::new();
test.foo.unwrap()(&test);
}
Also if you gonna assign a field in new() function, and the value must always set, then there is no need to use Option instead it can be like that:
extern crate chrono;
struct Test {
foo: fn(&Test)
}
impl Test {
fn new() -> Test {
Test {
foo: Test::a
}
}
fn a(&self) {
println!("a run!");
}
}
fn main() {
let test = Test::new();
(test.foo)(&test); // Make sure the paranthesis are there
}
I'm trying to select a function to call depending on a condition. I want to store that function in a variable so that I can call it again later without carrying the condition around. Here's a working minimal example:
fn foo() {
println! ("Foo");
}
fn bar() {
println! ("Bar");
}
fn main() {
let selector = 0;
let foo: &Fn() = &foo;
let bar: &Fn() = &bar;
let test = match selector {
0 => foo,
_ => bar
};
test();
}
My question is: is it possible to get rid of the intermediate variables? I've tried simply removing them:
fn foo() {
println! ("Foo");
}
fn bar() {
println! ("Bar");
}
fn main() {
let selector = 0;
let test = match selector {
0 => &foo as &Fn(),
_ => &bar as &Fn()
};
test();
}
but then the borrow checker complains that the borrowed values are only valid until the end of the match (btw, why? the functions are 'static anyway so should be valid to the end of times). I've also tried making the 'static lifetime explicit by using &foo as &'static Fn() but that doesn't work either.
The following works, if you only need to work with static functions and not closures:
fn foo() {
println!("Foo");
}
fn bar() {
println!("Bar");
}
fn main() {
let selector = 0;
let test: fn() = match selector {
0 => foo,
_ => bar
};
test();
}
(try on playground)
Here I've used function type instead of function trait.
The reason that the borrowed trait object doesn't work is probably the following. Any trait object is a fat pointer which consists of a pointer to some value and a pointer to a virtual table. When the trait object is created out of a closure, everything is clear - the value would be represented by the closure itself (internally being an instance of a structure containing all captured variables) and the virtual table would contain a pointer to the implementation of the corresponding Fn*() trait generated by the compiler whose body would be the closure body.
With functions, however, things are not so clear. There are no value to create a trait object from because the function itself should correspond to the implementation of Fn() trait. Therefore, rustc probably generates an empty structure and implements Fn() for it, and this implementation calls the static function directly (not actual Rust, but something close):
struct SomeGeneratedStructFoo;
impl Fn<()> for SomeGeneratedStructFoo {
type Output = ();
fn call(&self, args: ()) -> () {
foo();
}
}
Therefore, when a trait object is created out of fn foo(), a reference is taken in fact to a temporary value of type SomeGeneratedStructFoo. However, this value is created inside the match, and only a reference to it is returned from the match, thus this value does not live long enough, and that's what the error is about.
fn() is a function pointer type. It's already a pointer type. You can check this with std::mem::size_of::<fn()>(). It is not a zero-sized type.
When you do &foo, you take a pointer to a stack allocated pointer. This inner pointer does not survive very long, causing the error.
You can cast these to the generic fn() type as suggested. I would be interested in knowing why you can't cast fn() to &Fn(), though.