rust - 嵌套结构:“借来的值不够长”
问题描述
我一直在努力创建一个Table
可以解析为Val
特征对象以及其他数据类型(Number
作为示例实现)的结构,并且可以在 Rust Playground 中看到。我无法解决这个借用/终身问题,但我的想法是,Number
两者Table
都是Val
对象。但是,任何将对象写入String
缓冲区的尝试都会导致编译失败。
我在这里做错了什么?借用检查器以这种方式运行的基本原理是什么?
use std::fmt;
use std::fmt::Write;
struct Number(f64);
struct Table<'a> {
rows: Vec<Row<'a>>
// Will have column vector as a member
}
impl <'a>Table<'a> {
fn new(rows: Vec<Vec<Box<dyn Val>>>) -> Table {
let mut table = Table {
rows: rows.into_iter().map(|r| {
Row {
parent: std::ptr::null_mut(),
cells: r
}
}).collect()
};
let parent = &mut table as *mut Table;
table.rows = table.rows.into_iter().map(|mut r| {
r.parent = parent;
r
}).collect();
table
}
}
struct Row<'a> {
parent: *mut Table<'a>,
cells: Vec<Box<dyn Val<'a>>>
}
impl <'a>Row<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result {
let mut cell_iter = self.cells.iter().enumerate().peekable();
let _parent = unsafe { self.parent.as_ref() }; // Real implementation will need parent ref
while let Some((idx,_c)) = cell_iter.next() { // Real implementation will cycle through columns in parent struct
match self.cells.get(idx) {
Some(v) => v.to_str(buf),
None => Ok(())
}?;
if let Some(_) = cell_iter.peek() {
write!(buf, ",")?;
}
}
Ok(())
}
}
pub trait Val<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result;
}
pub trait ObjWriter<'a> {
fn to_str(&'a self, buf: &'a mut String) -> fmt::Result;
}
impl <'a>ObjWriter<'a> for dyn Val<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result { self.to_str(buf) }
}
impl <'a>Val<'a> for Table<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result {
write!(buf, "(START TABLE:")?;
let mut row_iter = self.rows.iter().peekable();
while let Some(r) = row_iter.next() {
r.to_str(buf)?;
write!(buf, "\n")?;
}
write!(buf, "END TABLE)")
}
}
impl Number {
fn to_str(&self, buf: &mut String) -> fmt::Result {
write!(buf,"{}",self.0)
}
}
impl <'a>Val<'a> for Number {
fn to_str(&self, buf: &mut String) -> fmt::Result {
self.to_str(buf)
}
}
fn main() {
let table = Table::new(vec![
vec![Box::new(Number(0.5)),Box::new(Table::new(Vec::new()))],
vec![Box::new(Table::new(Vec::new())),Box::new(Number(0.5))],
]);
let mut buf = String::new();
table.to_str(&mut buf);
println!("{}",buf)
}
error[E0597]: `table` does not live long enough
--> src/main.rs:98:5
|
92 | let table = Table::new(vec![
| ____________________________-
93 | | vec![Box::new(Number(0.5)),Box::new(Table::new(Vec::new()))],
94 | | vec![Box::new(Table::new(Vec::new())),Box::new(Number(0.5))],
95 | | ]);
| |_____- cast requires that `table` is borrowed for `'static`
...
98 | table.to_str(&mut buf);
| ^^^^^ borrowed value does not live long enough
99 | println!("{}",buf)
100 | }
| - `table` dropped here while still borrowed
解决方案
我按照trentcl的建议做了,注意到我的指针在移动时会失效,我重构了我的代码,以便任何Row
方法都将父表的引用作为第一个参数。然后我删除了所有<'a>
后续的编译器错误,直到它起作用。
所以整个问题是允许生命周期失控并使用不安全的方法来获取父引用。去搞清楚...
推荐阅读
- javascript - Switch 语句输出 - JavaScript
- php - 访问特定页面(wordpress之外)自定义php页面时如何清除woocommerce购物车
- python - 如何以 Z 单位的间隔生成从日期 X 到日期 Y 的常规时间序列?
- mobile - 在颤振中使用哪个上下文?有什么区别?
- javascript - 错误:$(...).material_select 不是函数(materialize.css)
- java - 更新 listView 行的文本
- c# - WPF 在通过资源字典引用时锁定图像
- python - Python numpy 多维数组索引
- amp-html - AMP JS 更新是否破坏了 ON 属性?
- python - 使用 pyspark 解析特定列