about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-12-09 22:21:55 +0000
committerbors <bors@rust-lang.org>2020-12-09 22:21:55 +0000
commit1cc410710993d036730c11556039e40109f6ab41 (patch)
treecaecfd6645df9d4f5952048915e8c08936ebb773 /src
parentf0f68778f798d6d34649745b41770829b17ba5b8 (diff)
parentf74f3b2f37aaad4d78b85404ec1cc5e525c550d1 (diff)
downloadrust-1cc410710993d036730c11556039e40109f6ab41.tar.gz
rust-1cc410710993d036730c11556039e40109f6ab41.zip
Auto merge of #79867 - tmandry:rollup-7mubs3b, r=tmandry
Rollup of 12 pull requests

Successful merges:

 - #79732 (minor stylistic clippy cleanups)
 - #79750 (Fix trimming of lint docs)
 - #79777 (Remove `first_merge` from liveness debug logs)
 - #79795 (Privatize some of libcore unicode_internals)
 - #79803 (Update xsv to prevent random CI failures)
 - #79810 (Account for gaps in def path table during decoding)
 - #79818 (Fixes to Rust coverage)
 - #79824 (Strip prefix instead of replacing it with empty string)
 - #79826 (Simplify visit_{foreign,trait}_item)
 - #79844 (Move RWUTable to a separate module)
 - #79861 (Update LLVM submodule)
 - #79862 (Remove tab-lock and replace it with ctrl+up/down arrows to switch between search result tabs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/setup.rs5
-rw-r--r--src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md91
-rw-r--r--src/librustdoc/html/markdown.rs2
-rw-r--r--src/librustdoc/html/static/main.js33
m---------src/llvm-project0
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/Makefile22
-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/expected_show_coverage_counters.async.txt10
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.generics.txt4
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.uses_crate.txt10
-rw-r--r--src/tools/cargotest/main.rs2
-rw-r--r--src/tools/lint-docs/src/lib.rs4
12 files changed, 137 insertions, 50 deletions
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 55d2445fc49..2d4484c562c 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -198,7 +198,7 @@ simply delete the `pre-commit` file from .git/hooks."
         };
     };
 
-    Ok(if should_install {
+    if should_install {
         let src = src_path.join("src").join("etc").join("pre-commit.sh");
         let git = t!(Command::new("git").args(&["rev-parse", "--git-common-dir"]).output().map(
             |output| {
@@ -217,5 +217,6 @@ simply delete the `pre-commit` file from .git/hooks."
         };
     } else {
         println!("Ok, skipping installation!");
-    })
+    }
+    Ok(())
 }
diff --git a/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md b/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
index 9930bc67cd5..6ca5ae40707 100644
--- a/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
+++ b/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
@@ -213,19 +213,102 @@ Then run the `cov` tool, with the `profdata` file and all test binaries:
 $ cargo cov -- report \
     --use-color --ignore-filename-regex='/.cargo/registry' \
     --instr-profile=json5format.profdata \
-    target/debug/deps/lib-30768f9c53506dc5 \
-    target/debug/deps/json5format-fececd4653271682
+    --object target/debug/deps/lib-30768f9c53506dc5 \
+    --object target/debug/deps/json5format-fececd4653271682
 $ cargo cov -- show \
     --use-color --ignore-filename-regex='/.cargo/registry' \
     --instr-profile=json5format.profdata \
-    target/debug/deps/lib-30768f9c53506dc5 \
-    target/debug/deps/json5format-fececd4653271682 \
+    --object target/debug/deps/lib-30768f9c53506dc5 \
+    --object target/debug/deps/json5format-fececd4653271682 \
     --show-instantiations --show-line-counts-or-regions \
     --Xdemangler=rustfilt | less -R
 ```
 
 _Note the command line option `--ignore-filename-regex=/.cargo/registry`, which excludes the sources for dependencies from the coverage results._
 
+### Tips for listing the binaries automatically
+
+For `bash` users, one suggested way to automatically complete the `cov` command with the list of binaries is with a command like:
+
+```bash
+$ cargo cov -- report \
+    $( \
+      for file in \
+        $( \
+          RUSTFLAGS="-Zinstrument-coverage" \
+            cargo test --tests --no-run --message-format=json \
+              | jq -r "select(.profile.test == true) | .filenames[]" \
+              | grep -v dSYM - \
+        ); \
+      do \
+        printf "%s %s " -object $file; \
+      done \
+    ) \
+  --instr-profile=json5format.profdata --summary-only # and/or other options
+```
+
+Adding `--no-run --message-format=json` to the _same_ `cargo test` command used to run
+the tests (including the same environment variables and flags) generates output in a JSON
+format that `jq` can easily query.
+
+The `printf` command takes this list and generates the `--object <binary>` arguments
+for each listed test binary.
+
+### Including doc tests
+
+The previous examples run `cargo test` with `--tests`, which excludes doc tests.[^79417]
+
+To include doc tests in the coverage results, drop the `--tests` flag, and apply the
+`-Zinstrument-coverage` flag, and some doc-test-specific options in the
+`RUSTDOCFLAGS` environment variable. (The `cargo profdata` command does not change.)
+
+```bash
+$ RUSTFLAGS="-Zinstrument-coverage" \
+  RUSTDOCFLAGS="-Zinstrument-coverage -Zunstable-options --persist-doctests target/debug/doctestbins" \
+  LLVM_PROFILE_FILE="json5format-%m.profraw" \
+    cargo test
+$ cargo profdata -- merge \
+    -sparse json5format-*.profraw -o json5format.profdata
+```
+
+The `-Zunstable-options --persist-doctests` flag is required, to save the test binaries
+(with their coverage maps) for `llvm-cov`.
+
+```bash
+$ cargo cov -- report \
+    $( \
+      for file in \
+        $( \
+          RUSTFLAGS="-Zinstrument-coverage" \
+          RUSTDOCFLAGS="-Zinstrument-coverage -Zunstable-options --persist-doctests target/debug/doctestbins" \
+            cargo test --no-run --message-format=json \
+              | jq -r "select(.profile.test == true) | .filenames[]" \
+              | grep -v dSYM - \
+        ) \
+        target/debug/doctestbins/*/rust_out; \
+      do \
+        [[ -x $file ]] && printf "%s %s " -object $file; \
+      done \
+    ) \
+  --instr-profile=json5format.profdata --summary-only # and/or other options
+```
+
+Note, the differences in this `cargo cov` command, compared with the version without
+doc tests, include:
+
+* The `cargo test ... --no-run` command is updated with the same environment variables
+  and flags used to _build_ the tests, _including_ the doc tests. (`LLVM_PROFILE_FILE`
+  is only used when _running_ the tests.)
+* The file glob pattern `target/debug/doctestbins/*/rust_out` adds the `rust_out`
+  binaries generated for doc tests (note, however, that some `rust_out` files may not
+  be executable binaries).
+* `[[ -x $file ]] &&` filters the files passed on to the `printf`, to include only
+  executable binaries.
+
+[^79417]: There is ongoing work to resolve a known issue
+[(#79417)](https://github.com/rust-lang/rust/issues/79417) that doc test coverage
+generates incorrect source line numbers in `llvm-cov show` results.
+
 ## Other references
 
 Rust's implementation and workflow for source-based code coverage is based on the same library and tools used to implement [source-based code coverage in Clang]. (This document is partially based on the Clang guide.)
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index fb17eb462e1..bdbb90837c7 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -391,7 +391,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
                 _,
             ))) => {
                 debug!("saw end of shortcut link to {}", dest);
-                if self.links.iter().find(|&link| *link.href == **dest).is_some() {
+                if self.links.iter().any(|link| *link.href == **dest) {
                     assert!(self.shortcut_link.is_some(), "saw closing link without opening tag");
                     self.shortcut_link = None;
                 }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 0884351a9fd..a0ccb078c4a 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1469,16 +1469,21 @@ function defocusSearchBar() {
                 });
 
                 if (e.which === 38) { // up
-                    if (!actives[currentTab].length ||
-                        !actives[currentTab][0].previousElementSibling) {
-                        return;
+                    if (e.ctrlKey) { // Going through result tabs.
+                        printTab(currentTab > 0 ? currentTab - 1 : 2);
+                    } else {
+                        if (!actives[currentTab].length ||
+                            !actives[currentTab][0].previousElementSibling) {
+                            return;
+                        }
+                        addClass(actives[currentTab][0].previousElementSibling, "highlighted");
+                        removeClass(actives[currentTab][0], "highlighted");
                     }
-
-                    addClass(actives[currentTab][0].previousElementSibling, "highlighted");
-                    removeClass(actives[currentTab][0], "highlighted");
                     e.preventDefault();
                 } else if (e.which === 40) { // down
-                    if (!actives[currentTab].length) {
+                    if (e.ctrlKey) { // Going through result tabs.
+                        printTab(currentTab > 1 ? 0 : currentTab + 1);
+                    } else if (!actives[currentTab].length) {
                         var results = document.getElementById("results").childNodes;
                         if (results.length > 0) {
                             var res = results[currentTab].getElementsByClassName("result");
@@ -1496,13 +1501,6 @@ function defocusSearchBar() {
                         document.location.href =
                             actives[currentTab][0].getElementsByTagName("a")[0].href;
                     }
-                } else if (e.which === 9) { // tab
-                    if (e.shiftKey) {
-                        printTab(currentTab > 0 ? currentTab - 1 : 2);
-                    } else {
-                        printTab(currentTab > 1 ? 0 : currentTab + 1);
-                    }
-                    e.preventDefault();
                 } else if (e.which === 16) { // shift
                     // Does nothing, it's just to avoid losing "focus" on the highlighted element.
                 } else if (actives[currentTab].length > 0) {
@@ -2898,11 +2896,14 @@ function defocusSearchBar() {
             ["T", "Focus the theme picker menu"],
             ["↑", "Move up in search results"],
             ["↓", "Move down in search results"],
-            ["↹", "Switch tab"],
+            ["ctrl + ↑ / ↓", "Switch result tab"],
             ["&#9166;", "Go to active search result"],
             ["+", "Expand all sections"],
             ["-", "Collapse all sections"],
-        ].map(x => "<dt><kbd>" + x[0] + "</kbd></dt><dd>" + x[1] + "</dd>").join("");
+        ].map(x => "<dt>" +
+            x[0].split(" ")
+                .map((y, index) => (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : y)
+                .join("") + "</dt><dd>" + x[1] + "</dd>").join("");
         var div_shortcuts = document.createElement("div");
         addClass(div_shortcuts, "shortcuts");
         div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 7ade8dc4b84142abd3e6d1fb8a0f4111b0bbd57
+Subproject 8d78ad13896b955f630714f386a95ed91b237e3
diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile
index 302f09ae422..a5d6970009a 100644
--- a/src/test/run-make-fulldeps/coverage-reports/Makefile
+++ b/src/test/run-make-fulldeps/coverage-reports/Makefile
@@ -147,13 +147,19 @@ else
 	# Note `llvm-cov show` output for some programs can vary, but can be ignored
 	# by inserting `// ignore-llvm-cov-show-diffs` at the top of the source file.
 	#
-	# FIXME(richkadel): It looks like most past variations seem to have been mitigated. None of the
-	# Rust test source samples have the `// ignore-llvm-cov-show-diffs` anymore. The main variation
-	# I had seen (and is still present in the new `coverage/lib/used_crate.rs`) is the `llvm-cov show`
-	# reporting of multiple instantiations of a generic function with different type substitutions.
-	# For some reason, `llvm-cov show` can report these in a non-deterministic order, breaking the
-	# `diff` comparision. I was able to work around the problem with `diff --ignore-matching-lines=RE`
+	# FIXME(richkadel): None of the Rust test source samples have the
+	# `// ignore-llvm-cov-show-diffs` anymore. This directive exists to work around a limitation
+	# with `llvm-cov show`. When reporting coverage for multiple instantiations of a generic function,
+	# with different type substitutions, `llvm-cov show` prints these in a non-deterministic order,
+	# breaking the `diff` comparision.
+	#
+	# A partial workaround is implemented below, with `diff --ignore-matching-lines=RE`
 	# to ignore each line prefixing each generic instantiation coverage code region.
+	#
+	# This workaround only works if the coverage counts are identical across all reported
+	# instantiations. If there is no way to ensure this, you may need to apply the
+	# `// ignore-llvm-cov-show-diffs` directive, and rely on the `.json` and counter
+	# files for validating results have not changed.
 
 	$(DIFF) --ignore-matching-lines='::<.*>.*:$$' \
 		expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
@@ -190,10 +196,6 @@ endif
 			$(call BIN,"$(TMPDIR)"/$@) \
 		| "$(PYTHON)" $(BASEDIR)/prettify_json.py \
 		> "$(TMPDIR)"/actual_export_coverage.$@.json
-	# FIXME(richkadel): With the addition of `--ignore-matching-lines=RE` to ignore the
-	# non-deterministically-ordered coverage results for multiple instantiations of generics with
-	# differing type substitutions, I probably don't need the `.json` files anymore (and may not
-	# need `prettify_json.py` either).
 
 ifdef RUSTC_BLESS_TEST
 	cp "$(TMPDIR)"/actual_export_coverage.$@.json expected_export_coverage.$@.json
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 4c03e950af0..e14e733fff6 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::<&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|}
   ------------------
-  | 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|}
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt
index abc2d32a897..ed91e8898ee 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.async.txt
@@ -35,9 +35,6 @@ Counter in file 0 11:1 -> 11:2, (#2 + (#1 - #2))
 Counter in file 0 21:1 -> 21:23, #1
 Counter in file 0 67:5 -> 67:23, #1
 Counter in file 0 38:1 -> 38:19, #1
-Counter in file 0 29:1 -> 29:22, #1
-Counter in file 0 93:1 -> 101:2, #1
-Counter in file 0 91:1 -> 91:25, #1
 Counter in file 0 38:19 -> 42:12, #1
 Counter in file 0 43:9 -> 43:10, #3
 Counter in file 0 43:14 -> 43:18, (#1 + 0)
@@ -49,11 +46,14 @@ Counter in file 0 44:27 -> 44:32, #8
 Counter in file 0 44:36 -> 44:38, (#6 + 0)
 Counter in file 0 45:14 -> 45:16, #7
 Counter in file 0 47:1 -> 47:2, (#5 + (#6 + #7))
+Counter in file 0 29:1 -> 29:22, #1
+Counter in file 0 93:1 -> 101:2, #1
+Counter in file 0 91:1 -> 91:25, #1
 Counter in file 0 51:5 -> 52:18, #1
 Counter in file 0 53:13 -> 53:14, #2
 Counter in file 0 63:13 -> 63:14, (#1 - #2)
 Counter in file 0 65:5 -> 65:6, (#2 + (#1 - #2))
-Counter in file 0 13:20 -> 13:21, #1
+Counter in file 0 17:20 -> 17:21, #1
 Counter in file 0 49:1 -> 68:12, #1
 Counter in file 0 69:9 -> 69:10, #2
 Counter in file 0 69:14 -> 69:27, (#1 + 0)
@@ -69,8 +69,8 @@ Counter in file 0 86:14 -> 86:16, #2
 Counter in file 0 87:14 -> 87:16, #3
 Counter in file 0 89:1 -> 89:2, (#3 + (#2 + (#1 - (#3 + #2))))
 Counter in file 0 17:1 -> 17:20, #1
-Counter in file 0 17:20 -> 17:21, #1
 Counter in file 0 66:5 -> 66:23, #1
+Counter in file 0 13:20 -> 13:21, #1
 Counter in file 0 17:9 -> 17:10, #1
 Counter in file 0 17:9 -> 17:10, #1
 Counter in file 0 117:17 -> 117:19, #1
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.generics.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.generics.txt
index b41f482173b..e2cbf6f709e 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.generics.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.generics.txt
@@ -32,12 +32,12 @@ Combined regions:
   10:5 -> 12:6 (count=1)
 Segment at 10:5 (count = 1), RegionEntry
 Segment at 12:6 (count = 0), Skipped
-Emitting segments for function: _RNvXs_Cs4fqI2P2rA04_8genericsINtB4_8FireworklENtNtNtCs6HRHKMTmAen_4core3ops4drop4Drop4dropB4_
+Emitting segments for function: _RNvXs_Cs4fqI2P2rA04_8genericsINtB4_8FireworklENtNtNtCs3rFBWs28XFJ_4core3ops4drop4Drop4dropB4_
 Combined regions:
   17:5 -> 19:6 (count=1)
 Segment at 17:5 (count = 1), RegionEntry
 Segment at 19:6 (count = 0), Skipped
-Emitting segments for function: _RNvXs_Cs4fqI2P2rA04_8genericsINtB4_8FireworkdENtNtNtCs6HRHKMTmAen_4core3ops4drop4Drop4dropB4_
+Emitting segments for function: _RNvXs_Cs4fqI2P2rA04_8genericsINtB4_8FireworkdENtNtNtCs3rFBWs28XFJ_4core3ops4drop4Drop4dropB4_
 Combined regions:
   17:5 -> 19:6 (count=1)
 Segment at 17:5 (count = 1), RegionEntry
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.uses_crate.txt
index 42cc4904e5f..b0319cd9e18 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.uses_crate.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage_counters.uses_crate.txt
@@ -1,5 +1,5 @@
-Counter in file 0 25:1 -> 27:2, #1
 Counter in file 0 17:1 -> 19:2, #1
+Counter in file 0 25:1 -> 27:2, #1
 Counter in file 0 17:1 -> 19:2, #1
 Counter in file 0 5:1 -> 12:2, #1
 Counter in file 0 17:1 -> 19:2, 0
@@ -78,17 +78,17 @@ Segment at 51:1 (count = 0), RegionEntry
 Segment at 51:2 (count = 0), Skipped
 Segment at 53:1 (count = 1), RegionEntry
 Segment at 61:2 (count = 0), Skipped
-Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate41used_only_from_bin_crate_generic_functionRINtNtCsFAjihUSTht_5alloc3vec3VeclEECs4fqI2P2rA04_10uses_crate
+Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate41used_only_from_bin_crate_generic_functionReECs4fqI2P2rA04_10uses_crate
 Combined regions:
   17:1 -> 19:2 (count=1)
 Segment at 17:1 (count = 1), RegionEntry
 Segment at 19:2 (count = 0), Skipped
-Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate41used_only_from_bin_crate_generic_functionReECs4fqI2P2rA04_10uses_crate
+Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate41used_only_from_bin_crate_generic_functionRINtNtCs3QflaznQylx_5alloc3vec3VeclEECs4fqI2P2rA04_10uses_crate
 Combined regions:
   17:1 -> 19:2 (count=1)
 Segment at 17:1 (count = 1), RegionEntry
 Segment at 19:2 (count = 0), Skipped
-Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate46used_only_from_this_lib_crate_generic_functionINtNtCsFAjihUSTht_5alloc3vec3VeclEEB2_
+Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate46used_only_from_this_lib_crate_generic_functionINtNtCs3QflaznQylx_5alloc3vec3VeclEEB2_
 Combined regions:
   21:1 -> 23:2 (count=1)
 Segment at 21:1 (count = 1), RegionEntry
@@ -98,7 +98,7 @@ Combined regions:
   21:1 -> 23:2 (count=1)
 Segment at 21:1 (count = 1), RegionEntry
 Segment at 23:2 (count = 0), Skipped
-Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate50used_from_bin_crate_and_lib_crate_generic_functionINtNtCsFAjihUSTht_5alloc3vec3VeclEECs4fqI2P2rA04_10uses_crate
+Emitting segments for function: _RINvCsbDqzXfLQacH_10used_crate50used_from_bin_crate_and_lib_crate_generic_functionINtNtCs3QflaznQylx_5alloc3vec3VeclEECs4fqI2P2rA04_10uses_crate
 Combined regions:
   25:1 -> 27:2 (count=1)
 Segment at 25:1 (count = 1), RegionEntry
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 8aabe077cf1..0a6bac48ebb 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -36,7 +36,7 @@ const TEST_REPOS: &[Test] = &[
     Test {
         name: "xsv",
         repo: "https://github.com/BurntSushi/xsv",
-        sha: "66956b6bfd62d6ac767a6b6499c982eae20a2c9f",
+        sha: "3de6c04269a7d315f7e9864b9013451cd9580a08",
         lock: None,
         packages: &[],
     },
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index 326b7948098..ea54a351e03 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -143,8 +143,8 @@ impl<'a> LintExtractor<'a> {
                     Some((lineno, line)) => {
                         let line = line.trim();
                         if let Some(text) = line.strip_prefix("/// ") {
-                            doc_lines.push(text.trim().to_string());
-                        } else if line.starts_with("///") {
+                            doc_lines.push(text.to_string());
+                        } else if line == "///" {
                             doc_lines.push("".to_string());
                         } else if line.starts_with("// ") {
                             // Ignore comments.