From 5848c27c7995eabe0db76eb7c1360c77e9fefba4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 20 Jul 2022 10:22:16 -0400 Subject: [PATCH 01/23] make raw_eq precondition more restrictive --- library/core/src/array/equality.rs | 7 ++++--- library/core/src/intrinsics.rs | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index 33f7f494e9d84..a85f13a4b9e80 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -173,13 +173,14 @@ macro_rules! is_raw_eq_comparable { )+}; } -// SAFETY: All the ordinary integer types allow all bit patterns as distinct values +// SAFETY: All the ordinary integer types have no padding, and are no poointers. is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); -// SAFETY: bool and char have *niches*, but no *padding*, so this is sound +// SAFETY: bool and char have *niches*, but no *padding* (and these are not pointer types), so this +// is sound is_raw_eq_comparable!(bool, char); -// SAFETY: Similarly, the non-zero types have a niche, but no undef, +// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers, // and they compare like their underlying numeric type. is_raw_eq_comparable!( NonZeroU8, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 998f7be3f7396..565c32d688874 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2277,7 +2277,8 @@ extern "rust-intrinsic" { /// /// # Safety /// - /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized. + /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized or carries a + /// pointer value. /// Note that this is a stricter criterion than just the *values* being /// fully-initialized: if `T` has padding, it's UB to call this intrinsic. /// From 2d1c683112f6bacb0dbc06379d7b1d40a93d0523 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 20 Jul 2022 10:39:21 -0400 Subject: [PATCH 02/23] fix typo Co-authored-by: Marco Colombo --- library/core/src/array/equality.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index a85f13a4b9e80..97300adb0097d 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -173,7 +173,7 @@ macro_rules! is_raw_eq_comparable { )+}; } -// SAFETY: All the ordinary integer types have no padding, and are no poointers. +// SAFETY: All the ordinary integer types have no padding, and are no pointers. is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); // SAFETY: bool and char have *niches*, but no *padding* (and these are not pointer types), so this From a61c8413852a704f9f06e4fead7742fe0a7c68da Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 3 Aug 2022 12:44:21 -0400 Subject: [PATCH 03/23] actually call assert_send_and_sync --- library/core/tests/slice.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 0656109e9db88..b8f6fe6961a8e 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1197,7 +1197,6 @@ fn chunks_mut_are_send_and_sync() { use std::slice::{ChunksExactMut, ChunksMut, RChunksExactMut, RChunksMut}; use std::sync::MutexGuard; - #[allow(unused)] fn assert_send_and_sync() where ChunksMut<'static, Cell>: Send, @@ -1210,6 +1209,8 @@ fn chunks_mut_are_send_and_sync() { RChunksExactMut<'static, MutexGuard<'static, u32>>: Sync, { } + + assert_send_and_sync(); } #[test] From 725da8787610e3ccdcdac179f90157aaff2a49a8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 29 Jul 2022 00:17:24 +0000 Subject: [PATCH 04/23] provide correct size hint for unsupported platform CommandArgs --- library/std/src/sys/unsupported/process.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs index 42a1ff730e379..633f17c054bc6 100644 --- a/library/std/src/sys/unsupported/process.rs +++ b/library/std/src/sys/unsupported/process.rs @@ -200,6 +200,9 @@ impl<'a> Iterator for CommandArgs<'a> { fn next(&mut self) -> Option<&'a OsStr> { None } + fn size_hint(&self) -> (usize, Option) { + (0, Some(0)) + } } impl<'a> ExactSizeIterator for CommandArgs<'a> {} From 775c3c0493e9a383a7f1c521b06d36f2e3d0d886 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 31 Jul 2022 14:02:31 -0500 Subject: [PATCH 05/23] Add `x.sh` and `x.ps1` shell scripts This is a more ambitious version of https://github.com/rust-lang/rust/pull/98716. It still changes the shebang back to python3, for compatibility with non-Unix systems, but also adds alternative entrypoints for systems without `python3` installed. These scripts will be necessary for the rust entrypoint (#94829), so I see little downside in adding them early. --- src/bootstrap/mk/Makefile.in | 11 +++++-- .../host-x86_64/x86_64-gnu-llvm-12/Dockerfile | 18 ++++++++-- src/tools/tidy/src/bins.rs | 8 +++-- x.ps1 | 28 ++++++++++++++++ x.py | 30 +++-------------- x.sh | 33 +++++++++++++++++++ 6 files changed, 94 insertions(+), 34 deletions(-) create mode 100755 x.ps1 create mode 100755 x.sh diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 5a1f2e7041378..1e0f7e9acf4f2 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -66,16 +66,21 @@ TESTS_IN_2 := \ src/test/ui \ src/tools/linkchecker +## MSVC native builders + +# these intentionally don't use `$(BOOTSTRAP)` so we can test the shebang on Windows ci-subset-1: - $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_2:%=--exclude %) + $(Q)$(CFG_SRC_DIR)/x.py test --stage 2 $(TESTS_IN_2:%=--exclude %) ci-subset-2: - $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_2) + $(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 $(TESTS_IN_2) + +## MingW native builders TESTS_IN_MINGW_2 := \ src/test/ui ci-mingw-subset-1: - $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %) + $(Q)$(CFG_SRC_DIR)/x.sh test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %) ci-mingw-subset-2: $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile index df1fbc29cf5e6..8de9045c3baa7 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile @@ -1,6 +1,8 @@ FROM ubuntu:20.04 ARG DEBIAN_FRONTEND=noninteractive + +# NOTE: intentionally installs both python2 and python3 so we can test support for both. RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ gcc-multilib \ @@ -10,6 +12,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ ca-certificates \ python2.7 \ + python3.9 \ git \ cmake \ sudo \ @@ -23,6 +26,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ nodejs +# Install powershell so we can test x.ps1 on Linux +RUN apt-get update && \ + apt-get install -y apt-transport-https software-properties-common && \ + curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \ + dpkg -i packages-microsoft-prod.deb && \ + apt-get update && \ + apt-get install -y powershell + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -33,21 +44,22 @@ ENV RUST_CONFIGURE_ARGS \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 -ENV SCRIPT python2.7 ../x.py --stage 2 test --exclude src/tools/tidy && \ +# NOTE: intentionally uses all of `x.py`, `x.sh`, and `x.ps1` to make sure they all work on Linux. +ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \ # Run the `mir-opt` tests again but this time for a 32-bit target. # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have # both 32-bit and 64-bit outputs updated by the PR author, before # the PR is approved and tested for merging. # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`, # despite having different output on 32-bit vs 64-bit targets. - python2.7 ../x.py --stage 2 test src/test/mir-opt \ + ../x.sh --stage 2 test src/test/mir-opt \ --host='' --target=i686-unknown-linux-gnu && \ # Run the UI test suite again, but in `--pass=check` mode # # This is intended to make sure that both `--pass=check` continues to # work. # - python2.7 ../x.py --stage 2 test src/test/ui --pass=check \ + ../x.ps1 --stage 2 test src/test/ui --pass=check \ --host='' --target=i686-unknown-linux-gnu && \ # Run tidy at the very end, after all the other tests. python2.7 ../x.py --stage 2 test src/tools/tidy diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 9615c4db6b4b5..025b8ab9f0af5 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -96,6 +96,8 @@ mod os_impl { #[cfg(unix)] pub fn check(path: &Path, bad: &mut bool) { + use std::ffi::OsStr; + const ALLOWED: &[&str] = &["configure"]; crate::walk_no_read( @@ -117,9 +119,9 @@ mod os_impl { }, &mut |entry| { let file = entry.path(); - let filename = file.file_name().unwrap().to_string_lossy(); - let extensions = [".py", ".sh"]; - if extensions.iter().any(|e| filename.ends_with(e)) { + let extension = file.extension(); + let scripts = ["py", "sh", "ps1"]; + if scripts.into_iter().any(|e| extension == Some(OsStr::new(e))) { return; } diff --git a/x.ps1 b/x.ps1 new file mode 100755 index 0000000000000..1225443735f7b --- /dev/null +++ b/x.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh + +# See x.sh for why these scripts exist. + +$xpy = Join-Path $PSScriptRoot x.py +# Start-Process for some reason splits arguments on spaces. (Isn't powershell supposed to be simpler than bash?) +# Double-quote all the arguments so it doesn't do that. +$xpy_args = @("""$xpy""") +foreach ($arg in $args) { + $xpy_args += """$arg""" +} + +foreach ($python in "py", "python3", "python", "python2") { + # NOTE: this only tests that the command exists in PATH, not that it's actually + # executable. The latter is not possible in a portable way, see + # https://github.com/PowerShell/PowerShell/issues/12625. + if (Get-Command $python -ErrorAction SilentlyContinue) { + if ($python -eq "py") { + # Use python3, not python2 + $xpy_args = @("-3") + $xpy_args + } + $process = Start-Process -NoNewWindow -Wait -PassThru $python $xpy_args + Exit $process.ExitCode + } +} + +Write-Error "${PSCommandPath}: error: did not find python installed" +Exit 1 diff --git a/x.py b/x.py index 0289056fdcb16..6c68907c58145 100755 --- a/x.py +++ b/x.py @@ -1,36 +1,16 @@ -#!/usr/bin/env bash +#!/usr/bin/env python3 +# Some systems don't have `python3` in their PATH. This isn't supported by x.py directly; +# they should use `x.sh` or `x.ps1` instead. -# Modern Linux and macOS systems commonly only have a thing called `python3` and -# not `python`, while Windows commonly does not have `python3`, so we cannot -# directly use python in the shebang and have it consistently work. Instead we -# embed some bash to look for a python to run the rest of the script. -# -# On Windows, `py -3` sometimes works. We need to try it first because `python3` -# sometimes tries to launch the app store on Windows. -'''': -for PYTHON in "py -3" python3 python python2; do - if command -v $PYTHON >/dev/null; then - exec $PYTHON "$0" "$@" - break - fi -done -echo "$0: error: did not find python installed" >&2 -exit 1 -''' - -# The rest of this file is Python. -# # This file is only a "symlink" to bootstrap.py, all logic should go there. import os import sys # If this is python2, check if python3 is available and re-execute with that -# interpreter. +# interpreter. Only python3 allows downloading CI LLVM. # -# `./x.py` would not normally benefit from this because the bash above tries -# python3 before 2, but this matters if someone ran `python x.py` and their -# system's `python` is python2. +# This matters if someone's system `python` is python2. if sys.version_info.major < 3: try: os.execvp("py", ["py", "-3"] + sys.argv) diff --git a/x.sh b/x.sh new file mode 100755 index 0000000000000..704d0f791f333 --- /dev/null +++ b/x.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# Modern Linux and macOS systems commonly only have a thing called `python3` and +# not `python`, while Windows commonly does not have `python3`, so we cannot +# directly use python in the x.py shebang and have it consistently work. Instead we +# have a shell script to look for a python to run x.py. + +set -eu + +realpath() { + if [ -d "$1" ]; then + CDPATH='' command cd "$1" && pwd -P + else + echo "$(realpath "$(dirname "$1")")/$(basename "$1")" + fi +} + +xpy=$(dirname "$(realpath "$0")")/x.py + +# On Windows, `py -3` sometimes works. We need to try it first because `python3` +# sometimes tries to launch the app store on Windows. +for SEARCH_PYTHON in py python3 python python2; do + if python=$(command -v $SEARCH_PYTHON) && [ -x "$python" ]; then + if [ $SEARCH_PYTHON = py ]; then + extra_arg="-3" + else + extra_arg="" + fi + exec "$python" $extra_arg "$xpy" "$@" + fi +done +echo "$0: error: did not find python installed" >&2 +exit 1 From c32969d8e6f8fc7faa7f265a1a3e2e8c75104094 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 9 Aug 2022 15:31:23 +1000 Subject: [PATCH 06/23] Move JSON tests into a directory. To get around the "following path contains more than 968 entries, you should move the test to some relevant subdirectory" tidy error. --- src/test/ui/json-multiple.stderr | 1 - src/test/ui/json-options.stderr | 1 - src/test/ui/{ => json}/json-and-color.rs | 0 src/test/ui/{ => json}/json-and-color.stderr | 0 src/test/ui/{ => json}/json-and-error-format.rs | 0 src/test/ui/{ => json}/json-and-error-format.stderr | 0 src/test/ui/{ => json}/json-bom-plus-crlf-multifile-aux.rs | 0 src/test/ui/{ => json}/json-bom-plus-crlf-multifile.rs | 0 src/test/ui/{ => json}/json-bom-plus-crlf-multifile.stderr | 0 src/test/ui/{ => json}/json-bom-plus-crlf.rs | 0 src/test/ui/{ => json}/json-bom-plus-crlf.stderr | 0 src/test/ui/{ => json}/json-invalid.rs | 0 src/test/ui/{ => json}/json-invalid.stderr | 0 src/test/ui/{ => json}/json-multiple.polonius.stderr | 0 src/test/ui/{ => json}/json-multiple.rs | 0 src/test/ui/json/json-multiple.stderr | 1 + src/test/ui/{ => json}/json-options.polonius.stderr | 0 src/test/ui/{ => json}/json-options.rs | 0 src/test/ui/json/json-options.stderr | 1 + src/test/ui/{ => json}/json-short.rs | 0 src/test/ui/{ => json}/json-short.stderr | 0 21 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 src/test/ui/json-multiple.stderr delete mode 100644 src/test/ui/json-options.stderr rename src/test/ui/{ => json}/json-and-color.rs (100%) rename src/test/ui/{ => json}/json-and-color.stderr (100%) rename src/test/ui/{ => json}/json-and-error-format.rs (100%) rename src/test/ui/{ => json}/json-and-error-format.stderr (100%) rename src/test/ui/{ => json}/json-bom-plus-crlf-multifile-aux.rs (100%) rename src/test/ui/{ => json}/json-bom-plus-crlf-multifile.rs (100%) rename src/test/ui/{ => json}/json-bom-plus-crlf-multifile.stderr (100%) rename src/test/ui/{ => json}/json-bom-plus-crlf.rs (100%) rename src/test/ui/{ => json}/json-bom-plus-crlf.stderr (100%) rename src/test/ui/{ => json}/json-invalid.rs (100%) rename src/test/ui/{ => json}/json-invalid.stderr (100%) rename src/test/ui/{ => json}/json-multiple.polonius.stderr (100%) rename src/test/ui/{ => json}/json-multiple.rs (100%) create mode 100644 src/test/ui/json/json-multiple.stderr rename src/test/ui/{ => json}/json-options.polonius.stderr (100%) rename src/test/ui/{ => json}/json-options.rs (100%) create mode 100644 src/test/ui/json/json-options.stderr rename src/test/ui/{ => json}/json-short.rs (100%) rename src/test/ui/{ => json}/json-short.stderr (100%) diff --git a/src/test/ui/json-multiple.stderr b/src/test/ui/json-multiple.stderr deleted file mode 100644 index 7ed345113cb47..0000000000000 --- a/src/test/ui/json-multiple.stderr +++ /dev/null @@ -1 +0,0 @@ -{"artifact":"$TEST_BUILD_DIR/json-multiple/libjson_multiple.rlib","emit":"link"} diff --git a/src/test/ui/json-options.stderr b/src/test/ui/json-options.stderr deleted file mode 100644 index 24977731d17b7..0000000000000 --- a/src/test/ui/json-options.stderr +++ /dev/null @@ -1 +0,0 @@ -{"artifact":"$TEST_BUILD_DIR/json-options/libjson_options.rlib","emit":"link"} diff --git a/src/test/ui/json-and-color.rs b/src/test/ui/json/json-and-color.rs similarity index 100% rename from src/test/ui/json-and-color.rs rename to src/test/ui/json/json-and-color.rs diff --git a/src/test/ui/json-and-color.stderr b/src/test/ui/json/json-and-color.stderr similarity index 100% rename from src/test/ui/json-and-color.stderr rename to src/test/ui/json/json-and-color.stderr diff --git a/src/test/ui/json-and-error-format.rs b/src/test/ui/json/json-and-error-format.rs similarity index 100% rename from src/test/ui/json-and-error-format.rs rename to src/test/ui/json/json-and-error-format.rs diff --git a/src/test/ui/json-and-error-format.stderr b/src/test/ui/json/json-and-error-format.stderr similarity index 100% rename from src/test/ui/json-and-error-format.stderr rename to src/test/ui/json/json-and-error-format.stderr diff --git a/src/test/ui/json-bom-plus-crlf-multifile-aux.rs b/src/test/ui/json/json-bom-plus-crlf-multifile-aux.rs similarity index 100% rename from src/test/ui/json-bom-plus-crlf-multifile-aux.rs rename to src/test/ui/json/json-bom-plus-crlf-multifile-aux.rs diff --git a/src/test/ui/json-bom-plus-crlf-multifile.rs b/src/test/ui/json/json-bom-plus-crlf-multifile.rs similarity index 100% rename from src/test/ui/json-bom-plus-crlf-multifile.rs rename to src/test/ui/json/json-bom-plus-crlf-multifile.rs diff --git a/src/test/ui/json-bom-plus-crlf-multifile.stderr b/src/test/ui/json/json-bom-plus-crlf-multifile.stderr similarity index 100% rename from src/test/ui/json-bom-plus-crlf-multifile.stderr rename to src/test/ui/json/json-bom-plus-crlf-multifile.stderr diff --git a/src/test/ui/json-bom-plus-crlf.rs b/src/test/ui/json/json-bom-plus-crlf.rs similarity index 100% rename from src/test/ui/json-bom-plus-crlf.rs rename to src/test/ui/json/json-bom-plus-crlf.rs diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json/json-bom-plus-crlf.stderr similarity index 100% rename from src/test/ui/json-bom-plus-crlf.stderr rename to src/test/ui/json/json-bom-plus-crlf.stderr diff --git a/src/test/ui/json-invalid.rs b/src/test/ui/json/json-invalid.rs similarity index 100% rename from src/test/ui/json-invalid.rs rename to src/test/ui/json/json-invalid.rs diff --git a/src/test/ui/json-invalid.stderr b/src/test/ui/json/json-invalid.stderr similarity index 100% rename from src/test/ui/json-invalid.stderr rename to src/test/ui/json/json-invalid.stderr diff --git a/src/test/ui/json-multiple.polonius.stderr b/src/test/ui/json/json-multiple.polonius.stderr similarity index 100% rename from src/test/ui/json-multiple.polonius.stderr rename to src/test/ui/json/json-multiple.polonius.stderr diff --git a/src/test/ui/json-multiple.rs b/src/test/ui/json/json-multiple.rs similarity index 100% rename from src/test/ui/json-multiple.rs rename to src/test/ui/json/json-multiple.rs diff --git a/src/test/ui/json/json-multiple.stderr b/src/test/ui/json/json-multiple.stderr new file mode 100644 index 0000000000000..55ccfd5fa70de --- /dev/null +++ b/src/test/ui/json/json-multiple.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json/json-multiple/libjson_multiple.rlib","emit":"link"} diff --git a/src/test/ui/json-options.polonius.stderr b/src/test/ui/json/json-options.polonius.stderr similarity index 100% rename from src/test/ui/json-options.polonius.stderr rename to src/test/ui/json/json-options.polonius.stderr diff --git a/src/test/ui/json-options.rs b/src/test/ui/json/json-options.rs similarity index 100% rename from src/test/ui/json-options.rs rename to src/test/ui/json/json-options.rs diff --git a/src/test/ui/json/json-options.stderr b/src/test/ui/json/json-options.stderr new file mode 100644 index 0000000000000..645a26f5ad407 --- /dev/null +++ b/src/test/ui/json/json-options.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json/json-options/libjson_options.rlib","emit":"link"} diff --git a/src/test/ui/json-short.rs b/src/test/ui/json/json-short.rs similarity index 100% rename from src/test/ui/json-short.rs rename to src/test/ui/json/json-short.rs diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json/json-short.stderr similarity index 100% rename from src/test/ui/json-short.stderr rename to src/test/ui/json/json-short.stderr From 5938fd704d4358a12081cba810f3055531da4386 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Sat, 16 Jul 2022 09:07:40 -0700 Subject: [PATCH 07/23] rustdoc: simplify highlight.rs Split render_with_highlighting, which took many optional parameters, into three functions for specific purposes, which each take a smaller number of mostly required parameters. Remove some plumbing to pass through an "edition" parameter, which was used solely to avoid highlighting some 2021 Edition keywords in non-2021 code. --- src/librustdoc/html/highlight.rs | 88 +++++++++++++++--------- src/librustdoc/html/highlight/tests.rs | 11 ++- src/librustdoc/html/markdown.rs | 23 +++---- src/librustdoc/html/render/mod.rs | 3 +- src/librustdoc/html/render/print_item.rs | 12 +--- src/librustdoc/html/sources.rs | 17 ++--- 6 files changed, 75 insertions(+), 79 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index d2ef89078bf6d..7dfae15ad034f 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -33,27 +33,39 @@ pub(crate) struct HrefContext<'a, 'b, 'c> { /// Decorations are represented as a map from CSS class to vector of character ranges. /// Each range will be wrapped in a span with that class. +#[derive(Default)] pub(crate) struct DecorationInfo(pub(crate) FxHashMap<&'static str, Vec<(u32, u32)>>); -/// Highlights `src`, returning the HTML output. -pub(crate) fn render_with_highlighting( +#[derive(Eq, PartialEq, Clone, Copy)] +pub(crate) enum Tooltip { + Ignore, + CompileFail, + ShouldPanic, + Edition(Edition), + None, +} + +/// Highlights `src` as an inline example, returning the HTML output. +pub(crate) fn render_example_with_highlighting( src: &str, out: &mut Buffer, - class: Option<&str>, + tooltip: Tooltip, playground_button: Option<&str>, - tooltip: Option<(Option, &str)>, - edition: Edition, - extra_content: Option, - href_context: Option>, - decoration_info: Option, ) { - debug!("highlighting: ================\n{}\n==============", src); - if let Some((edition_info, class)) = tooltip { + let class = match tooltip { + Tooltip::Ignore => " ignore", + Tooltip::CompileFail => " compile_fail", + Tooltip::ShouldPanic => " should_panic", + Tooltip::Edition(_) => " edition", + Tooltip::None => "", + }; + + if tooltip != Tooltip::None { write!( out, - "
", + "
", class, - if let Some(edition_info) = edition_info { + if let Tooltip::Edition(edition_info) = tooltip { format!(" data-edition=\"{}\"", edition_info) } else { String::new() @@ -61,20 +73,40 @@ pub(crate) fn render_with_highlighting( ); } - write_header(out, class, extra_content); - write_code(out, src, edition, href_context, decoration_info); + write_header(out, &format!("rust-example-rendered{}", class), None); + write_code(out, src, None, None); write_footer(out, playground_button); } -fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option) { +/// Highlights `src` as a macro, returning the HTML output. +pub(crate) fn render_macro_with_highlighting(src: &str, out: &mut Buffer) { + write_header(out, "macro", None); + write_code(out, src, None, None); + write_footer(out, None); +} + +/// Highlights `src` as a source code page, returning the HTML output. +pub(crate) fn render_source_with_highlighting( + src: &str, + out: &mut Buffer, + line_numbers: Buffer, + href_context: HrefContext<'_, '_, '_>, + decoration_info: DecorationInfo, +) { + write_header(out, "", Some(line_numbers)); + write_code(out, src, Some(href_context), Some(decoration_info)); + write_footer(out, None); +} + +fn write_header(out: &mut Buffer, class: &str, extra_content: Option) { write!(out, "
"); if let Some(extra) = extra_content { out.push_buffer(extra); } - if let Some(class) = class { - write!(out, "
", class);
-    } else {
+    if class.is_empty() {
         write!(out, "
");
+    } else {
+        write!(out, "
", class);
     }
     write!(out, "");
 }
@@ -93,7 +125,6 @@ fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option>,
     decoration_info: Option,
 ) {
@@ -102,7 +133,6 @@ fn write_code(
     let mut closing_tags: Vec<&'static str> = Vec::new();
     Classifier::new(
         &src,
-        edition,
         href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
         decoration_info,
     )
@@ -220,7 +250,7 @@ impl<'a> Iterator for TokenIter<'a> {
 }
 
 /// Classifies into identifier class; returns `None` if this is a non-keyword identifier.
-fn get_real_ident_class(text: &str, edition: Edition, allow_path_keywords: bool) -> Option {
+fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option {
     let ignore: &[&str] =
         if allow_path_keywords { &["self", "Self", "super", "crate"] } else { &["self", "Self"] };
     if ignore.iter().any(|k| *k == text) {
@@ -229,7 +259,7 @@ fn get_real_ident_class(text: &str, edition: Edition, allow_path_keywords: bool)
     Some(match text {
         "ref" | "mut" => Class::RefKeyWord,
         "false" | "true" => Class::Bool,
-        _ if Symbol::intern(text).is_reserved(|| edition) => Class::KeyWord,
+        _ if Symbol::intern(text).is_reserved(|| Edition::Edition2021) => Class::KeyWord,
         _ => return None,
     })
 }
@@ -311,7 +341,6 @@ struct Classifier<'a> {
     in_attribute: bool,
     in_macro: bool,
     in_macro_nonterminal: bool,
-    edition: Edition,
     byte_pos: u32,
     file_span: Span,
     src: &'a str,
@@ -321,12 +350,7 @@ struct Classifier<'a> {
 impl<'a> Classifier<'a> {
     /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
     /// file span which will be used later on by the `span_correspondance_map`.
-    fn new(
-        src: &str,
-        edition: Edition,
-        file_span: Span,
-        decoration_info: Option,
-    ) -> Classifier<'_> {
+    fn new(src: &str, file_span: Span, decoration_info: Option) -> Classifier<'_> {
         let tokens = PeekIter::new(TokenIter { src });
         let decorations = decoration_info.map(Decorations::new);
         Classifier {
@@ -334,7 +358,6 @@ impl<'a> Classifier<'a> {
             in_attribute: false,
             in_macro: false,
             in_macro_nonterminal: false,
-            edition,
             byte_pos: 0,
             file_span,
             src,
@@ -354,7 +377,6 @@ impl<'a> Classifier<'a> {
         let start = self.byte_pos as usize;
         let mut pos = start;
         let mut has_ident = false;
-        let edition = self.edition;
 
         loop {
             let mut nb = 0;
@@ -376,7 +398,7 @@ impl<'a> Classifier<'a> {
 
             if let Some((None, text)) = self.tokens.peek().map(|(token, text)| {
                 if *token == TokenKind::Ident {
-                    let class = get_real_ident_class(text, edition, true);
+                    let class = get_real_ident_class(text, true);
                     (class, text)
                 } else {
                     // Doesn't matter which Class we put in here...
@@ -634,7 +656,7 @@ impl<'a> Classifier<'a> {
                 sink(Highlight::Token { text, class: None });
                 return;
             }
-            TokenKind::Ident => match get_real_ident_class(text, self.edition, false) {
+            TokenKind::Ident => match get_real_ident_class(text, false) {
                 None => match text {
                     "Option" | "Result" => Class::PreludeTy,
                     "Some" | "None" | "Ok" | "Err" => Class::PreludeVal,
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index 1fea7e983b448..4861a8ad32da6 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -3,7 +3,6 @@ use crate::html::format::Buffer;
 use expect_test::expect_file;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::create_default_session_globals_then;
-use rustc_span::edition::Edition;
 
 const STYLE: &str = r#"