rust expected named lifetime parameter in solana smart contract with anchor - rust

I am working with Solana smart contracts using the anchor library, I am trying to make a struct that will store an array of public keys of other Solana accounts, but it is giving errors around lifetimes and borrowing the array. Can someone explain to me what is wrong and how to fix it? I am still iffy on how stuff like borrowing and ownership works in rust.
// This is your program's public key and it will update
// automatically when you build the project.
declare_id!("********************************************");
#[program]
mod hello_anchor {
use super::*;
pub fn initialize(ctx: Context<Initialize>, entries: u64, keys: [&[u8]]) -> Result<()> {
ctx.accounts.new_account.entries = entries;
ctx.accounts.new_account.keys = keys;
msg!("Changed entry number to: {}!", entries); // Message will show up in the tx logs
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
// We must specify the space in order to initialize an account.
// First 8 bytes are default account discriminator,
// next 8 bytes come from NewAccount.data being type u64.
// (u64 = 64 bits unsigned integer = 8 bytes)
#[account(init, payer = signer, space = 8 + 8)]
pub new_account: Account<'info, NewAccount>,
#[account(mut)]
pub signer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
pub struct NewAccount {
pub entries: u64,
pub keys: [&[u8]],
}
#[account]
pub struct NewEntry {
pubkey: String,
day: u8,
month: u8,
year: u16,
}
error log
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> /src/lib.rs:7:1
|
7 | #[program]
| ^ explicit lifetime name needed here
|
= note: this error originates in the attribute macro `program` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> /src/lib.rs:34:16
|
34 | pub keys: [&[u8]],
| ^ explicit lifetime name needed here
error[E0106]: missing lifetime specifier
--> /src/lib.rs:34:16
|
34 | pub keys: [&[u8]],
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
32 ~ pub struct NewAccount<'a> {
33 | pub entries: u64,
34 ~ pub keys: [&'a [u8]],
|
error[E0106]: missing lifetime specifier
--> /src/lib.rs:7:1
|
7 | #[program]
| ^ expected named lifetime parameter
|
= note: this error originates in the attribute macro `program` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider introducing a named lifetime parameter
|
7 ~ #<'a>[program]
8 | mod hello_anchor {
9 | use super::*;
10~ pub fn initialize<'a>(ctx: Context<Initialize>, entries: u64, keys: [&[u8]]) -> Result<()> {
|
Some errors have detailed explanations: E0106, E0637.
error: could not compile `solpg` due to 4 previous errors

Related

How can I instruct sqlx about this custom type I'm using for OffsetDateTime?

I have a custom time type because time's authors doesn't want to add a Default value yet:
#[derive(Debug, Clone, Copy)]
pub struct OffsetDateTime(pub time::OffsetDateTime);
impl OffsetDateTime {
pub fn now_utc() -> Self {
Self(time::OffsetDateTime::now_utc())
}
}
impl Default for OffsetDateTime {
fn default() -> Self {
Self(time::OffsetDateTime::UNIX_EPOCH)
}
}
impl From<time::OffsetDateTime> for OffsetDateTime {
fn from(o: time::OffsetDateTime) -> Self {
Self(o)
}
}
impl From<OffsetDateTime> for time::OffsetDateTime {
fn from(o: OffsetDateTime) -> Self {
o.0
}
}
If I use this simple sqlx code:
#[derive(Debug, Default, sqlx::FromRow)]
pub struct Player {
pub id: String,
pub created_at: OffsetDateTime,
pub name: String,
}
let pla = sqlx::query_as!(
Player,
r#"SELECT * from player where id = $1"#,
'1'
)
.fetch_one(&*self.pool)
.await?;
it errors with:
error[E0308]: mismatched types
|
66 | let pla = sqlx::query_as!(
| ___________________^
67 | | Player,
68 | | r#"SELECT * from player where id = $1"#,
70 | | id
71 | | )
| |_________^ expected struct `custom::types::OffsetDateTime`, found struct `time::OffsetDateTime`
|
= note: struct `time::OffsetDateTime` and struct `custom::types::OffsetDateTime` have similar names, but are actually distinct types
note: struct `time::OffsetDateTime` is defined in crate `time`
--> C:\Users\Fred\.cargo\registry\src\github.com-1ecc6299db9ec823\time-0.3.17\src\offset_date_time.rs:31:1
|
31 | pub struct OffsetDateTime {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: struct `custom::types::OffsetDateTime` is defined in crate `custom`
|
4 | pub struct OffsetDateTime(pub time::OffsetDateTime);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
help: try wrapping the expression in `custom::types::OffsetDateTime`
--> C:\Users\Fred\.cargo\registry\src\github.com-1ecc6299db9ec823\sqlx-0.6.2\src\macros\mod.rs:561:9
|
561| custom::types::OffsetDateTime($crate::sqlx_macros::expand_query!(record = $out_struct, source = $query, args = [$($args)*]))
| ++++++++++++++++++++++++++++++ +
How can I fix this?
Should I instruct sqlx to handle my custom OffsetDateTime? How?
From the docs on query_as:
The field types must be the Rust equivalent of their SQL counterparts
Means you have to use the types in the type map corresponding to your db (example for postgres).
Or in other words, you can't use custom types with query_as

How to return a struct whose property has a type of &str from a function in rust?

I am trying to do the following
// Just removes redundant white space while also splitting the string
// with a whitespace.
fn split_whitespace(string: &str) -> Vec<&str> {
let words: Vec<&str> = string
.split_whitespace()
.filter(|&word| word != "")
.collect();
words
}
pub fn get_websites_from_hosts(hosts_path: &Path) -> Result<Vec<Website>, std::io::Error> {
let hosts_string = read_to_string(hosts_path)?;
let result: Vec<Website> = hosts_string
.lines()
.filter(|&line| split_whitespace(&line.to_owned()).len() == 2)
.map(|line| {
let ip_domain = split_whitespace(&line.to_owned());
Website {
domain_name: ip_domain[1], // This won't work because it is refering hosts_string which is a local variable of the function
redirect_ip: ip_domain[0], // the same case with this one.
is_blocked: true,
hosts_path,
}
})
.collect();
Ok(result)
}
What I want to achieve is to successfully return the Website struct while probably not editing the struct declaration.
And here is the Website struct declaration
#[derive(Debug, Clone)]
pub struct Website<'a> {
pub domain_name: &'a str,
pub redirect_ip: &'a str,
pub is_blocked: bool,
pub hosts_path: &'a Path,
}
And here is the error
error[E0515]: cannot return value referencing temporary value
--> src/parser.rs:21:13
|
20 | let ip_domain = split_whitespace(&line.to_owned());
| --------------- temporary value created here
21 | / Website {
22 | | domain_name: ip_domain[1],
23 | | redirect_ip: ip_domain[0],
24 | | is_blocked: true,
25 | | hosts_path,
26 | | }
| |_____________^ returns a value referencing data owned by the current function
For more information about this error, try `rustc --explain E0515`.
error: could not compile `website-blocker` due to previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `website-blocker` due to previous error
I would love a deep explanation and general tips to use when encountering this and the like problems
The &str references in your struct refer to segments of the string returned by read_to_string. That string (hosts_string) is dropped and deallocated at the end of fn get_websites_from_hosts, so if you could return references to it, they would be dangling. Rust prevents you from doing that.
Instead, you'll need to either move the read_to_string outside that function, and pass the string in as an &str or change your struct to hold owned values like String, IpAddr, etc.
#[derive(Debug, Clone)]
pub struct Website<'a> {
pub domain_name: String,
pub redirect_ip: IpAddr,
pub is_blocked: bool,
pub hosts_path: &'a Path,
}
If you want to avoid some String allocations, you could use a "small-string optimization" library like compact_str
#[derive(Debug, Clone)]
pub struct Website<'a> {
// Stores a domain name of up to 24 bytes in place,
// without an extra heap allocation
pub domain_name: CompactString,
pub redirect_ip: IpAddr,
pub is_blocked: bool,
pub hosts_path: &'a Path,
}

BorshDeserialize gives try_from_slice error

I was exploring the "BorshDeserialize" option in Rust. and noticed the following issues when using trait bounds. Any help is appreciated
Sample code
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::pubkey::Pubkey;
use std::mem;
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct SampleData<'a> {
accounts: (&'a Pubkey, &'a Pubkey),
data: String,
timestamp: u64,
owner: &'a Pubkey,
}
fn main() {
println!(
"Size of SampleData is {} bytes",
mem::size_of::<SampleData>()
);
let _pub_key = Pubkey::default();
let _a = SampleData {
accounts: (&_pub_key, &_pub_key),
data: "ABCDE".to_string(),
timestamp: 1643116047,
owner: &_pub_key,
};
let _encoded_a = _a.try_to_vec().unwrap();
println!("{:?}", _encoded_a);
let _decoded_a = SampleData::try_from_slice(&_encoded_a).unwrap();
println!("decoded_a: {:?}", _decoded_a);
}
Error message
error[E0599]: the function or associated item try_from_slice exists
for struct SampleData<'_>, but its trait bounds were not satisfied
--> src/main.rs:27:34 | 6 | struct SampleData<'a> { | --------------------- | | | function or associated item try_from_slice not found for this | doesn't satisfy
SampleData<'_>: BorshDeserialize ... 27 | let _decoded_a =
SampleData::try_from_slice(&_encoded_a).unwrap(); |
^^^^^^^^^^^^^^ function or associated item cannot be called on
SampleData<'_> due to unsatisfied trait bounds | note: the
following trait bounds were not satisfied because of the requirements
of the implementation of BorshDeserialize for _:
(&Pubkey, &Pubkey): BorshDeserialize
&Pubkey: BorshDeserialize --> src/main.rs:5:26 | 5 | #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] | ^^^^^^^^^^^^^^^^ 6 | struct SampleData<'a> { |
^^^^^^^^^^^^^^ = help: items from traits can only be used if the
trait is implemented and in scope = note: the following trait
defines an item try_from_slice, perhaps you need to implement it:
candidate #1: BorshDeserialize = note: this error originates in the derive macro BorshDeserialize (in Nightly builds,
run with -Z macro-backtrace for more info)
For more information about this error, try rustc --explain E0599.
error: could not compile seralize due to previous error
The problem is that SampleData contains references, which isn't supported in normal Borsh deserialization. Borsh creates a new instance of your type based on a slice, but it won't be able to create references.
If you want to stick with Borsh, you should change the type to:
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct SampleData {
accounts: (Pubkey, Pubkey),
data: String,
timestamp: u64,
owner: Pubkey,
}

Cannot infer an appropriate lifetime for borrow expression due to conflicting requirement(s) [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 1 year ago.
I'm having a hard time resolving a lifetime issue:
pub struct A<'a> {
pub a: &'a str,
pub b: &'a u8,
}
pub enum Executable<'a> {
ExecutableA(A<'a>),
}
pub struct Config {
pub a: String,
pub b: u8, // some more config values to follow
}
impl Config {
pub fn new() -> Config {
// Implementation details omitted due to irrelevancy
unimplemented!();
}
}
pub struct Cli<'a> {
pub config: Config,
pub execution_list: Vec<Executable<'a>>,
}
impl<'a> Cli<'a> {
pub fn new() -> Cli<'a> {
Cli {
config: Config::new(),
execution_list: vec![],
}
}
pub fn prepare(&mut self) {
self.execution_list.push(
// Compilation error occurs for following line
Executable::ExecutableA(A {
a: &self.config.a,
b: &self.config.b,
}),
)
}
}
The compilation error is:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/lib.rs:39:20
|
39 | a: &self.config.a,
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 35:20...
--> src/lib.rs:35:20
|
35 | pub fn prepare(&mut self) {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:39:20
|
39 | a: &self.config.a,
| ^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 27:6...
--> src/lib.rs:27:6
|
27 | impl<'a> Cli<'a> {
| ^^
note: ...so that the expression is assignable
--> src/lib.rs:38:13
|
38 | / Executable::ExecutableA(A {
39 | | a: &self.config.a,
40 | | b: &self.config.b,
41 | | }),
| |______________^
= note: expected `Executable<'a>`
found `Executable<'_>`
(Playground)
After doing a lot of reading and looking at other questions, I still can't convince myself that I'm understanding the error correctly, mainly because I can't reason why the compiler is attaching the "anonymous" lifetime to the &mut self reference in the prepare function.
My general design idea is that I'll have my Cli struct contain a config, and a list of executables such that I can add all relevant executables to that list in the Cli's prepare function (where I'd like those executables to be able to reference values owned by the Config). I'll then iterate over that execution list to start/stop executables.
I think one answer to this question is to not have executables maintain references to config values and instead copy those values, but I feel like that shouldn't be necessary, and would like to use this issue as a learning opportunity.
I'm totally open to suggestions around "Maybe you should rethink your design and do X, instead."
Anonymous lifetimes are inferred by the compiler, most of them will point to 'static,
If you add this (&'a mut self):
pub fn prepare (&'a mut self) /* ... */
It compiles just fine, since the impl lifetime requirement is not conflicting with the Executable one.
Edit:
As pointed out, i was wrong (probably because the rust style did reach into my mind but lifetimes did not), i though about generic lifetimes but i looked at the already existing lifetime 'a and found that it compiled, at least mutably borrowing the class for eternity makes sense.
About your design:
I found it good for what you are trying to do, also i am not the expert with designs, specially in rust, so i found nothing wrong about it.
Viable solution:
Like pointed out, you could add the generic lifetime:
pub fn prepare <'b> (&'b mut self) { ... }
Now whenever the function is called the mutable borrow will last the needed lifetime, and when you want to immutably borrow it, it will work.

Lifetimes in Structs that Contain both a piece of data and the data being referenced [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 2 years ago.
I am writing a little Cards Against Humanity clone for personal use and am using it as a chance to learn Rust. I currently have the following structs:
// game.rs
pub struct Game<'c> {
deck: Deck,
players: Vec<Player<'c>>,
current_czar_index: usize,
}
// player.rs
pub struct Player<'c> {
pub hand: Vec<&'c Card>,
pub max_hand_size: usize,
pub is_czar: bool,
pub score: u8,
pub name: String,
}
// deck.rs
struct DiscardPile {
pub white: Mutex<Vec<usize>>,
pub black: Mutex<Vec<usize>>,
}
pub struct Deck {
white: Vec<Card>,
black: Vec<Card>,
pub used_sets: Vec<String>,
discard_pile: DiscardPile,
}
// card.rs
pub struct Card {
pub text: String,
pub uuid: Uuid,
pub pick: Option<u8>,
}
There are a few others (namely set which is used for reading in JSON files), but they aren't relevant.
I have a function in game.rs
pub fn deal_hands(&self) -> Result<(), Box<dyn std::error::Error>> {
for player in &mut self.players {
while player.hand.len() < player.max_hand_size {
player.add_card(self.deck.draw_white().unwrap())?;
}
}
Ok(())
}
that is giving me the following error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/game.rs:42:31
|
42 | player.add_card(self.deck.draw_white().unwrap())?;
| ^^^^^^^^^^
|
It specifically says that it is expecting &mut Player<'_> but found a lifetime of &mut Player<'c>.
HERE if you want to see the code firsthand.
How do I fix such a lifetime error, or do I need to rethink my architecture?
The architecture seems fine to me. You are probably just missing the passing of a lifetime parameter somewhere.
I'm not totally certain, but I believe issue may be that .draw_white() is returning Option<&Card> and it's not clear what the lifetime of the contained Card should be. I believe it is the case that anytime you return a borrowed value, you must attach a lifetime to the borrowed value. Otherwise, the borrow checker cannot tell how long the borrowed value will live.
Maybe try the following definition for .draw_white() instead
pub fn draw_white<'a>(&self) -> Option<&'a Card> {
You will then need to tweak deal_hands() to be something like the following. (Working on figuring out the right syntax, but I think it's something like this.)
pub fn deal_hands(&self) -> Result<(), Box<dyn std::error::Error>> {
for player<'c> in &mut self.players {
while player.hand.len() < player.max_hand_size {
player.add_card(self.deck.draw_white<'c>().unwrap())?;
}
}
Ok(())
}
I think I got it sorted out. Luckily everything builds just fine after pushing through a handful of errors.
Original Error
Ok. Here is the full error I saw when I tried to build your crate.
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/game.rs:42:31
|
42 | player.add_card(self.deck.draw_white().unwrap())?;
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 39:2...
--> src/game.rs:39:2
|
39 | pub fn deal_hands(&self) -> Result<(), Box<dyn std::error::Error>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/game.rs:42:21
|
42 | player.add_card(self.deck.draw_white().unwrap())?;
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'c` as defined on the impl at 20:6...
--> src/game.rs:20:6
|
20 | impl<'c> Game<'c> {
| ^^
note: ...so that the types are compatible
--> src/game.rs:42:12
|
42 | player.add_card(self.deck.draw_white().unwrap())?;
| ^^^^^^^^
= note: expected `&mut Player<'_>`
found `&mut Player<'c>`
It looks like the problem is actually with deal_hands(). Rather than allowing the lifetime of &self to be elided, you need to specify the lifetime as &'c mut self. (The mut is because you are mutating self.players.) I'm not totally sure why Rust doesn't elide the lifetime of self to 'c, but that's probably another topic.
Next Error
The next error I ran into was
error: captured variable cannot escape `FnMut` closure body
--> src/game.rs:106:17
|
106 | .map(|num| player.play_card_by_index(num as usize))
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a reference to a
captured variable which escapes the closure body
| |
| inferred to be a `FnMut` closure
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
For this one, the problem is actually not in the error message. You need to specify the lifetime of Card in the return value of .play_card_by_index() because otherwise it's not clear that the reference to Card actually outlives the closure. This means you need to adjust .play_card_by_index() to return &'c Card' instead of &Card`.
Final Error
There was a trivial error in your .get_player_names(). You just need to use .iter() instead of .into_iter() because the former will not take ownership of self. Also, you probably want to .clone() the player names too for a similar reason.
Full Diff
Here's the full diff
diff --git a/src/game.rs b/src/game.rs
index 573d09d..5ccbf6b 100644
--- a/src/game.rs
+++ b/src/game.rs
## -36,7 +36,7 ## impl<'c> Game<'c> {
/// Hands need to be filled on every turn, so this lets us fill everyones'
/// hands at once.
- pub fn deal_hands(&self) -> Result<(), Box<dyn std::error::Error>> {
+ pub fn deal_hands(&'c mut self) -> Result<(), Box<dyn std::error::Error>> {
for player in &mut self.players {
while player.hand.len() < player.max_hand_size {
player.add_card(self.deck.draw_white().unwrap())?;
## -124,7 +124,10 ## impl<'c> Game<'c> {
}
pub fn get_player_names(&self) -> Vec<String> {
- self.players.into_iter().map(|player| player.name).collect()
+ self.players
+ .iter()
+ .map(|player| player.name.clone())
+ .collect()
}
}
diff --git a/src/player.rs b/src/player.rs
index 4bd6848..9f95373 100644
--- a/src/player.rs
+++ b/src/player.rs
## -46,7 +46,7 ## impl<'c> Player<'c> {
/// Used in the TUI, we can play a card by index and get the reference
/// to the card we played
- pub fn play_card_by_index(&mut self, index: usize) -> & Card {
+ pub fn play_card_by_index(&mut self, index: usize) -> &'c Card {
self.hand.remove(index)
}
## -56,7 +56,7 ## impl<'c> Player<'c> {
/// instead of making the card on the client and sending the full card info,
/// we can just send the UUID[s] of the cards that were played with some
/// data about the order they were played in.
- pub fn play_card_by_uuid(&mut self, uuid: Uuid) -> Option<& Card> {
+ pub fn play_card_by_uuid(&mut self, uuid: Uuid) -> Option<&Card> {
// TODO: Find a better way to do this
let mut index_of_card: usize = self.hand.len() + 1;
for (index, card) in self.hand.iter().enumerate() {
Good Luck!
This looks like a fun project. I hope you continue to build it in Rust!

Resources