【问题标题】:How to handle passing a mutably borrowed struct to function closure?如何处理将可变借用的结构传递给函数闭包?
【发布时间】:2019-12-09 09:43:26
【问题描述】:

我正在使用 proptest crate 在 no_std 环境中运行一些属性测试。 proptest 的默认 test_runner::TestRunner::run() 实现需要一些输入(作为 proptest 中定义的 StrategyValueTree 对象)和函数闭包作为参数,因此您可以使用值树或策略中的值运行任意数量的测试。

我需要测试一个函数调用,该函数调用将可变借用结构作为参数。这不会编译:

error[E0596]: cannot borrow `*<obj>` as mutable, as it is a captured variable in a 'Fn' closure

obj 是通过上一层的函数调用传递给test_runner 的结构,作为可变借用对象。

挖掘proptest的源代码,很明显编译错误是由于test_runner::TestRunner::run()的函数签名引起的:

pub fn run<S: Strategy>(
    &mut self,
    strategy: &S,
    test: impl Fn(S::Value) -> TestCaseResult,
) -> TestRunResult<S>

参数需要为FnMut,以便捕获的变量在函数调用中可以是可变的。我的问题是:有没有一种惯用的 rust 方式来做到这一点?

这是从条件编译的 run func 传递的函数:

fn test_mod(runner: &mut TestRunner, obj: &mut MyObjStruct) -> Result<(), TestError(u32)>>{
    runner.run(&(0x400_0000u32..0xe00_0000u32), |addr| {
        if mod::test::test_page_map(addr, obj).is_ok() {
            Ok(())
        } else {
            Err(TestCaseError::fail(Reason::from("Failed to map address")))
        }
    })
}

mod::test::test_page_map 采用obj,在结构中使用相关元数据,相应地更新该数据,并将页面映射到输入地址。它根据映射是否成功返回结果。值得注意的是,我无法克隆该对象。

有没有人看到符合“Rust 方式”的解决这个问题的方法?在 no_std 领域是否有一些可用的机制,比如 Cell 或者我可以用它来包装可变对象,使其具有内部可变性但可以作为捕获的变量传递给“Fn”闭包?我对 Rust 很陌生,所以不确定通常如何处理这种事情。

【问题讨论】:

  • 在 no_std 领域中是否有一些可用的机制,比如 cell——你的意思是像 core::cell::Cell 这样的机制吗?
  • 欢迎来到 Stack Overflow!很难回答您的问题,因为它不包含minimal reproducible example。我们无法分辨代码中存在哪些 crate(及其版本)、类型、特征、字段等。如果您尝试在Rust Playground 上重现您的错误,如果可能的话,这将使我们更容易为您提供帮助,否则在全新的 Cargo 项目中,然后在edit 您的问题中包含附加信息。您可以使用Rust-specific MRE tips 来减少您在此处发布的原始代码。谢谢!
  • 是的,这样可以解决函数签名问题吗?
  • 由于我的其他评论,我们无法告诉您。如果没有minimal reproducible example,我们尝试的任何事情都只是猜测。我相信您不需要no_std 来重现您的问题。我还相信您可以在一个全新的 Cargo 项目中编写 30-50 行代码total,该项目仅使用 proptest 来重现您遇到的问题。
  • 明确地说,我们不需要您的代码。时期。尤其是“大量”。应该有零 IP 问题,因为您在本地获取代码,最小化它,最小化它,最小化它,然后在最后给它一些新名称(然后再最小化一些)。这就是你发布的内容。它通常也可以解决您的问题,因为您 (a) 使用 ARM (b) 使用 no_std (c) 使用 proptest (d) 使用 nightly (e) 使用自定义测试框架这一事实可能并不重要解决根本问题。

标签: testing rust closures ownership proptest


【解决方案1】:

找到了一个可行的答案,尽管可能还有其他答案。我发现有效的是使用core::cell::RefCell::new(obj) 来包装对象。然后通过调用RefCell提供的borrow_mut()方法将RefCell包装的对象作为可变借用传递给函数

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    相关资源
    最近更新 更多