【问题标题】:Rust: how to tell the borrow checker that the move is depend on a bool?Rust:如何告诉借用检查器移动取决于布尔值?
【发布时间】:2021-02-21 01:58:29
【问题描述】:

以下代码没有通过借用检查器,因为 Label-A 使用 Label-B 使用的值,但代码实际上是安全的:Label-A 由 processed 保护,仅在以下情况下设置标签-B 已运行。

我如何告诉编译器依赖关系,或者如果我不能,解决这个问题的成语是什么?

(做XCopy/Clone是不行的,也不能做consume引用,Rc<X>也没有吸引力(数据结构已经很复杂了))


struct X(i32);

fn consume1(_x: X) {
    ()
}

fn consume2(_x: X) {
    ()
}

fn predicate(_x: &X) -> bool {
    true
}

pub fn main() {
    let xs = vec![X(1), X(2)];
    
    for x in xs {
        let mut processed = false;

        // for _ in _ {
        if predicate(&x) {
            consume1(x); // Label-B
            processed = true;
        }
        // } end for
        // this for loop here is just to show that the real code
        // is more complicated, the consume1() is actually called
        // (somehow) inside this inner loop

        // some more code
        
        if !processed {
            consume2(x);  // Label-A
        }
    }
}

【问题讨论】:

  • if predicate { } else { } 有效吗?
  • @Thilo 对于问题中的代码,是的,但不幸的是真正的代码更复杂,我不能在if 后面直接放一个else。我已经更新了代码以反映这一点,谢谢。
  • 如果您希望静态代码路径分析起作用,您可能需要稍微重构您的代码以更接近if/else 设置。编译器无法对复杂的逻辑依赖项进行逆向工程。
  • 我不确定我是否完全遵循了您的问题(真实代码可能会有所帮助),但您可以将内容放入 Option 中,然后使用 take 退出该选项。
  • @Thilo 我想我必须重组代码(这会使业务逻辑更加复杂),但值得一问,谢谢。

标签: rust borrow-checker unsafe-pointers


【解决方案1】:

除非我误解了,否则我认为对您来说最好的选择是使用“选项”。这样你也可以摆脱 boolean 标志。

struct X( i32 );

fn consume1( _x: X ) { }

fn consume2( _x: X ) { }

fn predicate( _x: &X ) -> bool {
    true
}

pub fn main( ) {
    let xs = vec![ Some( X( 1 ) ), Some( X( 2 ) ) ];

    for mut x in xs {
        if predicate( x.as_ref( ).unwrap( ) ) {
            consume1( x.take( ).unwrap( ) );
        }   
        if let Some( x ) = x {
            consume2( x );
        }
    }
 }

【讨论】:

  • 感谢您的回答,如果xs 中包含Option,这确实是一个很好的解决方案。 (我决定接受 Thilo 的评论 - 重构代码)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多