about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorArpad Borsos <arpad.borsos@googlemail.com>2020-12-06 13:57:37 +0100
committerArpad Borsos <arpad.borsos@googlemail.com>2020-12-19 13:22:24 +0100
commit830ceaa41908bd428e36b1a804dd93c9a257aea8 (patch)
tree300dd4817bf2f7890417671bf6421994bc605bc4 /src/test
parent3d9ada686fb42bd036b3a4916526f413f1d5d1f8 (diff)
Remap instrument-coverage line numbers in doctests
This uses the `SourceMap::doctest_offset_line` method to re-map line
numbers from doctests. Remapping columns is not yet done.

Part of issue #79417.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/Makefile22
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt79
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt4
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/normalize_paths.py10
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html127
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html173
-rw-r--r--src/test/run-make-fulldeps/coverage/compiletest-ignore-dir4
-rw-r--r--src/test/run-make-fulldeps/coverage/coverage_tools.mk4
-rw-r--r--src/test/run-make-fulldeps/coverage/doctest.rs66
-rw-r--r--src/test/run-make-fulldeps/coverage/lib/doctest_crate.rs9
10 files changed, 488 insertions, 10 deletions
diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile
index 5c24f909130..c4700b317ef 100644
--- a/src/test/run-make-fulldeps/coverage-reports/Makefile
+++ b/src/test/run-make-fulldeps/coverage-reports/Makefile
@@ -98,7 +98,7 @@ endif
 	# Run it in order to generate some profiling data,
 	# with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
 	# output the coverage stats for this run.
-	LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
+	LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \
 			$(call RUN,$@) || \
 			( \
 				status=$$?; \
@@ -108,9 +108,16 @@ endif
 				) \
 			)
 
+	# Run it through rustdoc as well to cover doctests
+	LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \
+			$(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
+			$$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/$@.rs && echo "--edition=2018" ) \
+			-L "$(TMPDIR)" -Zinstrument-coverage \
+			-Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
+
 	# Postprocess the profiling data so it can be used by the llvm-cov tool
 	"$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
-			"$(TMPDIR)"/$@.profraw \
+			"$(TMPDIR)"/$@-*.profraw \
 			-o "$(TMPDIR)"/$@.profdata
 
 	# Generate a coverage report using `llvm-cov show`.
@@ -121,8 +128,15 @@ endif
 			--show-line-counts-or-regions \
 			--instr-profile="$(TMPDIR)"/$@.profdata \
 			$(call BIN,"$(TMPDIR)"/$@) \
-		> "$(TMPDIR)"/actual_show_coverage.$@.txt \
-		2> "$(TMPDIR)"/show_coverage_stderr.$@.txt || \
+			$$( \
+				for file in $(TMPDIR)/rustdoc-$@/*/rust_out; \
+				do \
+				[[ -x $$file ]] && printf "%s %s " -object $$file; \
+				done \
+			) \
+		2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
+		| "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
+		> "$(TMPDIR)"/actual_show_coverage.$@.txt || \
 	( status=$$? ; \
 		>&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
 		exit $$status \
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
new file mode 100644
index 00000000000..e1731c7223c
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
@@ -0,0 +1,79 @@
+../coverage/doctest.rs:
+    1|       |//! This test ensures that code from doctests is properly re-mapped.
+    2|       |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+    3|       |//!
+    4|       |//! Just some random code:
+    5|      1|//! ```
+    6|      1|//! if true {
+    7|       |//!     // this is executed!
+    8|      1|//!     assert_eq!(1, 1);
+    9|       |//! } else {
+   10|       |//!     // this is not!
+   11|       |//!     assert_eq!(1, 2);
+   12|       |//! }
+   13|      1|//! ```
+   14|       |//!
+   15|       |//! doctest testing external code:
+   16|       |//! ```
+   17|      1|//! extern crate doctest_crate;
+   18|      1|//! doctest_crate::fn_run_in_doctests(1);
+   19|      1|//! ```
+   20|       |//!
+   21|       |//! doctest returning a result:
+   22|      1|//! ```
+   23|      1|//! #[derive(Debug)]
+   24|      1|//! struct SomeError;
+   25|      1|//! let mut res = Err(SomeError);
+   26|      1|//! if res.is_ok() {
+   27|      0|//!   res?;
+   28|      1|//! } else {
+   29|      1|//!   res = Ok(0);
+   30|      1|//! }
+   31|       |//! // need to be explicit because rustdoc cant infer the return type
+   32|      1|//! Ok::<(), SomeError>(())
+   33|      1|//! ```
+   34|       |//!
+   35|       |//! doctest with custom main:
+   36|       |//! ```
+   37|       |//! #[derive(Debug)]
+   38|       |//! struct SomeError;
+   39|       |//!
+   40|       |//! extern crate doctest_crate;
+   41|       |//!
+   42|      1|//! fn doctest_main() -> Result<(), SomeError> {
+   43|      1|//!     doctest_crate::fn_run_in_doctests(2);
+   44|      1|//!     Ok(())
+   45|      1|//! }
+   46|       |//!
+   47|       |//! // this `main` is not shown as covered, as it clashes with all the other
+   48|       |//! // `main` functions that were automatically generated for doctests
+   49|       |//! fn main() -> Result<(), SomeError> {
+   50|       |//!     doctest_main()
+   51|       |//! }
+   52|       |//! ```
+   53|       |
+   54|       |/// doctest attached to fn testing external code:
+   55|       |/// ```
+   56|      1|/// extern crate doctest_crate;
+   57|      1|/// doctest_crate::fn_run_in_doctests(3);
+   58|      1|/// ```
+   59|       |///
+   60|      1|fn main() {
+   61|      1|    if true {
+   62|      1|        assert_eq!(1, 1);
+   63|       |    } else {
+   64|       |        assert_eq!(1, 2);
+   65|       |    }
+   66|      1|}
+
+../coverage/lib/doctest_crate.rs:
+    1|       |/// A function run only from within doctests
+    2|      3|pub fn fn_run_in_doctests(conditional: usize) {
+    3|      3|    match conditional {
+    4|      1|        1 => assert_eq!(1, 1), // this is run,
+    5|      1|        2 => assert_eq!(1, 1), // this,
+    6|      1|        3 => assert_eq!(1, 1), // and this too
+    7|      0|        _ => assert_eq!(1, 2), // however this is not
+    8|       |    }
+    9|      3|}
+
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
index e14e733fff6..4c03e950af0 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
@@ -19,12 +19,12 @@
    18|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
    19|      2|}
   ------------------
-  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
+  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
   |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   19|      1|}
   ------------------
-  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
   |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   19|      1|}
diff --git a/src/test/run-make-fulldeps/coverage-reports/normalize_paths.py b/src/test/run-make-fulldeps/coverage-reports/normalize_paths.py
new file mode 100644
index 00000000000..05fb412cdb6
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-reports/normalize_paths.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+
+import sys
+
+# Normalize file paths in output
+for line in sys.stdin:
+    if line.startswith("..") and line.rstrip().endswith(".rs:"):
+        print(line.replace("\\", "/"), end='')
+    else:
+        print(line, end='')
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..8d074558aae
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>doctest.main - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 59"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="61:8-61:12: @0[1]: _1 = const true
+61:8-61:12: @0[2]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">@5⦊</span></span></span><span class="code even" style="--layer: 2" title="62:9-62:26: @6[5]: _75 = const main::promoted[3]
+62:9-62:26: @6[6]: _18 = &amp;(*_75)
+62:9-62:26: @6[7]: _17 = &amp;(*_18)
+62:9-62:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
+62:9-62:26: @6[17]: _26 = &amp;(*_8)
+62:9-62:26: @6[18]: _25 = &amp;_26
+62:9-62:26: @6[21]: _28 = &amp;(*_9)
+62:9-62:26: @6[22]: _27 = &amp;_28
+62:9-62:26: @6[23]: _24 = (move _25, move _27)
+62:9-62:26: @6[26]: FakeRead(ForMatchedPlace, _24)
+62:9-62:26: @6[28]: _29 = (_24.0: &amp;&amp;i32)
+62:9-62:26: @6[30]: _30 = (_24.1: &amp;&amp;i32)
+62:9-62:26: @6[33]: _32 = &amp;(*_29)
+62:9-62:26: @6[35]: _33 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+62:9-62:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17]
+62:9-62:26: @7[4]: _35 = &amp;(*_30)
+62:9-62:26: @7[6]: _36 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+62:9-62:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17]
+62:9-62:26: @8[2]: _23 = [move _31, move _34]
+62:9-62:26: @8[7]: _22 = &amp;_23
+62:9-62:26: @8[8]: _21 = &amp;(*_22)
+62:9-62:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+62:9-62:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17]
+62:9-62:26: @9.Call: core::panicking::panic_fmt(move _15) -&gt; bb17"><span class="annotation">@4,6,7,8,9⦊</span>assert_eq!(1, 1);<span class="annotation">⦉@4,6,7,8,9</span></span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">@11⦊</span></span></span><span class="code even" style="--layer: 2" title="64:9-64:26: @12[5]: _72 = const main::promoted[0]
+64:9-64:26: @12[6]: _53 = &amp;(*_72)
+64:9-64:26: @12[7]: _52 = &amp;(*_53)
+64:9-64:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
+64:9-64:26: @12[17]: _61 = &amp;(*_43)
+64:9-64:26: @12[18]: _60 = &amp;_61
+64:9-64:26: @12[21]: _63 = &amp;(*_44)
+64:9-64:26: @12[22]: _62 = &amp;_63
+64:9-64:26: @12[23]: _59 = (move _60, move _62)
+64:9-64:26: @12[26]: FakeRead(ForMatchedPlace, _59)
+64:9-64:26: @12[28]: _64 = (_59.0: &amp;&amp;i32)
+64:9-64:26: @12[30]: _65 = (_59.1: &amp;&amp;i32)
+64:9-64:26: @12[33]: _67 = &amp;(*_64)
+64:9-64:26: @12[35]: _68 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+64:9-64:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17]
+64:9-64:26: @13[4]: _70 = &amp;(*_65)
+64:9-64:26: @13[6]: _71 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+64:9-64:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17]
+64:9-64:26: @14[2]: _58 = [move _66, move _69]
+64:9-64:26: @14[7]: _57 = &amp;_58
+64:9-64:26: @14[8]: _56 = &amp;(*_57)
+64:9-64:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+64:9-64:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17]
+64:9-64:26: @15.Call: core::panicking::panic_fmt(move _50) -&gt; bb17"><span class="annotation">@10,12,13,14,15⦊</span>assert_eq!(1, 2);<span class="annotation">⦉@10,12,13,14,15</span></span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    }</span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="66:2-66:2: @16.Return: return"><span class="annotation">@16⦊</span>‸<span class="annotation">⦉@16</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..ae119d9ca9f
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest_crate/doctest_crate.fn_run_in_doctests.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>doctest_crate.fn_run_in_doctests - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 1"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>pub fn fn_run_in_doctests(conditional: usize) <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
+<span class="line"><span class="code" style="--layer: 0">    match </span><span><span class="code even" style="--layer: 1" title="3:11-3:22: @0[0]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>conditional<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        1 =&gt; </span><span><span class="code odd" style="--layer: 1" title="4:14-4:30: @7[0]: _0 = const ()"><span class="annotation">@7⦊</span></span></span><span class="code even" style="--layer: 2" title="4:14-4:30: @8[5]: _138 = const fn_run_in_doctests::promoted[0]
+4:14-4:30: @8[6]: _17 = &amp;(*_138)
+4:14-4:30: @8[7]: _16 = &amp;(*_17)
+4:14-4:30: @8[8]: _15 = move _16 as &amp;[&amp;str] (Pointer(Unsize))
+4:14-4:30: @8[17]: _25 = &amp;(*_7)
+4:14-4:30: @8[18]: _24 = &amp;_25
+4:14-4:30: @8[21]: _27 = &amp;(*_8)
+4:14-4:30: @8[22]: _26 = &amp;_27
+4:14-4:30: @8[23]: _23 = (move _24, move _26)
+4:14-4:30: @8[26]: FakeRead(ForMatchedPlace, _23)
+4:14-4:30: @8[28]: _28 = (_23.0: &amp;&amp;i32)
+4:14-4:30: @8[30]: _29 = (_23.1: &amp;&amp;i32)
+4:14-4:30: @8[33]: _31 = &amp;(*_28)
+4:14-4:30: @8[35]: _32 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+4:14-4:30: @8.Call: _30 = ArgumentV1::new::&lt;&amp;i32&gt;(move _31, move _32) -&gt; [return: bb9, unwind: bb33]
+4:14-4:30: @9[4]: _34 = &amp;(*_29)
+4:14-4:30: @9[6]: _35 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+4:14-4:30: @9.Call: _33 = ArgumentV1::new::&lt;&amp;i32&gt;(move _34, move _35) -&gt; [return: bb10, unwind: bb33]
+4:14-4:30: @10[2]: _22 = [move _30, move _33]
+4:14-4:30: @10[7]: _21 = &amp;_22
+4:14-4:30: @10[8]: _20 = &amp;(*_21)
+4:14-4:30: @10[9]: _19 = move _20 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+4:14-4:30: @10.Call: _14 = Arguments::new_v1(move _15, move _19) -&gt; [return: bb11, unwind: bb33]
+4:14-4:30: @11.Call: core::panicking::panic_fmt(move _14) -&gt; bb33"><span class="annotation">@6,8,9,10,11⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@6,8,9,10,11</span></span><span><span class="code odd" style="--layer: 1" title="4:14-4:30: @7[0]: _0 = const ()"><span class="annotation">⦉@7</span></span></span><span class="code" style="--layer: 0">, // this is run,</span></span>
+<span class="line"><span class="code" style="--layer: 0">        2 =&gt; </span><span><span class="code even" style="--layer: 1" title="5:14-5:30: @14[0]: _0 = const ()"><span class="annotation">@14⦊</span></span></span><span class="code even" style="--layer: 2" title="5:14-5:30: @15[5]: _141 = const fn_run_in_doctests::promoted[3]
+5:14-5:30: @15[6]: _51 = &amp;(*_141)
+5:14-5:30: @15[7]: _50 = &amp;(*_51)
+5:14-5:30: @15[8]: _49 = move _50 as &amp;[&amp;str] (Pointer(Unsize))
+5:14-5:30: @15[17]: _59 = &amp;(*_41)
+5:14-5:30: @15[18]: _58 = &amp;_59
+5:14-5:30: @15[21]: _61 = &amp;(*_42)
+5:14-5:30: @15[22]: _60 = &amp;_61
+5:14-5:30: @15[23]: _57 = (move _58, move _60)
+5:14-5:30: @15[26]: FakeRead(ForMatchedPlace, _57)
+5:14-5:30: @15[28]: _62 = (_57.0: &amp;&amp;i32)
+5:14-5:30: @15[30]: _63 = (_57.1: &amp;&amp;i32)
+5:14-5:30: @15[33]: _65 = &amp;(*_62)
+5:14-5:30: @15[35]: _66 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+5:14-5:30: @15.Call: _64 = ArgumentV1::new::&lt;&amp;i32&gt;(move _65, move _66) -&gt; [return: bb16, unwind: bb33]
+5:14-5:30: @16[4]: _68 = &amp;(*_63)
+5:14-5:30: @16[6]: _69 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+5:14-5:30: @16.Call: _67 = ArgumentV1::new::&lt;&amp;i32&gt;(move _68, move _69) -&gt; [return: bb17, unwind: bb33]
+5:14-5:30: @17[2]: _56 = [move _64, move _67]
+5:14-5:30: @17[7]: _55 = &amp;_56
+5:14-5:30: @17[8]: _54 = &amp;(*_55)
+5:14-5:30: @17[9]: _53 = move _54 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+5:14-5:30: @17.Call: _48 = Arguments::new_v1(move _49, move _53) -&gt; [return: bb18, unwind: bb33]
+5:14-5:30: @18.Call: core::panicking::panic_fmt(move _48) -&gt; bb33"><span class="annotation">@13,15,16,17,18⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@13,15,16,17,18</span></span><span><span class="code even" style="--layer: 1" title="5:14-5:30: @14[0]: _0 = const ()"><span class="annotation">⦉@14</span></span></span><span class="code" style="--layer: 0">, // this,</span></span>
+<span class="line"><span class="code" style="--layer: 0">        3 =&gt; </span><span><span class="code odd" style="--layer: 1" title="6:14-6:30: @21[0]: _0 = const ()"><span class="annotation">@21⦊</span></span></span><span class="code even" style="--layer: 2" title="6:14-6:30: @22[5]: _144 = const fn_run_in_doctests::promoted[6]
+6:14-6:30: @22[6]: _85 = &amp;(*_144)
+6:14-6:30: @22[7]: _84 = &amp;(*_85)
+6:14-6:30: @22[8]: _83 = move _84 as &amp;[&amp;str] (Pointer(Unsize))
+6:14-6:30: @22[17]: _93 = &amp;(*_75)
+6:14-6:30: @22[18]: _92 = &amp;_93
+6:14-6:30: @22[21]: _95 = &amp;(*_76)
+6:14-6:30: @22[22]: _94 = &amp;_95
+6:14-6:30: @22[23]: _91 = (move _92, move _94)
+6:14-6:30: @22[26]: FakeRead(ForMatchedPlace, _91)
+6:14-6:30: @22[28]: _96 = (_91.0: &amp;&amp;i32)
+6:14-6:30: @22[30]: _97 = (_91.1: &amp;&amp;i32)
+6:14-6:30: @22[33]: _99 = &amp;(*_96)
+6:14-6:30: @22[35]: _100 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+6:14-6:30: @22.Call: _98 = ArgumentV1::new::&lt;&amp;i32&gt;(move _99, move _100) -&gt; [return: bb23, unwind: bb33]
+6:14-6:30: @23[4]: _102 = &amp;(*_97)
+6:14-6:30: @23[6]: _103 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+6:14-6:30: @23.Call: _101 = ArgumentV1::new::&lt;&amp;i32&gt;(move _102, move _103) -&gt; [return: bb24, unwind: bb33]
+6:14-6:30: @24[2]: _90 = [move _98, move _101]
+6:14-6:30: @24[7]: _89 = &amp;_90
+6:14-6:30: @24[8]: _88 = &amp;(*_89)
+6:14-6:30: @24[9]: _87 = move _88 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+6:14-6:30: @24.Call: _82 = Arguments::new_v1(move _83, move _87) -&gt; [return: bb25, unwind: bb33]
+6:14-6:30: @25.Call: core::panicking::panic_fmt(move _82) -&gt; bb33"><span class="annotation">@20,22,23,24,25⦊</span>assert_eq!(1, 1)<span class="annotation">⦉@20,22,23,24,25</span></span><span><span class="code odd" style="--layer: 1" title="6:14-6:30: @21[0]: _0 = const ()"><span class="annotation">⦉@21</span></span></span><span class="code" style="--layer: 0">, // and this too</span></span>
+<span class="line"><span class="code" style="--layer: 0">        _ =&gt; </span><span><span class="code even" style="--layer: 1" title="7:14-7:30: @27[0]: _0 = const ()"><span class="annotation">@27⦊</span></span></span><span class="code even" style="--layer: 2" title="7:14-7:30: @28[5]: _147 = const fn_run_in_doctests::promoted[9]
+7:14-7:30: @28[6]: _119 = &amp;(*_147)
+7:14-7:30: @28[7]: _118 = &amp;(*_119)
+7:14-7:30: @28[8]: _117 = move _118 as &amp;[&amp;str] (Pointer(Unsize))
+7:14-7:30: @28[17]: _127 = &amp;(*_109)
+7:14-7:30: @28[18]: _126 = &amp;_127
+7:14-7:30: @28[21]: _129 = &amp;(*_110)
+7:14-7:30: @28[22]: _128 = &amp;_129
+7:14-7:30: @28[23]: _125 = (move _126, move _128)
+7:14-7:30: @28[26]: FakeRead(ForMatchedPlace, _125)
+7:14-7:30: @28[28]: _130 = (_125.0: &amp;&amp;i32)
+7:14-7:30: @28[30]: _131 = (_125.1: &amp;&amp;i32)
+7:14-7:30: @28[33]: _133 = &amp;(*_130)
+7:14-7:30: @28[35]: _134 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+7:14-7:30: @28.Call: _132 = ArgumentV1::new::&lt;&amp;i32&gt;(move _133, move _134) -&gt; [return: bb29, unwind: bb33]
+7:14-7:30: @29[4]: _136 = &amp;(*_131)
+7:14-7:30: @29[6]: _137 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+7:14-7:30: @29.Call: _135 = ArgumentV1::new::&lt;&amp;i32&gt;(move _136, move _137) -&gt; [return: bb30, unwind: bb33]
+7:14-7:30: @30[2]: _124 = [move _132, move _135]
+7:14-7:30: @30[7]: _123 = &amp;_124
+7:14-7:30: @30[8]: _122 = &amp;(*_123)
+7:14-7:30: @30[9]: _121 = move _122 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+7:14-7:30: @30.Call: _116 = Arguments::new_v1(move _117, move _121) -&gt; [return: bb31, unwind: bb33]
+7:14-7:30: @31.Call: core::panicking::panic_fmt(move _116) -&gt; bb33"><span class="annotation">@26,28,29,30,31⦊</span>assert_eq!(1, 2)<span class="annotation">⦉@26,28,29,30,31</span></span><span><span class="code even" style="--layer: 1" title="7:14-7:30: @27[0]: _0 = const ()"><span class="annotation">⦉@27</span></span></span><span class="code" style="--layer: 0">, // however this is not</span></span>
+<span class="line"><span class="code" style="--layer: 0">    }</span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="9:2-9:2: @32.Return: return"><span class="annotation">@32⦊</span>‸<span class="annotation">⦉@32</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir b/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir
index abf8df8fdc9..d1824d189e3 100644
--- a/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir
+++ b/src/test/run-make-fulldeps/coverage/compiletest-ignore-dir
@@ -1,3 +1,3 @@
-# Directory "instrument-coverage" supports the tests at prefix ../instrument-coverage-*
+# Directory "coverage" supports the tests at prefix ../coverage-*
 
-# Use ./x.py [options] test src/test/run-make-fulldeps/instrument-coverage to run all related tests.
+# Use ./x.py [options] test src/test/run-make-fulldeps/coverage to run all related tests.
diff --git a/src/test/run-make-fulldeps/coverage/coverage_tools.mk b/src/test/run-make-fulldeps/coverage/coverage_tools.mk
index 7dc485cd94d..4d340d4b1da 100644
--- a/src/test/run-make-fulldeps/coverage/coverage_tools.mk
+++ b/src/test/run-make-fulldeps/coverage/coverage_tools.mk
@@ -1,7 +1,7 @@
-# Common Makefile include for Rust `run-make-fulldeps/instrument-coverage-* tests. Include this
+# Common Makefile include for Rust `run-make-fulldeps/coverage-* tests. Include this
 # file with the line:
 #
-# -include ../instrument-coverage/coverage_tools.mk
+# -include ../coverage/coverage_tools.mk
 
 -include ../tools.mk
 
diff --git a/src/test/run-make-fulldeps/coverage/doctest.rs b/src/test/run-make-fulldeps/coverage/doctest.rs
new file mode 100644
index 00000000000..e41d669bf0c
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage/doctest.rs
@@ -0,0 +1,66 @@
+//! This test ensures that code from doctests is properly re-mapped.
+//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+//!
+//! Just some random code:
+//! ```
+//! if true {
+//!     // this is executed!
+//!     assert_eq!(1, 1);
+//! } else {
+//!     // this is not!
+//!     assert_eq!(1, 2);
+//! }
+//! ```
+//!
+//! doctest testing external code:
+//! ```
+//! extern crate doctest_crate;
+//! doctest_crate::fn_run_in_doctests(1);
+//! ```
+//!
+//! doctest returning a result:
+//! ```
+//! #[derive(Debug)]
+//! struct SomeError;
+//! let mut res = Err(SomeError);
+//! if res.is_ok() {
+//!   res?;
+//! } else {
+//!   res = Ok(0);
+//! }
+//! // need to be explicit because rustdoc cant infer the return type
+//! Ok::<(), SomeError>(())
+//! ```
+//!
+//! doctest with custom main:
+//! ```
+//! #[derive(Debug)]
+//! struct SomeError;
+//!
+//! extern crate doctest_crate;
+//!
+//! fn doctest_main() -> Result<(), SomeError> {
+//!     doctest_crate::fn_run_in_doctests(2);
+//!     Ok(())
+//! }
+//!
+//! // this `main` is not shown as covered, as it clashes with all the other
+//! // `main` functions that were automatically generated for doctests
+//! fn main() -> Result<(), SomeError> {
+//!     doctest_main()
+//! }
+//! ```
+
+/// doctest attached to fn testing external code:
+/// ```
+/// extern crate doctest_crate;
+/// doctest_crate::fn_run_in_doctests(3);
+/// ```
+///
+fn main() {
+    if true {
+        assert_eq!(1, 1);
+    } else {
+        assert_eq!(1, 2);
+    }
+}
diff --git a/src/test/run-make-fulldeps/coverage/lib/doctest_crate.rs b/src/test/run-make-fulldeps/coverage/lib/doctest_crate.rs
new file mode 100644
index 00000000000..c3210146d69
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage/lib/doctest_crate.rs
@@ -0,0 +1,9 @@
+/// A function run only from within doctests
+pub fn fn_run_in_doctests(conditional: usize) {
+    match conditional {
+        1 => assert_eq!(1, 1), // this is run,
+        2 => assert_eq!(1, 1), // this,
+        3 => assert_eq!(1, 1), // and this too
+        _ => assert_eq!(1, 2), // however this is not
+    }
+}