I have code like this:
pub trait Action {
fn execute(&self);
}
struct AddAction<'a> {
rpn_calculator: &'a RpnCalculator
}
struct DeductAction<'a> {
rpn_calculator: &'a RpnCalculator
}
impl Action for DeductAction<'_> {
fn execute(&self) {
// ...
}
}
impl Action for AddAction<'_> {
fn execute(&self) {
// ...
}
}
impl<'a> RpnCalculator {
fn actions(&self) -> Vec<Box<dyn Action + 'a>> {
let mut actions: Vec<Box<dyn Action + 'a>> = vec![
Box::new(AddAction { rpn_calculator: &self })
Box::new(AddAction { rpn_calculator: &self })
// ...
];
// ...
actions
}
}
The intention of my code is that RpnCalculator.actions() should create some instances of some structs that implement trait Action and return a vector containing those instances. Those structs have a property rpn_calculator which is a reference to a RpnCalculator. The RpnCalculator.actions() should put self (the RpnCalculator that creates it) into this reference.
Now the error I get is "cannot infer the appropiate lifetime". I get this error in the line where I create an instance that I add to the vector:
Box::new(AddAction { rpn_calculator: &self })
For that reason I have 'a in the vector declaration, but it still doesn't work.
You should probably use fn actions(&'a self) because the lifetime
'a you use in dyn Action + 'a is related to the lifetime
of the RpnCalculator.
Related
How can I keep ownership of a value after passing it to a function that takes a impl Trait as a parameter? I've tried both passing the parameter as a reference and without the & but none of them worked.
trait Noise{
fn make_noise(&self);
fn call_by_name(&self);
}
struct Person {
name: String,
}
impl Noise for Person{
fn make_noise(&self){
println!("Hello");
}
fn call_by_name(&self) {
println!("Hey, {:?}, how are you doing?", self.name)
}
}
fn talk(noisy: impl Noise){
noisy.make_noise();
}
fn main() {
let john_person = Person { name: String::from("John") };
talk(john_person);
john_person.call_by_name(); // ERROR WHEN CALLING THE FUNCTION.
}
You should make fn talk take trait object by reference rather than by value:
trait Noise {
fn make_noise(&self);
fn call_by_name(&self);
}
struct Person {
name: String,
}
impl Noise for Person {
fn make_noise(&self) {
println!("Hello");
}
fn call_by_name(&self) {
println!("Hey, {:?}, how are you doing?", self.name)
}
}
fn talk(noisy: &impl Noise) { // <- used &impl Noise
noisy.make_noise();
}
fn main() {
let john_person = Person {
name: String::from("John"),
};
talk(&john_person); // call by reference, not move
john_person.call_by_name();
}
Otherwise, john_person is moved to function talk. That means you can not access it anymore.
If you pass it by reference, it is borrowed until the end of function.
Consider next function for example:
fn print(input: &dyn Display) {
println!("{}", input);
}
It works fine, as intended.
Now consider a little bit more complex example using trait with the same function inside:
trait Print {
type Input: ?Sized;
fn print(input: &Self::Input);
}
impl Print for f64 {
type Input = dyn Display;
// actually the same function as before
fn print(input: &dyn Display) {
println!("{}", input);
}
}
Now if I modify first function like this:
fn print(input: &dyn Display) {
f64::print(input);
}
I got compile error:
error[E0759]: `input` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
Why is this happening? I see no reason for 'static lifetime requirement in trait's associated type.
Worked example here.
Yes, when a dyn _ type is used as an associated type, it implicitly receives a lifetime bound of 'static. This is to prevent situations like this:
pub trait Stew {
type Item: ?Sized;
fn stew(&mut self, item: Box<Self::Item>);
}
use std::fmt::Display;
pub struct DisplayStew(Vec<Box<dyn Display>>);
impl Stew for DisplayStew {
type Item = dyn Display;
fn stew(&mut self, item: Box<Self::Item>) {
self.0.push(item);
}
}
impl DisplayStew {
pub fn new() -> Self {
DisplayStew(Vec::new())
}
pub fn look(&self) {
for item in &self.0 {
println!("- {}", item);
}
}
}
fn main() {
let mut bowl = DisplayStew::new();
bowl.stew(Box::new(123.456));
bowl.stew(Box::new("abcdef"));
{ // 'a begins
let s = "foo".to_owned();
bowl.stew(Box::new(&s)); // Box<&'a str>
} // 'a expires
// s was borrowed by bowl, but has ceased to exist, what now?
bowl.look();
}
Without a lifetime parameter, the compiler has no way of restricting how long a type may keep a reference to its associated type.
On stable Rust (1.58.1), there is currently no way to address this, but the following version works on unstable:
#![feature(generic_associated_types)]
use std::fmt::Display;
trait Print {
type Input<'a>: ?Sized;
fn print<'a>(input: &'a Self::Input<'a>);
}
impl Print for f64 {
type Input<'a> = dyn Display + 'a;
fn print<'a>(input: &'a (dyn Display + 'a)) {
println!("{}", input);
}
}
fn print(input: &dyn Display) {
println!("{}", input);
f64::print(input);
}
fn main() {
print(&123.);
}
I've been struggling with trying to understand how to properly annotate lifetimes in my application. I've simplified the actual code I had to this:
struct Item<'a> {
rf: &'a i32,
}
impl<'a> Item<'a> {
fn new(main: &'a App) -> Item<'a> {
Item{
rf: &main.i
}
}
}
struct App<'a> {
i: i32,
vec: Vec<Item<'a>>
}
impl<'a> App<'a> {
fn new() -> App<'a> {
App {
i: 32,
vec: vec![]
}
}
fn init(&mut self) {
self.vec.push(Item::new(self))
}
fn update(&self) {
for item in self.vec.iter() {
println!("{}", item.rf)
}
}
}
fn main() {
let app = App::new();
app.init();
app.update();
}
So there's a vector of items that hold a reference to something in App, which I know would exist as long as the app is alive, but the borrow-checker doesn't accept this. Could someone explain what's wrong with this code and how I could fix it?
You can find this code in rust playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ee8980c9e1b2a0622548525dbcf9f50f
I think the problem lays with how rust handles references and infers them. Here's a possible solution.
In short, we tell the rust compiler that in the App struct the i member lives for 'a length. This member we can then share with another struct that lives for at least 'a. we achieve this by telling the Item struct when creating it, that it at least has to live for at least the lifetime of the App struct. Because the compiler can be a bit picky about inferring and anonymous lifetimes we have to be explicit. We do this by adding a 'b to the new method of the Item struct. When we then call this method with the lifetime 'a of the app struct, the compiler knows that Item lives for as long as App. Sorry for the short explanation cause more than I probably know goes on here.
struct Item<'a> {
rf: &'a i32,
}
impl<'a> Item<'a> {
fn new<'b>(main: &'b App<'a>) -> Item<'a> {
Item{
rf: main.i
}
}
}
struct App<'a> {
i: &'a i32,
vec: Vec<Item<'a>>
}
impl<'a> App<'a> {
fn new() -> App<'a> {
App {
i: &32,
vec: vec![]
}
}
fn init(&mut self) {
let item = Item::new(self);
self.vec.push(item)
}
fn update(&self) {
for item in self.vec.iter() {
println!("{}", item.rf)
}
}
}
fn main() {
let mut app = App::new();
app.init();
app.update();
}
I have this trait and implementation:
#[async_trait]
pub trait AsyncKeyProvider {
async fn get_key_async(&mut self, key_id: &str) -> Result<Option<Jwk>, ()>;
fn as_any(&self) -> &dyn Any;
}
#[async_trait]
impl AsyncKeyProvider for GoogleKeyProvider {
async fn get_key_async(&mut self, key_id: &str) -> Result<Option<Jwk>, ()> {
{...}
}
fn as_any(&self) -> &dyn Any {
self
}
}
In order to pass it into my handler in actix-web, I'm passing through a GoogleKeyProvider like this:
let key_provider = web::Data::from(Arc::new(GoogleKeyProvider::default()));
let server = HttpServer::new(move || {
App::new()
.app_data(key_provider.clone())
.route("/validate", web::post().to(validate))
})
With the handler doing this:
pub async fn validate(jwt_body: web::Json<JwtBody>, provider: web::Data<Box<dyn AsyncKeyProvider>>) -> impl Responder {
let provider_object: &GoogleKeyProvider = provider.as_any().downcast_ref::<GoogleKeyProvider>().expect("Wasn't a GoogleKeyProvider");
match validate_jwt(&jwt_body.jwt, provider_object).await {
{...}
}
}
validate_jwt then tries to call a method on the provider struct like this:
async fn validate_jwt(jwt: &String, provider: &GoogleKeyProvider) -> Result<bool, Box<dyn std::error::Error>> {
let key_to_use = provider.get_key_async(<thing>).await.unwrap();
}
Which presents me with this error:
error[E0596]: cannot borrow `*provider` as mutable, as it is behind a `&` reference
--> src\routes\validate.rs:48:22
|
48 | let key_to_use = provider.get_key_async(<thing>).await.unwrap();
| ^^^^^^^^ `provider` is a `&` reference, so the data it refers to cannot be borrowed as mutable
As far as I can understand, this is happening because the result of my downcasting is a reference (due to downcast_ref), but I think I'd be wanting the plain GoogleKeyProvider type instead - I'm not sure on that though. I believe the provider needs to be mutable as the values inside it (see below) can change during the lifetime of the provider (it's intended to provide a temporary cache for some keys, and automatically update them if they're out of date)
#[derive(Clone)]
pub struct GoogleKeyProvider {
cached: Option<JwkSet>,
expiration_time: Instant,
}
I'm not sure how to get this working with downcasting, though. Is anyone able to help me see where I've gone wrong?
You have to choice if get_key_async update somme thing at the struct.
The simple code below show you the error
trait Atrait {
fn afn(&mut self) -> i32;
}
struct Astruct {}
impl Atrait for Astruct {
fn afn(&mut self) -> i32 {
2
}
}
fn main()
{
// test should be mutable
let test = Astruct{};
let value = test.afn();
println!("Value {}", value);
}
This work because afn(self) is not declared mutable afn(&mut self)
trait Atrait {
fn afn(&self) -> i32;
}
struct Astruct {}
impl Atrait for Astruct {
fn afn(&self) -> i32 {
2
}
}
fn main()
{
let test = Astruct{};
let value = test.afn();
println!("Value {}", value);
}
I have two structs, VM and Word. I need a new struct Control which behaves just like VM, but with one more field master. Because Rust has no inheritance, I try to extend the struct through composition. I move the functions of VM into a new trait Core, and implement Core for Control. The resulting code works.
struct Word<T> {
action: fn(target: &T)
}
struct VM {
word: Word<VM>
}
trait Core<T> {
fn word(&self) -> &Word<T>;
fn hello(&self) { println!("Hello"); }
fn execute(&self);
}
impl Core<VM> for VM {
fn word(&self) -> &Word<VM> { &self.word }
fn execute(&self) { (self.word().action)(self); }
}
struct Control {
word: Word<Control>,
master: i32,
}
impl Core<Control> for Control {
fn word(&self) -> &Word<Control> { &self.word }
fn execute(&self) { (self.word().action)(self); }
}
fn main() {
let vm = VM{
word: Word {action: Core::hello}
};
vm.execute();
let control = Control{
word: Word {action: Core::hello},
master: 0,
};
vm.execute();
}
The two implementation of execute are identical. So I move execute into trait Core.
trait Core<T> {
fn word(&self) -> &Word<T>;
fn hello(&self) { println!("Hello"); }
fn execute(&self) { (self.word().action)(self); }
}
impl Core<VM> for VM {
fn word(&self) -> &Word<VM> { &self.word }
}
impl Core<Control> for Control {
fn word(&self) -> &Word<Control> { &self.word }
}
Which compiles with the following error:
main.rs:14:44: 14:48 error: mismatched types:
expected `&T`,
found `&Self`
(expected type parameter,
found Self) [E0308]
main.rs:14 fn execute(&self) { (self.word().action)(self); }
How can I solve this problem?
if you move execute in Core, there is nothing in the trait definition that says that T is the same type as Self.
trait Core<T> {
fn word(&self) -> &Word<T>;
fn hello(&self) { println!("Hello"); }
fn execute(&self) {
(self.word() // this is a &Word<T>
.action) // this is a fn(T)
(self); // this type is Self. T is not necessarily = Self
}
}
When execute is in the impl Core<Control> for Control, the impl says that Self and T are both = Control, so execute works. But if T can be anything like in the definition of the trait, Rust can't let your code compile.
How to fix it depends on what you need to do.
If your trait is always meant to be implemented this way (impl Core<Something> for Something or impl Core<SomethingElse> for SomethingElse but NEVER as impl Core<Something> for SomethingElse), you can drop the parameter from the trait definition and have just:
trait Core: Sized {
fn word(&self) -> &Word<Self>; // now you can't parametrize what
// Word to return. It will be Self.
fn hello(&self) { println!("Hello"); }
fn execute(&self) { (self.word().action)(self); } // ...and this works
}