wrong number of lifetime parameters: expected 1, found 0 - rust

I'm having a really hard time fathoming pointers in Rust. This code won't compile because: wrong number of lifetime parameters: expected 1, found 0 [E0107]. What does that mean?
struct Planet<'a> {
name: &'a str,
radius_km: i32,
surface_area_km2: i64,
orbital_period_days: i32,
distance_from_sun: i64
}
fn mercury() -> Planet {
Planet {
name: "Mercury",
radius_km: 2_440,
surface_area_km2: 74_800_000,
orbital_period_days: 88,
distance_from_sun: 57_910_000
}
}
fn main() {
let mercury = Box::new(mercury());
println!("{}",mercury.name)
}

It's saying that your definition for the struct includes a type parameter and, therefore, so must your function that creates one.
struct Planet<'a>{
name : &'a str,
radius_km: i32,
surface_area_km2: i64,
orbital_period_days: i32,
distance_from_sun: i64
}
fn mercury<'a>()->Planet<'a>{
Planet{
name:"Mercudy",
radius_km: 2_440,
surface_area_km2: 74_800_000,
orbital_period_days: 88,
distance_from_sun: 57_910_000
}
}
fn main(){
let planet = mercury();
println!("{}", planet.name)
}

Related

the method `fold` exists for reference `&[T]`, but its trait bounds were not satisfied, I don't understand the given bounds in question

So I'm building a chip-8 CPU emulator and to make copying data into the memory easier I created the following two methods:
pub struct CPU {
// ... other unrelated fields
pub memory: [u8; 0x1000],
}
impl CPU {
pub fn raw_copy_to_mem(&mut self, loc: usize, data: &[u8]) {
data.chunks(2).fold(loc, |loc, bytes| {
self.raw_add_to_mem(loc, *bytes.first().unwrap(), *bytes.last().unwrap())
});
}
pub fn raw_add_to_mem(&mut self, loc: usize, high: u8, low: u8) -> usize {
self.memory[loc] = high; self.memory[loc + 1] = low;
loc + 2
}
}
Now this works for this for example:
fn make_cpu() -> processor::CPU {
processor::CPU {
// ... other unrelated fields
memory: [0; 0x1000],
}
}
#[test]
fn test_raw_memory_copy() {
let mut cpu = make_cpu();
let add_twice: [u8; 6] = [
0x80, 0x14,
0x80, 0x14,
0x00, 0xEE,
];
cpu.raw_copy_to_mem(0x100 , &add_twice);
assert_eq!(cpu.memory[0x100..0x106], add_twice);
}
Now to make doing OpCodes easier I have the following struct and functions:
#[derive(Debug, Clone, Copy)]
pub struct OpCode(u8, u8);
impl OpCode {
pub fn high_byte(&self) -> u8 {
self.0
}
pub fn low_byte(&self) -> u8 {
self.1
}
}
impl From<OpCode> for u16 {
fn from(c: OpCode) -> Self {
(c.0 as u16) << 8 | c.1 as u16
}
}
impl From<&OpCode> for u16 {
fn from(c: &OpCode) -> u16 {
c.into()
}
}
impl OpCode {
pub fn add(h: u8, l: u8) -> Self {
Self (0x8 << 4 | h, (l << 4) | 4)
}
}
And the following CPU function also works great:
impl CPU {
pub fn add_to_mem(&mut self, loc: usize, oc: &OpCode) -> usize {
self.memory[loc] = oc.high_byte(); self.memory[loc + 1] = oc.low_byte();
loc + 2
}
}
The problem occurs when I try to add a copy_to_mem() function for the OpCode struct:
impl CPU {
pub fn copy_to_mem(&mut self, loc: usize, data: &[OpCode]) {
data.fold(loc, |loc, opcode| {
self.add_to_mem(loc, opcode)
});
}
}
I get the following error that I only vaguely understand:
error[E0599]: the method `fold` exists for reference `&[OpCode]`, but its trait bounds were not satisfied
--> src/processor.rs:21:14
|
21 | data.fold(loc, |loc, bytes| {
| ^^^^ method cannot be called on `&[OpCode]` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`&[OpCode]: Iterator`
which is required by `&mut &[OpCode]: Iterator`
`[OpCode]: Iterator`
which is required by `&mut [OpCode]: Iterator`
I get that it's saying that whilst there is a fold() function & that it can't call it because some trait bounds weren't satisfied so it can't call it but it doesn't state what those bounds are in a way that I can understand.
So, could someone explain what is going on, and how to fix?
The error message is misleading: the problem is that you're trying to use a slice as an iterator, but it isn't. To obtain an iterator for the slice, call it's iter() method (or iter_mut() for mutable iterator).
pub fn copy_to_mem(&mut self, loc: usize, data: &[OpCode]) {
data.iter().fold(loc, |loc, bytes| {
self.add_to_mem(loc, bytes.high_byte())
});
}
Note that it'll still error with:
error[E0308]: mismatched types
--> src/lib.rs:60:34
|
60 | self.add_to_mem(loc, bytes.high_byte())
| ^^^^^^^^^^^^^^^^^ expected `&OpCode`, found `u8`
Because add_to_mem expects &OpCode but while bytes is indeed &OpCode bytes.high_byte() is u8.

Error: `Info` doesn't implement `Display` (required by {})

I got error: Info doesn't implement Display (required by {}):11 while running this code:
struct Info<'a> {
name: &'a str,
age: u8,
}
fn main() {
let john = Info {
name: "John",
age: 32,
};
println!("{}", john);
}
I have no idea what im doing wrong. Can anyone explain me?
In order for a struct to be formatable via "{}" format specifier it needs to implement the std::fmt::Display trait.
Therefore, to make your code compile, you need to impl Display for Info:
impl std::fmt::Display for Info<'_> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(fmt, "My name is {} and I'm {} years old.", self.name, self.age)
}
}
Note that Display trait is idiomatically used for user-facing representations.
Alternatively, you could use "{:?}" format specifier and #[derive(Debug)] annotation on your type to use formatter provided by std::fmt::Debug trait:
#[derive(Debug)]
struct Info<'a> {
name: &'a str,
age: u8,
}
fn main() {
let john = Info {
name: "John",
age: 32,
};
println!("{:?}", john);
}

How to properly solve lifetime inferences in struct?

The Rust playground code is here.
I have a struct of Token which has lifetime 'tok, and a scanner has lifetime 'lexer. I'm using both of them in another struct Parser, then I had a problem:
pub struct Token<'tok> {
pub value: Cow<'tok, str>,
pub line: usize,
}
pub struct Scanner {
pub source: Vec<char>,
pub current: usize,
pub line: usize,
}
pub struct Parser<'lexer> {
pub curr: &'lexer Token<'lexer>,
pub prev: &'lexer Token<'lexer>,
scanner: &'lexer mut Scanner,
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
self.prev = self.curr;
self.curr = &self.scanner.next(); // cannot inference lifetime
}
}
I think the problem is Token has lifetime 'tok, and the borrow checker doesn't know the relation between 'tok and 'lexer so it can't inference proper lifetime.
However, I can avoid the problem by modifying it into the updated code:
pub struct Parser<'lexer> {
pub curr: Token<'lexer>,
pub prev: Token<'lexer>,
scanner: &'lexer mut Scanner,
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
let prev = std::mem::replace(&mut self.curr, self.scanner.next());
self.prev = prev;
}
}
And with Token produced by next() is static:
impl Scanner {
pub fn next(&mut self) -> Token<'static> {
Token {
value: Cow::from(""),
line: 0,
}
}
}
It does compile but I think it's not ideal because all tokens are cloned from scanner into parser(they are not references anymore) and living until end of Parser's life. So memory usage is doubled. Is there a more proper way to deal with this?
Actualy your code structure is not ideal to deal with the borrow checker here why:
Token struct should be owned, the struct itself do not require any allocations (as the token is owned some indrection are required to allow prev <-> next switching)
None of the Parser or Lexer should own the base data so it will be easy to bound proper lifetime
In our case Vec<Char> is not a friendly type to work with (we do not need to own the data and this will be harder to make the comipler understand lifetimes), instead we're going to use an &'str but you could reproduce the exact behaviours with an &[char])
Here is an example that compile just fine
pub struct Token<'source> {
pub value: Cow<'source, str>,
pub line: usize,
}
pub struct Scanner<'source> {
pub source: &'source str,
pub current: usize,
pub line: usize,
}
pub struct Parser<'source> {
pub curr: Option<Token<'source>>,
pub prev: Option<Token<'source>>,
scanner: Scanner<'source>,
}
impl <'source>Scanner<'source> {
pub fn next(&'source /* DONT Forget to bound 'source to `self` */ self) -> Token<'source> {
Token {
value: Cow::from(self.source), /* `self.source` is bound to `'source` so the compiler understand that the token lifetime is the same than the source's one */
line: 0,
}
}
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&'lexer mut self) {
self.prev = self.curr.take();
self.curr = Some(self.scanner.next());
}
}

Cannot move out of borrowed content in Rust

pub struct Character {
name: String,
hp: i32,
level: i32,
xp: i32,
xp_needed: i32,
gold: i32
}
impl Character {
pub fn new(name: String) -> Character {
let mut rng = thread_rng();
let hp: i32 = rng.gen_range(12, 75);
let gold: i32 = rng.gen_range(10, 50);
Character { name: name, hp: hp, level: 1, xp: 0, gold: gold, xp_needed: 100 }
}
pub fn get_name(&self) -> String {
self.name
}
// ...
}
How exactly am I breaking the rules here?
At a high-level, this is against-the-grain for Rust. You cannot transfer ownership of something borrowed because you don't own it.
Um don't I? I have other functions like:
pub fn get_hp(&self) -> i32 {
self.hp
}
And that works just fine.
|
23 | self.name
| ^^^^ cannot move out of borrowed content
error: aborting due to previous error
What's going on? What is the appropriate approach to return the character name? Why does the get_hp method work but not get_name?
The difference between get_hp and get_name is that get_hp returns a i32. i32 is a Copy type. Copy types can be copied by simply copying bits and are never moved out. On the other hand String is not Copy, it manages some memory which must either be transferred (moved out) or Cloned.
For getters like this, it is more idiomatic to return references instead of cloning. And for Strings, it should specifically be &str.
pub fn get_name(&self) -> &str {
&self.name
}

What is the optimal way to convert a `usize` to a `&str`?

I need to convert a usize to a &str to pass to a fn foo(&str). I found the following two ways, but don't know if there is a difference between using as_str() or Deref. Maybe the work done by self in as_str links with Deref somehow? I do not know if it may be better to use one or the other or if they actually are the same.
Using temp.to_string().as_str():
#[inline]
#[stable(feature = "string_as_str", since = "1.7.0")]
pub fn as_str(&self) -> &str {
self
}
Using &*temp.to_string() or &temp.to_string(). This works via Deref:
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for String {
type Target = str;
#[inline]
fn deref(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.vec) }
}
}
The question may depend on what you want to do in foo: does the passed
&str need to outlive foo or not ?
foo(&str) is a minimal example for s: &str in this code:
extern crate termbox_sys as termbox;
pub fn print(&self, x: usize, y: usize, sty: Style, fg: Color, bg: Color, s: &str) {
let fg = Style::from_color(fg) | (sty & style::TB_ATTRIB);
let bg = Style::from_color(bg);
for (i, ch) in s.chars().enumerate() {
unsafe {
self.change_cell(x + i, y, ch as u32, fg.bits(), bg.bits());
}
}
}
pub unsafe fn change_cell(&self, x: usize, y: usize, ch: u32, fg: u16, bg: u16) {
termbox::tb_change_cell(x as c_int, y as c_int, ch, fg, bg)
}
termbox_sys
As you noticed, as_str doesn't appear to do anything. In fact it returns self, a &String, where a &str is expected. This causes the compiler to insert a call to Deref. So your two ways are exactly the same.

Resources