Consider the following Rust function using lifetime elision rules. What will be printed when calling print_first_word?
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
fn print_first_word() {
let sentence = String::from("hello world");
let word = first_word(&sentence);
println!("{}", word);
}
fn main() {
print_first_word();
}Remember that Rust applies lifetime elision rules to functions with references. The returned reference lifetime is tied to the input reference.
The function first_word returns a slice of the input string up to the first space. The lifetime elision rules allow omitting explicit lifetime annotations because the output lifetime is tied to the input reference &str. The printed output is the first word: "hello".
Given the following Rust function, what will be printed when main runs?
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let string1 = String::from("short");
let string2 = String::from("longer string");
let result = longest(&string1, &string2);
println!("{}", result);
}Functions with multiple input references returning a reference require explicit lifetime annotations unless elision rules apply.
The function longest takes two references and returns one of them. Rust's lifetime elision rules do not cover multiple input references returning a reference without explicit lifetime annotations. This code will not compile without specifying lifetimes.
Examine the following Rust code. What lifetime-related error will the compiler report?
fn get_str<'a>() -> &'a str { let s = String::from("hello"); &s } fn main() { let result = get_str(); println!("{}", result); }
Think about the scope of the variable s and the returned reference.
The function tries to return a reference to a local variable s which is dropped when the function ends. This causes a lifetime error because the returned reference would be dangling.
Choose the function signature that compiles without explicit lifetime annotations and correctly applies Rust's lifetime elision rules.
Recall the three lifetime elision rules Rust applies to function signatures.
Rust applies lifetime elision rules as follows: if there is exactly one input lifetime, that lifetime is assigned to all output lifetimes. For multiple input lifetimes, explicit annotations are needed. Option B has one input reference and one output reference, so it compiles without explicit lifetimes.
Given this Rust code, how many explicit lifetime annotations are required for it to compile?
struct Container {
value: &str,
}
impl Container {
fn get_value(&self) -> &str {
self.value
}
}
fn main() {
let s = String::from("data");
let c = Container { value: &s };
println!("{}", c.get_value());
}Struct fields with references require explicit lifetimes. Methods borrowing self usually do not need extra annotations if struct has lifetimes.
The struct Container has a reference field &str which requires an explicit lifetime parameter. The method get_value borrows &self and returns a reference tied to self, so lifetime elision applies and no extra annotation is needed there.