This question already has an answer here:
What does the ampersand (&) before `self` mean in Rust?
(1 answer)
Closed 12 months ago.
It is unclear for my what difference between self and &self!
Because in my example both work.
&self The variable created with the struct/enum is borrowed by the function means the the ownership is not given. The function in which the variable is created will have the ownership.
self The ownership is transferred and the variable is destroyed after execution of the function
struct User {
name: String,
id: i32
}
impl User {
fn print_name(&self) -> () {
println!("{}", self.name);
}
fn print_id(self) -> () {
println!("{}", self.id);
}
}
fn main() {
let me = User { name: "Haider".to_owned(), id: 1234 };
// me is borrowed so this means the variable is still owned by the `main` function we can call as many as functions until the ownership isn't transferred
me.print_name();
me.print_name();
me.print_name();
me.print_name();
// ownership transferred and the `me` is destroyed after the execution of `me.print_id()` we will get error if run any other function on `me`
me.print_id();
// Error
me.print_name();
}
&self
&self is a reference to the instance(object) of a struct that calls it. Is good to know that when you add a method (A function that is used by an instance of a struct) by an impl block, you must add &self or &mut self (&mut self means that only mutable instance of the struct can access it`) For example, this is a method:
fn a_method(&self){
//Stuff that goes in a method
}
//When you call it, you can just ignore `&self` or `&mut self`
a_method();
self
self represents the instance of a struct.
struct animal{
age: i32,
name: String
}
impl animal{ //Add methods and function in an impl block
fn display_name(&self) { //A method
println!("Hello, my name is {}.", self.name); //`self` used here to represent that animal (instance of the animal struct)
}
}
fn main(){
let my_cat: animal = animal{age: 32, name: "Cat".to_string()}; //Declare an instance of the animal struct
my_cat.display_name(); //Calling the method
}
For the result it should be:
Hello my name is Cat.
Related
this happens to me a lot of times, for example,
pub struct EmailTemplateMessageBuilder(Translator);
impl EmailTemplateMessageBuilder {
pub fn new(locale: LanguageIdentifier) -> Self{
Self(Translator::new(locale))
}
fn render<C>(&self, template_name: &str, email_template: &EmailTemplate, context: &C) -> String {
let mut template_engine = TinyTemplate::new();
let translator = self.0;
//The add_formatter method below has signature:
// pub fn add_formatter<F>(&mut self, name: &'template str, formatter: F)
// where
// F: 'static + Fn(&Value, &mut String) -> Result<()>
template_engine.add_formatter(
"trans",
|value: &Value, output: &mut String| {
match value {
Value::String(s) => {
output.push_str(translator.trans_simple(s).as_ref());
Ok(())
}
_ => panic!("Unable to translate {}", value),
}
});
template_engine.render("default", context)
.expect(&format!("Enable to render email template {}", template_name))
}
}
Since the EmailTemplateMessageBuilder struct owns the translator, I know its lifetime outlives the template_engine variable, so does to the closure,
the translator variable should be always valid when its get called. it seems I need a way to turn self-owned reference to 'static lifetime.
Note:
The Translator can't implement Copy trait, because it depends on other variable which is not copied.
This code is run in the same thread, no future, no multiple threads.
it seems I need a way to turn self-owned reference to 'static lifetime.
That's what Rc is for. Define the struct as EmailTemplateMessageBuilder(Rc<Translator>), and define translator as self.0.clone(). The clone() only clones the pointer and increases the reference count, so it's cheap. Finally, make the closure move, so it owns all captured data.
I am new to rust, and especially to embedded rust. I have written something which maintains an 'alarm system', which can be in a variety of defined states. The Alarm struct, when transitioning to the armed state, sets up a GPIO pin interrupt with a closure that should be able to set the alarm's state to Alarm when triggered. The compiler complains that there is no guarantee that the closure will not outlive the struct. I understand the issue, but I am not clear on how to fix it.
use crate::pins::CustomPin;
use sysfs_gpio::Pin;
#[derive(Debug)]
pub enum States {
Disarmed,
Armed,
Alarm,
Error,
}
pub struct Alarm {
pub state: States,
pub trigger_pin: Pin,
}
impl Alarm {
pub fn arm(&mut self) -> () { // `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
match self.trigger_pin.set_interrupt(Box::new(|| self.trigger())) { //...is captured and required to live as long as `'static` here
Ok(_) => self.update(States::Armed),
Err(_) => self.update(States::Error),
};
}
pub fn disarm(&mut self) -> () {
self.update(States::Disarmed);
}
pub fn trigger(&mut self) -> () {
self.update(States::Alarm);
}
pub fn new(trigger_pin: u64) -> Alarm {
let input = Pin::new(trigger_pin);
Alarm {
state: States::Disarmed,
trigger_pin: input,
}
}
fn update(&mut self, state: States) -> () {
self.state = state;
}
}
--
extern crate sysfs_gpio;
use sysfs_gpio::{Direction, Edge, Pin};
pub trait CustomPin {
fn set_interrupt(&self, callback: Box<dyn Fn() -> ()>) -> sysfs_gpio::Result<()>;
}
impl CustomPin for Pin {
fn set_interrupt(&self, callback: Box<dyn Fn() -> ()>) -> sysfs_gpio::Result<()> {
self.with_exported(|| {
self.set_direction(Direction::In)?;
self.set_edge(Edge::FallingEdge)?;
let mut poller = self.get_poller()?;
loop {
match poller.poll(1000)? {
Some(_) => callback(),
None => (),
}
}
})
}
}
I understand the compiler message, but I don't know how to fix it. I considered a RefCell, but my understanding is that this would force the Alarm to live for as long as the closure, when in fact, the closure should not outlive the Alarm.
I suppose the point fundamentally is that I don't know how to drop that closure explicitly.
Your problem is that Box assumes a static lifetime unless explicitly stated otherwise. Consequently, the lifetime problem in your example can be fixed by defining an explicit lifetime parameter to the trait like:
pub trait CustomPin {
fn set_interrupt<'a>(&self, callback: Box<dyn FnMut() -> () + 'a>) -> sysfs_gpio::Result<()>;
}
Unfortunately, there are more fundamental ownership issues in your example that the borrow checker will reject. Your essential problem is that you're referencing self from every closure, especially even from functions requiring &mut self. This will always fail, you need an Rc or similar constructs to reference the same Alarm struct from multiple places following the "average C++ construct" you're probably migrating from.
I am trying to create a struct that modifies its current_value by appending some "constant" string first_step which is defined when the struct is first created.
code
fn main() {
let mut adder = Adder {
current_value: "init".to_string(),
first_step: ", first".to_string(),
};
adder.do_something()
}
struct Adder {
current_value: String,
first_step: String,
}
impl Adder {
fn add(&mut self, value: &String) {
self.current_value = format!("{}{}", self.current_value, value);
}
fn do_something(&mut self) {
// cannot borrow `*self` as mutable because it is also borrowed as immutable
// mutable borrow occurs here rustc(E0502)
// main.rs(24, 18): immutable borrow occurs here
// main.rs(24, 14): immutable borrow later used by call
self.add(&self.first_step);
}
}
playground
I think the errors are quite clear (the self in self.add is borrowed as mutable because the signature of add has &mut self, but then the value to be appended also comes from self, but this time borrowed as immutable, and we cannot borrow self both mutable and immutable).
But I don't know how to fix this, creating a data structure that can update itself with some "constant" values that are defined when the structure itself is created. In the actual "real life" case I have a struct that contains both a file and file_header: String, and I want to have a method that writes the file_header into the file.
Rust does allow for borrowing parts of a struct separately, but when you call a function/method that takes &mut Self, that always borrows the entire struct — the body of the function is never used as additional information. So, a solution to problems like where you want to mutate part of your structure using information from another part is to rewrite your function signature so that it does have the necessary information.
impl Adder {
/// Algorithm implementation; takes all components explicitly.
/// Is not a method.
fn add_impl(current_value: &mut String, add_value: &str) {
current_value.push_str(add_value);
}
/// Method for external use — less flexible, but simple.
pub fn add(&mut self, value: &str) {
Self::add_impl(&mut self.current_value, value);
}
fn do_something(&mut self) {
Self::add_impl(&mut self.current_value, &self.first_step);
}
}
Your description “…a data structure that can update itself with some "constant" values that are defined when the structure itself is created…” suggests that you might have a more complicated situation than this simple example. If you have more than one mutable field that needs updating (or even if you really want to use method syntax), you can make another struct that contains the right subset of fields — then the methods like do_something can call ordinary &mut self methods on the inner struct.
struct FancyAdder {
first_step: String,
data: AdderData,
}
struct AdderData {
current_value: String,
...
}
impl FancyAdder {
fn do_something(&mut self) {
// This borrows `self.data` mutably and `self.first_step` immutably.
// No overlap.
self.data.add(&self.first_step);
}
}
impl AdderData {
fn add(&mut self, value: &str) {
self.current_value.push_str(value);
}
}
There are already a lot of threads on this topic but I fail to see if the discussed problems apply to my specific problem.
I have a structure that stores a name and a callback function. Stripped down to the problem it looks like this:
pub struct Command<'a> {
name: &'a str,
callback: &'a Fn(&[&str]) -> ()
}
impl <'a> Command<'a> {
pub fn new(name: &'a str, callback: &'a Fn(&[&str]) -> ()) -> Command<'a> {
Command {
name: name,
callback: callback
}
}
}
What I want to do is store a callback function associated with a name (and prob. more stuff in the future).
But when I try to use this bit of code like so:
fn main() {
let play_callback = |args| {
println!("Playing something.");
for arg in args {
println!("{}", arg);
}
};
let play_command = Command::new("play", &play_callback);
}
I get the following error message:
src/main.rs:22:42: 22:56 error: type mismatch resolving `for<'r, 'r> <[closure#src/main.rs:16:22: 21:3] as std::ops::FnOnce<(&'r [&'r str],)>>::Output == ()`:
expected bound lifetime parameter ,
found concrete lifetime [E0271]
src/main.rs:22 let play_command = Command::new("play", &play_callback);
^~~~~~~~~~~~~~
I tried to inline the closure like this
fn main() {
let play_command = Command::new("play", &|args| {
println!("Playing something.");
for arg in args {
println!("{}", arg);
}
});
}
but then I get another error
src/main.rs:16:47: 21:7 error: borrowed value does not live long enough
which I believe I understand why I get.
I tried using a generic type parameter for Command before switching to a function reference first to store in my Command structure, but when I wanted to initialize a HashSet of command objects like this:
let mut commands: HashSet<Command> = HashSet::new();
the compiler wanted me to specify the generic parameter which I think I cannot do as that would mean I could only store the same closure in all my Command objects.
So my question would be: How can I achieve what I want and what is the best way to do so (and why)?
The easy fix (by ljedrz) is that args: &[&str] is not inferred in this case. However, it may not be enough to solve your problem.
When you use a reference to some trait as a function argument, it is treated as a trait object. In this case, the &Fn is a trait object that references the closure on the stack.
An easy analogy of trait objects are objects that implement interfaces in other languages.
However, lifetimes work a bit differently with the trait objects. You can think of them as "detached" from the usual ownership flow. If we were to annotate the Fn trait object lifetime 'c in your example, we would get the following code:
pub struct Command<'a> {
name: &'a str,
callback: &'a for<'c> Fn(&'c [&'c str]) -> ()
}
impl <'a> Command<'a> {
pub fn new<'r>(name: &'r str, callback: &'r for<'c> Fn(&'c [&'c str]) -> ()) -> Command<'r> {
Command {
name: name,
callback: callback
}
}
}
fn main() {
let play_callback = |args: &[&str]| {
println!("Playing something.");
for arg in args {
println!("{}", arg);
}
};
let play_command = Command::new("play", &play_callback);
}
In the code above, the lifetime 'c describes a scope in which the callback function will be called.
The above code, however, is not very practical. It couples the command to the scope in which the closure was created (remember, the trait object references the closure in that scope). So you can't exit from the function in which your Command was created, because that would destroy the closure!
The likely solution is to store the closure on the heap, in Box<Fn(&[&str])>. The lifetime of a trait object in the box (heap memory) is controlled by the creation and destruction of the box, so it is the broadest possible ('static).
pub struct Command<'a> {
name: &'a str,
callback: Box<Fn(&[&str]) -> ()>
}
impl <'a> Command<'a> {
pub fn new<'r>(name: &'r str, callback: Box<Fn(&[&str]) -> ()>) -> Command<'r> {
Command {
name: name,
callback: callback
}
}
}
fn main() {
let play_callback = |args: &[&str]| {
println!("Playing something.");
for arg in args {
println!("{}", arg);
}
};
let play_command = Command::new("play", Box::new(play_callback));
}
In the example above, the closure will be moved into the box when the box is created, and will be destroyed together with Command.
Have you tried specifying the type of args? The following compiles for me:
fn main() {
let play_callback = |args: &[&str]| {
println!("Playing something.");
for arg in args {
println!("{}", arg);
}
};
let play_command = Command::new("play", &play_callback);
}
I don't know why it is not inferred, though.
I have a problem with the borrow checker when using traits as type parameter in a structure:
trait Trait {}
struct FooBar;
impl Trait for FooBar{}
struct Observer<Arg> {
action: Box<Fn(Arg) + Send>,
// Other fields
}
impl <Arg> Observer<Arg> {
fn new(action: Box<Fn(Arg) + Send>) -> Observer<Arg> {
Observer{action: action}
}
fn execute(&self, arg: Arg) {
(*self.action)(arg);
}
}
fn test() {
let mut foobar = FooBar;
{
let mut observer = Observer::new(Box::new(|&: param: &mut Trait| {
// do something with param here
}));
observer.execute(&mut foobar); // First borrow passes ...
observer.execute(&mut foobar); // This fails as "foobar" is already borrowed
} // The previous borrow ends here (lifetime of "observer")
}
The output is:
error: cannot borrow `foobar` as mutable more than once at a time
observer.execute(&mut foobar); // This fails as "foobar" is already borrowed
^~~~~~
note: previous borrow of `foobar` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foobar` until the borrow ends
observer.execute(&mut foobar); // First borrow passes ...
^~~~~~
note: previous borrow ends here
{
...
} // The previous borrow ends here (lifetime of "observer")
^
Yet the following example works:
trait Trait {}
struct FooBar;
impl Trait for FooBar{}
struct Observer {
action: Box<Fn(&mut Trait) + Send>,
// Other fields
}
impl Observer {
fn new(action: Box<Fn(&mut Trait) + Send>) -> Observer {
Observer{action: action}
}
fn execute(&self, arg: &mut Trait) {
(*self.action)(arg);
}
}
fn test() {
let mut foobar = FooBar;
{
let mut observer = Observer::new(Box::new(|&: param: &mut Trait| {
// do something with param here
}));
observer.execute(&mut foobar);
observer.execute(&mut foobar);
}
}
This looks really weird to me, as the second example is just an instantiation of the first example, and I could probably (painfully) implement the same thing with macros.
I guess this is quite tricky, as I need to know the type of the parameter taken by the closure, but I don't need to store this reference ...
Is this a bug in the borrow checker? Or am I doing something wrong?
rustc 1.0.0-nightly (44a287e6e 2015-01-08 17:03:40 -0800)
EDIT 1: Precised the use case
EDIT 2: As explained in the answer below, the issue is that the borrow checker forces the lifetime of Observer<&mut Type> to be the same as the &mut Type, so in fact the issue is not related to the fact that we use a trait as a type parameter (it does the same with an actual structure).
So in my case, I can have a workaround by defining Observer<Arg> like this:
struct Observer<Arg> {
action: Box<Fn(&mut Arg) + Send>,
}
so the type parameter Arg itself is not a reference, but this makes the code less generic. Anybody has a better solution?
The problem here is that the borrow checker is forcing the lifetime of the &mut Trait reference to be the same as the whole GenericStruct. I believe this is because the reference is a type parameter of the struct itself.
Since your struct has no fields that store the reference (if you need to do this in your original code, please update your question), then you can move the type parameter to the method itself, instead of the struct:
trait Trait{}
struct FooBar;
impl Trait for FooBar{}
struct GenericStruct;
impl GenericStruct {
fn bar<T>(&self, _: T) {}
}
fn main() {
let mut foobar = FooBar;
{
let foo = GenericStruct;
foo.bar(&mut foobar);
foo.bar(&mut foobar);
}
}
This will make the borrow last only as long as the call to foo.bar().