Rust:使用部分移动的值

时间:2013-12-12 12:35:19

标签: rust

在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中存在错误:

  

错误:使用部分移动的值:strs

这有点违反直觉。我的意思是,无论第一个assert_eq可能产生什么影响,当执行到达第二个assert_eq时,它应该远远超出范围。除非当然,它会在场景后面产生一些东西。是吗?

如果没有,为什么会出现这个神秘的错误?希望我对Rust指针的理解没有根本的缺陷。

2 个答案:

答案 0 :(得分:6)

在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_valexpected_val。这就是造成错误的原因。

在当前的主人中,这已得到修复。 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)
            }
        }
    )
)

这意味着它不再移动其参数,从而修复了您的错误。

如果您需要坚持使用生锈0.8,您可以将其更改为使用assert!()而直接进行比较,这样可以避免移动。但我的建议是升级到最新的主人。

答案 1 :(得分:3)

适用于Git master。它必须是在0.8被切断后修复的错误。一般来说,发布的版本在发布之前并不局限于特别稳定 - 它们本质上只是快照。

libsyntaxassert_eq!宏的定义引用了参数,因此不应移动参数,并且可以在调用宏后使用它们。

如果您确实发现了其他错误,请尽量编译master,或者只创建一个新的issue