'Why does vscode's "Run Doctest" helper filter all of my crate's Doctests?
Expected Behavior:
Clicking "Run doctest" in vscode should execute one test from doctest snippets.
Terminal output SHOULD say ("1 passed;" or "1 failed;"), and "1 filtered out;".
Actual Behavior:
Clicking "Run doctest" in vscode executes 0 tests, and shows that 2 were filtered out.
Terminal output:
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.00s
Source code:
My misbehaving crate: https://github.com/darrow-olykos/rusty-gists/blob/main/crates/my_cache/src/lib.rs
Behaving crate (where this is not an issue): https://github.com/darrow-olykos/rusty-gists/blob/main/crates/math/src/lib.rs
My machine:
macOS 12
rustc 1.57.0
rust analyzer v0.3.954
What I have done to try to narrow down the scope of the problem:
- Running the "same" command in the terminal demonstrates expected behavior. The terminal output shows
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.40s
when I runcargo test --doc --package my_cache -- "Cacher<T>::new" --nocapture
, which is exactly what the terminal says is ran when I click on "Run Doctest". - Clicking "Run Doctest" in another crate I have, (called "math") in the same repo, demonstrates expected behavior.
Looking at the differences between my misbehaving crate and my working crate:
A. This misbehaving crate has it's doctest is inside of an impl
where-as that other crate's doctest is at the root level of the file.
B. This misbehaving crate's doctest is for a generic struct that accepts a closure
type.
C. Executing cargo test
from crates/my_cache
demonstrates expected behavior, with the following terminal output:
// ... 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
Again, here is the source code:
Misbehaving crate: https://github.com/darrow-olykos/rusty-gists/blob/main/crates/my_cache/src/lib.rs
Behaving crate: https://github.com/darrow-olykos/rusty-gists/blob/main/crates/math/src/lib.rs
Maybe? notable details:
- I have modeled my git repo after the structure of https://github.com/rust-analyzer/rust-analyzer, such that I'm using cargo
workspaces
andcrates/*
are members. I have a rootcargo.toml
which can specify local dependencies with something likemy_cache = {path = "crates/my_cache}
, however I cannot think of a reason why this would be a contributing factor because I've proven that mymath
crate can be in this structure without vscode getting confused and filtering out doctests in that crate unexpected.
My suspicions?:
- Something is happening that is causing the doctest to be filtered out when it should not be filtered out.
- Maybe the command that claims to be executing when I click
Run Doctest
isn't the ACTUAL command getting executed. - Maybe the (bug?) has something to do with the closure type. I forget where I read this, but I vaguely recall Rust closure types are "unnamed" in a way that makes referencing them strange. Unfortunately I cannot find the resource that I was reviewing that walked through this in detail. (It might have been a resource that was covering the Rust compiler and how the Rust compiler manifests data types in memory, but I do not recall details (maybe someone reading this will know what I'm referring to here)).
- Maybe the command that claims to be executing when I click
Here is the misbehaving crate's source code copied into this answer for the sake of longevity in case I make changes to my github repo:
// 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
}
}
}
Solution 1:[1]
This is a bug in a pre-release version of vscode's rust analyzer extension (v3.0.954
) and can be mitigated by switching back to the latest release version of rust analyzer.
I realized to check this once I posted my question and confirmed that the unexpected behavior was only present in v3.0.954
, however the latest release of rust analyzer vscode extension v0.2.948
works as expected (does not filter out the doctest unexpectedly).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |