cargo buildwarning: field is never used: `head`--> src/fifth.rs:4:5|4| head:Link<T>,|^^^^^^^^^^^^^|= note: #[warn(dead_code)] on by defaultwarning: field is never used: `tail`--> src/fifth.rs:5:5|5| tail:*mutNode<T>,|^^^^^^^^^^^^^^^^^^warning: field is never used: `elem`--> src/fifth.rs:11:5|11| elem:T,|^^^^^^^warning: field is never used: `head`--> src/fifth.rs:12:5|12| head:Link<T>,|^^^^^^^^^^^^^
pubfnpush(&mut self, elem:T) {letmut new_tail =Box::new(Node { elem: elem, next:None, });let raw_tail:*mut _ =&mut*new_tail;// .is_null checks for null, equivalent to checking for Noneif!self.tail.is_null() {// If the old tail existed, update it to point to the new tail self.tail.next =Some(new_tail); } else {// Otherwise, update the head to point to it self.head =Some(new_tail); } self.tail = raw_tail;}
> cargo builderror[E0609]: no field `next` on type `*mut fifth::Node<T>`--> src/fifth.rs:31:23|31| self.tail.next =Some(new_tail);|----------^^^^||| help: `self.tail` is a raw pointer; try dereferencing it: `(*self.tail).next`
> cargo build
error[E0609]: no field `next` on type `*mut fifth::Node<T>`
--> src/fifth.rs:31:23
|
31 | *self.tail.next = Some(new_tail);
| -----------^^^^
| |
| help: `self.tail` is a raw pointer; try dereferencing it: `(*self.tail).next`
操作符优先级。
(*self.tail).next =Some(new_tail);
> cargo build
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
--> src/fifth.rs:31:13
|
31 | (*self.tail).next = Some(new_tail);
| ^^^^^^^^^^^^^^^^^ dereference of raw pointer
|
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
pubfnpush(&mut self, elem:T) {letmut new_tail =Box::new(Node { elem: elem, next:None, });let raw_tail:*mut _ =&mut*new_tail;// Put the box in the right place, and then grab a reference to its Nodeif!self.tail.is_null() {// If the old tail existed, update it to point to the new tailunsafe { (*self.tail).next =Some(new_tail); } } else {// Otherwise, update the head to point to it self.head =Some(new_tail); } self.tail = raw_tail;}
> cargo buildwarning: field is never used: `elem`--> src/fifth.rs:11:5|11| elem:T,|^^^^^^^|= note: #[warn(dead_code)] on by default
这种污染是可控的,因为隐私。在我们的模块之外,我们的所有结构字段都是完全私有的,所以没有其他人可以以任意的方式干扰我们的状态。只要我们公开的 api 没有组合导致糟糕的事情发生,对于外部观察者来说,我们所有的代码都是安全的!事实上,这和 FFI 的案子没什么不同。只要 python 数学库公开了一个安全的接口,就没有人需要关心它是否外壳到 C 中。
#[cfg(test)]mod test {use super::List; #[test]fnbasics() {letmut list =List::new();// Check empty list behaves rightassert_eq!(list.pop(), None);// Populate list list.push(1); list.push(2); list.push(3);// Check normal removalassert_eq!(list.pop(), Some(1));assert_eq!(list.pop(), Some(2));// Push some more just to make sure nothing's corrupted list.push(4); list.push(5);// Check normal removalassert_eq!(list.pop(), Some(3));assert_eq!(list.pop(), Some(4));// Check exhaustionassert_eq!(list.pop(), Some(5));assert_eq!(list.pop(), None);// Check the exhaustion case fixed the pointer right list.push(6); list.push(7);// Check normal removalassert_eq!(list.pop(), Some(6));assert_eq!(list.pop(), Some(7));assert_eq!(list.pop(), None); }}
这只是堆栈测试,但是预期的 pop 结果反过来了。我还在结尾添加了一些额外的步骤,以确保 pop 中的尾指针损坏情况不会发生。
cargo test
Running target/debug/lists-5c71138492ad4b4a
running 12 tests
test fifth::test::basics ... ok
test first::test::basics ... ok
test fourth::test::basics ... ok
test fourth::test::peek ... ok
test second::test::basics ... ok
test fourth::test::into_iter ... ok
test second::test::into_iter ... ok
test second::test::iter ... ok
test second::test::iter_mut ... ok
test second::test::peek ... ok
test third::test::basics ... ok
test third::test::iter ... ok
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured