In the following code, I don't understand why the Span require a lifetime. Since all the arguments implement the copy trait, my understanding is that the Span own all the required variables.
use ratatui::{
style::{Color, Style},
text::Span,
};
/// Take a u8, and render a colorized ascii, or placeholdler
fn render_ascii_char(val: u8) -> Span {
match val {
val if val > 0x20 && val < 0x7f => {
Span::styled(
val.to_string(),
Style::default().fg(Color::LightCyan)
)
},
_ => {
Span::styled(
"•",
Style::default().fg(Color::Yellow)
)
}
}
}
fn test_function() -> Span {
let val = 0x42;
render_ascii_char(val)
}
fn main() {
let _my_span = test_function();
}
This code use ratatui
. Bellow the Cargo.toml
:
[package]
name = "span_lifetime"
version = "0.1.0"
edition = "2024"
[dependencies]
crossterm = "0.27.0"
ratatui = "0.26.2"
I have the following error message when compiling with cargo build
:
$ cargo build
Compiling span_lifetime v0.1.0 (/tmp/playground/span_lifetime)
error[E0106]: missing lifetime specifier
--> src/main.rs:7:34
|
7 | fn render_ascii_char(val: u8) -> Span {
| ^^^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
7 | fn render_ascii_char(val: u8) -> Span<'static> {
| +++++++++
error[E0106]: missing lifetime specifier
--> src/main.rs:26:23
|
26 | fn test_function() -> Span {
| ^^^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
26 | fn test_function() -> Span<'static> {
| +++++++++
For more information about this error, try `rustc --explain E0106`.
error: could not compile `span_lifetime` (bin "span_lifetime") due to 2 previous errors
Using a <'static>
lifetime doesn't seems like a good idea, since I don't use this function only with constants.
Using a reference val: &u8
as an argument, instead of val: u8
does work.
But it create issues when the value passed goes out of scope.
My solution so far is to specify a lifetime:
fn render_ascii_char<'a>(val: u8) -> Span<'a> {
match val {
[...]
But I don't really understand why this is required, nor the implications of this lifetime.
From the definition of Span
:
pub struct Span<'a> {
pub content: Cow<'a, str>,
pub style: Style,
}
You can see it contains a Cow
which might contain a reference in the Borrowed
variant:
pub enum Cow<'a, B>
where
B: 'a + ToOwned + ?Sized,
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
and because of that the struct itself needs to be annotated with a lifetime as you can't add a lifetime dynamically (that's inherently impossible because types and lifetimes are a compile time construct only!).
Since you don't fulfill any of the conditions in which the lifetime can be elided, you have to explicitly add it.
'static
is the correct lifetime to use here, it doesn't at all mean you do or can only use the returned Span
with constants, but instead that it doesn't contain any references that live shorter than 'static
.