Skip to content

Commit fb1736e

Browse files
committed
Fix cargo test --doc with dev-deps
Previously Cargo accidentally didn't pull in dev-dependencies due to the way `cargo test --doc` was interpreted in terms of top-level targets. This PR special cases this situation by ensuring that the doctest intention makes its way all to the backend and the dependencies can be correctly calculated. Closes #3422
1 parent 154a30b commit fb1736e

File tree

10 files changed

+70
-8
lines changed

10 files changed

+70
-8
lines changed

src/bin/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
105105
let empty = Vec::new();
106106
let (mode, filter);
107107
if options.flag_doc {
108-
mode = ops::CompileMode::Build;
108+
mode = ops::CompileMode::Doctest;
109109
filter = ops::CompileFilter::new(true, &empty, &empty, &empty, &empty);
110110
} else {
111111
mode = ops::CompileMode::Test;

src/cargo/core/manifest.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ pub struct Profiles {
170170
pub doc: Profile,
171171
pub custom_build: Profile,
172172
pub check: Profile,
173+
pub doctest: Profile,
173174
}
174175

175176
/// Information about a binary, a library, an example, etc. that is part of the
@@ -535,6 +536,14 @@ impl Profile {
535536
..Profile::default_dev()
536537
}
537538
}
539+
540+
pub fn default_doctest() -> Profile {
541+
Profile {
542+
doc: true,
543+
test: true,
544+
..Profile::default_dev()
545+
}
546+
}
538547
}
539548

540549
impl Default for Profile {

src/cargo/core/workspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ impl<'cfg> Workspace<'cfg> {
461461
doc: Profile::default_doc(),
462462
custom_build: Profile::default_custom_build(),
463463
check: Profile::default_check(),
464+
doctest: Profile::default_doctest(),
464465
};
465466

466467
for pkg in self.members().filter(|p| p.manifest_path() != root_manifest) {

src/cargo/ops/cargo_clean.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
5151
for kind in [Kind::Host, Kind::Target].iter() {
5252
let Profiles {
5353
ref release, ref dev, ref test, ref bench, ref doc,
54-
ref custom_build, ref test_deps, ref bench_deps, ref check
54+
ref custom_build, ref test_deps, ref bench_deps, ref check,
55+
ref doctest,
5556
} = *profiles;
5657
let profiles = [release, dev, test, bench, doc, custom_build,
57-
test_deps, bench_deps, check];
58+
test_deps, bench_deps, check, doctest];
5859
for profile in profiles.iter() {
5960
units.push(Unit {
6061
pkg: &pkg,

src/cargo/ops/cargo_compile.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub enum CompileMode {
6969
Check,
7070
Bench,
7171
Doc { deps: bool },
72+
Doctest,
7273
}
7374

7475
#[derive(Clone, Copy, PartialEq, Eq, RustcDecodable)]
@@ -290,6 +291,7 @@ fn generate_targets<'a>(pkg: &'a Package,
290291
CompileMode::Build => build,
291292
CompileMode::Check => &profiles.check,
292293
CompileMode::Doc { .. } => &profiles.doc,
294+
CompileMode::Doctest => &profiles.doctest,
293295
};
294296
match *filter {
295297
CompileFilter::Everything => {
@@ -329,6 +331,15 @@ fn generate_targets<'a>(pkg: &'a Package,
329331
Ok(pkg.targets().iter().filter(|t| t.documented())
330332
.map(|t| (t, profile)).collect())
331333
}
334+
CompileMode::Doctest => {
335+
if let Some(t) = pkg.targets().iter().find(|t| t.is_lib()) {
336+
if t.doctested() {
337+
return Ok(vec![(t, profile)])
338+
}
339+
}
340+
341+
Ok(Vec::new())
342+
}
332343
}
333344
}
334345
CompileFilter::Only { lib, bins, examples, tests, benches } => {

src/cargo/ops/cargo_rustc/context.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
224224

225225
map.insert(crate_type.to_string(), Some((prefix.to_string(), suffix.to_string())));
226226
}
227-
227+
228228
let cfg = if has_cfg {
229229
Some(try!(lines.map(Cfg::from_str).collect()))
230230
} else {
@@ -554,7 +554,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
554554
pub fn dep_targets(&self, unit: &Unit<'a>) -> CargoResult<Vec<Unit<'a>>> {
555555
if unit.profile.run_custom_build {
556556
return self.dep_run_custom_build(unit)
557-
} else if unit.profile.doc {
557+
} else if unit.profile.doc && !unit.profile.test {
558558
return self.doc_deps(unit);
559559
}
560560

@@ -626,7 +626,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
626626
// the library of the same package. The call to `resolve.deps` above
627627
// didn't include `pkg` in the return values, so we need to special case
628628
// it here and see if we need to push `(pkg, pkg_lib_target)`.
629-
if unit.target.is_lib() {
629+
if unit.target.is_lib() && !unit.profile.doc {
630630
return Ok(ret)
631631
}
632632
ret.extend(self.maybe_lib(unit));

src/cargo/ops/cargo_rustc/job_queue.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,10 @@ impl<'a> JobQueue<'a> {
292292
// being a compiled package
293293
Dirty => {
294294
if key.profile.doc {
295-
self.documented.insert(key.pkg);
296-
config.shell().status("Documenting", key.pkg)?;
295+
if !key.profile.test {
296+
self.documented.insert(key.pkg);
297+
config.shell().status("Documenting", key.pkg)?;
298+
}
297299
} else {
298300
self.compiled.insert(key.pkg);
299301
config.shell().status("Compiling", key.pkg)?;

src/cargo/ops/cargo_rustc/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use core::{Profile, Profiles, Workspace};
1313
use core::shell::ColorConfig;
1414
use util::{self, CargoResult, ProcessBuilder, human, machine_message};
1515
use util::{Config, internal, ChainError, profile, join_paths, short_hash};
16+
use util::Freshness;
1617

1718
use self::job::{Job, Work};
1819
use self::job_queue::JobQueue;
@@ -183,6 +184,9 @@ fn compile<'a, 'cfg: 'a>(cx: &mut Context<'a, 'cfg>,
183184

184185
let (dirty, fresh, freshness) = if unit.profile.run_custom_build {
185186
custom_build::prepare(cx, unit)?
187+
} else if unit.profile.doc && unit.profile.test {
188+
// we run these targets later, so this is just a noop for now
189+
(Work::new(|_| Ok(())), Work::new(|_| Ok(())), Freshness::Fresh)
186190
} else {
187191
let (freshness, dirty, fresh) = fingerprint::prepare_target(cx, unit)?;
188192
let work = if unit.profile.doc {

src/cargo/util/toml.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,7 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
12531253
custom_build: Profile::default_custom_build(),
12541254
check: merge(Profile::default_check(),
12551255
profiles.and_then(|p| p.dev.as_ref())),
1256+
doctest: Profile::default_doctest(),
12561257
};
12571258
// The test/bench targets cannot have panic=abort because they'll all get
12581259
// compiled with --test which requires the unwind runtime currently

tests/test.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,6 +2143,7 @@ fn only_test_docs() {
21432143
}
21442144
21452145
/// ```
2146+
/// foo::bar();
21462147
/// println!("ok");
21472148
/// ```
21482149
pub fn bar() {
@@ -2524,3 +2525,35 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
25242525
25252526
"));
25262527
}
2528+
2529+
#[test]
2530+
fn doctest_only_with_dev_dep() {
2531+
let p = project("workspace")
2532+
.file("Cargo.toml", r#"
2533+
[project]
2534+
name = "a"
2535+
version = "0.1.0"
2536+
2537+
[dev-dependencies]
2538+
b = { path = "b" }
2539+
"#)
2540+
.file("src/lib.rs", r#"
2541+
/// ```
2542+
/// extern crate b;
2543+
///
2544+
/// b::b();
2545+
/// ```
2546+
pub fn a() {}
2547+
"#)
2548+
.file("b/Cargo.toml", r#"
2549+
[project]
2550+
name = "b"
2551+
version = "0.1.0"
2552+
"#)
2553+
.file("b/src/lib.rs", r#"
2554+
pub fn b() {}
2555+
"#);
2556+
2557+
assert_that(p.cargo_process("test").arg("--doc").arg("-v"),
2558+
execs().with_status(0));
2559+
}

0 commit comments

Comments
 (0)