We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ownership III: Lifetimes, Explicitly step 8 of 22
longest: writing your first 'a
Return a borrowed string without copying its contents. This exercise compares two functions: one needs a named lifetime to connect its inputs and output; the other can use Rust's lifetime-elision rules.
Your task
Fix longest and implement longest_of:
| Function | Required result |
|---|---|
longest(a, b) |
The longer input by byte length; return a on a tie. |
longest_of(items) |
A borrowed view of the first longest string, or None for an empty slice. |
Keep the two function-pointer declarations below the functions. Return &str
values borrowed from the inputs, not new String values. An empty string is
still an element: longest_of(&[String::new()]) returns Some(""), not None.
Length means UTF-8 bytes. For example, "é" and "ab" both have length 2,
so longest("ab", "é") returns "ab". Do not compare character counts.
Connect both inputs to the result
In fn longest(a: &str, b: &str) -> &str, the two input references have
separate elided lifetimes. The signature does not say which one constrains
the returned reference, so Rust reports a missing lifetime specifier.
The function can return either argument. A shared lifetime expresses that:
pub fn longest<'a>(a: &'a str, b: &'a str) -> &'a str
Both inputs must be valid for the lifetime used by the result. Their owners do not need identical scopes, and the annotation does not change when either owner is dropped. A caller can borrow a longer-lived value for a shorter period so both inputs meet this contract.
The caller must respect the signature even when it can predict which branch will win. It cannot keep the result past an input's valid borrow just because that input happens to be shorter.
Read the starter's error
The starter gives the inputs independent lifetimes, then promises a result valid for the first one:
pub fn longest<'a, 'b>(a: &'a str, b: &'b str) -> &'a str
Returning b cannot satisfy that promise without a relationship between
'b and 'a. Use the shared-lifetime signature above. Adding 'a only to
the first input and output still leaves the second input unrelated.
Let longest_of use elision
pub fn longest_of(items: &[String]) -> Option<&str>
There is only one input reference lifetime, so the elision rules connect it
to the reference inside Option. The returned slice borrows from a string
owned by items.
An explicit equivalent lifetime is valid Rust, but unnecessary here. Keep this signature elided: the exercise's Clippy gate rejects needless lifetime annotations. This is a style check, not a memory-safety error.
To keep the first longest element, replace your current choice only when a
later string is strictly longer. max_by_key chooses the last maximum on a
tie, so using it directly would violate the requested behavior. A loop, fold
or reduce can keep the first match.
What the driver checks
The driver creates the second input in an inner block. It calls longest
there and copies the result into an owned String before leaving the block.
That owned copy can survive the second input; the borrowed result could not.
The supplied declarations also require compatible borrowed-return types:
const _: for<'a> fn(&'a str, &'a str) -> &'a str = longest;
const _: for<'a> fn(&'a [String]) -> Option<&'a str> = longest_of;
for<'a> means the function pointer must support any lifetime chosen for a
call. These declarations catch incompatible signatures, such as returning an
owned String or requiring static inputs. They do not prove that the function
selects the correct string; the value tests check lengths, ties and emptiness.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.