@amarao asked in another thread:
#![deny(elided_lifetimes_in_paths)]
is a "allowed by default" lint (not even on warn by default!), that I like to enable to help me catch the following type of errors:
fn main ()
{
let result = {
let numbers = [42, 27];
try_sum(&numbers)
};
match result {
| Ok(sum) => println!("Sum is {}", sum),
| Err(err_msg) => eprintln!("Error: {}", err_msg),
}
}
fn try_sum (numbers: &[i32]) -> Result<i32, ErrMsg>
{
numbers
.iter().cloned()
.try_fold(0, i32::checked_add)
.ok_or("sum overflowed")
}
/// `ErrMsg` is an alias for `&str`:
type ErrMsg<'a> = &'a str;
This code fails to compile with:
error[E0597]: `numbers` does not live long enough
--> src/main.rs:5:17
|
3 | let result = {
| ------ borrow later stored here
4 | let numbers = [42, 27];
5 | try_sum(&numbers)
| ^^^^^^^^ borrowed value does not live long enough
6 | };
| - `numbers` dropped here while still borrowed
Where does the problem come from?
The error message gives us some hint:
numbers
dropped here while still borrowed
In other words, the return value of try_sum
is still borrowing the input numbers
:
fn try_sum (numbers: &[i32]) -> Result<i32, ErrMsg>
{
numbers
.iter().cloned()
.try_fold(0, i32::checked_add)
.ok_or("sum overflowed")
}
For some people, specially beginners, the reason may not be obvious, specially when more complex code is involved. But with #![deny(elided_lifetimes_in_paths)]
, we get the following error:
error: hidden lifetime parameters in types are deprecated
--> src/main.rs:15:45
|
15 | fn try_sum (numbers: &[i32]) -> Result<i32, ErrMsg>
| ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
which gives:
fn try_sum (numbers: &[i32]) -> Result<i32, ErrMsg<'_>>
In other words, the function signature has an elided lifetime parameter in return position, which points towards the root of the problem:
there already was a single input elided lifetime parameter with &[i32]
(I wish there was a lint for that too), and now that there is an output elided parameter, they "connect", as dictated by lifetime elision rules:
If there is exactly one lifetime used in the parameters (elided or not), that lifetime is assigned to all elided output lifetimes.
leading to:
fn try_sum<'numbers> (numbers: &'numbers [i32]) -> Result<i32, ErrMsg<'numbers>>
for Rust, this means that the error message is borrowing from numbers
, which is definitely not the case here.
Solution
Since our function is actually returning a &'static str
on error, either we explicit it with ErrMsg<'static>
or, in this case, declare ErrMsg
to be always 'static
:
type ErrMsg = &'static str;
ErrMsg
, self::ErrMsg
, or more generally, path::to::ErrMsg
, is a path
element
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.