gpt4 book ai didi

rust - 如何创建包含引用的结构的 Quickcheck Arbitrary?

转载 作者:行者123 更新时间:2023-11-29 08:05:23 26 4
gpt4 key购买 nike

rust quickcheck documentation注意对于任何实现 Arbitrary

的类型

They must also be sendable and static since every test is run in its own thread using thread::Builder::spawn, which requires the Send + 'static bounds.

如果我需要为包含引用的结构生成数据,我该怎么做呢?例如:

#![cfg_attr(test, feature(plugin))]
#![cfg_attr(test, plugin(quickcheck_macros))]

#[cfg(test)]
extern crate quickcheck;

#[cfg(test)]
use quickcheck::{Arbitrary,Gen};

#[allow(dead_code)]
#[derive(Debug,Clone)]
pub struct C<'a> {
s: &'a str,
b: bool
}

#[cfg(test)]
impl<'a> Arbitrary for C<'a> {
fn arbitrary<G: Gen>(g: &mut G) -> C<'a> {
let s = g.gen::<&str>();
C{s: s, b: (s.len() > 0)}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[quickcheck]
fn len_checks_out(c: C) -> bool {
(c.s.len() > 0) == c.b
}
}

失败了

cargo test
Compiling qcq v0.1.0 (file:///Users/blt/projects/us/troutwine/qcquestion)
src/lib.rs:18:10: 18:19 error: the type `C<'a>` does not fulfill the required lifetime [E0477]
src/lib.rs:18 impl<'a> Arbitrary for C<'a> {
^~~~~~~~~
note: type must outlive the static lifetime
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
error: Could not compile `qcq`.

这是一个有点人为的例子,但它与原始问题的精神是一样的。生命周期注解可以解决,但正在测试中。

最佳答案

您不能这样做有两个原因。一、Arbitrary有一个 'static绑定(bind),这意味着实现 Arbitrary 的类型可能没有引用,除非它们的生命周期是 'static .这确保实例不会引用它们不“拥有”的对象。

其次,为了返回一个C<'a>其中 'a'static 以外的任何东西,大多数时候你还需要一个包含具有相同生命周期参数的引用的参数(这并不总是必要的,例如,当使用生命周期参数的字段可以稍后初始化时,但这里不适用)。因此,您需要一个像这样定义的函数:

fn arbitrary<'a, G: Gen>(g: &'a mut G) -> C<'a> {
let s = g.gen::<&str>();
C { s: s, b: (s.len() > 0) }
}

(注意 'a 是在函数上定义的,而不是在 impl 上定义的。)

这有两个大问题:

  • Arbitrary::arbitrary()返回 Self .这意味着该函数必须返回 Arbitrary 所在的类型。实现。然而,在这里,C<'a>取决于在函数上定义的生命周期参数; C<'a>不可能与 impl 相同目标,因为该类型不能使用该生命周期参数。
  • Rng::gen()只需调用 Rand::rand() ,它也返回 Self ,因此遇到与 Arbitrary::arbitrary() 相同的问题.另外,Rand未针对 &str 实现(甚至是 String )。

那你能做什么?而不是存储 &str在你的结构中,你应该存储一个 String .这使得你的结构 'static , 你可以使用 Arbitrary 的实现对于 String生成测试值。

但是如果您不想使用 String 怎么办?在您的实际应用程序代码中?您可以通过接受 &str 来使您的结构通用或 String .标准库中有两个特性可以帮助您做到这一点: AsRef Borrow .这是一个使用 Borrow 的示例:

use std::borrow::Borrow;

#[derive(Debug, Clone)]
pub struct C<S: Borrow<str>> {
s: S,
b: bool
}

现在,您可以使用 C<&str>C<String> ,取决于需要什么。显然,您无法实现 Arbitrary对于 C<&str> , 但您可以为 C<String> 实现它.实际上,为什么不为所有实现 Arbitrary 的类型实现它呢? ?

impl<S: Borrow<str> + Arbitrary> Arbitrary for C<S> {
fn arbitrary<G: Gen>(g: &mut G) -> C<S> {
let s: S = Arbitrary::arbitrary(g);
let b = s.borrow().len() > 0;
C { s: s, b: b }
}
}

关于rust - 如何创建包含引用的结构的 Quickcheck Arbitrary?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36390808/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com