Lifetime woes implementing ratatui::Widget for a reference
⚓ Rust 📅 2026-04-22 👤 surdeus 👁️ 1I have this helper struct:
use ratatui::buffer::Buffer;
use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use ratatui::prelude::{Style, Text, Widget};
use ratatui::widgets::Paragraph;
/// A table.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Table<const COLS: usize, const ROWS: usize, T> {
elements: [[T; COLS]; ROWS],
}
impl<const COLS: usize, const ROWS: usize, T> From<[[T; COLS]; ROWS]> for Table<COLS, ROWS, T> {
fn from(elements: [[T; COLS]; ROWS]) -> Self {
Self { elements }
}
}
impl<'a, const COLS: usize, const ROWS: usize, T> Widget for &'a Table<COLS, ROWS, T>
where
&'a T: Into<Text<'a>>,
{
fn render(self, area: Rect, buf: &mut Buffer) {
// Build 3 rows inside inner block
let rows = Layout::default()
.direction(Direction::Vertical)
.constraints(
[Constraint::Percentage(
u16::try_from(100usize / ROWS).expect("Percentage always fits."),
); ROWS],
)
.split(area);
for (row_area, row) in rows.iter().zip(&self.elements) {
let cols = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[Constraint::Percentage(
u16::try_from(100usize / COLS).expect("Percentage always fits."),
); COLS],
)
.split(*row_area);
for (cell_area, cell) in cols.iter().zip(row) {
let cell = Paragraph::new(cell)
.style(Style::default())
.alignment(Alignment::Center);
cell.render(*cell_area, buf);
}
}
}`
}
However, I cannot seem to get the lifetime constraints right on impl Widget:
Compiling uml-tui v0.1.0 (/home/rne/Projekte/usb-missile-launcher/tui)
error[E0599]: the method `render` exists for struct `table::Table<3, 3, &str>`, but its trait bounds were not satisfied
--> tui/src/app.rs:131:76
|
131 | Table::from([["", "^", ""], ["<", "<Enter>", ">"], ["", "v", ""]]).render(inner, buf);
| ^^^^^^ method cannot be called on `table::Table<3, 3, &str>` due to unsatisfied trait bounds
|
::: tui/src/table.rs:8:1
|
8 | pub struct Table<const COLS: usize, const ROWS: usize, T> {
| --------------------------------------------------------- method `render` not found for this struct
|
note: trait bound `&&str: Into<Text<'_>>` was not satisfied
--> tui/src/table.rs:20:12
|
18 | impl<'a, const COLS: usize, const ROWS: usize, T> Widget for &'a Table<COLS, ROWS, T>
| ------ ------------------------
19 | where
20 | &'a T: Into<Text<'a>>,
| ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `render`, perhaps you need to implement one of them:
candidate #1: `Widget`
candidate #2: `ratatui::prelude::StatefulWidget`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `uml-tui` (bin "uml-tui") due to 1 previous error
I also tried using HRTBs:
impl<'a, const COLS: usize, const ROWS: usize, T> Widget for &'a Table<COLS, ROWS, T>
where
for<'b> &'b T: Into<Text<'a>>,
{
fn render(self, area: Rect, buf: &mut Buffer) {
// Build 3 rows inside inner block
let rows = Layout::default()
.direction(Direction::Vertical)
.constraints(
[Constraint::Percentage(
u16::try_from(100usize / ROWS).expect("Percentage always fits."),
); ROWS],
)
.split(area);
for (row_area, row) in rows.iter().zip(&self.elements) {
let cols = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[Constraint::Percentage(
u16::try_from(100usize / COLS).expect("Percentage always fits."),
); COLS],
)
.split(*row_area);
for (cell_area, cell) in cols.iter().zip(row) {
let cell = Paragraph::new(cell)
.style(Style::default())
.alignment(Alignment::Center);
cell.render(*cell_area, buf);
}
}
}
}
Resulting in:
Compiling uml-tui v0.1.0 (/home/rne/Projekte/usb-missile-launcher/tui)
error[E0599]: the method `render` exists for struct `table::Table<3, 3, &str>`, but its trait bounds were not satisfied
--> tui/src/app.rs:131:76
|
131 | Table::from([["", "^", ""], ["<", "<Enter>", ">"], ["", "v", ""]]).render(inner, buf);
| ^^^^^^ method cannot be called on `table::Table<3, 3, &str>` due to unsatisfied trait bounds
|
::: tui/src/table.rs:8:1
|
8 | pub struct Table<const COLS: usize, const ROWS: usize, T> {
| --------------------------------------------------------- method `render` not found for this struct
|
note: trait bound `&'b &str: Into<Text<'_>>` was not satisfied
--> tui/src/table.rs:20:20
|
18 | impl<'a, const COLS: usize, const ROWS: usize, T> Widget for &'a Table<COLS, ROWS, T>
| ------ ------------------------
19 | where
20 | for<'b> &'b T: Into<Text<'a>>,
| ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `render`, perhaps you need to implement one of them:
candidate #1: `Widget`
candidate #2: `ratatui::prelude::StatefulWidget`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `uml-tui` (bin "uml-tui") due to 1 previous error
How can I convince the borrow checker, that this works for any type of reference?
10 posts - 3 participants
🏷️ Rust_feed