use std::{fmt::Display, ops::Deref};
#[derive(Debug, Clone, Copy)]
struct StackNode<'a, T> {
data: &'a T,
next: Option<&'a StackNode<'a, T>>,
}
impl<'a, T> StackNode<'a, T> {
fn new(data: &'a T, next: Option<&'a StackNode<'a, T>>) -> Self {
Self { data, next }
}
pub fn len(&self) -> usize {
self.into_iter().count()
}
fn insert(&mut self, sn: &'a mut Self) -> &mut Self {
match self.next {
Some(_) => {
sn.next = self.next;
self.next = Some(sn);
}
None => {
self.next = Some(sn);
}
}
self
}
}
impl<'a, T> Deref for StackNode<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.data
}
}
pub struct RefNodeIterator<'a, T> {
current: Option<&'a StackNode<'a, T>>,
}
impl<'a, T> Iterator for RefNodeIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match self.current {
Some(node) => {
self.current = node.next;
Some(node.data)
}
None => None,
}
}
}
impl<'a, T> IntoIterator for &'a StackNode<'a, T> {
type Item = &'a T;
type IntoIter = RefNodeIterator<'a, T>;
fn into_iter(self) -> Self::IntoIter {
RefNodeIterator {
current: Some(self),
}
}
}
impl<'a, T: Display> Display for StackNode<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut repr = String::new();
let mut iter = self.into_iter();
loop {
match iter.next() {
Some(d) => {
repr += &format!("{d} --> ");
}
None => {
repr += "NULL";
break;
}
}
}
write!(f, "{repr}")
}
}
#[test]
fn insert() {
let data = (0..4)
.into_iter()
.map(|i| format!("{i}"))
.collect::<Vec<_>>();
let mut data_iter = data.iter();
let mut n0 = StackNode::new(data_iter.next().unwrap(), None);
let mut n1 = StackNode::new(data_iter.next().unwrap(), None);
n0.insert(&mut n1);
let mut n2 = StackNode::new(data_iter.next().unwrap(), None);
n1.insert(&mut n2); // this does NOT work
n0.insert(&mut n2); // this works. why ?
let mut n3 = StackNode::new(data_iter.next().unwrap(), None);
n0.insert(&mut n3);
assert_eq!(n0.to_string(), "0 --> 3 --> 2 --> 1 --> NULL");
}
cargo t --tests
Compiling smart_pointers v0.1.0 (/home/akash/Programming/rust/projects/smart_pointers)
error[E0499]: cannot borrow `n1` as mutable more than once at a time
--> src/test/stack_linked_list.rs:115:5
|
112 | n0.insert(&mut n1);
| ------- first mutable borrow occurs here
...
115 | n1.insert(&mut n2);
| ^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
...
118 | n0.insert(&mut n3);
| ------------------ first borrow later used here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `smart_pointers` (bin "smart_pointers" test) due to previous error
在上面的代码片段中,第一个借位使用在哪里,而第二个借位用于 n1? rust 编译器是否将 n1 的第一个可变借用的范围扩展到 n0 的范围?这就是为什么 n1 的第二次借用不被允许的原因吗?目前还不清楚 rust 编译器如何从错误消息中推断出借用的长度。 Rust 到底是如何推断出可变借用的持续时间/范围的?
sn
方法中可变借用insert
的存储可能会导致n1
可变借用的范围扩展到整个测试函数的范围。这是因为节点本身包含从 vec 借用的内容,这迫使 Rust 延长 n0
的持续时间范围,从而延长 n1
的持续时间范围,因为它存储在其中。