Skip to content

Commit 465c7a4

Browse files
committed
Auto merge of rust-lang#137096 - ehuss:stabilize-doctest-xcompile, r=<try>
Stabilize flags for doctest cross compilation This makes the following changes in preparation for supporting doctest cross-compiling in cargo: - Renames `--runtool` and `--runtool-arg` to `--test-runtool` and `--test-runtool-arg` to maintain consistency with other `--test-*` arguments. - Stabilizes the `--test-runtool` and `--test-runtool-arg`. These are needed in order to support cargo's `target.runner` option which specifies a runner to execute a cross-compiled doctest (for example, qemu). - Stabilizes the `--enable-per-target-ignores` flag by removing it and making it unconditionally enabled. This makes it possible to disable a doctest on a per-target basis, which I think will be helpful for rolling out this feature. These changes were suggested in https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/stabilizing.20doctest.20xcompile/near/409281127 The intent is to stabilize the doctest-xcompile feature in cargo. This will help ensure that for projects that do cross-compile testing that their doctests are also covered. Currently there is a somewhat surprising behavior that they are ignored. Closes rust-lang#64245
2 parents 79de6c0 + f535922 commit 465c7a4

File tree

18 files changed

+133
-136
lines changed

18 files changed

+133
-136
lines changed

src/doc/rustdoc/src/command-line-arguments.md

+22
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,28 @@ For more, see [the chapter on documentation tests](write-documentation/documenta
222222

223223
See also `--test`.
224224

225+
## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it
226+
227+
A doctest wrapper program can be specified with the `--test-runtool` flag.
228+
Rustdoc will execute that wrapper instead of the doctest executable when
229+
running tests. The first arguments to the wrapper will be any arguments
230+
specified with the `--test-runtool-arg` flag, followed by the path to the
231+
doctest executable to run.
232+
233+
Using these options looks like this:
234+
235+
```bash
236+
$ rustdoc src/lib.rs --test-runtool path/to/runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing
237+
```
238+
239+
For example, if you want to run your doctests under valgrind you might run:
240+
241+
```bash
242+
$ rustdoc src/lib.rs --test-runtool valgrind
243+
```
244+
245+
Another use case would be to run a test inside an emulator, or through a Virtual Machine.
246+
225247
## `--target`: generate documentation for the specified target triple
226248

227249
Using this flag looks like this:

src/doc/rustdoc/src/unstable-features.md

-54
Original file line numberDiff line numberDiff line change
@@ -631,60 +631,6 @@ The generated output (formatted) will look like this:
631631
`--output-format html` has no effect, as the default output is HTML. This is
632632
accepted on stable, even though the other options for this flag aren't.
633633

634-
## `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
635-
636-
* Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
637-
638-
Using this flag looks like this:
639-
640-
```bash
641-
$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores
642-
```
643-
644-
This flag allows you to tag doctests with compiletest style `ignore-foo` filters that prevent
645-
rustdoc from running that test if the target triple string contains foo. For example:
646-
647-
```rust
648-
///```ignore-foo,ignore-bar
649-
///assert!(2 == 2);
650-
///```
651-
struct Foo;
652-
```
653-
654-
This will not be run when the build target is `super-awesome-foo` or `less-bar-awesome`.
655-
If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and
656-
the above example will be run for all targets.
657-
If you want to preserve backwards compatibility for older versions of rustdoc, you can use
658-
659-
```rust
660-
///```ignore,ignore-foo
661-
///assert!(2 == 2);
662-
///```
663-
struct Foo;
664-
```
665-
666-
In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will
667-
override `ignore`.
668-
669-
## `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it
670-
671-
* Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
672-
673-
Using these options looks like this:
674-
675-
```bash
676-
$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing
677-
```
678-
679-
These options can be used to run the doctest under a program, and also pass arguments to
680-
that program. For example, if you want to run your doctests under valgrind you might run
681-
682-
```bash
683-
$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind
684-
```
685-
686-
Another use case would be to run a test inside an emulator, or through a Virtual Machine.
687-
688634
## `--with-examples`: include examples of uses of items as documentation
689635

690636
* Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791)

src/doc/rustdoc/src/write-documentation/documentation-tests.md

+37
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,43 @@ should not be merged with the others. So the previous code should use it:
427427
In this case, it means that the line information will not change if you add/remove other
428428
doctests.
429429

430+
### Ignoring targets
431+
432+
Attributes starting with `ignore-` can be used to ignore doctests for specific
433+
targets. For example, `ignore-x86_64` will avoid building doctests when the
434+
target name contains `x86_64`.
435+
436+
```rust
437+
/// ```ignore-x86_64
438+
/// assert!(2 == 2);
439+
/// ```
440+
struct Foo;
441+
```
442+
443+
This doctest will not be built for targets such as `x86_64-unknown-linux-gnu`.
444+
445+
Multiple ignore attributes can be specified to ignore multiple targets:
446+
447+
```rust
448+
/// ```ignore-x86_64,ignore-windows
449+
/// assert!(2 == 2);
450+
/// ```
451+
struct Foo;
452+
```
453+
454+
If you want to preserve backwards compatibility for older versions of rustdoc,
455+
you can specify both `ignore` and `ignore-`, such as:
456+
457+
```rust
458+
/// ```ignore,ignore-x86_64
459+
/// assert!(2 == 2);
460+
/// ```
461+
struct Foo;
462+
```
463+
464+
In older versions, this will be ignored on all targets, but starting with
465+
version CURRENT_RUSTC_VERSION, `ignore-x86_64` will override `ignore`.
466+
430467
### Custom CSS classes for code blocks
431468

432469
```rust

src/librustdoc/config.rs

+8-15
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,9 @@ pub(crate) struct Options {
124124
/// temporary directory if not set.
125125
pub(crate) persist_doctests: Option<PathBuf>,
126126
/// Runtool to run doctests with
127-
pub(crate) runtool: Option<String>,
127+
pub(crate) test_runtool: Option<String>,
128128
/// Arguments to pass to the runtool
129-
pub(crate) runtool_args: Vec<String>,
130-
/// Whether to allow ignoring doctests on a per-target basis
131-
/// For example, using ignore-foo to ignore running the doctest on any target that
132-
/// contains "foo" as a substring
133-
pub(crate) enable_per_target_ignores: bool,
129+
pub(crate) test_runtool_args: Vec<String>,
134130
/// Do not run doctests, compile them if should_test is active.
135131
pub(crate) no_run: bool,
136132
/// What sources are being mapped.
@@ -215,9 +211,8 @@ impl fmt::Debug for Options {
215211
.field("persist_doctests", &self.persist_doctests)
216212
.field("show_coverage", &self.show_coverage)
217213
.field("crate_version", &self.crate_version)
218-
.field("runtool", &self.runtool)
219-
.field("runtool_args", &self.runtool_args)
220-
.field("enable-per-target-ignores", &self.enable_per_target_ignores)
214+
.field("test_runtool", &self.test_runtool)
215+
.field("test_runtool_args", &self.test_runtool_args)
221216
.field("run_check", &self.run_check)
222217
.field("no_run", &self.no_run)
223218
.field("test_builder_wrappers", &self.test_builder_wrappers)
@@ -779,9 +774,8 @@ impl Options {
779774
let unstable_opts_strs = matches.opt_strs("Z");
780775
let lib_strs = matches.opt_strs("L");
781776
let extern_strs = matches.opt_strs("extern");
782-
let runtool = matches.opt_str("runtool");
783-
let runtool_args = matches.opt_strs("runtool-arg");
784-
let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores");
777+
let test_runtool = matches.opt_str("test-runtool");
778+
let test_runtool_args = matches.opt_strs("test-runtool-arg");
785779
let document_private = matches.opt_present("document-private-items");
786780
let document_hidden = matches.opt_present("document-hidden-items");
787781
let run_check = matches.opt_present("check");
@@ -843,9 +837,8 @@ impl Options {
843837
crate_version,
844838
test_run_directory,
845839
persist_doctests,
846-
runtool,
847-
runtool_args,
848-
enable_per_target_ignores,
840+
test_runtool,
841+
test_runtool_args,
849842
test_builder,
850843
run_check,
851844
no_run,

src/librustdoc/doctest.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,9 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
218218
let crate_name = tcx.crate_name(LOCAL_CRATE).to_string();
219219
let crate_attrs = tcx.hir_attrs(CRATE_HIR_ID);
220220
let opts = scrape_test_config(crate_name, crate_attrs, args_path);
221-
let enable_per_target_ignores = options.enable_per_target_ignores;
222221

223222
let hir_collector = HirCollector::new(
224223
ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()),
225-
enable_per_target_ignores,
226224
tcx,
227225
);
228226
let tests = hir_collector.collect_crate();
@@ -781,10 +779,10 @@ fn run_test(
781779
let mut cmd;
782780

783781
let output_file = make_maybe_absolute_path(output_file);
784-
if let Some(tool) = &rustdoc_options.runtool {
782+
if let Some(tool) = &rustdoc_options.test_runtool {
785783
let tool = make_maybe_absolute_path(tool.into());
786784
cmd = Command::new(tool);
787-
cmd.args(&rustdoc_options.runtool_args);
785+
cmd.args(&rustdoc_options.test_runtool_args);
788786
cmd.arg(&output_file);
789787
} else {
790788
cmd = Command::new(&output_file);

src/librustdoc/doctest/markdown.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,7 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> {
104104
};
105105
let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
106106

107-
find_testable_code(
108-
&input_str,
109-
&mut md_collector,
110-
codes,
111-
options.enable_per_target_ignores,
112-
None,
113-
);
107+
find_testable_code(&input_str, &mut md_collector, codes, None);
114108

115109
let mut collector = CreateRunnableDocTests::new(options.clone(), opts);
116110
md_collector.tests.into_iter().for_each(|t| collector.add_test(t));

src/librustdoc/doctest/rust.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,18 @@ impl DocTestVisitor for RustCollector {
6363
pub(super) struct HirCollector<'tcx> {
6464
codes: ErrorCodes,
6565
tcx: TyCtxt<'tcx>,
66-
enable_per_target_ignores: bool,
6766
collector: RustCollector,
6867
}
6968

7069
impl<'tcx> HirCollector<'tcx> {
71-
pub fn new(codes: ErrorCodes, enable_per_target_ignores: bool, tcx: TyCtxt<'tcx>) -> Self {
70+
pub fn new(codes: ErrorCodes, tcx: TyCtxt<'tcx>) -> Self {
7271
let collector = RustCollector {
7372
source_map: tcx.sess.psess.clone_source_map(),
7473
cur_path: vec![],
7574
position: DUMMY_SP,
7675
tests: vec![],
7776
};
78-
Self { codes, enable_per_target_ignores, tcx, collector }
77+
Self { codes, tcx, collector }
7978
}
8079

8180
pub fn collect_crate(mut self) -> Vec<ScrapedDocTest> {
@@ -131,7 +130,6 @@ impl HirCollector<'_> {
131130
&doc,
132131
&mut self.collector,
133132
self.codes,
134-
self.enable_per_target_ignores,
135133
Some(&crate::html::markdown::ExtraInfo::new(self.tcx, def_id, span)),
136134
);
137135
}

src/librustdoc/html/markdown.rs

+8-22
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
246246
match kind {
247247
CodeBlockKind::Fenced(ref lang) => {
248248
let parse_result =
249-
LangString::parse_without_check(lang, self.check_error_codes, false);
249+
LangString::parse_without_check(lang, self.check_error_codes);
250250
if !parse_result.rust {
251251
let added_classes = parse_result.added_classes;
252252
let lang_string = if let Some(lang) = parse_result.unknown.first() {
@@ -707,17 +707,15 @@ pub(crate) fn find_testable_code<T: doctest::DocTestVisitor>(
707707
doc: &str,
708708
tests: &mut T,
709709
error_codes: ErrorCodes,
710-
enable_per_target_ignores: bool,
711710
extra_info: Option<&ExtraInfo<'_>>,
712711
) {
713-
find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false)
712+
find_codes(doc, tests, error_codes, extra_info, false)
714713
}
715714

716715
pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
717716
doc: &str,
718717
tests: &mut T,
719718
error_codes: ErrorCodes,
720-
enable_per_target_ignores: bool,
721719
extra_info: Option<&ExtraInfo<'_>>,
722720
include_non_rust: bool,
723721
) {
@@ -733,12 +731,7 @@ pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
733731
if lang.is_empty() {
734732
Default::default()
735733
} else {
736-
LangString::parse(
737-
lang,
738-
error_codes,
739-
enable_per_target_ignores,
740-
extra_info,
741-
)
734+
LangString::parse(lang, error_codes, extra_info)
742735
}
743736
}
744737
CodeBlockKind::Indented => Default::default(),
@@ -1162,18 +1155,13 @@ impl Default for LangString {
11621155
}
11631156

11641157
impl LangString {
1165-
fn parse_without_check(
1166-
string: &str,
1167-
allow_error_code_check: ErrorCodes,
1168-
enable_per_target_ignores: bool,
1169-
) -> Self {
1170-
Self::parse(string, allow_error_code_check, enable_per_target_ignores, None)
1158+
fn parse_without_check(string: &str, allow_error_code_check: ErrorCodes) -> Self {
1159+
Self::parse(string, allow_error_code_check, None)
11711160
}
11721161

11731162
fn parse(
11741163
string: &str,
11751164
allow_error_code_check: ErrorCodes,
1176-
enable_per_target_ignores: bool,
11771165
extra: Option<&ExtraInfo<'_>>,
11781166
) -> Self {
11791167
let allow_error_code_check = allow_error_code_check.as_bool();
@@ -1203,10 +1191,8 @@ impl LangString {
12031191
LangStringToken::LangToken(x)
12041192
if let Some(ignore) = x.strip_prefix("ignore-") =>
12051193
{
1206-
if enable_per_target_ignores {
1207-
ignores.push(ignore.to_owned());
1208-
seen_rust_tags = !seen_other_tags;
1209-
}
1194+
ignores.push(ignore.to_owned());
1195+
seen_rust_tags = !seen_other_tags;
12101196
}
12111197
LangStringToken::LangToken("rust") => {
12121198
data.rust = true;
@@ -1968,7 +1954,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
19681954
let lang_string = if syntax.is_empty() {
19691955
Default::default()
19701956
} else {
1971-
LangString::parse(syntax, ErrorCodes::Yes, false, Some(extra_info))
1957+
LangString::parse(syntax, ErrorCodes::Yes, Some(extra_info))
19721958
};
19731959
if !lang_string.rust {
19741960
continue;

src/librustdoc/html/markdown/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn test_unique_id() {
4949
fn test_lang_string_parse() {
5050
fn t(lg: LangString) {
5151
let s = &lg.original;
52-
assert_eq!(LangString::parse(s, ErrorCodes::Yes, true, None), lg)
52+
assert_eq!(LangString::parse(s, ErrorCodes::Yes, None), lg)
5353
}
5454

5555
t(Default::default());
@@ -479,7 +479,7 @@ fn test_markdown_html_escape() {
479479
fn test_find_testable_code_line() {
480480
fn t(input: &str, expect: &[usize]) {
481481
let mut lines = Vec::<usize>::new();
482-
find_testable_code(input, &mut lines, ErrorCodes::No, false, None);
482+
find_testable_code(input, &mut lines, ErrorCodes::No, None);
483483
assert_eq!(lines, expect);
484484
}
485485

src/librustdoc/lib.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -507,26 +507,18 @@ fn opts() -> Vec<RustcOptGroup> {
507507
"",
508508
),
509509
opt(
510-
Unstable,
511-
FlagMulti,
512-
"",
513-
"enable-per-target-ignores",
514-
"parse ignore-foo for ignoring doctests on a per-target basis",
515-
"",
516-
),
517-
opt(
518-
Unstable,
510+
Stable,
519511
Opt,
520512
"",
521-
"runtool",
513+
"test-runtool",
522514
"",
523515
"The tool to run tests with when building for a different target than host",
524516
),
525517
opt(
526-
Unstable,
518+
Stable,
527519
Multi,
528520
"",
529-
"runtool-arg",
521+
"test-runtool-arg",
530522
"",
531523
"One (of possibly many) arguments to pass to the runtool",
532524
),

src/librustdoc/passes/calculate_doc_coverage.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> {
212212
let has_docs = !i.attrs.doc_strings.is_empty();
213213
let mut tests = Tests { found_tests: 0 };
214214

215-
find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None);
215+
find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, None);
216216

217217
let has_doc_example = tests.found_tests != 0;
218218
let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();

0 commit comments

Comments
 (0)