В следующем коде я не понимаю, почему для Span требуется время жизни. Поскольку все аргументы реализуют свойство копирования, я понимаю, что Span владеет всеми необходимыми переменными.
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();
}
Используйте этот код ratatui. Ниже Cargo.toml:
[package]
name = "span_lifetime"
version = "0.1.0"
edition = "2024"
[dependencies]
crossterm = "0.27.0"
ratatui = "0.26.2"
При компиляции с 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
Использование времени жизни <'static> не кажется хорошей идеей, поскольку я не использую эту функцию только с константами.
Использование ссылки val: &u8 в качестве аргумента вместо val: u8 работает.
Но это создает проблемы, когда переданное значение выходит за рамки.
Мое решение до сих пор состоит в том, чтобы указать время жизни:
fn render_ascii_char<'a>(val: u8) -> Span<'a> {
match val {
[...]
Но я действительно не понимаю, почему это необходимо и какие последствия это может иметь в этой жизни.

Из определения Пролета:
pub struct Span<'a> {
pub content: Cow<'a, str>,
pub style: Style,
}
Вы можете видеть, что он содержит Корову , которая может содержать ссылку в варианте Заимствованный:
pub enum Cow<'a, B>
where
B: 'a + ToOwned + ?Sized,
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
и из-за этого сама структура должна быть аннотирована временем жизни, поскольку вы не можете добавлять время жизни динамически (это по своей сути невозможно, потому что типы и время жизни являются только конструкцией времени компиляции!).
Поскольку вы не выполняете ни одного из условий, при которых время жизни может быть исключено, вам необходимо явно добавить его.
'static — это правильное время жизни, которое следует использовать здесь, это вовсе не означает, что вы используете или можете использовать только возвращаемый Span с константами, но вместо этого он не содержит ссылок, которые живут короче, чем 'static.
Хорошо, я понимаю, что использование 'static означает, что мы указываем на некую память, которая всегда действительна. Либо константа (здесь наш '•'), либо собственное значение. Поскольку val копируется при передаче в функцию, это собственное значение. Итак, 'static — правильный образ действий. Буду рад, если кто-нибудь это подтвердит
'static здесь не имеет никакого эффекта для варианта Cow::Owned (String). Он используется только в Cow::Borrowed, и в этом случае да, указанная память должна жить до конца программы, но это тривиально верно для строковых литералов, таких как "•", они компилируются в исполняемый файл. Аннотация времени жизни (даже 'static) сама по себе не может создать утечку памяти, это может сделать только явный метод, такой как Box::leak. Однако это распространенное заблуждение всей жизни
Насколько я понимаю, использование
'staticделает переменную активной на время работы программы (doc.rust-lang.org/rust-by-example/scope/lifetime/…). Поскольку эта функция часто используется в моем коде, кажется, что использование'staticприведет к утечке памяти, когда я всегда выделяю память, которая никогда не освобождается. Или я здесь что-то не понимаю?