在 Rust 0.8 中:
struct TwoStr {
one: ~str,
two: ~str,
}
#[test]
fn test_contents() {
let strs = TwoStr {
one: ~"pillar",
two: ~"post",
};
assert_eq!(strs.one, ~"pillar");
assert_eq!(strs.two, ~"post");
}
代码甚至无法编译。 rust test
认为第二个 assert_eq
有错误:
error: use of partially moved value:
strs
这有点违反直觉。我的意思是,无论第一个 assert_eq
可能产生什么影响,当执行到第二个 assert_eq
时,它应该完全超出范围。当然,除非它确实在幕后产生了一些。是吗?
如果不是,为什么会出现这个神秘的错误?希望我对 Rust 指针的理解没有根本性的缺陷。
最佳答案
在 Rust 0.8 中,assert_eq!
定义为
macro_rules! assert_eq (
($given:expr , $expected:expr) => (
{
let given_val = $given;
let expected_val = $expected;
// check both directions of equality....
if !((given_val == expected_val) && (expected_val == given_val)) {
fail!(\"assertion failed: `(left == right) && (right == \
left)` (left: `%?`, right: `%?`)\", given_val, expected_val);
}
}
)
)
请注意,它会将两个参数都移动到本地 let-bindings given_val
和 expected_val
中。这就是导致错误的原因。
在当前的 master 中,这已得到修复。 assert_eq!
现在引用参数:
macro_rules! assert_eq (
($given:expr , $expected:expr) => (
{
let given_val = &($given);
let expected_val = &($expected);
// check both directions of equality....
if !((*given_val == *expected_val) &&
(*expected_val == *given_val)) {
fail!("assertion failed: `(left == right) && (right == left)` \
(left: `{:?}`, right: `{:?}`)", *given_val, *expected_val)
}
}
)
)
这意味着它不再移动其参数,从而修复了您的错误。
如果你需要坚持使用 rust 0.8,你可以改为使用 assert!()
并直接进行比较,这样可以避免移动。但我的建议是升级到最新的 master。
关于Rust:使用部分移动的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20543746/