1

预期行为:

在 vscode 中单击“运行 doctest”应该从 doctest 片段执行一项测试。

终端输出应该说(“1 通过;”或“1 失败;”)和“1 被过滤掉;”。

实际行为:

在 vscode 中点击“Run doctest”会执行 0 个测试,显示有 2 个被过滤掉了。

终端输出:

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.00s

源代码:

我的机器:

  • macOS 12
  • rustc 1.57.0
  • rust analyzer v0.3.954

我为缩小问题范围所做的工作:

  1. 在终端中运行“相同”命令演示了预期的行为。终端输出显示test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.40s当我运行时cargo test --doc --package my_cache -- "Cacher<T>::new" --nocapture这正是我单击“运行 Doctest”时终端所说的运行
  2. 在同一个 repo 中的另一个 crate(称为“math”)中单击“Run Doctest”,展示了预期的行为。

看看我的行为不端的箱子和我的工作箱子之间的区别:

A. 这个行为不端的 crate 的 doctest 位于 where-impl因为其他 crate 的 doctest 位于文件的根级别。

B. 这个行为不端的 crate 的 doctest 适用于接受closure类型的通用结构。

C. 执行cargo testfromcrates/my_cache演示了预期的行为,具有以下终端输出:

// ... some output omitted

   Doc-tests my_cache

running 2 tests
test src/lib.rs - Cacher<T>::new (line 26) ... ok
test src/lib.rs - Cacher<T>::value (line 42) ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.44s

同样,这里是源代码:

也许?值得注意的细节

  • 我已经按照https://github.com/rust-analyzer/rust-analyzer的结构对我的 git 仓库进行了建模,这样我就使用了 cargoworkspaces并且crates/*是成员。我有一个根cargo.toml,可以使用类似的东西指定本地依赖my_cache = {path = "crates/my_cache}项,但是我想不出这是一个促成因素的原因,因为我已经证明我的mathcrate 可以在这种结构中,而不会混淆vscode并过滤掉其中的 doctests意想不到的板条箱。

我的怀疑?

  • 发生了一些事情,导致 doctest 在不应该被过滤掉时被过滤掉。
    • 也许当我单击时声称正在执行Run Doctest的命令不是正在执行的 ACTUAL 命令。
    • 也许(错误?)与闭包类型有关。我忘记了我在哪里读到的,但我隐约记得 Rust 闭包类型是“未命名”的,这使得引用它们变得很奇怪。不幸的是,我找不到我正在查看的详细介绍了此内容的资源。(它可能是涵盖 Rust 编译器以及 Rust 编译器如何在内存中显示数据类型的资源,但我不记得细节(也许阅读本文的人会知道我在这里指的是什么))。

这是为了长寿而复制到此答案中的行为不端的 crate 源代码,以防我对 github 存储库进行更改:

// Credit to: https://doc.rust-lang.org/book/ch13-01-closures.html
// (I've modified their example to use a HashMap instead of a single value)
use std::collections::HashMap;

/// cacher for calculation with two u64's as input and u64 as output
/// can be generalized more
pub struct Cacher<T>
where
    T: FnMut(u64, u64) -> u64,
{
    calculation: T,
    values: HashMap<String, u64>,
}

impl<T> Cacher<T>
where
    T: FnMut(u64, u64) -> u64,
{
    /// Returns a Cacher<T> which can cache results of calculations for the provided closure.
    ///
    /// # Arguments
    ///
    /// `T` - Closure that computes produces a value. Value is cached based on args. Cached value is returend on subsequent calls if args are the same.
    ///
    /// # Examples
    /// ```rust
    /// use my_cache::Cacher;
    /// let mut cacher = Cacher::new(|x,y|x+y);
    /// ```
    pub fn new(calculation: T) -> Self {
        let values = HashMap::new();
        Cacher {
            calculation,
            values,
        }
    }

    /// Returns value of calculation `T`. Cached value is returned if unique `n`, `k` pair provided, otherwise calcuation runs and then value is cached.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use std::rc::Rc;
    /// use std::cell::{RefCell, RefMut};
    ///
    /// use my_cache::Cacher;
    ///
    /// let mut count = Rc::new(RefCell::new(0));
    /// let add = |x, y| {
    ///     let mut count_mut_ref = count.borrow_mut();
    ///     *count_mut_ref += 1; x + y
    /// };
    /// let mut cacher = Cacher::new(add);
    ///
    /// assert_eq!(*count.borrow(), 0);
    /// assert_eq!(cacher.value(2, 3), 5); // new calculation, count += 1
    /// assert_eq!(*count.borrow(), 1);
    /// assert_eq!(cacher.value(2, 3), 5); // repeat, use cache
    /// assert_eq!(*count.borrow(), 1);
    /// assert_eq!(cacher.value(2, 4), 6); // new calculation, count += 1
    /// assert_eq!(*count.borrow(), 2);
    /// ```
    pub fn value(&mut self, n: u64, k: u64) -> u64 {
        let key = n.to_string() + &k.to_string();
        let cached_result = self.values.get(&key);
        if let Some(value) = cached_result {
            *value
        } else {
            let v = (self.calculation)(n, k);
            self.values.insert(key, v);
            v
        }
    }
}
4

1 回答 1

0

这是 vscode 的 rust 分析器扩展 ( ) 的预发布版本中的一个错误,v3.0.954可以通过切换回 rust 分析器的最新版本来缓解。

一旦我发布我的问题并确认意外行为仅存在于 中,我意识到要检查这一点v3.0.954,但是最新版本的 rust 分析器 vscode 扩展v0.2.948按预期工作(不会意外过滤掉 doctest)。

于 2022-02-28T01:18:38.487 回答